diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..e1aca79
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+
+SDL_CFLAGS = `sdl-config --cflags`
+SDL_LIBS = `sdl-config --libs`
+VORBIS_LIBS = -lvorbisidec
+ZLIB_LIBS = -lz
+
+DEFINES = -DBYPASS_PROTECTION
+#DEFINES = -DBYPASS_PROTECTION -DENABLE_PASSWORD_MENU -DNDEBUG
+
+CXXFLAGS += -Wall -Wuninitialized -Wshadow -Wundef -Wreorder -Wnon-virtual-dtor -Wno-multichar
+CXXFLAGS += -MMD $(SDL_CFLAGS) -DUSE_ZLIB $(DEFINES)
+
+SRCS = collision.cpp cutscene.cpp file.cpp fs.cpp game.cpp graphics.cpp main.cpp menu.cpp \
+ mixer.cpp mod_player.cpp ogg_player.cpp piege.cpp resource.cpp scaler.cpp seq_player.cpp \
+ sfx_player.cpp staticres.cpp systemstub_sdl.cpp unpack.cpp util.cpp video.cpp
+
+OBJS = $(SRCS:.cpp=.o)
+DEPS = $(SRCS:.cpp=.d)
+
+LIBS = $(SDL_LIBS) $(VORBIS_LIBS) $(ZLIB_LIBS)
+
+-include Makefile.local
+
+rs: $(OBJS)
+ $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+clean:
+ rm -f *.o *.d
+
+-include $(DEPS)
diff --git a/README b/README
new file mode 100644
index 0000000..fd9629a
--- /dev/null
+++ b/README
@@ -0,0 +1,110 @@
+
+REminiscence README
+Release version: 0.2.2 ($date)
+-------------------------------------------------------------------------------
+
+
+About:
+------
+
+REminiscence is a re-implementation of the engine used in the game Flashback
+made by Delphine Software and released in 1992. More informations about the
+game can be found at [1], [2] and [3].
+
+
+Compiling:
+----------
+
+Update the defines in the Makefile if needed. The SDL and zlib libraries are required.
+
+
+Data Files:
+-----------
+
+You will need the original files of the PC (DOS or CD) or Amiga release.
+If you have a version distributed by SSI, you'll have to rename the files
+and drop the 'ssi' suffix (ie. logosssi.cmd -> logos.cmd).
+
+To hear background music during polygonal cutscenes with the PC version,
+you'll need to copy the .mod files of the Amiga version :
+
+ mod.flashback-ascenseur
+ mod.flashback-ceinturea
+ mod.flashback-chute
+ mod.flashback-desintegr
+ mod.flashback-donneobjt
+ mod.flashback-fin
+ mod.flashback-fin2
+ mod.flashback-game_over
+ mod.flashback-holocube
+ mod.flashback-introb
+ mod.flashback-jungle
+ mod.flashback-logo
+ mod.flashback-memoire
+ mod.flashback-missionca
+ mod.flashback-options1
+ mod.flashback-options2
+ mod.flashback-reunion
+ mod.flashback-taxi
+ mod.flashback-teleport2
+ mod.flashback-teleporta
+ mod.flashback-voyage
+
+To hear voice during in-game dialogues, you'll need to copy the 'VOICE.VCE'
+file from the SegaCD version to the DATA directory.
+
+
+Running:
+--------
+
+By default, the engine will try to load the game data files from the 'DATA'
+directory (as the original game did). The savestates are saved in the current
+directory. These paths can be changed using command line switches :
+
+ Usage: rs [OPTIONS]...
+ --datapath=PATH Path to data files (default 'DATA')
+ --savepath=PATH Path to save files (default '.')
+
+In-game hotkeys :
+
+ Arrow Keys move Conrad
+ Enter use the current inventory object
+ Shift talk / use / run / shoot
+ Escape display the options
+ Backspace display the inventory
+ Alt Enter toggle windowed/fullscreen mode
+ Alt + and - change video scaler
+ Ctrl S save game state
+ Ctrl L load game state
+ Ctrl + and - change game state slot
+ Ctrl R toggle input keys record
+ Ctrl P toggle input keys replay
+
+Debug hotkeys :
+
+ Ctrl F toggle fast mode
+ Ctrl I Conrad 'infinite' life
+ Ctrl B toggle display of updated dirty blocks
+ Ctrl M mirror mode (right - left swapped)
+
+
+Credits:
+--------
+
+Delphine Software, obviously, for making another great game.
+Yaz0r, Pixel and gawd for sharing information they gathered on the game.
+Nicolas Bondoux for sound fixes.
+
+
+Contact:
+--------
+
+Gregory Montoir, cyx@users.sourceforge.net
+
+
+URLs:
+-----
+
+[1] http://www.mobygames.com/game/flashback-the-quest-for-identity
+[2] http://en.wikipedia.org/wiki/Flashback:_The_Quest_for_Identity
+[3] http://ramal.free.fr/fb_en.htm
diff --git a/collision.cpp b/collision.cpp
new file mode 100644
index 0000000..ccd4a89
--- /dev/null
+++ b/collision.cpp
@@ -0,0 +1,522 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "game.h"
+#include "resource.h"
+
+
+void Game::col_prepareRoomState() {
+ memset(_col_activeCollisionSlots, 0xFF, sizeof(_col_activeCollisionSlots));
+ _col_currentLeftRoom = _res._ctData[CT_LEFT_ROOM + _currentRoom];
+ _col_currentRightRoom = _res._ctData[CT_RIGHT_ROOM + _currentRoom];
+ for (int i = 0; i != _col_curPos; ++i) {
+ CollisionSlot *_di = _col_slotsTable[i];
+ uint8_t room = _di->ct_pos / 64;
+ if (room == _currentRoom) {
+ _col_activeCollisionSlots[0x30 + (_di->ct_pos & 0x3F)] = i;
+ } else if (room == _col_currentLeftRoom) {
+ _col_activeCollisionSlots[0x00 + (_di->ct_pos & 0x3F)] = i;
+ } else if (room == _col_currentRightRoom) {
+ _col_activeCollisionSlots[0x60 + (_di->ct_pos & 0x3F)] = i;
+ }
+ }
+#ifdef DEBUG_COLLISION
+ printf("---\n");
+ for (int y = 0; y < 7; ++y) {
+ for (int x = 0; x < 16; ++x) {
+ printf("%d", _res._ctData[0x100 + _currentRoom * 0x70 + y * 16 + x]);
+ }
+ printf("\n");
+ }
+#endif
+}
+
+void Game::col_clearState() {
+ _col_curPos = 0;
+ _col_curSlot = _col_slots;
+}
+
+void Game::col_preparePiegeState(LivePGE *pge) {
+ debug(DBG_COL, "Game::col_preparePiegeState() pge_num=%d", pge - &_pgeLive[0]);
+ CollisionSlot *ct_slot1, *ct_slot2;
+ if (pge->init_PGE->unk1C == 0) {
+ pge->collision_slot = 0xFF;
+ return;
+ }
+ int i = 0;
+ ct_slot1 = 0;
+ for (int c = 0; c < pge->init_PGE->unk1C; ++c) {
+ ct_slot2 = _col_curSlot;
+ if (ct_slot2 + 1 > &_col_slots[255])
+ return;
+ _col_curSlot = ct_slot2 + 1;
+ int16_t pos = col_getGridPos(pge, i);
+ if (pos < 0) {
+ if (ct_slot1 == 0) {
+ pge->collision_slot = 0xFF;
+ } else {
+ ct_slot1->index = 0xFFFF;
+ }
+ return;
+ }
+ ct_slot2->ct_pos = pos;
+ ct_slot2->live_pge = pge;
+ ct_slot2->index = 0xFFFF;
+ int16_t _ax = col_findSlot(pos);
+ if (_ax >= 0) {
+ ct_slot2->prev_slot = _col_slotsTable[_ax];
+ _col_slotsTable[_ax] = ct_slot2;
+ if (ct_slot1 == 0) {
+ pge->collision_slot = _ax;
+ } else {
+ ct_slot1->index = _ax;
+ }
+ LivePGE *temp_pge = ct_slot2->live_pge;
+ if (temp_pge->flags & 0x80) {
+ _pge_liveTable2[temp_pge->index] = temp_pge;
+ temp_pge->flags |= 4;
+ }
+ if (ct_slot2->prev_slot) {
+ temp_pge = ct_slot2->prev_slot->live_pge;
+ if (temp_pge->flags & 0x80) {
+ _pge_liveTable2[temp_pge->index] = temp_pge;
+ temp_pge->flags |= 4;
+ }
+ }
+ } else {
+ ct_slot2->prev_slot = 0;
+ _col_slotsTable[_col_curPos] = ct_slot2;
+ if (ct_slot1 == 0) {
+ pge->collision_slot = _col_curPos;
+ } else {
+ ct_slot1->index = _col_curPos;
+ }
+ _col_curPos++;
+ }
+ ct_slot1 = ct_slot2;
+ i += 0x10;
+ }
+}
+
+uint16_t Game::col_getGridPos(LivePGE *pge, int16_t dx) {
+ int16_t x = pge->pos_x + dx;
+ int16_t y = pge->pos_y;
+
+ int8_t c = pge->room_location;
+ if (c < 0) return 0xFFFF;
+
+ if (x < 0) {
+ c = _res._ctData[CT_LEFT_ROOM + c];
+ if (c < 0) return 0xFFFF;
+ x += 256;
+ } else if (x >= 256) {
+ c = _res._ctData[CT_RIGHT_ROOM + c];
+ if (c < 0) return 0xFFFF;
+ x -= 256;
+ } else if (y < 0) {
+ c = _res._ctData[CT_UP_ROOM + c];
+ if (c < 0) return 0xFFFF;
+ y += 216;
+ } else if (y >= 216) {
+ c = _res._ctData[CT_DOWN_ROOM + c];
+ if (c < 0) return 0xFFFF;
+ y -= 216;
+ }
+
+ x = (x + 8) >> 4;
+ y = (y - 8) / 72;
+ if (x < 0 || x > 15 || y < 0 || y > 2) {
+ return 0xFFFF;
+ } else {
+ return y * 16 + x + c * 64;
+ }
+}
+
+int16_t Game::col_findSlot(int16_t pos) {
+ for (uint16_t i = 0; i < _col_curPos; ++i) {
+ if (_col_slotsTable[i]->ct_pos == pos)
+ return i;
+ }
+ return -1;
+}
+
+int16_t Game::col_getGridData(LivePGE *pge, int16_t dy, int16_t dx) {
+ if (_pge_currentPiegeFacingDir) {
+ dx = -dx;
+ }
+ const int16_t pge_grid_y = _col_currentPiegeGridPosY + dy;
+ const int16_t pge_grid_x = _col_currentPiegeGridPosX + dx;
+ const int8_t *room_ct_data;
+ int8_t next_room;
+ if (pge_grid_x < 0) {
+ room_ct_data = &_res._ctData[CT_LEFT_ROOM];
+ next_room = room_ct_data[pge->room_location];
+ if (next_room < 0) return 1;
+ room_ct_data += pge_grid_x + 16 + pge_grid_y * 16 + next_room * 0x70;
+ return (int16_t)room_ct_data[0x40];
+ } else if (pge_grid_x >= 16) {
+ room_ct_data = &_res._ctData[CT_RIGHT_ROOM];
+ next_room = room_ct_data[pge->room_location];
+ if (next_room < 0) return 1;
+ room_ct_data += pge_grid_x - 16 + pge_grid_y * 16 + next_room * 0x70;
+ return (int16_t)room_ct_data[0x80];
+ } else if (pge_grid_y < 1) {
+ room_ct_data = &_res._ctData[CT_UP_ROOM];
+ next_room = room_ct_data[pge->room_location];
+ if (next_room < 0) return 1;
+ room_ct_data += pge_grid_x + (pge_grid_y + 6) * 16 + next_room * 0x70;
+ return (int16_t)room_ct_data[0x100];
+ } else if (pge_grid_y >= 7) {
+ room_ct_data = &_res._ctData[CT_DOWN_ROOM];
+ next_room = room_ct_data[pge->room_location];
+ if (next_room < 0) return 1;
+ room_ct_data += pge_grid_x + (pge_grid_y - 6) * 16 + next_room * 0x70;
+ return (int16_t)room_ct_data[0xC0];
+ } else {
+ room_ct_data = &_res._ctData[0x100];
+ room_ct_data += pge_grid_x + pge_grid_y * 16 + pge->room_location * 0x70;
+ return (int16_t)room_ct_data[0];
+ }
+}
+
+LivePGE *Game::col_findPiege(LivePGE *pge, uint16_t arg2) {
+ if (pge->collision_slot != 0xFF) {
+ CollisionSlot *slot = _col_slotsTable[pge->collision_slot];
+ while (slot) {
+ if (slot->live_pge == pge) {
+ slot = slot->prev_slot;
+ } else {
+ if (arg2 == 0xFFFF || arg2 == slot->live_pge->init_PGE->object_type) {
+ return slot->live_pge;
+ } else {
+ slot = slot->prev_slot;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+uint8_t Game::col_findCurrentCollidingObject(LivePGE *pge, uint8_t n1, uint8_t n2, uint8_t n3, LivePGE **pge_out) {
+ if (pge_out) {
+ *pge_out = pge;
+ }
+ if (pge->collision_slot != 0xFF) {
+ CollisionSlot *cs = _col_slotsTable[pge->collision_slot];
+ while (cs) {
+ LivePGE *col_pge = cs->live_pge;
+ if (pge_out) {
+ *pge_out = col_pge;
+ }
+ if (col_pge->init_PGE->object_type == n1 ||
+ col_pge->init_PGE->object_type == n2 ||
+ col_pge->init_PGE->object_type == n3) {
+ return col_pge->init_PGE->colliding_icon_num;
+ } else {
+ cs = cs->prev_slot;
+ }
+ }
+ }
+ return 0;
+}
+
+int16_t Game::col_detectHit(LivePGE *pge, int16_t arg2, int16_t arg4, col_Callback1 callback1, col_Callback2 callback2, int16_t argA, int16_t argC) {
+ debug(DBG_COL, "col_detectHit()");
+ int16_t pos_dx, pos_dy, var8, varA;
+ int16_t collision_score = 0;
+ int8_t pge_room = pge->room_location;
+ if (pge_room < 0 || pge_room >= 0x40) {
+ return 0;
+ }
+ int16_t thr = pge->init_PGE->counter_values[0];
+ if (thr > 0) {
+ pos_dx = -1;
+ pos_dy = -1;
+ } else {
+ pos_dx = 1;
+ pos_dy = 1;
+ thr = -thr;
+ }
+ if (_pge_currentPiegeFacingDir) {
+ pos_dx = -pos_dx;
+ }
+ int16_t grid_pos_x = (pge->pos_x + 8) >> 4;
+ int16_t grid_pos_y = (pge->pos_y / 72);
+ if (grid_pos_y >= 0 && grid_pos_y <= 2) {
+ grid_pos_y *= 16;
+ collision_score = 0;
+ var8 = 0;
+ varA = 0;
+ if (argA != 0) {
+ var8 = pos_dy;
+ grid_pos_x += pos_dx;
+ varA = 1;
+ }
+ while (varA <= thr) {
+ if (grid_pos_x < 0) {
+ pge_room = _res._ctData[CT_LEFT_ROOM + pge_room];
+ if (pge_room < 0) break;
+ grid_pos_x += 16;
+ }
+ if (grid_pos_x >= 16) {
+ pge_room = _res._ctData[CT_RIGHT_ROOM + pge_room];
+ if (pge_room < 0) break;
+ grid_pos_x -= 16;
+ }
+ int16_t slot = col_findSlot(grid_pos_y + grid_pos_x + pge_room * 64);
+ if (slot >= 0) {
+ CollisionSlot *cs = _col_slotsTable[slot];
+ while (cs) {
+ collision_score += (this->*callback1)(cs->live_pge, pge, arg2, arg4);
+ cs = cs->prev_slot;
+ }
+ }
+ if ((this->*callback2)(pge, var8, varA, arg2) != 0) {
+ break;
+ }
+ grid_pos_x += pos_dx;
+ ++varA;
+ var8 += pos_dy;
+ }
+ }
+ if (argC == -1) {
+ return collision_score;
+ } else {
+ return 0;
+ }
+}
+
+int Game::col_detectHitCallback1(LivePGE *pge, int16_t dy, int16_t unk1, int16_t unk2) {
+ if (col_getGridData(pge, 1, dy) != 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int Game::col_detectHitCallback6(LivePGE *pge, int16_t dy, int16_t unk1, int16_t unk2) {
+ return 0;
+}
+
+int Game::col_detectHitCallback2(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2) {
+ if (pge1 != pge2 && (pge1->flags & 4)) {
+ if (pge1->init_PGE->object_type == unk2) {
+ if ((pge1->flags & 1) == (pge2->flags & 1)) {
+ if (col_detectHitCallbackHelper(pge1, unk1) == 0) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::col_detectHitCallback3(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2) {
+ if (pge1 != pge2 && (pge1->flags & 4)) {
+ if (pge1->init_PGE->object_type == unk2) {
+ if ((pge1->flags & 1) != (pge2->flags & 1)) {
+ if (col_detectHitCallbackHelper(pge1, unk1) == 0) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::col_detectHitCallback4(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2) {
+ if (pge1 != pge2 && (pge1->flags & 4)) {
+ if (pge1->init_PGE->object_type == unk2) {
+ if ((pge1->flags & 1) != (pge2->flags & 1)) {
+ if (col_detectHitCallbackHelper(pge1, unk1) == 0) {
+ pge_updateGroup(pge2->index, pge1->index, unk1);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::col_detectHitCallback5(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2) {
+ if (pge1 != pge2 && (pge1->flags & 4)) {
+ if (pge1->init_PGE->object_type == unk2) {
+ if ((pge1->flags & 1) == (pge2->flags & 1)) {
+ if (col_detectHitCallbackHelper(pge1, unk1) == 0) {
+ pge_updateGroup(pge2->index, pge1->index, unk1);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::col_detectHitCallbackHelper(LivePGE *pge, int16_t groupId) {
+ InitPGE *init_pge = pge->init_PGE;
+ assert(init_pge->obj_node_number < _res._numObjectNodes);
+ ObjectNode *on = _res._objectNodesMap[init_pge->obj_node_number];
+ Object *obj = &on->objects[pge->first_obj_number];
+ int i = pge->first_obj_number;
+ while (pge->obj_type == obj->type && on->last_obj_number > i) {
+ if (obj->opcode2 == 0x6B) { // pge_op_isInGroupSlice
+ if (obj->opcode_arg2 == 0) {
+ if (groupId == 1 || groupId == 2) return 0xFFFF;
+ }
+ if (obj->opcode_arg2 == 1) {
+ if (groupId == 3 || groupId == 4) return 0xFFFF;
+ }
+ } else if (obj->opcode2 == 0x22) { // pge_op_isInGroup
+ if (obj->opcode_arg2 == groupId) return 0xFFFF;
+ }
+
+ if (obj->opcode1 == 0x6B) { // pge_op_isInGroupSlice
+ if (obj->opcode_arg1 == 0) {
+ if (groupId == 1 || groupId == 2) return 0xFFFF;
+ }
+ if (obj->opcode_arg1 == 1) {
+ if (groupId == 3 || groupId == 4) return 0xFFFF;
+ }
+ } else if (obj->opcode1 == 0x22) { // pge_op_isInGroup
+ if (obj->opcode_arg1 == groupId) return 0xFFFF;
+ }
+ ++obj;
+ ++i;
+ }
+ return 0;
+}
+
+int Game::col_detectGunHitCallback1(LivePGE *pge, int16_t arg2, int16_t arg4, int16_t arg6) {
+ int16_t _ax = col_getGridData(pge, 1, arg2);
+ if (_ax != 0) {
+ if (!(_ax & 2) || (arg6 != 1)) {
+ return _ax;
+ }
+ }
+ return 0;
+}
+
+int Game::col_detectGunHitCallback2(LivePGE *pge1, LivePGE *pge2, int16_t arg4, int16_t) {
+ if (pge1 != pge2 && (pge1->flags & 4)) {
+ if (pge1->init_PGE->object_type == 1 || pge1->init_PGE->object_type == 10) {
+ uint8_t id;
+ if ((pge1->flags & 1) != (pge2->flags & 1)) {
+ id = 4;
+ if (arg4 == 0) {
+ id = 3;
+ }
+ } else {
+ id = 2;
+ if (arg4 == 0) {
+ id = 1;
+ }
+ }
+ if (col_detectHitCallbackHelper(pge1, id) != 0) {
+ pge_updateGroup(pge2->index, pge1->index, id);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::col_detectGunHitCallback3(LivePGE *pge1, LivePGE *pge2, int16_t arg4, int16_t) {
+ if (pge1 != pge2 && (pge1->flags & 4)) {
+ if (pge1->init_PGE->object_type == 1 || pge1->init_PGE->object_type == 12 || pge1->init_PGE->object_type == 10) {
+ uint8_t id;
+ if ((pge1->flags & 1) != (pge2->flags & 1)) {
+ id = 4;
+ if (arg4 == 0) {
+ id = 3;
+ }
+ } else {
+ id = 2;
+ if (arg4 == 0) {
+ id = 1;
+ }
+ }
+ if (col_detectHitCallbackHelper(pge1, id) != 0) {
+ pge_updateGroup(pge2->index, pge1->index, id);
+ return 1;
+ }
+
+ }
+ }
+ return 0;
+}
+
+int Game::col_detectGunHit(LivePGE *pge, int16_t arg2, int16_t arg4, col_Callback1 callback1, col_Callback2 callback2, int16_t argA, int16_t argC) {
+ int8_t pge_room = pge->room_location;
+ if (pge_room < 0 || pge_room >= 0x40) return 0;
+ int16_t thr, pos_dx, pos_dy;
+ if (argC == -1) {
+ thr = pge->init_PGE->counter_values[0];
+ } else {
+ thr = pge->init_PGE->counter_values[3];
+ }
+ if (thr > 0) {
+ pos_dx = -1;
+ pos_dy = -1;
+ } else {
+ pos_dx = 1;
+ pos_dy = 1;
+ thr = -thr;
+ }
+ if (_pge_currentPiegeFacingDir) {
+ pos_dx = -pos_dx;
+ }
+ int16_t grid_pos_x = (pge->pos_x + 8) >> 4;
+ int16_t grid_pos_y = (pge->pos_y - 8) / 72;
+ if (grid_pos_y >= 0 && grid_pos_y <= 2) {
+ grid_pos_y *= 16;
+ int16_t var8 = 0;
+ int16_t varA = 0;
+ if (argA != 0) {
+ var8 = pos_dy;
+ grid_pos_x += pos_dx;
+ varA = 1;
+ }
+ while (varA <= thr) {
+ if (grid_pos_x < 0) {
+ pge_room = _res._ctData[CT_LEFT_ROOM + pge_room];
+ if (pge_room < 0) return 0;
+ grid_pos_x += 0x10;
+ }
+ if (grid_pos_x >= 0x10) {
+ pge_room = _res._ctData[CT_RIGHT_ROOM + pge_room];
+ if (pge_room < 0) return 0;
+ grid_pos_x -= 0x10;
+ }
+ int16_t slot = col_findSlot(pge_room * 64 + grid_pos_x + grid_pos_y);
+ if (slot >= 0) {
+ CollisionSlot *cs = _col_slotsTable[slot];
+ while (cs) {
+ int r = (this->*callback1)(cs->live_pge, pge, arg2, arg4);
+ if (r != 0) return r;
+ cs = cs->prev_slot;
+ }
+ }
+ if ((this->*callback2)(pge, var8, varA, arg2) != 0) {
+ break;
+ }
+ grid_pos_x += pos_dx;
+ ++varA;
+ var8 += pos_dy;
+ }
+ }
+ return 0;
+}
diff --git a/cutscene.cpp b/cutscene.cpp
new file mode 100644
index 0000000..c9677c4
--- /dev/null
+++ b/cutscene.cpp
@@ -0,0 +1,1031 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "resource.h"
+#include "systemstub.h"
+#include "video.h"
+#include "cutscene.h"
+
+
+Cutscene::Cutscene(Resource *res, SystemStub *stub, Video *vid)
+ : _res(res), _stub(stub), _vid(vid) {
+ memset(_palBuf, 0, sizeof(_palBuf));
+}
+
+void Cutscene::sync() {
+ // XXX input handling
+ if (!(_stub->_pi.dbgMask & PlayerInput::DF_FASTMODE)) {
+ int32_t delay = _stub->getTimeStamp() - _tstamp;
+ int32_t pause = _frameDelay * TIMER_SLICE - delay;
+ if (pause > 0) {
+ _stub->sleep(pause);
+ }
+ }
+ _tstamp = _stub->getTimeStamp();
+}
+
+void Cutscene::copyPalette(const uint8_t *pal, uint16_t num) {
+ uint8_t *dst = (uint8_t *)_palBuf;
+ if (num != 0) {
+ dst += 0x20;
+ }
+ memcpy(dst, pal, 0x20);
+ _newPal = true;
+}
+
+void Cutscene::updatePalette() {
+ if (_newPal) {
+ const uint8_t *p = _palBuf;
+ for (int i = 0; i < 32; ++i) {
+ uint16_t color = READ_BE_UINT16(p); p += 2;
+ uint8_t t = (color == 0) ? 0 : 3;
+ Color c;
+ c.r = ((color & 0xF00) >> 6) | t;
+ c.g = ((color & 0x0F0) >> 2) | t;
+ c.b = ((color & 0x00F) << 2) | t;
+ _stub->setPaletteEntry(0xC0 + i, &c);
+ }
+ _newPal = false;
+ }
+}
+
+void Cutscene::setPalette() {
+ sync();
+ updatePalette();
+ SWAP(_page0, _page1);
+ _stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _page0, 256);
+ _stub->updateScreen(0);
+}
+
+void Cutscene::initRotationData(uint16_t a, uint16_t b, uint16_t c) {
+ int16_t n1 = _sinTable[a];
+ int16_t n2 = _cosTable[a];
+ int16_t n3 = _sinTable[c];
+ int16_t n4 = _cosTable[c];
+ int16_t n5 = _sinTable[b];
+ int16_t n6 = _cosTable[b];
+ _rotData[0] = ((n2 * n6) >> 8) - ((((n4 * n1) >> 8) * n5) >> 8);
+ _rotData[1] = ((n1 * n6) >> 8) + ((((n4 * n2) >> 8) * n5) >> 8);
+ _rotData[2] = ( n3 * n1) >> 8;
+ _rotData[3] = (-n3 * n2) >> 8;
+}
+
+uint16_t Cutscene::findTextSeparators(const uint8_t *p) {
+ uint8_t *q = _textSep;
+ uint16_t ret = 0;
+ uint16_t pos = 0;
+ for (; *p != 0xA; ++p) {
+ if (*p == 0x7C) {
+ *q++ = pos;
+ if (pos > ret) {
+ ret = pos;
+ }
+ pos = 0;
+ } else {
+ ++pos;
+ }
+ }
+ *q++ = pos;
+ if (pos > ret) {
+ ret = pos;
+ }
+ *q++ = 0;
+ return ret;
+}
+
+void Cutscene::drawText(int16_t x, int16_t y, const uint8_t *p, uint16_t color, uint8_t *page, uint8_t n) {
+ debug(DBG_CUT, "Cutscene::drawText(x=%d, y=%d, c=%d)", x, y, color);
+ uint16_t last_sep = 0;
+ if (n != 0) {
+ last_sep = findTextSeparators(p);
+ if (n != 2) {
+ last_sep = 30;
+ }
+ }
+ const uint8_t *sep = _textSep;
+ y += 50;
+ x += 8;
+ int16_t yy = y;
+ int16_t xx = x;
+ if (n != 0) {
+ xx += ((last_sep - *sep++) & 0xFE) * 4;
+ }
+ for (; *p != 0xA; ++p) {
+ if (*p == 0x7C) {
+ yy += 8;
+ xx = x;
+ if (n != 0) {
+ xx += ((last_sep - *sep++) & 0xFE) * 4;
+ }
+ } else if (*p == 0x20) {
+ xx += 8;
+ } else {
+ uint8_t *dst_char = page + 256 * yy + xx;
+ const uint8_t *src = _res->_fnt + (*p - 32) * 32;
+ for (int h = 0; h < 8; ++h) {
+ for (int w = 0; w < 4; ++w) {
+ uint8_t c1 = (*src & 0xF0) >> 4;
+ uint8_t c2 = (*src & 0x0F) >> 0;
+ ++src;
+ if (c1 != 0) {
+ *dst_char = (c1 == 0xF) ? color : (0xE0 + c1);
+ }
+ ++dst_char;
+ if (c2 != 0) {
+ *dst_char = (c2 == 0xF) ? color : (0xE0 + c2);
+ }
+ ++dst_char;
+ }
+ dst_char += 256 - 8;
+ }
+ xx += 8;
+ }
+ }
+}
+
+void Cutscene::swapLayers() {
+ if (_clearScreen == 0) {
+ memcpy(_page1, _pageC, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ } else {
+ memset(_page1, 0xC0, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ }
+}
+
+void Cutscene::drawCreditsText() {
+ if (_creditsSequence) {
+ if (_textUnk2 != 0) {
+ if (_varText == 0) {
+ _textUnk2 = 0;
+ } else {
+ return;
+ }
+ }
+ if (_creditsTextCounter <= 0) { // XXX
+ uint8_t code = *_textCurPtr;
+ if (code == 0xFF) {
+ _textBuf[0] = 0xA;
+// _cut_status = 0;
+ } else if (code == 0xFE) {
+ ++_textCurPtr;
+ code = *_textCurPtr++;
+ _creditsTextCounter = code;
+ } else if (code == 1) {
+ ++_textCurPtr;
+ _creditsTextPosX = *_textCurPtr++;
+ _creditsTextPosY = *_textCurPtr++;
+ } else if (code == 0) {
+ _textCurBuf = _textBuf;
+ _textBuf[0] = 0xA;
+ ++_textCurPtr;
+ if (_varText != 0) {
+ _textUnk2 = 0xFF;
+ }
+ } else {
+ *_textCurBuf++ = code;
+ _textCurBuf = _textCurBuf;
+ *_textCurBuf = 0xA;
+ ++_textCurPtr;
+ }
+ } else {
+ _creditsTextCounter -= 10; // XXX adjust
+ }
+ drawText((_creditsTextPosX - 1) * 8, _creditsTextPosY * 8, _textBuf, 0xEF, _page1, 0);
+ }
+}
+
+void Cutscene::drawProtectionShape(uint8_t shapeNum, int16_t zoom) {
+ debug(DBG_CUT, "Cutscene::drawProtectionShape() shapeNum = %d", shapeNum);
+ _shape_ix = 64;
+ _shape_iy = 64;
+ _shape_count = 0;
+
+ int16_t x = 0;
+ int16_t y = 0;
+ zoom += 512;
+ initRotationData(0, 180, 90);
+
+ const uint8_t *shapeOffsetTable = _protectionShapeData + READ_BE_UINT16(_protectionShapeData + 0x02);
+ const uint8_t *shapeDataTable = _protectionShapeData + READ_BE_UINT16(_protectionShapeData + 0x0E);
+ const uint8_t *verticesOffsetTable = _protectionShapeData + READ_BE_UINT16(_protectionShapeData + 0x0A);
+ const uint8_t *verticesDataTable = _protectionShapeData + READ_BE_UINT16(_protectionShapeData + 0x12);
+
+ ++shapeNum;
+ const uint8_t *shapeData = shapeDataTable + READ_BE_UINT16(shapeOffsetTable + (shapeNum & 0x7FF) * 2);
+ uint16_t primitiveCount = READ_BE_UINT16(shapeData); shapeData += 2;
+
+ while (primitiveCount--) {
+ uint16_t verticesOffset = READ_BE_UINT16(shapeData); shapeData += 2;
+ const uint8_t *p = verticesDataTable + READ_BE_UINT16(verticesOffsetTable + (verticesOffset & 0x3FFF) * 2);
+ int16_t dx = 0;
+ int16_t dy = 0;
+ if (verticesOffset & 0x8000) {
+ dx = READ_BE_UINT16(shapeData); shapeData += 2;
+ dy = READ_BE_UINT16(shapeData); shapeData += 2;
+ }
+ _hasAlphaColor = (verticesOffset & 0x4000) != 0;
+ _primitiveColor = 0xC0 + *shapeData++;
+ drawShapeScaleRotate(p, zoom, dx, dy, x, y, 0, 0);
+ ++_shape_count;
+ }
+}
+
+void Cutscene::op_markCurPos() {
+ debug(DBG_CUT, "Cutscene::op_markCurPos()");
+ _cmdPtrBak = _cmdPtr;
+ drawCreditsText();
+ _frameDelay = 5;
+ setPalette();
+ swapLayers();
+ _varText = 0;
+}
+
+void Cutscene::op_refreshScreen() {
+ debug(DBG_CUT, "Cutscene::op_refreshScreen()");
+ _clearScreen = fetchNextCmdByte();
+ if (_clearScreen != 0) {
+ swapLayers();
+ _varText = 0;
+ }
+}
+
+void Cutscene::op_waitForSync() {
+ debug(DBG_CUT, "Cutscene::op_waitForSync()");
+ if (_creditsSequence) {
+ uint16_t n = fetchNextCmdByte() * 2;
+ do {
+ _varText = 0xFF;
+ _frameDelay = 3;
+ if (_textBuf == _textCurBuf) {
+ _creditsTextCounter = 20;
+ }
+ memcpy(_page1, _page0, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ drawCreditsText();
+ setPalette();
+ } while (--n);
+ swapLayers();
+ _varText = 0;
+ } else {
+ _frameDelay = fetchNextCmdByte() * 4;
+ sync(); // XXX handle input
+ }
+}
+
+void Cutscene::drawShape(const uint8_t *data, int16_t x, int16_t y) {
+ debug(DBG_CUT, "Cutscene::drawShape()");
+ _gfx._layer = _page1;
+ uint8_t numVertices = *data++;
+ if (numVertices & 0x80) {
+ Point pt;
+ pt.x = READ_BE_UINT16(data) + x; data += 2;
+ pt.y = READ_BE_UINT16(data) + y; data += 2;
+ uint16_t rx = READ_BE_UINT16(data); data += 2;
+ uint16_t ry = READ_BE_UINT16(data); data += 2;
+ _gfx.drawEllipse(_primitiveColor, _hasAlphaColor, &pt, rx, ry);
+ } else if (numVertices == 0) {
+ Point pt;
+ pt.x = READ_BE_UINT16(data) + x; data += 2;
+ pt.y = READ_BE_UINT16(data) + y; data += 2;
+ _gfx.drawPoint(_primitiveColor, &pt);
+ } else {
+ Point *pt = _vertices;
+ int16_t ix = READ_BE_UINT16(data); data += 2;
+ int16_t iy = READ_BE_UINT16(data); data += 2;
+ pt->x = ix + x;
+ pt->y = iy + y;
+ ++pt;
+ int16_t n = numVertices - 1;
+ ++numVertices;
+ for (; n >= 0; --n) {
+ int16_t dx = (int8_t)*data++;
+ int16_t dy = (int8_t)*data++;
+ if (dy == 0 && n != 0 && *(data + 1) == 0) {
+ ix += dx;
+ --numVertices;
+ } else {
+ ix += dx;
+ iy += dy;
+ pt->x = ix + x;
+ pt->y = iy + y;
+ ++pt;
+ }
+ }
+ _gfx.drawPolygon(_primitiveColor, _hasAlphaColor, _vertices, numVertices);
+ }
+}
+
+void Cutscene::op_drawShape() {
+ debug(DBG_CUT, "Cutscene::op_drawShape()");
+
+ int16_t x = 0;
+ int16_t y = 0;
+ uint16_t shapeOffset = fetchNextCmdWord();
+ if (shapeOffset & 0x8000) {
+ x = fetchNextCmdWord();
+ y = fetchNextCmdWord();
+ }
+
+ const uint8_t *shapeOffsetTable = _polPtr + READ_BE_UINT16(_polPtr + 0x02);
+ const uint8_t *shapeDataTable = _polPtr + READ_BE_UINT16(_polPtr + 0x0E);
+ const uint8_t *verticesOffsetTable = _polPtr + READ_BE_UINT16(_polPtr + 0x0A);
+ const uint8_t *verticesDataTable = _polPtr + READ_BE_UINT16(_polPtr + 0x12);
+
+ const uint8_t *shapeData = shapeDataTable + READ_BE_UINT16(shapeOffsetTable + (shapeOffset & 0x7FF) * 2);
+ uint16_t primitiveCount = READ_BE_UINT16(shapeData); shapeData += 2;
+
+ while (primitiveCount--) {
+ uint16_t verticesOffset = READ_BE_UINT16(shapeData); shapeData += 2;
+ const uint8_t *primitiveVertices = verticesDataTable + READ_BE_UINT16(verticesOffsetTable + (verticesOffset & 0x3FFF) * 2);
+ int16_t dx = 0;
+ int16_t dy = 0;
+ if (verticesOffset & 0x8000) {
+ dx = READ_BE_UINT16(shapeData); shapeData += 2;
+ dy = READ_BE_UINT16(shapeData); shapeData += 2;
+ }
+ _hasAlphaColor = (verticesOffset & 0x4000) != 0;
+ uint8_t color = *shapeData++;
+ if (_clearScreen == 0) {
+ color += 0x10;
+ }
+ _primitiveColor = 0xC0 + color;
+ drawShape(primitiveVertices, x + dx, y + dy);
+ }
+ if (_clearScreen != 0) {
+ memcpy(_pageC, _page1, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ }
+}
+
+void Cutscene::op_setPalette() {
+ debug(DBG_CUT, "Cutscene::op_setPalette()");
+ uint8_t num = fetchNextCmdByte();
+ uint8_t palNum = fetchNextCmdByte();
+ uint16_t off = READ_BE_UINT16(_polPtr + 6);
+ const uint8_t *p = _polPtr + off + num * 32;
+ copyPalette(p, palNum ^ 1);
+ if (_creditsSequence) {
+ _palBuf[0x20] = 0x0F;
+ _palBuf[0x21] = 0xFF;
+ }
+}
+
+void Cutscene::op_drawStringAtBottom() {
+ debug(DBG_CUT, "Cutscene::op_drawStringAtBottom()");
+ uint16_t strId = fetchNextCmdWord();
+ if (!_creditsSequence) {
+ memset(_pageC + 179 * 256, 0xC0, 45 * 256);
+ memset(_page1 + 179 * 256, 0xC0, 45 * 256);
+ memset(_page0 + 179 * 256, 0xC0, 45 * 256);
+ if (strId != 0xFFFF) {
+ const uint8_t *str = _res->getCineString(strId);
+ if (str) {
+ drawText(0, 129, str, 0xEF, _page1, 1);
+ drawText(0, 129, str, 0xEF, _pageC, 1);
+ }
+ }
+ }
+}
+
+void Cutscene::op_nop() {
+ debug(DBG_CUT, "Cutscene::op_nop()");
+}
+
+void Cutscene::op_skip3() {
+ debug(DBG_CUT, "Cutscene::op_skip3()");
+ _cmdPtr += 3;
+}
+
+void Cutscene::op_refreshAll() {
+ debug(DBG_CUT, "Cutscene::op_refreshAll()");
+ _frameDelay = 5;
+ setPalette();
+ swapLayers();
+ _varText = 0xFF;
+ op_handleKeys();
+}
+
+void Cutscene::drawShapeScale(const uint8_t *data, int16_t zoom, int16_t b, int16_t c, int16_t d, int16_t e, int16_t f, int16_t g) {
+ debug(DBG_CUT, "Cutscene::drawShapeScale(%d, %d, %d, %d, %d, %d, %d)", zoom, b, c, d, e, f, g);
+ _gfx._layer = _page1;
+ uint8_t numVertices = *data++;
+ if (numVertices & 0x80) {
+ int16_t x, y;
+ Point *pt = _vertices;
+ Point pr[2];
+ _shape_cur_x = b + READ_BE_UINT16(data); data += 2;
+ _shape_cur_y = c + READ_BE_UINT16(data); data += 2;
+ x = READ_BE_UINT16(data); data += 2;
+ y = READ_BE_UINT16(data); data += 2;
+ _shape_cur_x16 = 0;
+ _shape_cur_y16 = 0;
+ pr[0].x = 0;
+ pr[0].y = -y;
+ pr[1].x = -x;
+ pr[1].y = y;
+ if (_shape_count == 0) {
+ f -= ((((_shape_ix - _shape_ox) * zoom) * 128) + 0x8000) >> 16;
+ g -= ((((_shape_iy - _shape_oy) * zoom) * 128) + 0x8000) >> 16;
+ pt->x = f;
+ pt->y = g;
+ ++pt;
+ _shape_cur_x16 = f << 16;
+ _shape_cur_y16 = g << 16;
+ } else {
+ _shape_cur_x16 = _shape_prev_x16 + ((_shape_cur_x - _shape_prev_x) * zoom) * 128;
+ pt->x = (_shape_cur_x16 + 0x8000) >> 16;
+ _shape_cur_y16 = _shape_prev_y16 + ((_shape_cur_y - _shape_prev_y) * zoom) * 128;
+ pt->y = (_shape_cur_y16 + 0x8000) >> 16;
+ ++pt;
+ }
+ for (int i = 0; i < 2; ++i) {
+ _shape_cur_x += pr[i].x;
+ _shape_cur_x16 += pr[i].x * zoom * 128;
+ pt->x = (_shape_cur_x16 + 0x8000) >> 16;
+ _shape_cur_y += pr[i].y;
+ _shape_cur_y16 += pr[i].y * zoom * 128;
+ pt->y = (_shape_cur_y16 + 0x8000) >> 16;
+ ++pt;
+ }
+ _shape_prev_x = _shape_cur_x;
+ _shape_prev_y = _shape_cur_y;
+ _shape_prev_x16 = _shape_cur_x16;
+ _shape_prev_y16 = _shape_cur_y16;
+ Point po;
+ po.x = _vertices[0].x + d + _shape_ix;
+ po.y = _vertices[0].y + e + _shape_iy;
+ int16_t rx = _vertices[0].x - _vertices[2].x;
+ int16_t ry = _vertices[0].y - _vertices[1].y;
+ _gfx.drawEllipse(_primitiveColor, _hasAlphaColor, &po, rx, ry);
+ } else if (numVertices == 0) {
+ Point pt;
+ pt.x = _shape_cur_x = b + READ_BE_UINT16(data); data += 2;
+ pt.y = _shape_cur_y = c + READ_BE_UINT16(data); data += 2;
+ if (_shape_count == 0) {
+ f -= ((((_shape_ix - pt.x) * zoom) * 128) + 0x8000) >> 16;
+ g -= ((((_shape_iy - pt.y) * zoom) * 128) + 0x8000) >> 16;
+ pt.x = f + _shape_ix + d;
+ pt.y = g + _shape_iy + e;
+ _shape_cur_x16 = f << 16;
+ _shape_cur_y16 = g << 16;
+ } else {
+ _shape_cur_x16 = _shape_prev_x16 + ((pt.x - _shape_prev_x) * zoom) * 128;
+ _shape_cur_y16 = _shape_prev_y16 + ((pt.y - _shape_prev_y) * zoom) * 128;
+ pt.x = ((_shape_cur_x16 + 0x8000) >> 16) + _shape_ix + d;
+ pt.y = ((_shape_cur_y16 + 0x8000) >> 16) + _shape_iy + e;
+ }
+ _shape_prev_x = _shape_cur_x;
+ _shape_prev_y = _shape_cur_y;
+ _shape_prev_x16 = _shape_cur_x16;
+ _shape_prev_y16 = _shape_cur_y16;
+ _gfx.drawPoint(_primitiveColor, &pt);
+ } else {
+ Point *pt = _vertices;
+ int16_t ix, iy;
+ _shape_cur_x = ix = READ_BE_UINT16(data) + b; data += 2;
+ _shape_cur_y = iy = READ_BE_UINT16(data) + c; data += 2;
+ if (_shape_count == 0) {
+ f -= ((((_shape_ix - _shape_ox) * zoom) * 128) + 0x8000) >> 16;
+ g -= ((((_shape_iy - _shape_oy) * zoom) * 128) + 0x8000) >> 16;
+ pt->x = f + _shape_ix + d;
+ pt->y = g + _shape_iy + e;
+ ++pt;
+ _shape_cur_x16 = f << 16;
+ _shape_cur_y16 = g << 16;
+ } else {
+ _shape_cur_x16 = _shape_prev_x16 + ((_shape_cur_x - _shape_prev_x) * zoom) * 128;
+ _shape_cur_y16 = _shape_prev_y16 + ((_shape_cur_y - _shape_prev_y) * zoom) * 128;
+ pt->x = ix = ((_shape_cur_x16 + 0x8000) >> 16) + _shape_ix + d;
+ pt->y = iy = ((_shape_cur_y16 + 0x8000) >> 16) + _shape_iy + e;
+ ++pt;
+ }
+ int16_t n = numVertices - 1;
+ ++numVertices;
+ int16_t sx = 0;
+ for (; n >= 0; --n) {
+ ix = (int8_t)(*data++) + sx;
+ iy = (int8_t)(*data++);
+ if (iy == 0 && n != 0 && *(data + 1) == 0) {
+ sx = ix;
+ --numVertices;
+ } else {
+ sx = 0;
+ _shape_cur_x += ix;
+ _shape_cur_y += iy;
+ _shape_cur_x16 += ix * zoom * 128;
+ _shape_cur_y16 += iy * zoom * 128;
+ pt->x = ((_shape_cur_x16 + 0x8000) >> 16) + _shape_ix + d;
+ pt->y = ((_shape_cur_y16 + 0x8000) >> 16) + _shape_iy + e;
+ ++pt;
+ }
+ }
+ _shape_prev_x = _shape_cur_x;
+ _shape_prev_y = _shape_cur_y;
+ _shape_prev_x16 = _shape_cur_x16;
+ _shape_prev_y16 = _shape_cur_y16;
+ _gfx.drawPolygon(_primitiveColor, _hasAlphaColor, _vertices, numVertices);
+ }
+}
+
+void Cutscene::op_drawShapeScale() {
+ debug(DBG_CUT, "Cutscene::op_drawShapeScale()");
+
+ _shape_count = 0;
+
+ int16_t x = 0;
+ int16_t y = 0;
+ uint16_t shapeOffset = fetchNextCmdWord();
+ if (shapeOffset & 0x8000) {
+ x = fetchNextCmdWord();
+ y = fetchNextCmdWord();
+ }
+
+ uint16_t zoom = fetchNextCmdWord() + 512;
+ _shape_ix = fetchNextCmdByte();
+ _shape_iy = fetchNextCmdByte();
+
+ const uint8_t *shapeOffsetTable = _polPtr + READ_BE_UINT16(_polPtr + 0x02);
+ const uint8_t *shapeDataTable = _polPtr + READ_BE_UINT16(_polPtr + 0x0E);
+ const uint8_t *verticesOffsetTable = _polPtr + READ_BE_UINT16(_polPtr + 0x0A);
+ const uint8_t *verticesDataTable = _polPtr + READ_BE_UINT16(_polPtr + 0x12);
+
+ const uint8_t *shapeData = shapeDataTable + READ_BE_UINT16(shapeOffsetTable + (shapeOffset & 0x7FF) * 2);
+ uint16_t primitiveCount = READ_BE_UINT16(shapeData); shapeData += 2;
+
+ if (primitiveCount != 0) {
+ uint16_t verticesOffset = READ_BE_UINT16(shapeData);
+ int16_t dx = 0;
+ int16_t dy = 0;
+ if (verticesOffset & 0x8000) {
+ dx = READ_BE_UINT16(shapeData + 2);
+ dy = READ_BE_UINT16(shapeData + 4);
+ }
+ const uint8_t *p = verticesDataTable + READ_BE_UINT16(verticesOffsetTable + (verticesOffset & 0x3FFF) * 2) + 1;
+ _shape_ox = READ_BE_UINT16(p) + dx; p += 2;
+ _shape_oy = READ_BE_UINT16(p) + dy; p += 2;
+ while (primitiveCount--) {
+ verticesOffset = READ_BE_UINT16(shapeData); shapeData += 2;
+ p = verticesDataTable + READ_BE_UINT16(verticesOffsetTable + (verticesOffset & 0x3FFF) * 2);
+ dx = 0;
+ dy = 0;
+ if (verticesOffset & 0x8000) {
+ dx = READ_BE_UINT16(shapeData); shapeData += 2;
+ dy = READ_BE_UINT16(shapeData); shapeData += 2;
+ }
+ _hasAlphaColor = (verticesOffset & 0x4000) != 0;
+ uint8_t color = *shapeData++;
+ if (_clearScreen == 0) {
+ color += 0x10; // 2nd pal buf
+ }
+ _primitiveColor = 0xC0 + color;
+ drawShapeScale(p, zoom, dx, dy, x, y, 0, 0);
+ ++_shape_count;
+ }
+ }
+}
+
+void Cutscene::drawShapeScaleRotate(const uint8_t *data, int16_t zoom, int16_t b, int16_t c, int16_t d, int16_t e, int16_t f, int16_t g) {
+ debug(DBG_CUT, "Cutscene::drawShapeScaleRotate(%d, %d, %d, %d, %d, %d, %d)", zoom, b, c, d, e, f, g);
+ _gfx._layer = _page1;
+ uint8_t numVertices = *data++;
+ if (numVertices & 0x80) {
+ int16_t x, y, ix, iy;
+ Point pr[2];
+ Point *pt = _vertices;
+ _shape_cur_x = ix = b + READ_BE_UINT16(data); data += 2;
+ _shape_cur_y = iy = c + READ_BE_UINT16(data); data += 2;
+ x = READ_BE_UINT16(data); data += 2;
+ y = READ_BE_UINT16(data); data += 2;
+ _shape_cur_x16 = _shape_ix - ix;
+ _shape_cur_y16 = _shape_iy - iy;
+ _shape_ox = _shape_cur_x = _shape_ix + ((_shape_cur_x16 * _rotData[0] + _shape_cur_y16 * _rotData[1]) >> 8);
+ _shape_oy = _shape_cur_y = _shape_iy + ((_shape_cur_x16 * _rotData[2] + _shape_cur_y16 * _rotData[3]) >> 8);
+ pr[0].x = 0;
+ pr[0].y = -y;
+ pr[1].x = -x;
+ pr[1].y = y;
+ if (_shape_count == 0) {
+ f -= ((_shape_ix - _shape_cur_x) * zoom * 128 + 0x8000) >> 16;
+ g -= ((_shape_iy - _shape_cur_y) * zoom * 128 + 0x8000) >> 16;
+ pt->x = f;
+ pt->y = g;
+ ++pt;
+ _shape_cur_x16 = f << 16;
+ _shape_cur_y16 = g << 16;
+ } else {
+ _shape_cur_x16 = _shape_prev_x16 + (_shape_cur_x - _shape_prev_x) * zoom * 128;
+ _shape_cur_y16 = _shape_prev_y16 + (_shape_cur_y - _shape_prev_y) * zoom * 128;
+ pt->x = (_shape_cur_x16 + 0x8000) >> 16;
+ pt->y = (_shape_cur_y16 + 0x8000) >> 16;
+ ++pt;
+ }
+ for (int i = 0; i < 2; ++i) {
+ _shape_cur_x += pr[i].x;
+ _shape_cur_x16 += pr[i].x * zoom * 128;
+ pt->x = (_shape_cur_x16 + 0x8000) >> 16;
+ _shape_cur_y += pr[i].y;
+ _shape_cur_y16 += pr[i].y * zoom * 128;
+ pt->y = (_shape_cur_y16 + 0x8000) >> 16;
+ ++pt;
+ }
+ _shape_prev_x = _shape_cur_x;
+ _shape_prev_y = _shape_cur_y;
+ _shape_prev_x16 = _shape_cur_x16;
+ _shape_prev_y16 = _shape_cur_y16;
+ Point po;
+ po.x = _vertices[0].x + d + _shape_ix;
+ po.y = _vertices[0].y + e + _shape_iy;
+ int16_t rx = _vertices[0].x - _vertices[2].x;
+ int16_t ry = _vertices[0].y - _vertices[1].y;
+ _gfx.drawEllipse(_primitiveColor, _hasAlphaColor, &po, rx, ry);
+ } else if (numVertices == 0) {
+ Point pt;
+ pt.x = b + READ_BE_UINT16(data); data += 2;
+ pt.y = c + READ_BE_UINT16(data); data += 2;
+ _shape_cur_x16 = _shape_ix - pt.x;
+ _shape_cur_y16 = _shape_iy - pt.y;
+ _shape_cur_x = _shape_ix + ((_rotData[0] * _shape_cur_x16 + _rotData[1] * _shape_cur_y16) >> 8);
+ _shape_cur_y = _shape_iy + ((_rotData[2] * _shape_cur_x16 + _rotData[3] * _shape_cur_y16) >> 8);
+ if (_shape_count != 0) {
+ _shape_cur_x16 = _shape_prev_x16 + (_shape_cur_x - _shape_prev_x) * zoom * 128;
+ pt.x = ((_shape_cur_x16 + 0x8000) >> 16) + _shape_ix + d;
+ _shape_cur_y16 = _shape_prev_y16 + (_shape_cur_y - _shape_prev_y) * zoom * 128;
+ pt.y = ((_shape_cur_y16 + 0x8000) >> 16) + _shape_iy + e;
+ } else {
+ f -= (((_shape_ix - _shape_cur_x) * zoom * 128) + 0x8000) >> 16;
+ g -= (((_shape_iy - _shape_cur_y) * zoom * 128) + 0x8000) >> 16;
+ _shape_cur_x16 = f << 16;
+ _shape_cur_y16 = g << 16;
+ pt.x = f + _shape_ix + d;
+ pt.y = g + _shape_iy + e;
+ }
+ _shape_prev_x = _shape_cur_x;
+ _shape_prev_y = _shape_cur_y;
+ _shape_prev_x16 = _shape_cur_x16;
+ _shape_prev_y16 = _shape_cur_y16;
+ _gfx.drawPoint(_primitiveColor, &pt);
+ } else {
+ int16_t x, y, a, shape_last_x, shape_last_y;
+ Point tempVertices[40];
+ _shape_cur_x = b + READ_BE_UINT16(data); data += 2;
+ x = _shape_cur_x;
+ _shape_cur_y = c + READ_BE_UINT16(data); data += 2;
+ y = _shape_cur_y;
+ _shape_cur_x16 = _shape_ix - x;
+ _shape_cur_y16 = _shape_iy - y;
+
+ a = _shape_ix + ((_rotData[0] * _shape_cur_x16 + _rotData[1] * _shape_cur_y16) >> 8);
+ if (_shape_count == 0) {
+ _shape_ox = a;
+ }
+ _shape_cur_x = shape_last_x = a;
+ a = _shape_iy + ((_rotData[2] * _shape_cur_x16 + _rotData[3] * _shape_cur_y16) >> 8);
+ if (_shape_count == 0) {
+ _shape_oy = a;
+ }
+ _shape_cur_y = shape_last_y = a;
+
+ int16_t ix = x;
+ int16_t iy = y;
+ Point *pt2 = tempVertices;
+ int16_t sx = 0;
+ for (int16_t n = numVertices - 1; n >= 0; --n) {
+ x = (int8_t)(*data++) + sx;
+ y = (int8_t)(*data++);
+ if (y == 0 && n != 0 && *(data + 1) == 0) {
+ sx = x;
+ --numVertices;
+ } else {
+ ix += x;
+ iy += y;
+ sx = 0;
+ _shape_cur_x16 = _shape_ix - ix;
+ _shape_cur_y16 = _shape_iy - iy;
+ a = _shape_ix + ((_rotData[0] * _shape_cur_x16 + _rotData[1] * _shape_cur_y16) >> 8);
+ pt2->x = a - shape_last_x;
+ shape_last_x = a;
+ a = _shape_iy + ((_rotData[2] * _shape_cur_x16 + _rotData[3] * _shape_cur_y16) >> 8);
+ pt2->y = a - shape_last_y;
+ shape_last_y = a;
+ ++pt2;
+ }
+ }
+ Point *pt = _vertices;
+ if (_shape_count == 0) {
+ ix = _shape_ox;
+ iy = _shape_oy;
+ f -= (((_shape_ix - ix) * zoom * 128) + 0x8000) >> 16;
+ g -= (((_shape_iy - iy) * zoom * 128) + 0x8000) >> 16;
+ pt->x = f + _shape_ix + d;
+ pt->y = g + _shape_iy + e;
+ ++pt;
+ _shape_cur_x16 = f << 16;
+ _shape_cur_y16 = g << 16;
+ } else {
+ _shape_cur_x16 = _shape_prev_x16 + ((_shape_cur_x - _shape_prev_x) * zoom * 128);
+ pt->x = _shape_ix + d + ((_shape_cur_x16 + 0x8000) >> 16);
+ _shape_cur_y16 = _shape_prev_y16 + ((_shape_cur_y - _shape_prev_y) * zoom * 128);
+ pt->y = _shape_iy + e + ((_shape_cur_y16 + 0x8000) >> 16);
+ ++pt;
+ }
+ for (int i = 0; i < numVertices; ++i) {
+ _shape_cur_x += tempVertices[i].x;
+ _shape_cur_x16 += tempVertices[i].x * zoom * 128;
+ pt->x = d + _shape_ix + ((_shape_cur_x16 + 0x8000) >> 16);
+ _shape_cur_y += tempVertices[i].y;
+ _shape_cur_y16 += tempVertices[i].y * zoom * 128;
+ pt->y = e + _shape_iy + ((_shape_cur_y16 + 0x8000) >> 16);
+ ++pt;
+ }
+ _shape_prev_x = _shape_cur_x;
+ _shape_prev_y = _shape_cur_y;
+ _shape_prev_x16 = _shape_cur_x16;
+ _shape_prev_y16 = _shape_cur_y16;
+ _gfx.drawPolygon(_primitiveColor, _hasAlphaColor, _vertices, numVertices + 1);
+ }
+}
+
+void Cutscene::op_drawShapeScaleRotate() {
+ debug(DBG_CUT, "Cutscene::op_drawShapeScaleRotate()");
+
+ _shape_count = 0;
+
+ int16_t x = 0;
+ int16_t y = 0;
+ uint16_t shapeOffset = fetchNextCmdWord();
+ if (shapeOffset & 0x8000) {
+ x = fetchNextCmdWord();
+ y = fetchNextCmdWord();
+ }
+
+ uint16_t zoom = 512;
+ if (shapeOffset & 0x4000) {
+ zoom += fetchNextCmdWord();
+ }
+ _shape_ix = fetchNextCmdByte();
+ _shape_iy = fetchNextCmdByte();
+
+ uint16_t r1, r2, r3;
+ r1 = fetchNextCmdWord();
+ r2 = 180;
+ if (shapeOffset & 0x2000) {
+ r2 = fetchNextCmdWord();
+ }
+ r3 = 90;
+ if (shapeOffset & 0x1000) {
+ r3 = fetchNextCmdWord();
+ }
+ initRotationData(r1, r2, r3);
+
+ const uint8_t *shapeOffsetTable = _polPtr + READ_BE_UINT16(_polPtr + 0x02);
+ const uint8_t *shapeDataTable = _polPtr + READ_BE_UINT16(_polPtr + 0x0E);
+ const uint8_t *verticesOffsetTable = _polPtr + READ_BE_UINT16(_polPtr + 0x0A);
+ const uint8_t *verticesDataTable = _polPtr + READ_BE_UINT16(_polPtr + 0x12);
+
+ const uint8_t *shapeData = shapeDataTable + READ_BE_UINT16(shapeOffsetTable + (shapeOffset & 0x7FF) * 2);
+ uint16_t primitiveCount = READ_BE_UINT16(shapeData); shapeData += 2;
+
+ while (primitiveCount--) {
+ uint16_t verticesOffset = READ_BE_UINT16(shapeData); shapeData += 2;
+ const uint8_t *p = verticesDataTable + READ_BE_UINT16(verticesOffsetTable + (verticesOffset & 0x3FFF) * 2);
+ int16_t dx = 0;
+ int16_t dy = 0;
+ if (verticesOffset & 0x8000) {
+ dx = READ_BE_UINT16(shapeData); shapeData += 2;
+ dy = READ_BE_UINT16(shapeData); shapeData += 2;
+ }
+ _hasAlphaColor = (verticesOffset & 0x4000) != 0;
+ uint8_t color = *shapeData++;
+ if (_clearScreen == 0) {
+ color += 0x10; // 2nd pal buf
+ }
+ _primitiveColor = 0xC0 + color;
+ drawShapeScaleRotate(p, zoom, dx, dy, x, y, 0, 0);
+ ++_shape_count;
+ }
+}
+
+void Cutscene::op_drawCreditsText() {
+ debug(DBG_CUT, "Cutscene::op_drawCreditsText()");
+ _varText = 0xFF;
+ if (_textCurBuf == _textBuf) {
+ ++_creditsTextCounter;
+ }
+ memcpy(_page1, _page0, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ _frameDelay = 10;
+ setPalette();
+}
+
+void Cutscene::op_drawStringAtPos() {
+ debug(DBG_CUT, "Cutscene::op_drawStringAtPos()");
+ uint16_t strId = fetchNextCmdWord();
+ if (strId != 0xFFFF) {
+ int16_t x = (int8_t)fetchNextCmdByte() * 8;
+ int16_t y = (int8_t)fetchNextCmdByte() * 8;
+ if (!_creditsSequence) {
+ const uint8_t *str = _res->getCineString(strId & 0xFFF);
+ if (str) {
+ uint8_t color = 0xD0 + (strId >> 0xC);
+ drawText(x, y, str, color, _page1, 2);
+ }
+ // workaround for buggy cutscene script
+ if (_id == 0x34 && (strId & 0xFFF) == 0x45) {
+ if ((_cmdPtr - _cmdPtrBak) == 0xA) {
+ _stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _page1, 256);
+ _stub->updateScreen(0);
+ } else {
+ _stub->sleep(15);
+ }
+ }
+ }
+ }
+}
+
+void Cutscene::op_handleKeys() {
+ debug(DBG_CUT, "Cutscene::op_handleKeys()");
+ while (1) {
+ uint8_t key_mask = fetchNextCmdByte();
+ if (key_mask == 0xFF) {
+ return;
+ }
+ bool b = true;
+ switch (key_mask) {
+ case 1:
+ b = (_stub->_pi.dirMask & PlayerInput::DIR_UP) != 0;
+ break;
+ case 2:
+ b = (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) != 0;
+ break;
+ case 4:
+ b = (_stub->_pi.dirMask & PlayerInput::DIR_LEFT) != 0;
+ break;
+ case 8:
+ b = (_stub->_pi.dirMask & PlayerInput::DIR_RIGHT) != 0;
+ break;
+ case 0x80:
+ b = _stub->_pi.space || _stub->_pi.enter || _stub->_pi.shift;
+ break;
+ }
+ if (b) {
+ break;
+ }
+ _cmdPtr += 2;
+ }
+ _stub->_pi.dirMask = 0;
+ _stub->_pi.enter = false;
+ _stub->_pi.space = false;
+ _stub->_pi.shift = false;
+ int16_t n = fetchNextCmdWord();
+ if (n < 0) {
+ n = -n - 1;
+ if (_varKey == 0) {
+ _stop = true;
+ return;
+ }
+ if (_varKey != n) {
+ _cmdPtr = _cmdPtrBak;
+ return;
+ }
+ _varKey = 0;
+ --n;
+ _cmdPtr = _res->_cmd;
+ n = READ_BE_UINT16(_cmdPtr + n * 2 + 2);
+ }
+ _cmdPtr = _cmdPtrBak = _res->_cmd + n + _startOffset;
+}
+
+uint8_t Cutscene::fetchNextCmdByte() {
+ return *_cmdPtr++;
+}
+
+uint16_t Cutscene::fetchNextCmdWord() {
+ uint16_t i = READ_BE_UINT16(_cmdPtr);
+ _cmdPtr += 2;
+ return i;
+}
+
+void Cutscene::mainLoop(uint16_t offset) {
+ _frameDelay = 5;
+ _tstamp = _stub->getTimeStamp();
+
+ Color c;
+ c.r = c.g = c.b = 0;
+ for (int i = 0; i < 0x20; ++i) {
+ _stub->setPaletteEntry(0xC0 + i, &c);
+ }
+ _newPal = false;
+ _hasAlphaColor = false;
+ uint8_t *p = _res->_cmd;
+ if (offset != 0) {
+ offset = READ_BE_UINT16(p + (offset + 1) * 2);
+ }
+ _startOffset = (READ_BE_UINT16(p) + 1) * 2;
+ _varKey = 0;
+ _cmdPtr = _cmdPtrBak = p + _startOffset + offset;
+ _polPtr = _res->_pol;
+ debug(DBG_CUT, "_startOffset = %d offset = %d", _startOffset, offset);
+
+ while (!_stub->_pi.quit && !_interrupted && !_stop) {
+ uint8_t op = fetchNextCmdByte();
+ debug(DBG_CUT, "Cutscene::play() opcode = 0x%X (%d)", op, (op >> 2));
+ if (op & 0x80) {
+ break;
+ }
+ op >>= 2;
+ if (op >= NUM_OPCODES) {
+ error("Invalid cutscene opcode = 0x%02X", op);
+ }
+ (this->*_opcodeTable[op])();
+ _stub->processEvents();
+ if (_stub->_pi.backspace) {
+ _stub->_pi.backspace = false;
+ _interrupted = true;
+ }
+ }
+}
+
+void Cutscene::load(uint16_t cutName) {
+ assert(cutName != 0xFFFF);
+ const char *name = _namesTable[cutName & 0xFF];
+ switch (_res->_type) {
+ case kResourceTypeAmiga:
+ if (strncmp(name, "INTRO", 5) == 0) {
+ name = "INTRO";
+ }
+ _res->load(name, Resource::OT_CMP);
+ break;
+ case kResourceTypePC:
+ _res->load(name, Resource::OT_CMD);
+ _res->load(name, Resource::OT_POL);
+ _res->load_CINE();
+ break;
+ }
+}
+
+void Cutscene::prepare() {
+ _page0 = _vid->_frontLayer;
+ _page1 = _vid->_tempLayer;
+ _pageC = _vid->_tempLayer2;
+ _stub->_pi.dirMask = 0;
+ _stub->_pi.enter = false;
+ _stub->_pi.space = false;
+ _stub->_pi.shift = false;
+ _interrupted = false;
+ _stop = false;
+ _gfx.setClippingRect(8, 50, 240, 128);
+}
+
+void Cutscene::startCredits() {
+ _textCurPtr = _creditsData;
+ _textBuf[0] = 0xA;
+ _textCurBuf = _textBuf;
+ _creditsSequence = true;
+// _cut_status = 1;
+ _varText = 0;
+ _textUnk2 = 0;
+ _creditsTextCounter = 0;
+ _interrupted = false;
+ const uint16_t *cut_seq = _creditsCutSeq;
+ while (!_stub->_pi.quit && !_interrupted) {
+ uint16_t cut_id = *cut_seq++;
+ if (cut_id == 0xFFFF) {
+ break;
+ }
+ prepare();
+ uint16_t cutName = _offsetsTable[cut_id * 2 + 0];
+ uint16_t cutOff = _offsetsTable[cut_id * 2 + 1];
+ load(cutName);
+ mainLoop(cutOff);
+ }
+ _creditsSequence = false;
+}
+
+void Cutscene::play() {
+ if (_id != 0xFFFF) {
+ _textCurBuf = NULL;
+ debug(DBG_CUT, "Cutscene::play() _id=0x%X", _id);
+ _creditsSequence = false;
+ prepare();
+ uint16_t cutName = _offsetsTable[_id * 2 + 0];
+ uint16_t cutOff = _offsetsTable[_id * 2 + 1];
+ if (cutName != 0xFFFF) {
+ load(cutName);
+ mainLoop(cutOff);
+ }
+ _vid->fullRefresh();
+ if (_id != 0x3D) {
+ _id = 0xFFFF;
+ }
+ }
+}
diff --git a/cutscene.h b/cutscene.h
new file mode 100644
index 0000000..4feea07
--- /dev/null
+++ b/cutscene.h
@@ -0,0 +1,134 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 CUTSCENE_H__
+#define CUTSCENE_H__
+
+#include "intern.h"
+#include "graphics.h"
+
+struct Resource;
+struct SystemStub;
+struct Video;
+
+struct Cutscene {
+ typedef void (Cutscene::*OpcodeStub)();
+
+ enum {
+ NUM_OPCODES = 15,
+ TIMER_SLICE = 15
+ };
+
+ static const OpcodeStub _opcodeTable[];
+ static const char *_namesTable[];
+ static const uint16_t _offsetsTable[];
+ static const uint16_t _cosTable[];
+ static const uint16_t _sinTable[];
+ static const uint8_t _creditsData[];
+ static const uint16_t _creditsCutSeq[];
+ static const uint8_t _musicTable[];
+ static const uint8_t _protectionShapeData[];
+
+ Graphics _gfx;
+ Resource *_res;
+ SystemStub *_stub;
+ Video *_vid;
+
+ uint16_t _id;
+ uint16_t _deathCutsceneId;
+ bool _interrupted;
+ bool _stop;
+ uint8_t *_polPtr;
+ uint8_t *_cmdPtr;
+ uint8_t *_cmdPtrBak;
+ uint32_t _tstamp;
+ uint8_t _frameDelay;
+ bool _newPal;
+ uint8_t _palBuf[0x20 * 2];
+ uint16_t _startOffset;
+ bool _creditsSequence;
+ uint32_t _rotData[4];
+ uint8_t _primitiveColor;
+ uint8_t _clearScreen;
+ Point _vertices[0x80];
+ bool _hasAlphaColor;
+ uint8_t _varText;
+ uint8_t _varKey;
+ int16_t _shape_ix;
+ int16_t _shape_iy;
+ int16_t _shape_ox;
+ int16_t _shape_oy;
+ int16_t _shape_cur_x;
+ int16_t _shape_cur_y;
+ int16_t _shape_prev_x;
+ int16_t _shape_prev_y;
+ uint16_t _shape_count;
+ uint32_t _shape_cur_x16;
+ uint32_t _shape_cur_y16;
+ uint32_t _shape_prev_x16;
+ uint32_t _shape_prev_y16;
+ uint8_t _textSep[0x14];
+ uint8_t _textBuf[500];
+ const uint8_t *_textCurPtr;
+ uint8_t *_textCurBuf;
+ uint8_t _textUnk2;
+ uint8_t _creditsTextPosX;
+ uint8_t _creditsTextPosY;
+ int16_t _creditsTextCounter;
+ uint8_t *_page0, *_page1, *_pageC;
+
+ Cutscene(Resource *res, SystemStub *stub, Video *vid);
+
+ void sync();
+ void copyPalette(const uint8_t *pal, uint16_t num);
+ void updatePalette();
+ void setPalette();
+ void initRotationData(uint16_t a, uint16_t b, uint16_t c);
+ uint16_t findTextSeparators(const uint8_t *p);
+ void drawText(int16_t x, int16_t y, const uint8_t *p, uint16_t color, uint8_t *page, uint8_t n);
+ void swapLayers();
+ void drawCreditsText();
+ void drawProtectionShape(uint8_t shapeNum, int16_t zoom);
+ void drawShape(const uint8_t *data, int16_t x, int16_t y);
+ void drawShapeScale(const uint8_t *data, int16_t zoom, int16_t b, int16_t c, int16_t d, int16_t e, int16_t f, int16_t g);
+ void drawShapeScaleRotate(const uint8_t *data, int16_t zoom, int16_t b, int16_t c, int16_t d, int16_t e, int16_t f, int16_t g);
+
+ void op_markCurPos();
+ void op_refreshScreen();
+ void op_waitForSync();
+ void op_drawShape();
+ void op_setPalette();
+ void op_drawStringAtBottom();
+ void op_nop();
+ void op_skip3();
+ void op_refreshAll();
+ void op_drawShapeScale();
+ void op_drawShapeScaleRotate();
+ void op_drawCreditsText();
+ void op_drawStringAtPos();
+ void op_handleKeys();
+
+ uint8_t fetchNextCmdByte();
+ uint16_t fetchNextCmdWord();
+ void mainLoop(uint16_t offset);
+ void load(uint16_t cutName);
+ void prepare();
+ void startCredits();
+ void play();
+};
+
+#endif // CUTSCENE_H__
diff --git a/file.cpp b/file.cpp
new file mode 100644
index 0000000..aab81d3
--- /dev/null
+++ b/file.cpp
@@ -0,0 +1,260 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "fs.h"
+#ifdef USE_ZLIB
+#include "zlib.h"
+#endif
+#include "file.h"
+
+
+struct File_impl {
+ bool _ioErr;
+ File_impl() : _ioErr(false) {}
+ virtual ~File_impl() {}
+ virtual bool open(const char *path, const char *mode) = 0;
+ virtual void close() = 0;
+ virtual uint32_t size() = 0;
+ virtual void seek(int32_t off) = 0;
+ virtual uint32_t read(void *ptr, uint32_t len) = 0;
+ virtual uint32_t write(void *ptr, uint32_t len) = 0;
+};
+
+struct stdFile : File_impl {
+ FILE *_fp;
+ stdFile() : _fp(0) {}
+ bool open(const char *path, const char *mode) {
+ _ioErr = false;
+ _fp = fopen(path, mode);
+ return (_fp != 0);
+ }
+ void close() {
+ if (_fp) {
+ fclose(_fp);
+ _fp = 0;
+ }
+ }
+ uint32_t size() {
+ uint32_t sz = 0;
+ if (_fp) {
+ int pos = ftell(_fp);
+ fseek(_fp, 0, SEEK_END);
+ sz = ftell(_fp);
+ fseek(_fp, pos, SEEK_SET);
+ }
+ return sz;
+ }
+ void seek(int32_t off) {
+ if (_fp) {
+ fseek(_fp, off, SEEK_SET);
+ }
+ }
+ uint32_t read(void *ptr, uint32_t len) {
+ if (_fp) {
+ uint32_t r = fread(ptr, 1, len, _fp);
+ if (r != len) {
+ _ioErr = true;
+ }
+ return r;
+ }
+ return 0;
+ }
+ uint32_t write(void *ptr, uint32_t len) {
+ if (_fp) {
+ uint32_t r = fwrite(ptr, 1, len, _fp);
+ if (r != len) {
+ _ioErr = true;
+ }
+ return r;
+ }
+ return 0;
+ }
+};
+
+#ifdef USE_ZLIB
+struct zlibFile : File_impl {
+ gzFile _fp;
+ zlibFile() : _fp(0) {}
+ bool open(const char *path, const char *mode) {
+ _ioErr = false;
+ _fp = gzopen(path, mode);
+ return (_fp != 0);
+ }
+ void close() {
+ if (_fp) {
+ gzclose(_fp);
+ _fp = 0;
+ }
+ }
+ uint32_t size() {
+ uint32_t sz = 0;
+ if (_fp) {
+ int pos = gztell(_fp);
+ gzseek(_fp, 0, SEEK_END);
+ sz = gztell(_fp);
+ gzseek(_fp, pos, SEEK_SET);
+ }
+ return sz;
+ }
+ void seek(int32_t off) {
+ if (_fp) {
+ gzseek(_fp, off, SEEK_SET);
+ }
+ }
+ uint32_t read(void *ptr, uint32_t len) {
+ if (_fp) {
+ uint32_t r = gzread(_fp, ptr, len);
+ if (r != len) {
+ _ioErr = true;
+ }
+ return r;
+ }
+ return 0;
+ }
+ uint32_t write(void *ptr, uint32_t len) {
+ if (_fp) {
+ uint32_t r = gzwrite(_fp, ptr, len);
+ if (r != len) {
+ _ioErr = true;
+ }
+ return r;
+ }
+ return 0;
+ }
+};
+#endif
+
+
+File::File()
+ : _impl(0) {
+}
+
+File::~File() {
+ if (_impl) {
+ _impl->close();
+ delete _impl;
+ }
+}
+
+bool File::open(const char *filename, const char *mode, FileSystem *fs) {
+ if (_impl) {
+ _impl->close();
+ delete _impl;
+ _impl = 0;
+ }
+ assert(mode[0] != 'z');
+ _impl = new stdFile;
+ char *path = fs->findPath(filename);
+ if (path) {
+ debug(DBG_FILE, "Open file name '%s' mode '%s' path '%s'", filename, mode, path);
+ bool ret = _impl->open(path, mode);
+ free(path);
+ return ret;
+ }
+ return false;
+}
+
+bool File::open(const char *filename, const char *mode, const char *directory) {
+ if (_impl) {
+ _impl->close();
+ delete _impl;
+ _impl = 0;
+ }
+#ifdef USE_ZLIB
+ if (mode[0] == 'z') {
+ _impl = new zlibFile;
+ ++mode;
+ }
+#endif
+ if (!_impl) {
+ _impl = new stdFile;
+ }
+ char path[512];
+ snprintf(path, sizeof(path), "%s/%s", directory, filename);
+ debug(DBG_FILE, "Open file name '%s' mode '%s' path '%s'", filename, mode, path);
+ return _impl->open(path, mode);
+}
+
+void File::close() {
+ if (_impl) {
+ _impl->close();
+ }
+}
+
+bool File::ioErr() const {
+ return _impl->_ioErr;
+}
+
+uint32_t File::size() {
+ return _impl->size();
+}
+
+void File::seek(int32_t off) {
+ _impl->seek(off);
+}
+
+uint32_t File::read(void *ptr, uint32_t len) {
+ return _impl->read(ptr, len);
+}
+
+uint8_t File::readByte() {
+ uint8_t b;
+ read(&b, 1);
+ return b;
+}
+
+uint16_t File::readUint16LE() {
+ uint8_t lo = readByte();
+ uint8_t hi = readByte();
+ return (hi << 8) | lo;
+}
+
+uint32_t File::readUint32LE() {
+ uint16_t lo = readUint16LE();
+ uint16_t hi = readUint16LE();
+ return (hi << 16) | lo;
+}
+
+uint16_t File::readUint16BE() {
+ uint8_t hi = readByte();
+ uint8_t lo = readByte();
+ return (hi << 8) | lo;
+}
+
+uint32_t File::readUint32BE() {
+ uint16_t hi = readUint16BE();
+ uint16_t lo = readUint16BE();
+ return (hi << 16) | lo;
+}
+
+uint32_t File::write(void *ptr, uint32_t len) {
+ return _impl->write(ptr, len);
+}
+
+void File::writeByte(uint8_t b) {
+ write(&b, 1);
+}
+
+void File::writeUint16BE(uint16_t n) {
+ writeByte(n >> 8);
+ writeByte(n & 0xFF);
+}
+
+void File::writeUint32BE(uint32_t n) {
+ writeUint16BE(n >> 16);
+ writeUint16BE(n & 0xFFFF);
+}
diff --git a/file.h b/file.h
new file mode 100644
index 0000000..9fd5335
--- /dev/null
+++ b/file.h
@@ -0,0 +1,50 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 FILE_H__
+#define FILE_H__
+
+#include "intern.h"
+
+struct File_impl;
+struct FileSystem;
+
+struct File {
+ File();
+ ~File();
+
+ File_impl *_impl;
+
+ bool open(const char *filename, const char *mode, FileSystem *fs);
+ bool open(const char *filename, const char *mode, const char *directory);
+ void close();
+ bool ioErr() const;
+ uint32_t size();
+ void seek(int32_t off);
+ uint32_t read(void *ptr, uint32_t len);
+ uint8_t readByte();
+ uint16_t readUint16LE();
+ uint32_t readUint32LE();
+ uint16_t readUint16BE();
+ uint32_t readUint32BE();
+ uint32_t write(void *ptr, uint32_t size);
+ void writeByte(uint8_t b);
+ void writeUint16BE(uint16_t n);
+ void writeUint32BE(uint32_t n);
+};
+
+#endif // FILE_H__
diff --git a/fs.cpp b/fs.cpp
new file mode 100644
index 0000000..fbebbd5
--- /dev/null
+++ b/fs.cpp
@@ -0,0 +1,167 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 .
+ */
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include
+#else
+#include
+#include
+#endif
+#include "fs.h"
+
+struct FileName {
+ char *name;
+ int dir;
+};
+
+struct FileSystem_impl {
+
+ char **_dirsList;
+ int _dirsCount;
+ FileName *_filesList;
+ int _filesCount;
+
+ FileSystem_impl() :
+ _dirsList(0), _dirsCount(0), _filesList(0), _filesCount(0) {
+ }
+
+ ~FileSystem_impl() {
+ for (int i = 0; i < _dirsCount; ++i) {
+ free(_dirsList[i]);
+ }
+ free(_dirsList);
+ for (int i = 0; i < _filesCount; ++i) {
+ free(_filesList[i].name);
+ }
+ free(_filesList);
+ }
+
+ void setRootDirectory(const char *dir) {
+ getPathListFromDirectory(dir);
+ debug(DBG_FILE, "Found %d files and %d directories", _filesCount, _dirsCount);
+ }
+
+ char *findPath(const char *name) const {
+ for (int i = 0; i < _filesCount; ++i) {
+ if (strcasecmp(_filesList[i].name, name) == 0) {
+ const char *dir = _dirsList[_filesList[i].dir];
+ const int len = strlen(dir) + 1 + strlen(_filesList[i].name) + 1;
+ char *p = (char *)malloc(len);
+ if (p) {
+ snprintf(p, len, "%s/%s", dir, _filesList[i].name);
+ }
+ return p;
+ }
+ }
+ return 0;
+ }
+
+ void addPath(const char *dir, const char *name) {
+ int index = -1;
+ for (int i = 0; i < _dirsCount; ++i) {
+ if (strcmp(_dirsList[i], dir) == 0) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ _dirsList = (char **)realloc(_dirsList, (_dirsCount + 1) * sizeof(char *));
+ if (_dirsList) {
+ _dirsList[_dirsCount] = strdup(dir);
+ index = _dirsCount;
+ ++_dirsCount;
+ }
+ }
+ _filesList = (FileName *)realloc(_filesList, (_filesCount + 1) * sizeof(FileName));
+ if (_filesList) {
+ _filesList[_filesCount].name = strdup(name);
+ _filesList[_filesCount].dir = index;
+ ++_filesCount;
+ }
+ }
+
+ void getPathListFromDirectory(const char *dir);
+};
+
+#ifdef _WIN32
+void FileSystem_impl::getPathListFromDirectory(const char *dir) {
+ WIN32_FIND_DATA findData;
+ char searchPath[MAX_PATH];
+ snprintf(searchPath, sizeof(searchPath), "%s/*", dir);
+ HANDLE h = FindFirstFile(searchPath, &findData);
+ if (h) {
+ do {
+ if (findData.cFileName[0] == '.') {
+ continue;
+ }
+ char filePath[MAX_PATH];
+ snprintf(filePath, sizeof(filePath), "%s/%s", dir, findData.cFileName);
+ if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ getPathListFromDirectory(filePath);
+ } else {
+ addPath(dir, findData.cFileName);
+ }
+ } while (FindNextFile(h, &findData));
+ FindClose(h);
+ }
+}
+#else
+void FileSystem_impl::getPathListFromDirectory(const char *dir) {
+ DIR *d = opendir(dir);
+ if (d) {
+ dirent *de;
+ while ((de = readdir(d)) != NULL) {
+ if (de->d_name[0] == '.') {
+ continue;
+ }
+ char filePath[512];
+ snprintf(filePath, sizeof(filePath), "%s/%s", dir, de->d_name);
+ struct stat st;
+ if (stat(filePath, &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ getPathListFromDirectory(filePath);
+ } else {
+ addPath(dir, de->d_name);
+ }
+ }
+ }
+ closedir(d);
+ }
+}
+#endif
+
+FileSystem::FileSystem(const char *dataPath) {
+ _impl = new FileSystem_impl;
+ _impl->setRootDirectory(dataPath);
+}
+
+FileSystem::~FileSystem() {
+ delete _impl;
+}
+
+char *FileSystem::findPath(const char *filename) const {
+ return _impl->findPath(filename);
+}
+
+bool FileSystem::exists(const char *filename) const {
+ char *path = findPath(filename);
+ if (path) {
+ free(path);
+ }
+ return path != 0;
+}
diff --git a/fs.h b/fs.h
new file mode 100644
index 0000000..5a464d8
--- /dev/null
+++ b/fs.h
@@ -0,0 +1,36 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 FS_H__
+#define FS_H__
+
+#include "intern.h"
+
+struct FileSystem_impl;
+
+struct FileSystem {
+ FileSystem(const char *dataPath);
+ ~FileSystem();
+
+ FileSystem_impl *_impl;
+
+ char *findPath(const char *filename) const;
+ bool exists(const char *filename) const;
+};
+
+#endif // FS_H__
+
diff --git a/game.cpp b/game.cpp
new file mode 100644
index 0000000..d9cd72d
--- /dev/null
+++ b/game.cpp
@@ -0,0 +1,1805 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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
+#include "file.h"
+#include "fs.h"
+#include "systemstub.h"
+#include "unpack.h"
+#include "game.h"
+#include "seq_player.h"
+
+
+Game::Game(SystemStub *stub, FileSystem *fs, const char *savePath, int level, ResourceType ver, Language lang)
+ : _cut(&_res, stub, &_vid), _menu(&_res, stub, &_vid),
+ _mix(fs, stub), _res(fs, ver, lang), _seq(stub, &_mix), _vid(&_res, stub),
+ _stub(stub), _fs(fs), _savePath(savePath) {
+ _stateSlot = 1;
+ _inp_demo = 0;
+ _inp_record = false;
+ _inp_replay = false;
+ _skillLevel = 1;
+ _currentLevel = level;
+}
+
+void Game::run() {
+ _stub->init(g_caption, Video::GAMESCREEN_W, Video::GAMESCREEN_H);
+
+ _randSeed = time(0);
+
+ _res.load_TEXT();
+
+ switch (_res._type) {
+ case kResourceTypeAmiga:
+ _res.load("FONT8", Resource::OT_FNT, "SPR");
+ break;
+ case kResourceTypePC:
+ _res.load("FB_TXT", Resource::OT_FNT);
+ _res._hasSeqData = _fs->exists("INTRO.SEQ");
+ break;
+ }
+
+#ifndef BYPASS_PROTECTION
+ while (!handleProtectionScreen());
+ if (_stub->_pi.quit) {
+ return;
+ }
+#endif
+
+ _mix.init();
+
+ playCutscene(0x40);
+ playCutscene(0x0D);
+ if (!_cut._interrupted && _res._type == kResourceTypePC) {
+ playCutscene(0x4A);
+ }
+
+ switch (_res._type) {
+ case kResourceTypeAmiga:
+ _res.load("ICONE", Resource::OT_ICN, "SPR");
+ _res.load("ICON", Resource::OT_ICN, "SPR");
+ _res.load("PERSO", Resource::OT_SPM);
+ break;
+ case kResourceTypePC:
+ _res.load("GLOBAL", Resource::OT_ICN);
+ _res.load("GLOBAL", Resource::OT_SPC);
+ _res.load("PERSO", Resource::OT_SPR);
+ _res.load_SPR_OFF("PERSO", _res._spr1);
+ _res.load_FIB("GLOBAL");
+ break;
+ }
+
+ while (!_stub->_pi.quit) {
+ if (_res._type == kResourceTypePC) {
+ _mix.playMusic(1);
+ if (!_menu.handleTitleScreen(_skillLevel, _currentLevel)) {
+ break;
+ }
+ _mix.stopMusic();
+ }
+ if (_currentLevel == 7) {
+ _vid.fadeOut();
+ _vid.setTextPalette();
+ playCutscene(0x3D);
+ } else {
+ _vid.setTextPalette();
+ _vid.setPalette0xF();
+ _stub->setOverscanColor(0xE0);
+ _vid._unkPalSlot1 = 0;
+ _vid._unkPalSlot2 = 0;
+ _score = 0;
+ loadLevelData();
+ resetGameState();
+ _endLoop = false;
+ while (!_stub->_pi.quit && !_endLoop) {
+ mainLoop();
+ }
+ }
+ }
+
+ _res.free_TEXT();
+
+ _mix.free();
+ _stub->destroy();
+}
+
+void Game::resetGameState() {
+ _animBuffers._states[0] = _animBuffer0State;
+ _animBuffers._curPos[0] = 0xFF;
+ _animBuffers._states[1] = _animBuffer1State;
+ _animBuffers._curPos[1] = 0xFF;
+ _animBuffers._states[2] = _animBuffer2State;
+ _animBuffers._curPos[2] = 0xFF;
+ _animBuffers._states[3] = _animBuffer3State;
+ _animBuffers._curPos[3] = 0xFF;
+ _currentRoom = _res._pgeInit[0].init_room;
+ _cut._deathCutsceneId = 0xFFFF;
+ _pge_opTempVar2 = 0xFFFF;
+ _deathCutsceneCounter = 0;
+ _saveStateCompleted = false;
+ _loadMap = true;
+ pge_resetGroups();
+ _blinkingConradCounter = 0;
+ _pge_processOBJ = false;
+ _pge_opTempVar1 = 0;
+ _textToDisplay = 0xFFFF;
+}
+
+void Game::mainLoop() {
+ playCutscene();
+ if (_cut._id == 0x3D) {
+ showFinalScore();
+ _endLoop = true;
+ return;
+ }
+ if (_deathCutsceneCounter) {
+ --_deathCutsceneCounter;
+ if (_deathCutsceneCounter == 0) {
+ playCutscene(_cut._deathCutsceneId);
+ if (!handleContinueAbort()) {
+ playCutscene(0x41);
+ _endLoop = true;
+ } else {
+ if (_validSaveState) {
+ if (!loadGameState(0)) {
+ _endLoop = true;
+ }
+ } else {
+ loadLevelData();
+ resetGameState();
+ }
+ }
+ return;
+ }
+ }
+ memcpy(_vid._frontLayer, _vid._backLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ pge_getInput();
+ pge_prepare();
+ col_prepareRoomState();
+ uint8_t oldLevel = _currentLevel;
+ for (uint16_t i = 0; i < _res._pgeNum; ++i) {
+ LivePGE *pge = _pge_liveTable2[i];
+ if (pge) {
+ _col_currentPiegeGridPosY = (pge->pos_y / 36) & ~1;
+ _col_currentPiegeGridPosX = (pge->pos_x + 8) >> 4;
+ pge_process(pge);
+ }
+ }
+ if (oldLevel != _currentLevel) {
+ changeLevel();
+ _pge_opTempVar1 = 0;
+ return;
+ }
+ if (_loadMap) {
+ if (_currentRoom == 0xFF) {
+ _cut._id = 6;
+ _deathCutsceneCounter = 1;
+ } else {
+ _currentRoom = _pgeLive[0].room_location;
+ loadLevelMap();
+ _loadMap = false;
+ _vid.fullRefresh();
+ }
+ }
+ prepareAnims();
+ drawAnims();
+ drawCurrentInventoryItem();
+ drawLevelTexts();
+ printLevelCode();
+ if (_blinkingConradCounter != 0) {
+ --_blinkingConradCounter;
+ }
+ _vid.updateScreen();
+ updateTiming();
+ drawStoryTexts();
+ if (_stub->_pi.backspace) {
+ _stub->_pi.backspace = false;
+ handleInventory();
+ }
+ if (_stub->_pi.escape) {
+ _stub->_pi.escape = false;
+ if (handleConfigPanel()) {
+ _endLoop = true;
+ return;
+ }
+ }
+ inp_handleSpecialKeys();
+}
+
+void Game::updateTiming() {
+ static uint32_t tstamp = 0;
+ int32_t delay = _stub->getTimeStamp() - tstamp;
+ int32_t pause = (_stub->_pi.dbgMask & PlayerInput::DF_FASTMODE) ? 20 : 30;
+ pause -= delay;
+ if (pause > 0) {
+ _stub->sleep(pause);
+ }
+ tstamp = _stub->getTimeStamp();
+}
+
+void Game::playCutscene(int id) {
+ if (id != -1) {
+ _cut._id = id;
+ }
+ if (_cut._id != 0xFFFF) {
+ _mix.stopMusic();
+ if (_res._hasSeqData) {
+ int num = 0;
+ switch (_cut._id) {
+ case 0x02: {
+ static const uint8_t tab[] = { 1, 2, 1, 3, 3, 4, 4 };
+ num = tab[_currentLevel];
+ }
+ break;
+ case 0x05: {
+ static const uint8_t tab[] = { 1, 2, 3, 5, 5, 4, 4 };
+ num = tab[_currentLevel];
+ }
+ break;
+ case 0x0A: {
+ static const uint8_t tab[] = { 1, 2, 2, 2, 2, 2, 2 };
+ num = tab[_currentLevel];
+ }
+ break;
+ case 0x10: {
+ static const uint8_t tab[] = { 1, 1, 1, 2, 2, 3, 3 };
+ num = tab[_currentLevel];
+ }
+ break;
+ case 0x3C: {
+ static const uint8_t tab[] = { 1, 1, 1, 1, 1, 2, 2 };
+ num = tab[_currentLevel];
+ }
+ break;
+ case 0x40:
+ return;
+ case 0x4A:
+ return;
+ }
+ if (SeqPlayer::_namesTable[_cut._id]) {
+ char name[16];
+ snprintf(name, sizeof(name), "%s.SEQ", SeqPlayer::_namesTable[_cut._id]);
+ char *p = strchr(name, '0');
+ if (p) {
+ *p += num;
+ }
+ if (playCutsceneSeq(name)) {
+ if (_cut._id == 0x3D) {
+ playCutsceneSeq("CREDITS.SEQ");
+ _cut._interrupted = false;
+ } else {
+ _cut._id = 0xFFFF;
+ }
+ return;
+ }
+ }
+ }
+ if (_cut._id != 0x4A) {
+ _mix.playMusic(Cutscene::_musicTable[_cut._id]);
+ }
+ _cut.play();
+ if (id == 0x3D) {
+ _cut.startCredits();
+ }
+ if (_cut._interrupted || id != 0x0D) {
+ _mix.stopMusic();
+ }
+ }
+}
+
+bool Game::playCutsceneSeq(const char *name) {
+ File f;
+ if (f.open(name, "rb", _fs)) {
+ _seq.setBackBuffer(_res._memBuf);
+ _seq.play(&f);
+ _vid.fullRefresh();
+ return true;
+ }
+ return false;
+}
+
+void Game::inp_handleSpecialKeys() {
+ if (_stub->_pi.dbgMask & PlayerInput::DF_SETLIFE) {
+ _pgeLive[0].life = 0x7FFF;
+ }
+ if (_stub->_pi.load) {
+ loadGameState(_stateSlot);
+ _stub->_pi.load = false;
+ }
+ if (_stub->_pi.save) {
+ saveGameState(_stateSlot);
+ _stub->_pi.save = false;
+ }
+ if (_stub->_pi.stateSlot != 0) {
+ int8_t slot = _stateSlot + _stub->_pi.stateSlot;
+ if (slot >= 1 && slot < 100) {
+ _stateSlot = slot;
+ debug(DBG_INFO, "Current game state slot is %d", _stateSlot);
+ }
+ _stub->_pi.stateSlot = 0;
+ }
+ if (_stub->_pi.inpRecord || _stub->_pi.inpReplay) {
+ bool replay = false;
+ bool record = false;
+ char demoFile[20];
+ makeGameDemoName(demoFile);
+ if (_inp_demo) {
+ _inp_demo->close();
+ delete _inp_demo;
+ }
+ _inp_demo = new File;
+ if (_stub->_pi.inpRecord) {
+ if (_inp_record) {
+ debug(DBG_INFO, "Stop recording input keys");
+ } else {
+ if (_inp_demo->open(demoFile, "zwb", _savePath)) {
+ debug(DBG_INFO, "Recording input keys");
+ _inp_demo->writeUint32BE('FBDM');
+ _inp_demo->writeUint16BE(0);
+ _inp_demo->writeUint32BE(_randSeed);
+ record = true;
+ } else {
+ warning("Unable to save demo file '%s'", demoFile);
+ }
+ }
+ }
+ if (_stub->_pi.inpReplay) {
+ if (_inp_replay) {
+ debug(DBG_INFO, "Stop replaying input keys");
+ } else {
+ if (_inp_demo->open(demoFile, "zrb", _savePath)) {
+ debug(DBG_INFO, "Replaying input keys");
+ _inp_demo->readUint32BE();
+ _inp_demo->readUint16BE();
+ _randSeed = _inp_demo->readUint32BE();
+ replay = true;
+ } else {
+ warning("Unable to open demo file '%s'", demoFile);
+ }
+ }
+ }
+ _inp_record = record;
+ _inp_replay = replay;
+ _stub->_pi.inpReplay = false;
+ _stub->_pi.inpRecord = false;
+ }
+}
+
+void Game::drawCurrentInventoryItem() {
+ uint16_t src = _pgeLive[0].current_inventory_PGE;
+ if (src != 0xFF) {
+ _currentIcon = _res._pgeInit[src].icon_num;
+ drawIcon(_currentIcon, 232, 8, 0xA);
+ }
+}
+
+void Game::showFinalScore() {
+ playCutscene(0x49);
+ char buf[50];
+ snprintf(buf, sizeof(buf), "SCORE %08u", _score);
+ _vid.drawString(buf, (256 - strlen(buf) * 8) / 2, 40, 0xE5);
+ strcpy(buf, _menu._passwords[7][_skillLevel]);
+ _vid.drawString(buf, (256 - strlen(buf) * 8) / 2, 16, 0xE7);
+ while (!_stub->_pi.quit) {
+ _stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _vid._frontLayer, 256);
+ _stub->updateScreen(0);
+ _stub->processEvents();
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ break;
+ }
+ _stub->sleep(100);
+ }
+}
+
+bool Game::handleConfigPanel() {
+ if (_res._type == kResourceTypeAmiga) {
+ return true;
+ }
+ const int x = 7;
+ const int y = 10;
+ const int w = 17;
+ const int h = 12;
+
+ _vid._charShadowColor = 0xE2;
+ _vid._charFrontColor = 0xEE;
+ _vid._charTransparentColor = 0xFF;
+
+ _vid.PC_drawChar(0x81, y, x);
+ for (int i = 1; i < w; ++i) {
+ _vid.PC_drawChar(0x85, y, x + i);
+ }
+ _vid.PC_drawChar(0x82, y, x + w);
+ for (int j = 1; j < h; ++j) {
+ _vid.PC_drawChar(0x86, y + j, x);
+ for (int i = 1; i < w; ++i) {
+ _vid._charTransparentColor = 0xE2;
+ _vid.PC_drawChar(0x20, y + j, x + i);
+ }
+ _vid._charTransparentColor = 0xFF;
+ _vid.PC_drawChar(0x87, y + j, x + w);
+ }
+ _vid.PC_drawChar(0x83, y + h, x);
+ for (int i = 1; i < w; ++i) {
+ _vid.PC_drawChar(0x88, y + h, x + i);
+ }
+ _vid.PC_drawChar(0x84, y + h, x + w);
+
+ _menu._charVar3 = 0xE4;
+ _menu._charVar4 = 0xE5;
+ _menu._charVar1 = 0xE2;
+ _menu._charVar2 = 0xEE;
+
+ _vid.fullRefresh();
+ enum { MENU_ITEM_LOAD = 1, MENU_ITEM_SAVE = 2, MENU_ITEM_ABORT = 3 };
+ uint8_t colors[] = { 2, 3, 3, 3 };
+ int current = 0;
+ while (!_stub->_pi.quit) {
+ _menu.drawString(_res.getMenuString(LocaleData::LI_18_RESUME_GAME), y + 2, 9, colors[0]);
+ _menu.drawString(_res.getMenuString(LocaleData::LI_20_LOAD_GAME), y + 4, 9, colors[1]);
+ _menu.drawString(_res.getMenuString(LocaleData::LI_21_SAVE_GAME), y + 6, 9, colors[2]);
+ _menu.drawString(_res.getMenuString(LocaleData::LI_19_ABORT_GAME), y + 8, 9, colors[3]);
+ char buf[30];
+ snprintf(buf, sizeof(buf), "%s : %d-%02d", _res.getMenuString(LocaleData::LI_22_SAVE_SLOT), _currentLevel + 1, _stateSlot);
+ _menu.drawString(buf, y + 10, 9, 1);
+
+ _vid.updateScreen();
+ _stub->sleep(80);
+ inp_update();
+
+ int prev = current;
+ if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
+ current = (current + 3) % 4;
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
+ current = (current + 1) % 4;
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_LEFT) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_LEFT;
+ --_stateSlot;
+ if (_stateSlot < 1) {
+ _stateSlot = 1;
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_RIGHT) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
+ ++_stateSlot;
+ if (_stateSlot > 99) {
+ _stateSlot = 99;
+ }
+ }
+ if (prev != current) {
+ SWAP(colors[prev], colors[current]);
+ }
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ switch (current) {
+ case MENU_ITEM_LOAD:
+ _stub->_pi.load = true;
+ break;
+ case MENU_ITEM_SAVE:
+ _stub->_pi.save = true;
+ break;
+ }
+ break;
+ }
+ }
+ _vid.fullRefresh();
+ return (current == MENU_ITEM_ABORT);
+}
+
+bool Game::handleContinueAbort() {
+ playCutscene(0x48);
+ int timeout = 100;
+ int current_color = 0;
+ uint8_t colors[] = { 0xE4, 0xE5 };
+ uint8_t color_inc = 0xFF;
+ Color col;
+ _stub->getPaletteEntry(0xE4, &col);
+ memcpy(_vid._tempLayer, _vid._frontLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ while (timeout >= 0 && !_stub->_pi.quit) {
+ const char *str;
+ str = _res.getMenuString(LocaleData::LI_01_CONTINUE_OR_ABORT);
+ _vid.drawString(str, (256 - strlen(str) * 8) / 2, 64, 0xE3);
+ str = _res.getMenuString(LocaleData::LI_02_TIME);
+ char buf[50];
+ snprintf(buf, sizeof(buf), "%s : %d", str, timeout / 10);
+ _vid.drawString(buf, 96, 88, 0xE3);
+ str = _res.getMenuString(LocaleData::LI_03_CONTINUE);
+ _vid.drawString(str, (256 - strlen(str) * 8) / 2, 104, colors[0]);
+ str = _res.getMenuString(LocaleData::LI_04_ABORT);
+ _vid.drawString(str, (256 - strlen(str) * 8) / 2, 112, colors[1]);
+ snprintf(buf, sizeof(buf), "SCORE %08u", _score);
+ _vid.drawString(buf, 64, 154, 0xE3);
+ if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
+ if (current_color > 0) {
+ SWAP(colors[current_color], colors[current_color - 1]);
+ --current_color;
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
+ if (current_color < 1) {
+ SWAP(colors[current_color], colors[current_color + 1]);
+ ++current_color;
+ }
+ }
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ return (current_color == 0);
+ }
+ _stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _vid._frontLayer, 256);
+ _stub->updateScreen(0);
+ if (col.b >= 0x3D) {
+ color_inc = 0;
+ }
+ if (col.b < 2) {
+ color_inc = 0xFF;
+ }
+ if (color_inc == 0xFF) {
+ col.b += 2;
+ col.g += 2;
+ } else {
+ col.b -= 2;
+ col.g -= 2;
+ }
+ _stub->setPaletteEntry(0xE4, &col);
+ _stub->processEvents();
+ _stub->sleep(100);
+ --timeout;
+ memcpy(_vid._frontLayer, _vid._tempLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ }
+ return false;
+}
+
+bool Game::handleProtectionScreen() {
+ bool valid = true;
+ _cut.prepare();
+ _cut.copyPalette(_protectionPal, 0);
+ _cut.updatePalette();
+ _cut._gfx.setClippingRect(64, 48, 128, 128);
+
+ _menu._charVar1 = 0xE0;
+ _menu._charVar2 = 0xEF;
+ _menu._charVar4 = 0xE5;
+ _menu._charVar5 = 0xE2;
+
+ int shapeNum = getRandomNumber() % 30;
+ for (int16_t zoom = 2000; zoom != 0; zoom -= 100) {
+ _cut.drawProtectionShape(shapeNum, zoom);
+ _stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _vid._tempLayer, 256);
+ _stub->updateScreen(0);
+ _stub->sleep(30);
+ }
+ int codeNum = getRandomNumber() % 5;
+ _cut.drawProtectionShape(shapeNum, 1);
+ _vid.setTextPalette();
+ char codeText[7];
+ int len = 0;
+ do {
+ codeText[len] = '\0';
+ memcpy(_vid._frontLayer, _vid._tempLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ _menu.drawString("PROTECTION", 2, 11, 5);
+ char buf[20];
+ snprintf(buf, sizeof(buf), "CODE %d : %s", codeNum + 1, codeText);
+ _menu.drawString(buf, 23, 8, 5);
+ _vid.updateScreen();
+ _stub->sleep(50);
+ _stub->processEvents();
+ char c = _stub->_pi.lastChar;
+ if (c != 0) {
+ _stub->_pi.lastChar = 0;
+ if (len < 6) {
+ if (c >= 'a' && c <= 'z') {
+ c &= ~0x20;
+ }
+ if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) {
+ codeText[len] = c;
+ ++len;
+ }
+ }
+ }
+ if (_stub->_pi.backspace) {
+ _stub->_pi.backspace = false;
+ if (len > 0) {
+ --len;
+ }
+ }
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ if (len > 0) {
+ const uint8_t *p = _protectionCodeData + shapeNum * 0x1E + codeNum * 6;
+ for (int i = 0; i < len; ++i) {
+ uint8_t r = 0;
+ uint8_t ch = codeText[i];
+ for (int b = 0; b < 8; ++b) {
+ if (ch & (1 << b)) {
+ r |= (1 << (7 - b));
+ }
+ }
+ r ^= 0x55;
+ if (r != *p++) {
+ valid = false;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ } while (!_stub->_pi.quit);
+ _vid.fadeOut();
+ return valid;
+}
+
+void Game::printLevelCode() {
+ if (_printLevelCodeCounter != 0) {
+ --_printLevelCodeCounter;
+ if (_printLevelCodeCounter != 0) {
+ char buf[32];
+ snprintf(buf, sizeof(buf), "CODE: %s", _menu._passwords[_currentLevel][_skillLevel]);
+ _vid.drawString(buf, (Video::GAMESCREEN_W - strlen(buf) * 8) / 2, 16, 0xE7);
+ }
+ }
+}
+
+void Game::printSaveStateCompleted() {
+ if (_saveStateCompleted) {
+ const char *str = _res.getMenuString(LocaleData::LI_05_COMPLETED);
+ _vid.drawString(str, (176 - strlen(str) * 8) / 2, 34, 0xE6);
+ }
+}
+
+void Game::drawLevelTexts() {
+ LivePGE *pge = &_pgeLive[0];
+ int8_t obj = col_findCurrentCollidingObject(pge, 3, 0xFF, 0xFF, &pge);
+ if (obj == 0) {
+ obj = col_findCurrentCollidingObject(pge, 0xFF, 5, 9, &pge);
+ }
+ if (obj > 0) {
+ _printLevelCodeCounter = 0;
+ if (_textToDisplay == 0xFFFF) {
+ uint8_t icon_num = obj - 1;
+ drawIcon(icon_num, 80, 8, 0xA);
+ uint8_t txt_num = pge->init_PGE->text_num;
+ const char *str = (const char *)_res._tbn + READ_LE_UINT16(_res._tbn + txt_num * 2);
+ _vid.drawString(str, (176 - strlen(str) * 8) / 2, 26, 0xE6);
+ if (icon_num == 2) {
+ printSaveStateCompleted();
+ return;
+ }
+ } else {
+ _currentInventoryIconNum = obj - 1;
+ }
+ }
+ _saveStateCompleted = false;
+}
+
+void Game::drawStoryTexts() {
+ if (_textToDisplay != 0xFFFF) {
+ uint16_t text_col_mask = 0xE8;
+ const uint8_t *str = _res.getGameString(_textToDisplay);
+ memcpy(_vid._tempLayer, _vid._frontLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ int textSpeechSegment = 0;
+ while (!_stub->_pi.quit) {
+ drawIcon(_currentInventoryIconNum, 80, 8, 0xA);
+ if (*str == 0xFF) {
+ text_col_mask = READ_LE_UINT16(str + 1);
+ str += 3;
+ }
+ int16_t text_y_pos = 26;
+ while (1) {
+ uint16_t len = getLineLength(str);
+ str = (const uint8_t *)_vid.drawString((const char *)str, (176 - len * 8) / 2, text_y_pos, text_col_mask);
+ text_y_pos += 8;
+ if (*str == 0 || *str == 0xB) {
+ break;
+ }
+ ++str;
+ }
+ MixerChunk chunk;
+ _res.load_VCE(_textToDisplay, textSpeechSegment++, &chunk.data, &chunk.len);
+ if (chunk.data) {
+ _mix.play(&chunk, 32000, Mixer::MAX_VOLUME);
+ }
+ _vid.updateScreen();
+ while (!_stub->_pi.backspace && !_stub->_pi.quit) {
+ if (chunk.data && !_mix.isPlaying(&chunk)) {
+ break;
+ }
+ inp_update();
+ _stub->sleep(80);
+ }
+ if (chunk.data) {
+ _mix.stopAll();
+ free(chunk.data);
+ }
+ _stub->_pi.backspace = false;
+ if (*str == 0) {
+ break;
+ }
+ ++str;
+ memcpy(_vid._frontLayer, _vid._tempLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ }
+ _textToDisplay = 0xFFFF;
+ }
+}
+
+void Game::prepareAnims() {
+ if (!(_currentRoom & 0x80) && _currentRoom < 0x40) {
+ int8_t pge_room;
+ LivePGE *pge = _pge_liveTable1[_currentRoom];
+ while (pge) {
+ prepareAnimsHelper(pge, 0, 0);
+ pge = pge->next_PGE_in_room;
+ }
+ pge_room = _res._ctData[CT_UP_ROOM + _currentRoom];
+ if (pge_room >= 0 && pge_room < 0x40) {
+ pge = _pge_liveTable1[pge_room];
+ while (pge) {
+ if ((pge->init_PGE->object_type != 10 && pge->pos_y > 176) || (pge->init_PGE->object_type == 10 && pge->pos_y > 216)) {
+ prepareAnimsHelper(pge, 0, -216);
+ }
+ pge = pge->next_PGE_in_room;
+ }
+ }
+ pge_room = _res._ctData[CT_DOWN_ROOM + _currentRoom];
+ if (pge_room >= 0 && pge_room < 0x40) {
+ pge = _pge_liveTable1[pge_room];
+ while (pge) {
+ if (pge->pos_y < 48) {
+ prepareAnimsHelper(pge, 0, 216);
+ }
+ pge = pge->next_PGE_in_room;
+ }
+ }
+ pge_room = _res._ctData[CT_LEFT_ROOM + _currentRoom];
+ if (pge_room >= 0 && pge_room < 0x40) {
+ pge = _pge_liveTable1[pge_room];
+ while (pge) {
+ if (pge->pos_x > 224) {
+ prepareAnimsHelper(pge, -256, 0);
+ }
+ pge = pge->next_PGE_in_room;
+ }
+ }
+ pge_room = _res._ctData[CT_RIGHT_ROOM + _currentRoom];
+ if (pge_room >= 0 && pge_room < 0x40) {
+ pge = _pge_liveTable1[pge_room];
+ while (pge) {
+ if (pge->pos_x <= 32) {
+ prepareAnimsHelper(pge, 256, 0);
+ }
+ pge = pge->next_PGE_in_room;
+ }
+ }
+ }
+}
+
+void Game::prepareAnimsHelper(LivePGE *pge, int16_t dx, int16_t dy) {
+ debug(DBG_GAME, "Game::prepareAnimsHelper() dx=0x%X dy=0x%X pge_num=%d pge->flags=0x%X pge->anim_number=0x%X", dx, dy, pge - &_pgeLive[0], pge->flags, pge->anim_number);
+ if (!(pge->flags & 8)) {
+ if (pge->index != 0 && loadMonsterSprites(pge) == 0) {
+ return;
+ }
+ assert(pge->anim_number < 1287);
+ const uint8_t *dataPtr = _res._sprData[pge->anim_number];
+ if (dataPtr == 0) {
+ return;
+ }
+ const int8_t dw = (int8_t)dataPtr[0];
+ const int8_t dh = (int8_t)dataPtr[1];
+ uint8_t w = 0, h = 0;
+ switch (_res._type) {
+ case kResourceTypeAmiga:
+ w = ((dataPtr[2] >> 7) + 1) * 16;
+ h = dataPtr[2] & 0x7F;
+ break;
+ case kResourceTypePC:
+ w = dataPtr[2];
+ h = dataPtr[3];
+ dataPtr += 4;
+ break;
+ }
+ const int16_t ypos = dy + pge->pos_y - dh + 2;
+ int16_t xpos = dx + pge->pos_x - dw;
+ if (pge->flags & 2) {
+ xpos = dw + dx + pge->pos_x;
+ uint8_t _cl = w;
+ if (_cl & 0x40) {
+ _cl = h;
+ } else {
+ _cl &= 0x3F;
+ }
+ xpos -= _cl;
+ }
+ if (xpos <= -32 || xpos >= 256 || ypos < -48 || ypos >= 224) {
+ return;
+ }
+ xpos += 8;
+ if (pge == &_pgeLive[0]) {
+ _animBuffers.addState(1, xpos, ypos, dataPtr, pge, w, h);
+ } else if (pge->flags & 0x10) {
+ _animBuffers.addState(2, xpos, ypos, dataPtr, pge, w, h);
+ } else {
+ _animBuffers.addState(0, xpos, ypos, dataPtr, pge, w, h);
+ }
+ } else {
+ assert(pge->anim_number < _res._numSpc);
+ const uint8_t *dataPtr = _res._spc + READ_BE_UINT16(_res._spc + pge->anim_number * 2);
+ const int16_t xpos = dx + pge->pos_x + 8;
+ const int16_t ypos = dy + pge->pos_y + 2;
+ if (pge->init_PGE->object_type == 11) {
+ _animBuffers.addState(3, xpos, ypos, dataPtr, pge);
+ } else if (pge->flags & 0x10) {
+ _animBuffers.addState(2, xpos, ypos, dataPtr, pge);
+ } else {
+ _animBuffers.addState(0, xpos, ypos, dataPtr, pge);
+ }
+ }
+}
+
+void Game::drawAnims() {
+ debug(DBG_GAME, "Game::drawAnims()");
+ _eraseBackground = false;
+ drawAnimBuffer(2, _animBuffer2State);
+ drawAnimBuffer(1, _animBuffer1State);
+ drawAnimBuffer(0, _animBuffer0State);
+ _eraseBackground = true;
+ drawAnimBuffer(3, _animBuffer3State);
+}
+
+void Game::drawAnimBuffer(uint8_t stateNum, AnimBufferState *state) {
+ debug(DBG_GAME, "Game::drawAnimBuffer() state=%d", stateNum);
+ assert(stateNum < 4);
+ _animBuffers._states[stateNum] = state;
+ uint8_t lastPos = _animBuffers._curPos[stateNum];
+ if (lastPos != 0xFF) {
+ uint8_t numAnims = lastPos + 1;
+ state += lastPos;
+ _animBuffers._curPos[stateNum] = 0xFF;
+ do {
+ LivePGE *pge = state->pge;
+ if (!(pge->flags & 8)) {
+ if (stateNum == 1 && (_blinkingConradCounter & 1)) {
+ break;
+ }
+ switch (_res._type) {
+ case kResourceTypeAmiga:
+ _vid.AMIGA_decodeSpm(state->dataPtr, _res._memBuf);
+ drawCharacter(_res._memBuf, state->x, state->y, state->h, state->w, pge->flags);
+ break;
+ case kResourceTypePC:
+ if (!(state->dataPtr[-2] & 0x80)) {
+ decodeCharacterFrame(state->dataPtr, _res._memBuf);
+ drawCharacter(_res._memBuf, state->x, state->y, state->h, state->w, pge->flags);
+ } else {
+ drawCharacter(state->dataPtr, state->x, state->y, state->h, state->w, pge->flags);
+ }
+ break;
+ }
+ } else {
+ drawObject(state->dataPtr, state->x, state->y, pge->flags);
+ }
+ --state;
+ } while (--numAnims != 0);
+ }
+}
+
+void Game::drawObject(const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t flags) {
+ debug(DBG_GAME, "Game::drawObject() dataPtr[]=0x%X dx=%d dy=%d", dataPtr[0], (int8_t)dataPtr[1], (int8_t)dataPtr[2]);
+ assert(dataPtr[0] < 0x4A);
+ uint8_t slot = _res._rp[dataPtr[0]];
+ uint8_t *data = _res.findBankData(slot);
+ if (data == 0) {
+ data = _res.loadBankData(slot);
+ }
+ int16_t posy = y - (int8_t)dataPtr[2];
+ int16_t posx = x;
+ if (flags & 2) {
+ posx += (int8_t)dataPtr[1];
+ } else {
+ posx -= (int8_t)dataPtr[1];
+ }
+ int count = 0;
+ switch (_res._type) {
+ case kResourceTypeAmiga:
+ count = dataPtr[8];
+ dataPtr += 9;
+ break;
+ case kResourceTypePC:
+ count = dataPtr[5];
+ dataPtr += 6;
+ break;
+ }
+ for (int i = 0; i < count; ++i) {
+ drawObjectFrame(data, dataPtr, posx, posy, flags);
+ dataPtr += 4;
+ }
+}
+
+void Game::drawObjectFrame(const uint8_t *bankDataPtr, const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t flags) {
+ debug(DBG_GAME, "Game::drawObjectFrame(0x%X, %d, %d, 0x%X)", dataPtr, x, y, flags);
+ const uint8_t *src = bankDataPtr + dataPtr[0] * 32;
+
+ int16_t sprite_y = y + dataPtr[2];
+ int16_t sprite_x;
+ if (flags & 2) {
+ sprite_x = x - dataPtr[1] - (((dataPtr[3] & 0xC) + 4) * 2);
+ } else {
+ sprite_x = x + dataPtr[1];
+ }
+
+ uint8_t sprite_flags = dataPtr[3];
+ if (flags & 2) {
+ sprite_flags ^= 0x10;
+ }
+
+ uint8_t sprite_h = (((sprite_flags >> 0) & 3) + 1) * 8;
+ uint8_t sprite_w = (((sprite_flags >> 2) & 3) + 1) * 8;
+
+ switch (_res._type) {
+ case kResourceTypeAmiga:
+ if (sprite_w == 24) {
+ // TODO: fix p24xN
+ return;
+ }
+ _vid.AMIGA_decodeSpc(src, sprite_w, sprite_h, _res._memBuf);
+ break;
+ case kResourceTypePC:
+ _vid.PC_decodeSpc(src, sprite_w, sprite_h, _res._memBuf);
+ break;
+ }
+
+ src = _res._memBuf;
+ bool sprite_mirror_x = false;
+ int16_t sprite_clipped_w;
+ if (sprite_x >= 0) {
+ sprite_clipped_w = sprite_x + sprite_w;
+ if (sprite_clipped_w < 256) {
+ sprite_clipped_w = sprite_w;
+ } else {
+ sprite_clipped_w = 256 - sprite_x;
+ if (sprite_flags & 0x10) {
+ sprite_mirror_x = true;
+ src += sprite_w - 1;
+ }
+ }
+ } else {
+ sprite_clipped_w = sprite_x + sprite_w;
+ if (!(sprite_flags & 0x10)) {
+ src -= sprite_x;
+ sprite_x = 0;
+ } else {
+ sprite_mirror_x = true;
+ src += sprite_x + sprite_w - 1;
+ sprite_x = 0;
+ }
+ }
+ if (sprite_clipped_w <= 0) {
+ return;
+ }
+
+ int16_t sprite_clipped_h;
+ if (sprite_y >= 0) {
+ sprite_clipped_h = 224 - sprite_h;
+ if (sprite_y < sprite_clipped_h) {
+ sprite_clipped_h = sprite_h;
+ } else {
+ sprite_clipped_h = 224 - sprite_y;
+ }
+ } else {
+ sprite_clipped_h = sprite_h + sprite_y;
+ src -= sprite_w * sprite_y;
+ sprite_y = 0;
+ }
+ if (sprite_clipped_h <= 0) {
+ return;
+ }
+
+ if (!sprite_mirror_x && (sprite_flags & 0x10)) {
+ src += sprite_w - 1;
+ }
+
+ uint32_t dst_offset = 256 * sprite_y + sprite_x;
+ uint8_t sprite_col_mask = (flags & 0x60) >> 1;
+
+ if (_eraseBackground) {
+ if (!(sprite_flags & 0x10)) {
+ _vid.drawSpriteSub1(src, _vid._frontLayer + dst_offset, sprite_w, sprite_clipped_h, sprite_clipped_w, sprite_col_mask);
+ } else {
+ _vid.drawSpriteSub2(src, _vid._frontLayer + dst_offset, sprite_w, sprite_clipped_h, sprite_clipped_w, sprite_col_mask);
+ }
+ } else {
+ if (!(sprite_flags & 0x10)) {
+ _vid.drawSpriteSub3(src, _vid._frontLayer + dst_offset, sprite_w, sprite_clipped_h, sprite_clipped_w, sprite_col_mask);
+ } else {
+ _vid.drawSpriteSub4(src, _vid._frontLayer + dst_offset, sprite_w, sprite_clipped_h, sprite_clipped_w, sprite_col_mask);
+ }
+ }
+ _vid.markBlockAsDirty(sprite_x, sprite_y, sprite_clipped_w, sprite_clipped_h);
+}
+
+void Game::decodeCharacterFrame(const uint8_t *dataPtr, uint8_t *dstPtr) {
+ int n = READ_BE_UINT16(dataPtr); dataPtr += 2;
+ uint16_t len = n * 2;
+ uint8_t *dst = dstPtr + 0x400;
+ while (n--) {
+ uint8_t c = *dataPtr++;
+ dst[0] = (c & 0xF0) >> 4;
+ dst[1] = (c & 0x0F) >> 0;
+ dst += 2;
+ }
+ dst = dstPtr;
+ const uint8_t *src = dstPtr + 0x400;
+ do {
+ uint8_t c1 = *src++;
+ if (c1 == 0xF) {
+ uint8_t c2 = *src++;
+ uint16_t c3 = *src++;
+ if (c2 == 0xF) {
+ c1 = *src++;
+ c2 = *src++;
+ c3 = (c3 << 4) | c1;
+ len -= 2;
+ }
+ memset(dst, c2, c3 + 4);
+ dst += c3 + 4;
+ len -= 3;
+ } else {
+ *dst++ = c1;
+ --len;
+ }
+ } while (len != 0);
+}
+
+void Game::drawCharacter(const uint8_t *dataPtr, int16_t pos_x, int16_t pos_y, uint8_t a, uint8_t b, uint8_t flags) {
+ debug(DBG_GAME, "Game::drawCharacter(0x%X, %d, %d, 0x%X, 0x%X, 0x%X)", dataPtr, pos_x, pos_y, a, b, flags);
+
+ bool var16 = false; // sprite_mirror_y
+ if (b & 0x40) {
+ b &= 0xBF;
+ SWAP(a, b);
+ var16 = true;
+ }
+ uint16_t sprite_h = a;
+ uint16_t sprite_w = b;
+
+ const uint8_t *src = dataPtr;
+ bool var14 = false;
+
+ int16_t sprite_clipped_w;
+ if (pos_x >= 0) {
+ if (pos_x + sprite_w < 256) {
+ sprite_clipped_w = sprite_w;
+ } else {
+ sprite_clipped_w = 256 - pos_x;
+ if (flags & 2) {
+ var14 = true;
+ if (var16) {
+ src += (sprite_w - 1) * sprite_h;
+ } else {
+ src += sprite_w - 1;
+ }
+ }
+ }
+ } else {
+ sprite_clipped_w = pos_x + sprite_w;
+ if (!(flags & 2)) {
+ if (var16) {
+ src -= sprite_h * pos_x;
+ pos_x = 0;
+ } else {
+ src -= pos_x;
+ pos_x = 0;
+ }
+ } else {
+ var14 = true;
+ if (var16) {
+ src += sprite_h * (pos_x + sprite_w - 1);
+ pos_x = 0;
+ } else {
+ src += pos_x + sprite_w - 1;
+ var14 = true;
+ pos_x = 0;
+ }
+ }
+ }
+ if (sprite_clipped_w <= 0) {
+ return;
+ }
+
+ int16_t sprite_clipped_h;
+ if (pos_y >= 0) {
+ if (pos_y < 224 - sprite_h) {
+ sprite_clipped_h = sprite_h;
+ } else {
+ sprite_clipped_h = 224 - pos_y;
+ }
+ } else {
+ sprite_clipped_h = sprite_h + pos_y;
+ if (var16) {
+ src -= pos_y;
+ } else {
+ src -= sprite_w * pos_y;
+ }
+ pos_y = 0;
+ }
+ if (sprite_clipped_h <= 0) {
+ return;
+ }
+
+ if (!var14 && (flags & 2)) {
+ if (var16) {
+ src += sprite_h * (sprite_w - 1);
+ } else {
+ src += sprite_w - 1;
+ }
+ }
+
+ uint32_t dst_offset = 256 * pos_y + pos_x;
+ uint8_t sprite_col_mask = ((flags & 0x60) == 0x60) ? 0x50 : 0x40;
+
+ debug(DBG_GAME, "dst_offset=0x%X src_offset=0x%X", dst_offset, src - dataPtr);
+
+ if (!(flags & 2)) {
+ if (var16) {
+ _vid.drawSpriteSub5(src, _vid._frontLayer + dst_offset, sprite_h, sprite_clipped_h, sprite_clipped_w, sprite_col_mask);
+ } else {
+ _vid.drawSpriteSub3(src, _vid._frontLayer + dst_offset, sprite_w, sprite_clipped_h, sprite_clipped_w, sprite_col_mask);
+ }
+ } else {
+ if (var16) {
+ _vid.drawSpriteSub6(src, _vid._frontLayer + dst_offset, sprite_h, sprite_clipped_h, sprite_clipped_w, sprite_col_mask);
+ } else {
+ _vid.drawSpriteSub4(src, _vid._frontLayer + dst_offset, sprite_w, sprite_clipped_h, sprite_clipped_w, sprite_col_mask);
+ }
+ }
+ _vid.markBlockAsDirty(pos_x, pos_y, sprite_clipped_w, sprite_clipped_h);
+}
+
+int Game::loadMonsterSprites(LivePGE *pge) {
+ debug(DBG_GAME, "Game::loadMonsterSprites()");
+ InitPGE *init_pge = pge->init_PGE;
+ if (init_pge->obj_node_number != 0x49 && init_pge->object_type != 10) {
+ return 0xFFFF;
+ }
+ if (init_pge->obj_node_number == _curMonsterFrame) {
+ return 0xFFFF;
+ }
+ if (pge->room_location != _currentRoom) {
+ return 0;
+ }
+
+ const uint8_t *mList = _monsterListLevels[_currentLevel];
+ while (*mList != init_pge->obj_node_number) {
+ if (*mList == 0xFF) { // end of list
+ return 0;
+ }
+ mList += 2;
+ }
+ _curMonsterFrame = mList[0];
+ if (_curMonsterNum != mList[1]) {
+ _curMonsterNum = mList[1];
+ if (_res._type == kResourceTypeAmiga) {
+ _res.load(_monsterNames[1][_curMonsterNum], Resource::OT_SPM);
+ static const uint8_t tab[4] = { 0, 8, 0, 8 };
+ const int offset = _vid._mapPalSlot2 * 16 + tab[_curMonsterNum];
+ for (int i = 0; i < 8; ++i) {
+ _vid.setPaletteColorBE(0x50 + i, offset + i);
+ }
+ } else {
+ const char *name = _monsterNames[0][_curMonsterNum];
+ _res.load(name, Resource::OT_SPRM);
+ _res.load_SPR_OFF(name, _res._sprm);
+ _vid.setPaletteSlotLE(5, _monsterPals[_curMonsterNum]);
+ }
+ }
+ return 0xFFFF;
+}
+
+void Game::loadLevelMap() {
+ debug(DBG_GAME, "Game::loadLevelMap() room=%d", _currentRoom);
+ _currentIcon = 0xFF;
+ switch (_res._type) {
+ case kResourceTypeAmiga:
+ if (_currentLevel == 1) {
+ static const uint8_t tab[64] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 2, 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, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
+ };
+ const int num = tab[_currentRoom];
+ if (num != 0 && _res._levNum != num) {
+ char name[8];
+ snprintf(name, sizeof(name), "level2_%d", num);
+ _res.load(name, Resource::OT_LEV);
+ _res._levNum = num;
+ }
+ }
+ _vid.AMIGA_decodeLev(_currentLevel, _currentRoom);
+ break;
+ case kResourceTypePC:
+ _vid.PC_decodeMap(_currentLevel, _currentRoom);
+ _vid.PC_setLevelPalettes();
+ break;
+ }
+}
+
+void Game::loadLevelData() {
+ _res.clearLevelRes();
+ const Level *lvl = &_gameLevels[_currentLevel];
+ switch (_res._type) {
+ case kResourceTypeAmiga:
+ if (_fs->exists("demo.lev")) { // demo data files
+ Cutscene::_namesTable[1] = "HOLOCUBE";
+ Cutscene::_namesTable[4] = "CHUTE2";
+ static const char *fname1 = "demo";
+ static const char *fname2 = "demof";
+ _res.load(fname1, Resource::OT_MBK);
+ _res.load(fname1, Resource::OT_CT);
+ _res.load(fname1, Resource::OT_PAL);
+ _res.load(fname1, Resource::OT_RPC);
+ _res.load(fname1, Resource::OT_SPC);
+ _res.load(fname1, Resource::OT_LEV);
+ _res.load(fname2, Resource::OT_PGE);
+ _res.load(fname1, Resource::OT_OBJ);
+ _res.load(fname1, Resource::OT_ANI);
+ _res.load(fname2, Resource::OT_TBN);
+ _res.load_SPL_demo();
+ _res.load("level1", Resource::OT_SGD);
+ break;
+ }
+ {
+ const char *name = lvl->nameAmiga;
+ if (_currentLevel == 4) {
+ name = _gameLevels[3].nameAmiga;
+ }
+ _res.load(name, Resource::OT_MBK);
+ if (_currentLevel == 6) {
+ _res.load(_gameLevels[5].nameAmiga, Resource::OT_CT);
+ } else {
+ _res.load(name, Resource::OT_CT);
+ }
+ _res.load(name, Resource::OT_PAL);
+ _res.load(name, Resource::OT_RPC);
+ _res.load(name, Resource::OT_SPC);
+ if (_currentLevel == 1) {
+ _res.load("level2_1", Resource::OT_LEV);
+ _res._levNum = 1;
+ } else {
+ _res.load(name, Resource::OT_LEV);
+ }
+ }
+ _res.load(lvl->nameAmiga, Resource::OT_PGE);
+ _res.load(lvl->nameAmiga, Resource::OT_OBC);
+ _res.load(lvl->nameAmiga, Resource::OT_ANI);
+ _res.load(lvl->nameAmiga, Resource::OT_TBN);
+ {
+ char name[8];
+ snprintf(name, sizeof(name), "level%d", lvl->sound);
+ _res.load(name, Resource::OT_SPL);
+ }
+ if (_currentLevel == 0) {
+ _res.load(lvl->nameAmiga, Resource::OT_SGD);
+ }
+ break;
+ case kResourceTypePC:
+ _res.load(lvl->name, Resource::OT_MBK);
+ _res.load(lvl->name, Resource::OT_CT);
+ _res.load(lvl->name, Resource::OT_PAL);
+ _res.load(lvl->name, Resource::OT_RP);
+ _res.load(lvl->name, Resource::OT_MAP);
+ _res.load(lvl->name2, Resource::OT_PGE);
+ _res.load(lvl->name2, Resource::OT_OBJ);
+ _res.load(lvl->name2, Resource::OT_ANI);
+ _res.load(lvl->name2, Resource::OT_TBN);
+ break;
+ }
+
+ _cut._id = lvl->cutscene_id;
+
+ _curMonsterNum = 0xFFFF;
+ _curMonsterFrame = 0;
+
+ _res.clearBankData();
+ _printLevelCodeCounter = 150;
+
+ _col_slots2Cur = _col_slots2;
+ _col_slots2Next = 0;
+
+ memset(_pge_liveTable2, 0, sizeof(_pge_liveTable2));
+ memset(_pge_liveTable1, 0, sizeof(_pge_liveTable1));
+
+ _currentRoom = _res._pgeInit[0].init_room;
+ uint16_t n = _res._pgeNum;
+ while (n--) {
+ pge_loadForCurrentLevel(n);
+ }
+
+ for (uint16_t i = 0; i < _res._pgeNum; ++i) {
+ if (_res._pgeInit[i].skill <= _skillLevel) {
+ LivePGE *pge = &_pgeLive[i];
+ pge->next_PGE_in_room = _pge_liveTable1[pge->room_location];
+ _pge_liveTable1[pge->room_location] = pge;
+ }
+ }
+ pge_resetGroups();
+ _validSaveState = false;
+
+ _mix.playMusic(Mixer::MUSIC_TRACK + lvl->track);
+}
+
+void Game::drawIcon(uint8_t iconNum, int16_t x, int16_t y, uint8_t colMask) {
+ uint8_t buf[16 * 16];
+ switch (_res._type) {
+ case kResourceTypeAmiga:
+ if (iconNum > 30) {
+ // inventory icons
+ switch (iconNum) {
+ case 76: // cursor
+ memset(buf, 0, 16 * 16);
+ for (int i = 0; i < 3; ++i) {
+ buf[i] = buf[15 * 16 + (15 - i)] = 1;
+ buf[i * 16] = buf[(15 - i) * 16 + 15] = 1;
+ }
+ break;
+ case 77: // up - icon.spr 4
+ memset(buf, 0, 16 * 16);
+ _vid.AMIGA_decodeIcn(_res._icn, 35, buf);
+ break;
+ case 78: // down - icon.spr 5
+ memset(buf, 0, 16 * 16);
+ _vid.AMIGA_decodeIcn(_res._icn, 36, buf);
+ break;
+ default:
+ memset(buf, 5, 16 * 16);
+ break;
+ }
+ } else {
+ _vid.AMIGA_decodeIcn(_res._icn, iconNum, buf);
+ }
+ break;
+ case kResourceTypePC:
+ _vid.PC_decodeIcn(_res._icn, iconNum, buf);
+ break;
+ }
+ _vid.drawSpriteSub1(buf, _vid._frontLayer + x + y * 256, 16, 16, 16, colMask << 4);
+ _vid.markBlockAsDirty(x, y, 16, 16);
+}
+
+void Game::playSound(uint8_t sfxId, uint8_t softVol) {
+ if (sfxId < _res._numSfx) {
+ SoundFx *sfx = &_res._sfxList[sfxId];
+ if (sfx->data) {
+ MixerChunk mc;
+ mc.data = sfx->data;
+ mc.len = sfx->len;
+ const int freq = _res._type == kResourceTypeAmiga ? 3546897 / 650 : 6000;
+ _mix.play(&mc, freq, Mixer::MAX_VOLUME >> softVol);
+ }
+ } else {
+ // in-game music
+ _mix.playMusic(sfxId);
+ }
+}
+
+uint16_t Game::getRandomNumber() {
+ uint32_t n = _randSeed * 2;
+ if (_randSeed > n) {
+ n ^= 0x1D872B41;
+ }
+ _randSeed = n;
+ return n & 0xFFFF;
+}
+
+void Game::changeLevel() {
+ _vid.fadeOut();
+ loadLevelData();
+ loadLevelMap();
+ _vid.setPalette0xF();
+ _vid.setTextPalette();
+ _vid.fullRefresh();
+}
+
+uint16_t Game::getLineLength(const uint8_t *str) const {
+ uint16_t len = 0;
+ while (*str && *str != 0xB && *str != 0xA) {
+ ++str;
+ ++len;
+ }
+ return len;
+}
+
+void Game::handleInventory() {
+ LivePGE *selected_pge = 0;
+ LivePGE *pge = &_pgeLive[0];
+ if (pge->life > 0 && pge->current_inventory_PGE != 0xFF) {
+ playSound(66, 0);
+ InventoryItem items[24];
+ int num_items = 0;
+ uint8_t inv_pge = pge->current_inventory_PGE;
+ while (inv_pge != 0xFF) {
+ items[num_items].icon_num = _res._pgeInit[inv_pge].icon_num;
+ items[num_items].init_pge = &_res._pgeInit[inv_pge];
+ items[num_items].live_pge = &_pgeLive[inv_pge];
+ inv_pge = _pgeLive[inv_pge].next_inventory_PGE;
+ ++num_items;
+ }
+ items[num_items].icon_num = 0xFF;
+ int current_item = 0;
+ int num_lines = (num_items - 1) / 4 + 1;
+ int current_line = 0;
+ bool display_score = false;
+ while (!_stub->_pi.backspace && !_stub->_pi.quit) {
+ // draw inventory background
+ int icon_h = 5;
+ int icon_y = 140;
+ int icon_num = 31;
+ do {
+ int icon_x = 56;
+ int icon_w = 9;
+ do {
+ drawIcon(icon_num, icon_x, icon_y, 0xF);
+ ++icon_num;
+ icon_x += 16;
+ } while (--icon_w);
+ icon_y += 16;
+ } while (--icon_h);
+
+ if (!display_score) {
+ int icon_x_pos = 72;
+ for (int i = 0; i < 4; ++i) {
+ int item_it = current_line * 4 + i;
+ if (items[item_it].icon_num == 0xFF) {
+ break;
+ }
+ drawIcon(items[item_it].icon_num, icon_x_pos, 157, 0xA);
+ if (current_item == item_it) {
+ drawIcon(76, icon_x_pos, 157, 0xA);
+ selected_pge = items[item_it].live_pge;
+ uint8_t txt_num = items[item_it].init_pge->text_num;
+ const char *str = (const char *)_res._tbn + READ_LE_UINT16(_res._tbn + txt_num * 2);
+ _vid.drawString(str, (256 - strlen(str) * 8) / 2, 189, 0xED);
+ if (items[item_it].init_pge->init_flags & 4) {
+ char buf[10];
+ snprintf(buf, sizeof(buf), "%d", selected_pge->life);
+ _vid.drawString(buf, (256 - strlen(buf) * 8) / 2, 197, 0xED);
+ }
+ }
+ icon_x_pos += 32;
+ }
+ if (current_line != 0) {
+ drawIcon(78, 120, 176, 0xA); // down arrow
+ }
+ if (current_line != num_lines - 1) {
+ drawIcon(77, 120, 143, 0xA); // up arrow
+ }
+ } else {
+ char buf[50];
+ snprintf(buf, sizeof(buf), "SCORE %08u", _score);
+ _vid.drawString(buf, (114 - strlen(buf) * 8) / 2 + 72, 158, 0xE5);
+ snprintf(buf, sizeof(buf), "%s:%s", _res.getMenuString(LocaleData::LI_06_LEVEL), _res.getMenuString(LocaleData::LI_13_EASY + _skillLevel));
+ _vid.drawString(buf, (114 - strlen(buf) * 8) / 2 + 72, 166, 0xE5);
+ }
+
+ _vid.updateScreen();
+ _stub->sleep(80);
+ inp_update();
+
+ if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
+ if (current_line < num_lines - 1) {
+ ++current_line;
+ current_item = current_line * 4;
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
+ if (current_line > 0) {
+ --current_line;
+ current_item = current_line * 4;
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_LEFT) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_LEFT;
+ if (current_item > 0) {
+ int item_num = current_item % 4;
+ if (item_num > 0) {
+ --current_item;
+ }
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_RIGHT) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
+ if (current_item < num_items - 1) {
+ int item_num = current_item % 4;
+ if (item_num < 3) {
+ ++current_item;
+ }
+ }
+ }
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ display_score = !display_score;
+ }
+ }
+ _vid.fullRefresh();
+ _stub->_pi.backspace = false;
+ if (selected_pge) {
+ pge_setCurrentInventoryObject(selected_pge);
+ }
+ playSound(66, 0);
+ }
+}
+
+void Game::inp_update() {
+ if (_inp_replay && _inp_demo) {
+ uint8_t keymask = _inp_demo->readByte();
+ if (_inp_demo->ioErr()) {
+ _inp_replay = false;
+ } else {
+ _stub->_pi.dirMask = keymask & 0xF;
+ _stub->_pi.enter = (keymask & 0x10) != 0;
+ _stub->_pi.space = (keymask & 0x20) != 0;
+ _stub->_pi.shift = (keymask & 0x40) != 0;
+ _stub->_pi.quit = (keymask & 0x80) != 0;
+ }
+ }
+ _stub->processEvents();
+ if (_inp_record && _inp_demo) {
+ uint8_t keymask = _stub->_pi.dirMask;
+ if (_stub->_pi.enter) {
+ keymask |= 0x10;
+ }
+ if (_stub->_pi.space) {
+ keymask |= 0x20;
+ }
+ if (_stub->_pi.shift) {
+ keymask |= 0x40;
+ }
+ if (_stub->_pi.quit) {
+ keymask |= 0x80;
+ }
+ _inp_demo->writeByte(keymask);
+ if (_inp_demo->ioErr()) {
+ _inp_record = false;
+ }
+ }
+}
+
+void Game::makeGameDemoName(char *buf) {
+ sprintf(buf, "rs-level%d.demo", _currentLevel + 1);
+}
+
+void Game::makeGameStateName(uint8_t slot, char *buf) {
+ sprintf(buf, "rs-level%d-%02d.state", _currentLevel + 1, slot);
+}
+
+bool Game::saveGameState(uint8_t slot) {
+ bool success = false;
+ char stateFile[20];
+ makeGameStateName(slot, stateFile);
+ File f;
+ if (!f.open(stateFile, "zwb", _savePath)) {
+ warning("Unable to save state file '%s'", stateFile);
+ } else {
+ // header
+ f.writeUint32BE('FBSV');
+ f.writeUint16BE(2);
+ char buf[32];
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, sizeof(buf), "level=%d room=%d", _currentLevel + 1, _currentRoom);
+ f.write(buf, sizeof(buf));
+ // contents
+ saveState(&f);
+ if (f.ioErr()) {
+ warning("I/O error when saving game state");
+ } else {
+ debug(DBG_INFO, "Saved state to slot %d", slot);
+ success = true;
+ }
+ }
+ return success;
+}
+
+bool Game::loadGameState(uint8_t slot) {
+ bool success = false;
+ char stateFile[20];
+ makeGameStateName(slot, stateFile);
+ File f;
+ if (!f.open(stateFile, "zrb", _savePath)) {
+ warning("Unable to open state file '%s'", stateFile);
+ } else {
+ uint32_t id = f.readUint32BE();
+ if (id != 'FBSV') {
+ warning("Bad save state format");
+ } else {
+ uint16_t ver = f.readUint16BE();
+ if (ver != 2) {
+ warning("Invalid save state version");
+ } else {
+ // header
+ char buf[32];
+ f.read(buf, sizeof(buf));
+ // contents
+ loadState(&f);
+ if (f.ioErr()) {
+ warning("I/O error when loading game state");
+ } else {
+ debug(DBG_INFO, "Loaded state from slot %d", slot);
+ success = true;
+ }
+ }
+ }
+ }
+ return success;
+}
+
+void Game::saveState(File *f) {
+ f->writeByte(_skillLevel);
+ f->writeUint32BE(_score);
+ if (_col_slots2Cur == 0) {
+ f->writeUint32BE(0xFFFFFFFF);
+ } else {
+ f->writeUint32BE(_col_slots2Cur - &_col_slots2[0]);
+ }
+ if (_col_slots2Next == 0) {
+ f->writeUint32BE(0xFFFFFFFF);
+ } else {
+ f->writeUint32BE(_col_slots2Next - &_col_slots2[0]);
+ }
+ for (int i = 0; i < _res._pgeNum; ++i) {
+ LivePGE *pge = &_pgeLive[i];
+ f->writeUint16BE(pge->obj_type);
+ f->writeUint16BE(pge->pos_x);
+ f->writeUint16BE(pge->pos_y);
+ f->writeByte(pge->anim_seq);
+ f->writeByte(pge->room_location);
+ f->writeUint16BE(pge->life);
+ f->writeUint16BE(pge->counter_value);
+ f->writeByte(pge->collision_slot);
+ f->writeByte(pge->next_inventory_PGE);
+ f->writeByte(pge->current_inventory_PGE);
+ f->writeByte(pge->unkF);
+ f->writeUint16BE(pge->anim_number);
+ f->writeByte(pge->flags);
+ f->writeByte(pge->index);
+ f->writeUint16BE(pge->first_obj_number);
+ if (pge->next_PGE_in_room == 0) {
+ f->writeUint32BE(0xFFFFFFFF);
+ } else {
+ f->writeUint32BE(pge->next_PGE_in_room - &_pgeLive[0]);
+ }
+ if (pge->init_PGE == 0) {
+ f->writeUint32BE(0xFFFFFFFF);
+ } else {
+ f->writeUint32BE(pge->init_PGE - &_res._pgeInit[0]);
+ }
+ }
+ f->write(&_res._ctData[0x100], 0x1C00);
+ for (CollisionSlot2 *cs2 = &_col_slots2[0]; cs2 < _col_slots2Cur; ++cs2) {
+ if (cs2->next_slot == 0) {
+ f->writeUint32BE(0xFFFFFFFF);
+ } else {
+ f->writeUint32BE(cs2->next_slot - &_col_slots2[0]);
+ }
+ if (cs2->unk2 == 0) {
+ f->writeUint32BE(0xFFFFFFFF);
+ } else {
+ f->writeUint32BE(cs2->unk2 - &_res._ctData[0x100]);
+ }
+ f->writeByte(cs2->data_size);
+ f->write(cs2->data_buf, 0x10);
+ }
+}
+
+void Game::loadState(File *f) {
+ uint16_t i;
+ uint32_t off;
+ _skillLevel = f->readByte();
+ _score = f->readUint32BE();
+ memset(_pge_liveTable2, 0, sizeof(_pge_liveTable2));
+ memset(_pge_liveTable1, 0, sizeof(_pge_liveTable1));
+ off = f->readUint32BE();
+ if (off == 0xFFFFFFFF) {
+ _col_slots2Cur = 0;
+ } else {
+ _col_slots2Cur = &_col_slots2[0] + off;
+ }
+ off = f->readUint32BE();
+ if (off == 0xFFFFFFFF) {
+ _col_slots2Next = 0;
+ } else {
+ _col_slots2Next = &_col_slots2[0] + off;
+ }
+ for (i = 0; i < _res._pgeNum; ++i) {
+ LivePGE *pge = &_pgeLive[i];
+ pge->obj_type = f->readUint16BE();
+ pge->pos_x = f->readUint16BE();
+ pge->pos_y = f->readUint16BE();
+ pge->anim_seq = f->readByte();
+ pge->room_location = f->readByte();
+ pge->life = f->readUint16BE();
+ pge->counter_value = f->readUint16BE();
+ pge->collision_slot = f->readByte();
+ pge->next_inventory_PGE = f->readByte();
+ pge->current_inventory_PGE = f->readByte();
+ pge->unkF = f->readByte();
+ pge->anim_number = f->readUint16BE();
+ pge->flags = f->readByte();
+ pge->index = f->readByte();
+ pge->first_obj_number = f->readUint16BE();
+ off = f->readUint32BE();
+ if (off == 0xFFFFFFFF) {
+ pge->next_PGE_in_room = 0;
+ } else {
+ pge->next_PGE_in_room = &_pgeLive[0] + off;
+ }
+ off = f->readUint32BE();
+ if (off == 0xFFFFFFFF) {
+ pge->init_PGE = 0;
+ } else {
+ pge->init_PGE = &_res._pgeInit[0] + off;
+ }
+ }
+ f->read(&_res._ctData[0x100], 0x1C00);
+ for (CollisionSlot2 *cs2 = &_col_slots2[0]; cs2 < _col_slots2Cur; ++cs2) {
+ off = f->readUint32BE();
+ if (off == 0xFFFFFFFF) {
+ cs2->next_slot = 0;
+ } else {
+ cs2->next_slot = &_col_slots2[0] + off;
+ }
+ off = f->readUint32BE();
+ if (off == 0xFFFFFFFF) {
+ cs2->unk2 = 0;
+ } else {
+ cs2->unk2 = &_res._ctData[0x100] + off;
+ }
+ cs2->data_size = f->readByte();
+ f->read(cs2->data_buf, 0x10);
+ }
+ for (i = 0; i < _res._pgeNum; ++i) {
+ if (_res._pgeInit[i].skill <= _skillLevel) {
+ LivePGE *pge = &_pgeLive[i];
+ if (pge->flags & 4) {
+ _pge_liveTable2[pge->index] = pge;
+ }
+ pge->next_PGE_in_room = _pge_liveTable1[pge->room_location];
+ _pge_liveTable1[pge->room_location] = pge;
+ }
+ }
+ resetGameState();
+}
+
+void AnimBuffers::addState(uint8_t stateNum, int16_t x, int16_t y, const uint8_t *dataPtr, LivePGE *pge, uint8_t w, uint8_t h) {
+ debug(DBG_GAME, "AnimBuffers::addState() stateNum=%d x=%d y=%d dataPtr=0x%X pge=0x%X", stateNum, x, y, dataPtr, pge);
+ assert(stateNum < 4);
+ AnimBufferState *state = _states[stateNum];
+ state->x = x;
+ state->y = y;
+ state->w = w;
+ state->h = h;
+ state->dataPtr = dataPtr;
+ state->pge = pge;
+ ++_curPos[stateNum];
+ ++_states[stateNum];
+}
diff --git a/game.h b/game.h
new file mode 100644
index 0000000..d1c1e5f
--- /dev/null
+++ b/game.h
@@ -0,0 +1,383 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 GAME_H__
+#define GAME_H__
+
+#include "intern.h"
+#include "cutscene.h"
+#include "menu.h"
+#include "mixer.h"
+#include "resource.h"
+#include "seq_player.h"
+#include "video.h"
+
+struct File;
+struct FileSystem;
+struct SystemStub;
+
+struct Game {
+ typedef int (Game::*pge_OpcodeProc)(ObjectOpcodeArgs *args);
+ typedef int (Game::*pge_ZOrderCallback)(LivePGE *, LivePGE *, uint8_t, uint8_t);
+ typedef int (Game::*col_Callback1)(LivePGE *, LivePGE *, int16_t, int16_t);
+ typedef int (Game::*col_Callback2)(LivePGE *, int16_t, int16_t, int16_t);
+
+ enum {
+ CT_UP_ROOM = 0x00,
+ CT_DOWN_ROOM = 0x40,
+ CT_RIGHT_ROOM = 0x80,
+ CT_LEFT_ROOM = 0xC0
+ };
+
+ static const Level _gameLevels[];
+ static const uint16_t _scoreTable[];
+ static const uint8_t _monsterListLevel1[];
+ static const uint8_t _monsterListLevel2[];
+ static const uint8_t _monsterListLevel3[];
+ static const uint8_t _monsterListLevel4_1[];
+ static const uint8_t _monsterListLevel4_2[];
+ static const uint8_t _monsterListLevel5_1[];
+ static const uint8_t _monsterListLevel5_2[];
+ static const uint8_t *_monsterListLevels[];
+ static const uint8_t _monsterPals[4][32];
+ static const char *_monsterNames[2][4];
+ static const pge_OpcodeProc _pge_opcodeTable[];
+ static const uint8_t _pge_modKeysTable[];
+ static const uint8_t _protectionCodeData[];
+ static const uint8_t _protectionPal[];
+
+ Cutscene _cut;
+ Menu _menu;
+ Mixer _mix;
+ Resource _res;
+ SeqPlayer _seq;
+ Video _vid;
+ SystemStub *_stub;
+ FileSystem *_fs;
+ const char *_savePath;
+
+ const uint8_t *_stringsTable;
+ const char **_textsTable;
+ uint8_t _currentLevel;
+ uint8_t _skillLevel;
+ uint32_t _score;
+ uint8_t _currentRoom;
+ uint8_t _currentIcon;
+ bool _loadMap;
+ uint8_t _printLevelCodeCounter;
+ uint32_t _randSeed;
+ uint16_t _currentInventoryIconNum;
+ uint16_t _curMonsterFrame;
+ uint16_t _curMonsterNum;
+ uint8_t _blinkingConradCounter;
+ uint16_t _textToDisplay;
+ bool _eraseBackground;
+ AnimBufferState _animBuffer0State[41];
+ AnimBufferState _animBuffer1State[6]; // Conrad
+ AnimBufferState _animBuffer2State[42];
+ AnimBufferState _animBuffer3State[12];
+ AnimBuffers _animBuffers;
+ uint16_t _deathCutsceneCounter;
+ bool _saveStateCompleted;
+ bool _endLoop;
+
+ Game(SystemStub *, FileSystem *, const char *savePath, int level, ResourceType ver, Language lang);
+
+ void run();
+ void resetGameState();
+ void mainLoop();
+ void updateTiming();
+ void playCutscene(int id = -1);
+ bool playCutsceneSeq(const char *name);
+ void loadLevelMap();
+ void loadLevelData();
+ void drawIcon(uint8_t iconNum, int16_t x, int16_t y, uint8_t colMask);
+ void drawCurrentInventoryItem();
+ void printLevelCode();
+ void showFinalScore();
+ bool handleConfigPanel();
+ bool handleContinueAbort();
+ bool handleProtectionScreen();
+ void printSaveStateCompleted();
+ void drawLevelTexts();
+ void drawStoryTexts();
+ void prepareAnims();
+ void prepareAnimsHelper(LivePGE *pge, int16_t dx, int16_t dy);
+ void drawAnims();
+ void drawAnimBuffer(uint8_t stateNum, AnimBufferState *state);
+ void drawObject(const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t flags);
+ void drawObjectFrame(const uint8_t *bankDataPtr, const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t flags);
+ void decodeCharacterFrame(const uint8_t *dataPtr, uint8_t *dstPtr);
+ void drawCharacter(const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t a, uint8_t b, uint8_t flags);
+ int loadMonsterSprites(LivePGE *pge);
+ void playSound(uint8_t sfxId, uint8_t softVol);
+ uint16_t getRandomNumber();
+ void changeLevel();
+ uint16_t getLineLength(const uint8_t *str) const;
+ void handleInventory();
+
+
+ // pieges
+ bool _pge_playAnimSound;
+ GroupPGE _pge_groups[256];
+ GroupPGE *_pge_groupsTable[256];
+ GroupPGE *_pge_nextFreeGroup;
+ LivePGE *_pge_liveTable2[256]; // active pieges list (index = pge number)
+ LivePGE *_pge_liveTable1[256]; // pieges list by room (index = room)
+ LivePGE _pgeLive[256];
+ uint8_t _pge_currentPiegeRoom;
+ bool _pge_currentPiegeFacingDir; // (false == left)
+ bool _pge_processOBJ;
+ uint8_t _pge_inpKeysMask;
+ uint16_t _pge_opTempVar1;
+ uint16_t _pge_opTempVar2;
+ uint16_t _pge_compareVar1;
+ uint16_t _pge_compareVar2;
+
+ void pge_resetGroups();
+ void pge_removeFromGroup(uint8_t idx);
+ int pge_isInGroup(LivePGE *pge_dst, uint16_t group_id, uint16_t counter);
+ void pge_loadForCurrentLevel(uint16_t idx);
+ void pge_process(LivePGE *pge);
+ void pge_setupNextAnimFrame(LivePGE *pge, GroupPGE *le);
+ void pge_playAnimSound(LivePGE *pge, uint16_t arg2);
+ void pge_setupAnim(LivePGE *pge);
+ int pge_execute(LivePGE *live_pge, InitPGE *init_pge, const Object *obj);
+ void pge_prepare();
+ void pge_setupDefaultAnim(LivePGE *pge);
+ uint16_t pge_processOBJ(LivePGE *pge);
+ void pge_setupOtherPieges(LivePGE *pge, InitPGE *init_pge);
+ void pge_addToCurrentRoomList(LivePGE *pge, uint8_t room);
+ void pge_getInput();
+ int pge_op_isInpUp(ObjectOpcodeArgs *args);
+ int pge_op_isInpBackward(ObjectOpcodeArgs *args);
+ int pge_op_isInpDown(ObjectOpcodeArgs *args);
+ int pge_op_isInpForward(ObjectOpcodeArgs *args);
+ int pge_op_isInpUpMod(ObjectOpcodeArgs *args);
+ int pge_op_isInpBackwardMod(ObjectOpcodeArgs *args);
+ int pge_op_isInpDownMod(ObjectOpcodeArgs *args);
+ int pge_op_isInpForwardMod(ObjectOpcodeArgs *args);
+ int pge_op_isInpIdle(ObjectOpcodeArgs *args);
+ int pge_op_isInpNoMod(ObjectOpcodeArgs *args);
+ int pge_op_getCollision0u(ObjectOpcodeArgs *args);
+ int pge_op_getCollision00(ObjectOpcodeArgs *args);
+ int pge_op_getCollision0d(ObjectOpcodeArgs *args);
+ int pge_op_getCollision1u(ObjectOpcodeArgs *args);
+ int pge_op_getCollision10(ObjectOpcodeArgs *args);
+ int pge_op_getCollision1d(ObjectOpcodeArgs *args);
+ int pge_op_getCollision2u(ObjectOpcodeArgs *args);
+ int pge_op_getCollision20(ObjectOpcodeArgs *args);
+ int pge_op_getCollision2d(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide0u(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide00(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide0d(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide1u(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide10(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide1d(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide2u(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide20(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide2d(ObjectOpcodeArgs *args);
+ int pge_op_collides0o0d(ObjectOpcodeArgs *args);
+ int pge_op_collides2o2d(ObjectOpcodeArgs *args);
+ int pge_op_collides0o0u(ObjectOpcodeArgs *args);
+ int pge_op_collides2o2u(ObjectOpcodeArgs *args);
+ int pge_op_collides2u2o(ObjectOpcodeArgs *args);
+ int pge_op_isInGroup(ObjectOpcodeArgs *args);
+ int pge_op_updateGroup0(ObjectOpcodeArgs *args);
+ int pge_op_updateGroup1(ObjectOpcodeArgs *args);
+ int pge_op_updateGroup2(ObjectOpcodeArgs *args);
+ int pge_op_updateGroup3(ObjectOpcodeArgs *args);
+ int pge_op_isPiegeDead(ObjectOpcodeArgs *args);
+ int pge_op_collides1u2o(ObjectOpcodeArgs *args);
+ int pge_op_collides1u1o(ObjectOpcodeArgs *args);
+ int pge_op_collides1o1u(ObjectOpcodeArgs *args);
+ int pge_o_unk0x2B(ObjectOpcodeArgs *args);
+ int pge_o_unk0x2C(ObjectOpcodeArgs *args);
+ int pge_o_unk0x2D(ObjectOpcodeArgs *args);
+ int pge_op_nop(ObjectOpcodeArgs *args);
+ int pge_op_pickupObject(ObjectOpcodeArgs *args);
+ int pge_op_addItemToInventory(ObjectOpcodeArgs *args);
+ int pge_op_copyPiege(ObjectOpcodeArgs *args);
+ int pge_op_canUseCurrentInventoryItem(ObjectOpcodeArgs *args);
+ int pge_op_removeItemFromInventory(ObjectOpcodeArgs *args);
+ int pge_o_unk0x34(ObjectOpcodeArgs *args);
+ int pge_op_isInpMod(ObjectOpcodeArgs *args);
+ int pge_op_setCollisionState1(ObjectOpcodeArgs *args);
+ int pge_op_setCollisionState0(ObjectOpcodeArgs *args);
+ int pge_op_isInGroup1(ObjectOpcodeArgs *args);
+ int pge_op_isInGroup2(ObjectOpcodeArgs *args);
+ int pge_op_isInGroup3(ObjectOpcodeArgs *args);
+ int pge_op_isInGroup4(ObjectOpcodeArgs *args);
+ int pge_o_unk0x3C(ObjectOpcodeArgs *args);
+ int pge_o_unk0x3D(ObjectOpcodeArgs *args);
+ int pge_op_setPiegeCounter(ObjectOpcodeArgs *args);
+ int pge_op_decPiegeCounter(ObjectOpcodeArgs *args);
+ int pge_o_unk0x40(ObjectOpcodeArgs *args);
+ int pge_op_wakeUpPiege(ObjectOpcodeArgs *args);
+ int pge_op_removePiege(ObjectOpcodeArgs *args);
+ int pge_op_removePiegeIfNotNear(ObjectOpcodeArgs *args);
+ int pge_op_loadPiegeCounter(ObjectOpcodeArgs *args);
+ int pge_o_unk0x45(ObjectOpcodeArgs *args);
+ int pge_o_unk0x46(ObjectOpcodeArgs *args);
+ int pge_o_unk0x47(ObjectOpcodeArgs *args);
+ int pge_o_unk0x48(ObjectOpcodeArgs *args);
+ int pge_o_unk0x49(ObjectOpcodeArgs *args);
+ int pge_o_unk0x4A(ObjectOpcodeArgs *args);
+ int pge_op_killPiege(ObjectOpcodeArgs *args);
+ int pge_op_isInCurrentRoom(ObjectOpcodeArgs *args);
+ int pge_op_isNotInCurrentRoom(ObjectOpcodeArgs *args);
+ int pge_op_scrollPosY(ObjectOpcodeArgs *args);
+ int pge_op_playDefaultDeathCutscene(ObjectOpcodeArgs *args);
+ int pge_o_unk0x50(ObjectOpcodeArgs *args);
+ int pge_o_unk0x52(ObjectOpcodeArgs *args);
+ int pge_o_unk0x53(ObjectOpcodeArgs *args);
+ int pge_op_isPiegeNear(ObjectOpcodeArgs *args);
+ int pge_op_setLife(ObjectOpcodeArgs *args);
+ int pge_op_incLife(ObjectOpcodeArgs *args);
+ int pge_op_setPiegeDefaultAnim(ObjectOpcodeArgs *args);
+ int pge_op_setLifeCounter(ObjectOpcodeArgs *args);
+ int pge_op_decLifeCounter(ObjectOpcodeArgs *args);
+ int pge_op_playCutscene(ObjectOpcodeArgs *args);
+ int pge_op_isTempVar2Set(ObjectOpcodeArgs *args);
+ int pge_op_playDeathCutscene(ObjectOpcodeArgs *args);
+ int pge_o_unk0x5D(ObjectOpcodeArgs *args);
+ int pge_o_unk0x5E(ObjectOpcodeArgs *args);
+ int pge_o_unk0x5F(ObjectOpcodeArgs *args);
+ int pge_op_findAndCopyPiege(ObjectOpcodeArgs *args);
+ int pge_op_isInRandomRange(ObjectOpcodeArgs *args);
+ int pge_o_unk0x62(ObjectOpcodeArgs *args);
+ int pge_o_unk0x63(ObjectOpcodeArgs *args);
+ int pge_o_unk0x64(ObjectOpcodeArgs *args);
+ int pge_op_addToCredits(ObjectOpcodeArgs *args);
+ int pge_op_subFromCredits(ObjectOpcodeArgs *args);
+ int pge_o_unk0x67(ObjectOpcodeArgs *args);
+ int pge_op_setCollisionState2(ObjectOpcodeArgs *args);
+ int pge_op_saveState(ObjectOpcodeArgs *args);
+ int pge_o_unk0x6A(ObjectOpcodeArgs *args);
+ int pge_op_isInGroupSlice(ObjectOpcodeArgs *args);
+ int pge_o_unk0x6C(ObjectOpcodeArgs *args);
+ int pge_op_isCollidingObject(ObjectOpcodeArgs *args);
+ int pge_o_unk0x6E(ObjectOpcodeArgs *args);
+ int pge_o_unk0x6F(ObjectOpcodeArgs *args);
+ int pge_o_unk0x70(ObjectOpcodeArgs *args);
+ int pge_o_unk0x71(ObjectOpcodeArgs *args);
+ int pge_o_unk0x72(ObjectOpcodeArgs *args);
+ int pge_o_unk0x73(ObjectOpcodeArgs *args);
+ int pge_op_collides4u(ObjectOpcodeArgs *args);
+ int pge_op_doesNotCollide4u(ObjectOpcodeArgs *args);
+ int pge_op_isBelowConrad(ObjectOpcodeArgs *args);
+ int pge_op_isAboveConrad(ObjectOpcodeArgs *args);
+ int pge_op_isNotFacingConrad(ObjectOpcodeArgs *args);
+ int pge_op_isFacingConrad(ObjectOpcodeArgs *args);
+ int pge_op_collides2u1u(ObjectOpcodeArgs *args);
+ int pge_op_displayText(ObjectOpcodeArgs *args);
+ int pge_o_unk0x7C(ObjectOpcodeArgs *args);
+ int pge_op_playSound(ObjectOpcodeArgs *args);
+ int pge_o_unk0x7E(ObjectOpcodeArgs *args);
+ int pge_o_unk0x7F(ObjectOpcodeArgs *args);
+ int pge_op_setPiegePosX(ObjectOpcodeArgs *args);
+ int pge_op_setPiegePosModX(ObjectOpcodeArgs *args);
+ int pge_op_changeRoom(ObjectOpcodeArgs *args);
+ int pge_op_hasInventoryItem(ObjectOpcodeArgs *args);
+ int pge_op_changeLevel(ObjectOpcodeArgs *args);
+ int pge_op_shakeScreen(ObjectOpcodeArgs *args);
+ int pge_o_unk0x86(ObjectOpcodeArgs *args);
+ int pge_op_playSoundGroup(ObjectOpcodeArgs *args);
+ int pge_op_adjustPos(ObjectOpcodeArgs *args);
+ int pge_op_setTempVar1(ObjectOpcodeArgs *args);
+ int pge_op_isTempVar1Set(ObjectOpcodeArgs *args);
+ int pge_setCurrentInventoryObject(LivePGE *pge);
+ void pge_updateInventory(LivePGE *pge1, LivePGE *pge2);
+ void pge_reorderInventory(LivePGE *pge);
+ LivePGE *pge_getInventoryItemBefore(LivePGE *pge, LivePGE *last_pge);
+ void pge_addToInventory(LivePGE *pge1, LivePGE *pge2, LivePGE *pge3);
+ int pge_updateCollisionState(LivePGE *pge, int16_t pge_dy, uint8_t var8);
+ int pge_ZOrder(LivePGE *pge, int16_t num, pge_ZOrderCallback compare, uint16_t unk);
+ void pge_updateGroup(uint8_t idx, uint8_t unk1, int16_t unk2);
+ void pge_removeFromInventory(LivePGE *pge1, LivePGE *pge2, LivePGE *pge3);
+ int pge_ZOrderByAnimY(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+ int pge_ZOrderByAnimYIfType(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+ int pge_ZOrderIfIndex(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+ int pge_ZOrderByIndex(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+ int pge_ZOrderByObj(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+ int pge_ZOrderIfDifferentDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+ int pge_ZOrderIfSameDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+ int pge_ZOrderIfTypeAndSameDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+ int pge_ZOrderIfTypeAndDifferentDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+ int pge_ZOrderByNumber(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2);
+
+
+ // collision
+ CollisionSlot _col_slots[256];
+ uint8_t _col_curPos;
+ CollisionSlot *_col_slotsTable[256];
+ CollisionSlot *_col_curSlot;
+ CollisionSlot2 _col_slots2[256];
+ CollisionSlot2 *_col_slots2Cur;
+ CollisionSlot2 *_col_slots2Next;
+ uint8_t _col_activeCollisionSlots[0x30 * 3]; // left, current, right
+ uint8_t _col_currentLeftRoom;
+ uint8_t _col_currentRightRoom;
+ int16_t _col_currentPiegeGridPosX;
+ int16_t _col_currentPiegeGridPosY;
+
+ void col_prepareRoomState();
+ void col_clearState();
+ LivePGE *col_findPiege(LivePGE *pge, uint16_t arg2);
+ int16_t col_findSlot(int16_t pos);
+ void col_preparePiegeState(LivePGE *dst_pge);
+ uint16_t col_getGridPos(LivePGE *pge, int16_t dx);
+ int16_t col_getGridData(LivePGE *pge, int16_t dy, int16_t dx);
+ uint8_t col_findCurrentCollidingObject(LivePGE *pge, uint8_t n1, uint8_t n2, uint8_t n3, LivePGE **pge_out);
+ int16_t col_detectHit(LivePGE *pge, int16_t arg2, int16_t arg4, col_Callback1 callback1, col_Callback2 callback2, int16_t argA, int16_t argC);
+ int col_detectHitCallback2(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2);
+ int col_detectHitCallback3(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2);
+ int col_detectHitCallback4(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2);
+ int col_detectHitCallback5(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2);
+ int col_detectHitCallback1(LivePGE *pge, int16_t dy, int16_t unk1, int16_t unk2);
+ int col_detectHitCallback6(LivePGE *pge, int16_t dy, int16_t unk1, int16_t unk2);
+ int col_detectHitCallbackHelper(LivePGE *pge, int16_t unk1);
+ int col_detectGunHitCallback1(LivePGE *pge, int16_t arg2, int16_t arg4, int16_t arg6);
+ int col_detectGunHitCallback2(LivePGE *pge1, LivePGE *pge2, int16_t arg4, int16_t);
+ int col_detectGunHitCallback3(LivePGE *pge1, LivePGE *pge2, int16_t arg4, int16_t);
+ int col_detectGunHit(LivePGE *pge, int16_t arg2, int16_t arg4, col_Callback1 callback1, col_Callback2 callback2, int16_t argA, int16_t argC);
+
+
+ // input
+ uint8_t _inp_lastKeysHit;
+ uint8_t _inp_lastKeysHitLeftRight;
+ bool _inp_replay;
+ bool _inp_record;
+ File *_inp_demo;
+
+ void inp_handleSpecialKeys();
+ void inp_update();
+
+
+ // save/load state
+ uint8_t _stateSlot;
+ bool _validSaveState;
+
+ void makeGameDemoName(char *buf);
+ void makeGameStateName(uint8_t slot, char *buf);
+ bool saveGameState(uint8_t slot);
+ bool loadGameState(uint8_t slot);
+ void saveState(File *f);
+ void loadState(File *f);
+};
+
+#endif // GAME_H__
diff --git a/graphics.cpp b/graphics.cpp
new file mode 100644
index 0000000..1da5a4d
--- /dev/null
+++ b/graphics.cpp
@@ -0,0 +1,717 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "graphics.h"
+
+
+void Graphics::setClippingRect(int16_t rx, int16_t ry, int16_t rw, int16_t rh) {
+ debug(DBG_VIDEO, "Graphics::setClippingRect(%d, %d, %d, %d)", rx, ry, rw, rh);
+ _crx = rx;
+ _cry = ry;
+ _crw = rw;
+ _crh = rh;
+}
+
+void Graphics::drawPoint(uint8_t color, const Point *pt) {
+ debug(DBG_VIDEO, "Graphics::drawPoint() col=0x%X x=%d, y=%d", color, pt->x, pt->y);
+ if (pt->x >= 0 && pt->x < _crw && pt->y >= 0 && pt->y < _crh) {
+ *(_layer + (pt->y + _cry) * 256 + pt->x + _crx) = color;
+ }
+}
+
+void Graphics::drawLine(uint8_t color, const Point *pt1, const Point *pt2) {
+ debug(DBG_VIDEO, "Graphics::drawLine()");
+ int16_t dxincr1 = 1;
+ int16_t dyincr1 = 1;
+ int16_t dx = pt2->x - pt1->x;
+ if (dx < 0) {
+ dxincr1 = -1;
+ dx = -dx;
+ }
+ int16_t dy = pt2->y - pt1->y;
+ if (dy < 0) {
+ dyincr1 = -1;
+ dy = -dy;
+ }
+ int16_t dxincr2, dyincr2, delta1, delta2;
+ if (dx < dy) {
+ dxincr2 = 0;
+ dyincr2 = 1;
+ delta1 = dx;
+ delta2 = dy;
+ if (dyincr1 < 0) {
+ dyincr2 = -1;
+ }
+ } else {
+ dxincr2 = 1;
+ dyincr2 = 0;
+ delta1 = dy;
+ delta2 = dx;
+ if (dxincr1 < 0) {
+ dxincr2 = -1;
+ }
+ }
+ Point pt;
+ pt.x = pt1->x;
+ pt.y = pt1->y;
+ int16_t octincr1 = delta1 * 2 - delta2 * 2;
+ int16_t octincr2 = delta1 * 2;
+ int16_t oct = delta1 * 2 - delta2;
+ if (delta2 >= 0) {
+ drawPoint(color, &pt);
+ while (--delta2 >= 0) {
+ if (oct >= 0) {
+ pt.x += dxincr1;
+ pt.y += dyincr1;
+ oct += octincr1;
+ } else {
+ pt.x += dxincr2;
+ pt.y += dyincr2;
+ oct += octincr2;
+ }
+ drawPoint(color, &pt);
+ }
+ }
+}
+
+void Graphics::addEllipseRadius(int16_t y, int16_t x1, int16_t x2) {
+ debug(DBG_VIDEO, "Graphics::addEllipseRadius()");
+ if (y >= 0 && y <= _crh) {
+ y = (y - _areaPoints[0]) * 2;
+ if (x1 < 0) {
+ x1 = 0;
+ }
+ if (x2 >= _crw) {
+ x2 = _crw - 1;
+ }
+ _areaPoints[y + 1] = x1;
+ _areaPoints[y + 2] = x2;
+ }
+}
+
+void Graphics::drawEllipse(uint8_t color, bool hasAlpha, const Point *pt, int16_t rx, int16_t ry) {
+ debug(DBG_VIDEO, "Graphics::drawEllipse()");
+ bool flag = false;
+ int16_t y = pt->y - ry;
+ if (y < 0) {
+ y = 0;
+ }
+ if (y < _crh) {
+ if (pt->y + ry >= 0) {
+ _areaPoints[0] = y;
+ int32_t dy = 0;
+ int32_t rxsq = rx * rx;
+ int32_t rxsq2 = rx * rx * 2;
+ int32_t rxsq4 = rx * rx * 4;
+ int32_t rysq = ry * ry;
+ int32_t rysq2 = ry * ry * 2;
+ int32_t rysq4 = ry * ry * 4;
+
+ int32_t dx = 0;
+ int32_t b = rx * ((rysq2 & 0xFFFF) + (rysq2 >> 16));
+ int32_t a = 2 * b;
+
+ int32_t ny1, ny2, nx1, nx2;
+ ny1 = ny2 = rysq4 / 2 - a + rxsq;
+ nx1 = nx2 = rxsq2 - b + rysq;
+
+ while (ny2 < 0) {
+ int16_t x2 = pt->x + rx;
+ int16_t x1 = pt->x - rx;
+ int16_t by = pt->y + dy;
+ int16_t ty = pt->y - dy;
+ if (x1 != x2) {
+ addEllipseRadius(by, x1, x2);
+ if (ty < by) {
+ addEllipseRadius(ty, x1, x2);
+ }
+ }
+ dy += 1;
+ dx += rxsq4;
+ nx1 = dx;
+ if (nx2 < 0) {
+ nx2 += nx1 + rxsq2;
+ ny2 += nx1;
+ } else {
+ --rx;
+ a -= rysq4;
+ ny1 = a;
+ nx2 += nx1 + rxsq2 - ny1;
+ ny2 += nx1 + rysq2 - ny1;
+ }
+ }
+
+ while (rx >= 0) {
+ bool flag2 = false;
+ int16_t x2 = pt->x + rx;
+ int16_t x1 = pt->x - rx;
+ int16_t by = pt->y + dy;
+ int16_t ty = pt->y - dy;
+ if (!flag && x1 != x2) {
+ flag2 = true;
+ addEllipseRadius(by, x1, x2);
+ if (ty < by) {
+ addEllipseRadius(ty, x1, x2);
+ }
+ }
+ if (flag2) {
+ flag = true;
+ }
+ --rx;
+ a -= rysq4;
+ nx1 = a;
+ if (ny2 < 0) {
+ ++dy;
+ flag = false;
+ dx += rxsq4;
+ ny2 += dx - nx1 + rysq2;
+ ny1 = dx - nx1 + rysq2;
+ } else {
+ ny2 += rysq2 - nx1;
+ ny1 = rysq2 - nx1;
+ }
+ }
+ if (flag) {
+ ++dy;
+ }
+
+ while (dy <= ry) {
+ int16_t ty = pt->y - dy;
+ int16_t by = pt->y + dy;
+ if (ty < by) {
+ addEllipseRadius(ty, pt->x, pt->x);
+ }
+ addEllipseRadius(by, pt->x, pt->x);
+ ++dy;
+ }
+ y = pt->y + ry + 1;
+ if (y > _crh) {
+ y = _crh;
+ }
+ y = (y - _areaPoints[0]) * 2;
+ _areaPoints[y + 1] = -1;
+ fillArea(color, hasAlpha);
+ }
+ }
+}
+
+void Graphics::fillArea(uint8_t color, bool hasAlpha) {
+ debug(DBG_VIDEO, "Graphics::fillArea()");
+ int16_t *pts = _areaPoints;
+ uint8_t *dst = _layer + (_cry + *pts++) * 256 + _crx;
+ int16_t x1 = *pts++;
+ if (x1 >= 0) {
+ if (hasAlpha && color > 0xC7) {
+ do {
+ int16_t x2 = *pts++;
+ if (x2 < _crw && x2 >= x1) {
+ int len = x2 - x1 + 1;
+ for (int i = 0; i < len; ++i) {
+ *(dst + x1 + i) |= color & 8; // XXX 0x88
+ }
+ }
+ dst += 256;
+ x1 = *pts++;
+ } while (x1 >= 0);
+ } else {
+ do {
+ int16_t x2 = *pts++;
+ if (x2 < _crw && x2 >= x1) {
+ int len = x2 - x1 + 1;
+ memset(dst + x1, color, len);
+ }
+ dst += 256;
+ x1 = *pts++;
+ } while (x1 >= 0);
+ }
+ }
+}
+
+void Graphics::drawSegment(uint8_t color, bool hasAlpha, int16_t ys, const Point *pts, uint8_t numPts) {
+ debug(DBG_VIDEO, "Graphics::drawSegment()");
+ int16_t xmin, xmax, ymin, ymax;
+ xmin = xmax = pts[0].x;
+ ymin = ymax = pts[0].y;
+ for (int i = 1; i < numPts; ++i) {
+ int16_t x = pts[i].x;
+ int16_t y = pts[i].y;
+ if ((xmin << 16) + ymin > (x << 16) + y) {
+ xmin = x;
+ ymin = y;
+ }
+ if ((xmax << 16) + ymax < (x << 16) + y) {
+ xmax = x;
+ ymax = y;
+ }
+ }
+ if (xmin < 0) {
+ xmin = 0;
+ }
+ if (xmax >= _crw) {
+ xmax = _crw - 1;
+ }
+ _areaPoints[0] = ys;
+ _areaPoints[1] = xmin;
+ _areaPoints[2] = xmax;
+ _areaPoints[3] = -1;
+ fillArea(color, hasAlpha);
+}
+
+void Graphics::drawPolygonOutline(uint8_t color, const Point *pts, uint8_t numPts) {
+ debug(DBG_VIDEO, "Graphics::drawPolygonOutline()");
+ assert(numPts >= 2);
+ int i;
+ for (i = 0; i < numPts - 1; ++i) {
+ drawLine(color, &pts[i], &pts[i + 1]);
+ }
+ drawLine(color, &pts[i], &pts[0]);
+}
+
+static int32_t calcPolyStep1(int16_t dx, int16_t dy) {
+ debug(DBG_VIDEO, "Graphics::calcPolyStep1()");
+ assert(dy != 0);
+ int32_t a = dx * 256;
+ if ((a >> 16) < dy) {
+ a = ((int16_t)(a / dy)) * 256;
+ } else {
+ a = ((a / 256) / dy) & 0xFFFF0000;
+ }
+ return a;
+}
+
+static int32_t calcPolyStep2(int16_t dx, int16_t dy) {
+ debug(DBG_VIDEO, "Graphics::calcPolyStep2()");
+ assert(dy != 0);
+ int32_t a = dx * 256;
+ if ((a >> 16) < dy) {
+ a = ((int16_t)(a / dy)) * 256;
+ } else {
+ a = ((a / 256) / dy) << 16;
+ }
+ return a;
+}
+
+static void drawPolygonHelper1(int32_t &x, int16_t &y, int32_t &step, int16_t *&pts, int16_t *&start) {
+ bool first = true;
+ x = pts[0];
+ y = pts[1];
+ int16_t dy, dx;
+ do {
+ if (first) {
+ first = false;
+ } else {
+ x = *pts;
+ }
+ --pts;
+ dy = *pts - y;
+ --pts;
+ dx = *pts - x;
+ } while (dy <= 0 && start < pts);
+ x <<= 16;
+ if (dy > 0) {
+ step = calcPolyStep1(dx, dy);
+ }
+}
+
+static void drawPolygonHelper2(int32_t &x, int16_t &y, int32_t &step, int16_t *&pts, int16_t *&start) {
+ bool first = true;
+ x = *start++;
+ y = *start++;
+ int16_t dy, dx;
+ do {
+ if (first) {
+ first = false;
+ } else {
+ x = *start;
+ start += 2;
+ }
+ dy = start[1] - y;
+ dx = start[0] - x;
+ } while (dy <= 0 && start < pts);
+ x <<= 16;
+ if (dy > 0) {
+ step = calcPolyStep2(dx, dy);
+ }
+}
+
+void Graphics::drawPolygon(uint8_t color, bool hasAlpha, const Point *pts, uint8_t numPts) {
+ debug(DBG_VIDEO, "Graphics::drawPolygon()");
+ assert(numPts * 4 < 0x100);
+
+ int16_t *apts1 = &_areaPoints[0x100];
+ int16_t *apts2 = &_areaPoints[0x100 + numPts * 2];
+
+ int16_t xmin, xmax, ymin, ymax;
+ xmin = xmax = pts[0].x;
+ ymin = ymax = pts[0].y;
+
+ int16_t *spts = apts1;
+ *apts1++ = *apts2++ = pts[0].x;
+ *apts1++ = *apts2++ = pts[0].y;
+
+ for (int p = 1; p < numPts; ++p) {
+ int16_t x = pts[p].x;
+ int16_t y = pts[p].y;
+ if (ymin > y) {
+ ymin = y;
+ spts = apts1;
+ }
+ if (ymax < y) {
+ ymax = y;
+ }
+ *apts1++ = *apts2++ = x;
+ *apts1++ = *apts2++ = y;
+
+ if (xmin > x) {
+ xmin = x;
+ }
+ if (xmax < x) {
+ xmax = x;
+ }
+ }
+ int16_t *rpts = _areaPoints;
+ if (xmax < 0 || xmin >= _crw || ymax < 0 || ymin >= _crh) {
+ return;
+ }
+ if (numPts == 2) {
+ drawLine(color, &pts[0], &pts[1]);
+ return;
+ }
+ if (ymax == ymin) {
+ drawSegment(color, hasAlpha, ymax, pts, numPts);
+ return;
+ }
+ int16_t x, dx, y, dy;
+ int32_t a, b, d, f;
+ int32_t xstep1 = 0;
+ int32_t xstep2 = 0;
+
+ apts1 = &spts[numPts * 2];
+ xmax = _crw - 1;
+ ymax = _crh - 1;
+ int32_t l1 = 65536;
+ int32_t l2 = -65536;
+ if (ymin < 0) {
+ int16_t x0, y0;
+ do {
+ --apts1;
+ y0 = *apts1;
+ --apts1;
+ x0 = *apts1;
+ } while (y0 < 0);
+ x = apts1[2];
+ y = apts1[3];
+ dy = y0 - y;
+ dx = x0 - x;
+ xstep1 = (dy << 16) | dx;
+ assert(dy != 0);
+ a = y * dx / dy;
+ b = (x - a) << 16;
+ d = xstep1 = calcPolyStep1(dx, dy);
+ if (d < 0) {
+ d = -d;
+ }
+ if (d < l1) {
+ d = l2;
+ }
+ d /= 2;
+ b -= d;
+
+ do {
+ x0 = *spts++;
+ y0 = *spts++;
+ } while (*(spts + 1) < 0);
+ dy = spts[1] - y0;
+ dx = spts[0] - x0;
+ xstep2 = (dy << 16) | dx;
+ assert(dy != 0);
+ a = y0 * dx / dy;
+ f = (x0 - a) << 16;
+ d = xstep2 = calcPolyStep2(dx, dy);
+ if (d < 0) {
+ d = -d;
+ }
+ if (d < l1) {
+ d = l1;
+ }
+ d /= 2;
+ f += d;
+ ymin = 0;
+ *rpts++ = 0;
+ goto gfx_startLine;
+ }
+
+ *rpts++ = ymin;
+
+gfx_startNewLine:
+ drawPolygonHelper2(f, ymin, xstep2, apts1, spts);
+ if (spts >= apts1) {
+ b = apts1[0] << 16;
+ dy = apts1[1];
+ if (dy <= ymax) goto gfx_endLine;
+ goto gfx_fillArea;
+ }
+ drawPolygonHelper1(b, ymin, xstep1, apts1, spts);
+ d = xstep1;
+ if (d < 0) {
+ if (d >= l2) {
+ d = l1;
+ }
+ d /= 2;
+ b += d;
+ }
+ d = xstep2;
+ if (d >= 0) {
+ if (d <= l1) {
+ d = l1;
+ }
+ d /= 2;
+ f += d;
+ }
+ d = b;
+ if (d < 0) {
+ d = 0;
+ }
+ x = f >> 16;
+ if (x > xmax) {
+ x = xmax;
+ }
+ *rpts++ = d >> 16;
+ *rpts++ = x;
+ ++ymin;
+ d = xstep1;
+ if (d >= 0) {
+ if (d <= l1) {
+ d = l1;
+ }
+ d /= 2;
+ }
+ b += d;
+ d = xstep2;
+ if (d < 0) {
+ if (d >= l2) {
+ d = l1;
+ }
+ d /= 2;
+ }
+ f += d;
+
+gfx_startLine:
+ while (1) {
+ dy = apts1[1];
+ if (spts >= apts1) {
+ break;
+ } else if (dy > spts[1]) {
+ dy = spts[1];
+ if (dy > ymax) {
+ goto gfx_drawPolygonEnd;
+ }
+ dy -= ymin;
+ if (dy > 0) {
+ --dy;
+ do {
+ a = b;
+ if (a < 0) {
+ a = 0;
+ }
+ x = f >> 16;
+ if (x > xmax) {
+ x = xmax;
+ }
+ *rpts++ = a >> 16;
+ *rpts++ = x;
+ b += xstep1;
+ f += xstep2;
+ --dy;
+ } while (dy >= 0);
+ }
+ drawPolygonHelper2(f, ymin, xstep2, apts1, spts);
+ d = xstep2;
+ if (d >= 0) {
+ if (d <= l1) {
+ d = l1;
+ }
+ d /= 2;
+ f += d;
+ } else {
+ d = b;
+ if (d < 0) {
+ d = 0;
+ }
+ x = f >> 16;
+ if (x > xmax) {
+ x = xmax;
+ }
+ *rpts++ = d >> 16;
+ *rpts++ = x;
+ ++ymin;
+ d = xstep2;
+ if (d >= l2) {
+ d = l1;
+ }
+ d /= 2;
+ f += d;
+ b += xstep1;
+ }
+ } else if (dy == spts[1]) {
+ if (dy > ymax) goto gfx_drawPolygonEnd;
+ dy -= ymin;
+ if (dy > 0) {
+ --dy;
+ do {
+ a = b;
+ if (a < 0) {
+ a = 0;
+ }
+ x = f >> 16;
+ if (x > xmax) {
+ x = xmax;
+ }
+ *rpts++ = a >> 16;
+ *rpts++ = x;
+ b += xstep1;
+ f += xstep2;
+ --dy;
+ } while (dy >= 0);
+ }
+ goto gfx_startNewLine;
+ } else if (dy > ymax) {
+ goto gfx_drawPolygonEnd;
+ } else {
+ dy -= ymin;
+ if (dy > 0) {
+ --dy;
+ do {
+ a = b;
+ if (a < 0) {
+ a = 0;
+ }
+ x = f >> 16;
+ if (x > xmax) {
+ x = xmax;
+ }
+ *rpts++ = a >> 16;
+ *rpts++ = x;
+ b += xstep1;
+ f += xstep2;
+ --dy;
+ } while (dy >= 0);
+ }
+ drawPolygonHelper1(b, ymin, xstep1, apts1, spts);
+ d = xstep1;
+ if (d < 0) {
+ if (d >= l2) {
+ d = l1;
+ }
+ d /= 2;
+ b += d;
+ } else {
+ d = b;
+ if (d < 0) {
+ d = 0;
+ }
+ x = f >> 16;
+ if (x > xmax) {
+ x = xmax;
+ }
+ *rpts++ = d >> 16;
+ *rpts++ = x;
+ ++ymin;
+ d = xstep1;
+ if (d <= l1) {
+ d = l1;
+ }
+ d /= 2;
+ b += d;
+ f += xstep2;
+ }
+ }
+ }
+
+ if (dy > ymax) goto gfx_drawPolygonEnd;
+ dy -= ymin;
+ if (dy < 0) goto gfx_fillArea;
+ if (dy > 0) {
+ --dy;
+ do {
+ a = b;
+ if (a < 0) {
+ a = 0;
+ }
+ x = f >> 16;
+ if (x > xmax) {
+ x = xmax;
+ }
+ *rpts++ = a >> 16;
+ *rpts++ = x;
+ b += xstep1;
+ f += xstep2;
+ --dy;
+ } while (dy >= 0);
+ }
+
+ b = f = (apts1[0] << 16) | apts1[1];
+
+gfx_endLine:
+ d = xstep1;
+ if (d >= 0) {
+ if (d >= l1) {
+ d /= 2;
+ b -= d;
+ }
+ }
+ d = xstep2;
+ if (d < 0) {
+ d /= 2;
+ f -= d;
+ }
+ a = b;
+ if (a < 0) {
+ a = 0;
+ }
+ x = f >> 16;
+ if (x > xmax) {
+ x = xmax;
+ }
+ *rpts++ = a >> 16;
+ *rpts++ = x;
+ goto gfx_fillArea;
+
+gfx_drawPolygonEnd:
+ dy = ymax - ymin;
+ if (dy >= 0) {
+ do {
+ a = b;
+ if (a < 0) {
+ a = 0;
+ }
+ x = f >> 16;
+ if (x > xmax) {
+ x = xmax;
+ }
+ *rpts++ = a >> 16;
+ *rpts++ = x;
+ b += xstep1;
+ f += xstep2;
+ --dy;
+ } while (dy >= 0);
+ }
+
+gfx_fillArea:
+ *rpts++ = -1;
+ fillArea(color, hasAlpha);
+}
diff --git a/graphics.h b/graphics.h
new file mode 100644
index 0000000..d28421b
--- /dev/null
+++ b/graphics.h
@@ -0,0 +1,39 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 GRAPHICS_H__
+#define GRAPHICS_H__
+
+#include "intern.h"
+
+struct Graphics {
+ uint8_t *_layer;
+ int16_t _areaPoints[0x200];
+ int16_t _crx, _cry, _crw, _crh;
+
+ void setClippingRect(int16_t vx, int16_t vy, int16_t vw, int16_t vh);
+ void drawPoint(uint8_t color, const Point *pt);
+ void drawLine(uint8_t color, const Point *pt1, const Point *pt2);
+ void addEllipseRadius(int16_t y, int16_t x1, int16_t x2);
+ void drawEllipse(uint8_t color, bool hasAlpha, const Point *pt, int16_t rx, int16_t ry);
+ void fillArea(uint8_t color, bool hasAlpha);
+ void drawSegment(uint8_t color, bool hasAlpha, int16_t ys, const Point *pts, uint8_t numPts);
+ void drawPolygonOutline(uint8_t color, const Point *pts, uint8_t numPts);
+ void drawPolygon(uint8_t color, bool hasAlpha, const Point *pts, uint8_t numPts);
+};
+
+#endif // GRAPHICS_H__
diff --git a/intern.h b/intern.h
new file mode 100644
index 0000000..6e9df9e
--- /dev/null
+++ b/intern.h
@@ -0,0 +1,224 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 INTERN_H__
+#define INTERN_H__
+
+#include
+#include
+#include
+#include
+#include
+
+#include "util.h"
+
+#define ABS(x) ((x)<0?-(x):(x))
+#define MAX(x,y) ((x)>(y)?(x):(y))
+#define MIN(x,y) ((x)<(y)?(x):(y))
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
+#endif
+
+
+inline void SWAP_UINT16(uint16_t *ptr) {
+ const uint8_t hi = *ptr >> 8;
+ const uint8_t lo = *ptr & 255;
+ *ptr = (lo << 8) | hi;
+}
+
+inline uint16_t READ_BE_UINT16(const void *ptr) {
+ const uint8_t *b = (const uint8_t *)ptr;
+ return (b[0] << 8) | b[1];
+}
+
+inline uint32_t READ_BE_UINT32(const void *ptr) {
+ const uint8_t *b = (const uint8_t *)ptr;
+ return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
+}
+
+inline uint16_t READ_LE_UINT16(const void *ptr) {
+ const uint8_t *b = (const uint8_t *)ptr;
+ return (b[1] << 8) | b[0];
+}
+
+inline uint32_t READ_LE_UINT32(const void *ptr) {
+ const uint8_t *b = (const uint8_t *)ptr;
+ return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
+}
+
+template
+inline void SWAP(T &a, T &b) {
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+enum Language {
+ LANG_FR,
+ LANG_EN,
+ LANG_DE,
+ LANG_SP,
+ LANG_IT
+};
+
+enum ResourceType {
+ kResourceTypeAmiga,
+ kResourceTypePC
+};
+
+struct Color {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+};
+
+struct Point {
+ int16_t x;
+ int16_t y;
+};
+
+struct Level {
+ const char *name;
+ const char *name2;
+ const char *nameAmiga;
+ uint16_t cutscene_id;
+ uint8_t sound;
+ uint8_t track;
+};
+
+struct InitPGE {
+ uint16_t type;
+ int16_t pos_x;
+ int16_t pos_y;
+ uint16_t obj_node_number;
+ uint16_t life;
+ int16_t counter_values[4];
+ uint8_t object_type;
+ uint8_t init_room;
+ uint8_t room_location;
+ uint8_t init_flags;
+ uint8_t colliding_icon_num;
+ uint8_t icon_num;
+ uint8_t object_id;
+ uint8_t skill;
+ uint8_t mirror_x;
+ uint8_t flags;
+ uint8_t unk1C; // collidable, collision_data_len
+ uint16_t text_num;
+};
+
+struct LivePGE {
+ uint16_t obj_type;
+ int16_t pos_x;
+ int16_t pos_y;
+ uint8_t anim_seq;
+ uint8_t room_location;
+ int16_t life;
+ int16_t counter_value;
+ uint8_t collision_slot;
+ uint8_t next_inventory_PGE;
+ uint8_t current_inventory_PGE;
+ uint8_t unkF; // unk_inventory_PGE
+ uint16_t anim_number;
+ uint8_t flags;
+ uint8_t index;
+ uint16_t first_obj_number;
+ LivePGE *next_PGE_in_room;
+ InitPGE *init_PGE;
+};
+
+struct GroupPGE {
+ GroupPGE *next_entry;
+ uint16_t index;
+ uint16_t group_id;
+};
+
+struct Object {
+ uint16_t type;
+ int8_t dx;
+ int8_t dy;
+ uint16_t init_obj_type;
+ uint8_t opcode2;
+ uint8_t opcode1;
+ uint8_t flags;
+ uint8_t opcode3;
+ uint16_t init_obj_number;
+ int16_t opcode_arg1;
+ int16_t opcode_arg2;
+ int16_t opcode_arg3;
+};
+
+struct ObjectNode {
+ uint16_t last_obj_number;
+ Object *objects;
+ uint16_t num_objects;
+};
+
+struct ObjectOpcodeArgs {
+ LivePGE *pge; // arg0
+ int16_t a; // arg2
+ int16_t b; // arg4
+};
+
+struct AnimBufferState {
+ int16_t x, y;
+ uint8_t w, h;
+ const uint8_t *dataPtr;
+ LivePGE *pge;
+};
+
+struct AnimBuffers {
+ AnimBufferState *_states[4];
+ uint8_t _curPos[4];
+
+ void addState(uint8_t stateNum, int16_t x, int16_t y, const uint8_t *dataPtr, LivePGE *pge, uint8_t w = 0, uint8_t h = 0);
+};
+
+struct CollisionSlot {
+ int16_t ct_pos;
+ CollisionSlot *prev_slot;
+ LivePGE *live_pge;
+ uint16_t index;
+};
+
+struct BankSlot {
+ uint16_t entryNum;
+ uint8_t *ptr;
+};
+
+struct CollisionSlot2 {
+ CollisionSlot2 *next_slot;
+ int8_t *unk2;
+ uint8_t data_size;
+ uint8_t data_buf[0x10]; // XXX check size
+};
+
+struct InventoryItem {
+ uint8_t icon_num;
+ InitPGE *init_pge;
+ LivePGE *live_pge;
+};
+
+struct SoundFx {
+ uint32_t offset;
+ uint16_t len;
+ uint8_t *data;
+};
+
+extern const char *g_caption;
+
+#endif // INTERN_H__
diff --git a/locale.cpp b/locale.cpp
new file mode 100644
index 0000000..6ffbdc8
--- /dev/null
+++ b/locale.cpp
@@ -0,0 +1,49 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "locale.h"
+
+
+Locale::Locale(Version ver)
+ : _ver(ver) {
+ switch (_ver) {
+ case LANG_FR:
+ _stringsTable = _stringsTableFR;
+ _textsTable = _textsTableFR;
+ break;
+ case LANG_EN:
+ _stringsTable = _stringsTableEN;
+ _textsTable = _textsTableEN;
+ break;
+ case LANG_DE:
+ _stringsTable = _stringsTableDE;
+ _textsTable = _textsTableDE;
+ break;
+ case LANG_SP:
+ _stringsTable = _stringsTableSP;
+ _textsTable = _textsTableSP;
+ break;
+ }
+}
+
+const char *Locale::get(int id) const {
+ const char *text = 0;
+ if (id >= 0 && id < LI_NUM) {
+ text = _textsTable[id];
+ }
+ return text;
+}
diff --git a/locale.h b/locale.h
new file mode 100644
index 0000000..1e2823a
--- /dev/null
+++ b/locale.h
@@ -0,0 +1,68 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 LOCALE_H__
+#define LOCALE_H__
+
+#include "intern.h"
+
+struct Locale {
+ enum Id {
+ LI_01_CONTINUE_OR_ABORT = 0,
+ LI_02_TIME,
+ LI_03_CONTINUE,
+ LI_04_ABORT,
+ LI_05_COMPLETED,
+ LI_06_LEVEL,
+ LI_07_START,
+ LI_08_SKILL,
+ LI_09_PASSWORD,
+ LI_10_INFO,
+ LI_11_QUIT,
+ LI_12_SKILL_LEVEL,
+ LI_13_EASY,
+ LI_14_NORMAL,
+ LI_15_EXPERT,
+ LI_16_ENTER_PASSWORD1,
+ LI_17_ENTER_PASSWORD2,
+ LI_18_RESUME_GAME,
+ LI_19_ABORT_GAME,
+ LI_20_LOAD_GAME,
+ LI_21_SAVE_GAME,
+ LI_22_SAVE_SLOT,
+
+ LI_NUM
+ };
+
+ static const char *_textsTableFR[];
+ static const char *_textsTableEN[];
+ static const char *_textsTableDE[];
+ static const char *_textsTableSP[];
+ static const uint8_t _stringsTableFR[];
+ static const uint8_t _stringsTableEN[];
+ static const uint8_t _stringsTableDE[];
+ static const uint8_t _stringsTableSP[];
+
+ Version _ver;
+ const char **_textsTable;
+ const uint8_t *_stringsTable;
+
+ Locale(Version ver);
+ const char *get(int id) const;
+};
+
+#endif // LOCALE_H__
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..4dd1543
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,132 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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
+#include
+#include "file.h"
+#include "fs.h"
+#include "game.h"
+#include "systemstub.h"
+
+static const char *USAGE =
+ "REminiscence - Flashback Interpreter\n"
+ "Usage: %s [OPTIONS]...\n"
+ " --datapath=PATH Path to data files (default 'DATA')\n"
+ " --savepath=PATH Path to save files (default '.')\n"
+ " --levelnum=NUM Starting level (default '0')";
+
+static int detectVersion(FileSystem *fs) {
+ static const struct {
+ const char *filename;
+ int type;
+ const char *name;
+ } table[] = {
+ { "LEVEL1.MAP", kResourceTypePC, "PC" },
+ { "LEVEL1.LEV", kResourceTypeAmiga, "Amiga" },
+ { "DEMO.LEV", kResourceTypeAmiga, "Amiga" },
+ { 0, -1 }
+ };
+ for (int i = 0; table[i].filename; ++i) {
+ File f;
+ if (f.open(table[i].filename, "rb", fs)) {
+ debug(DBG_INFO, "Detected %s version", table[i].name);
+ return table[i].type;
+ }
+ }
+ return -1;
+}
+
+static Language detectLanguage(FileSystem *fs) {
+ static const struct {
+ const char *filename;
+ Language language;
+ } table[] = {
+ // PC
+ { "ENGCINE.TXT", LANG_EN },
+ { "FR_CINE.TXT", LANG_FR },
+ { "GERCINE.TXT", LANG_DE },
+ { "SPACINE.TXT", LANG_SP },
+ { "ITACINE.TXT", LANG_IT },
+ // Amiga
+ { "FRCINE.TXT", LANG_FR },
+ { 0, LANG_EN }
+ };
+ for (int i = 0; table[i].filename; ++i) {
+ File f;
+ if (f.open(table[i].filename, "rb", fs)) {
+ return table[i].language;
+ }
+ }
+ return LANG_EN;
+}
+
+const char *g_caption = "REminiscence";
+
+#undef main
+int main(int argc, char *argv[]) {
+ const char *dataPath = "DATA";
+ const char *savePath = ".";
+ int levelNum = 0;
+ if (argc == 2) {
+ // data path as the only command line argument
+ struct stat st;
+ if (stat(argv[1], &st) == 0 && S_ISDIR(st.st_mode)) {
+ dataPath = strdup(argv[1]);
+ }
+ }
+ while (1) {
+ static struct option options[] = {
+ { "datapath", required_argument, 0, 1 },
+ { "savepath", required_argument, 0, 2 },
+ { "levelnum", required_argument, 0, 3 },
+ { 0, 0, 0, 0 }
+ };
+ int index;
+ const int c = getopt_long(argc, argv, "", options, &index);
+ if (c == -1) {
+ break;
+ }
+ switch (c) {
+ case 1:
+ dataPath = strdup(optarg);
+ break;
+ case 2:
+ savePath = strdup(optarg);
+ break;
+ case 3:
+ levelNum = atoi(optarg);
+ break;
+ default:
+ printf(USAGE, argv[0]);
+ return 0;
+ }
+ }
+ g_debugMask = DBG_INFO; // DBG_CUT | DBG_VIDEO | DBG_RES | DBG_MENU | DBG_PGE | DBG_GAME | DBG_UNPACK | DBG_COL | DBG_MOD | DBG_SFX | DBG_FILE;
+ FileSystem fs(dataPath);
+ const int version = detectVersion(&fs);
+ if (version == -1) {
+ error("Unable to find data files, check that all required files are present");
+ return -1;
+ }
+ Language language = detectLanguage(&fs);
+ SystemStub *stub = SystemStub_SDL_create();
+ Game *g = new Game(stub, &fs, savePath, levelNum, (ResourceType)version, language);
+ g->run();
+ delete g;
+ delete stub;
+ return 0;
+}
diff --git a/menu.cpp b/menu.cpp
new file mode 100644
index 0000000..e9f8095
--- /dev/null
+++ b/menu.cpp
@@ -0,0 +1,407 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "game.h"
+#include "resource.h"
+#include "systemstub.h"
+#include "video.h"
+#include "menu.h"
+
+
+Menu::Menu(Resource *res, SystemStub *stub, Video *vid)
+ : _res(res), _stub(stub), _vid(vid) {
+}
+
+void Menu::drawString(const char *str, int16_t y, int16_t x, uint8_t color) {
+ debug(DBG_MENU, "Menu::drawString()");
+ uint8_t v1b = _vid->_charFrontColor;
+ uint8_t v2b = _vid->_charTransparentColor;
+ uint8_t v3b = _vid->_charShadowColor;
+ switch (color) {
+ case 0:
+ _vid->_charFrontColor = _charVar1;
+ _vid->_charTransparentColor = _charVar2;
+ _vid->_charShadowColor = _charVar2;
+ break;
+ case 1:
+ _vid->_charFrontColor = _charVar2;
+ _vid->_charTransparentColor = _charVar1;
+ _vid->_charShadowColor = _charVar1;
+ break;
+ case 2:
+ _vid->_charFrontColor = _charVar3;
+ _vid->_charTransparentColor = 0xFF;
+ _vid->_charShadowColor = _charVar1;
+ break;
+ case 3:
+ _vid->_charFrontColor = _charVar4;
+ _vid->_charTransparentColor = 0xFF;
+ _vid->_charShadowColor = _charVar1;
+ break;
+ case 4:
+ _vid->_charFrontColor = _charVar2;
+ _vid->_charTransparentColor = 0xFF;
+ _vid->_charShadowColor = _charVar1;
+ break;
+ case 5:
+ _vid->_charFrontColor = _charVar2;
+ _vid->_charTransparentColor = 0xFF;
+ _vid->_charShadowColor = _charVar5;
+ break;
+ }
+
+ drawString2(str, y, x);
+
+ _vid->_charFrontColor = v1b;
+ _vid->_charTransparentColor = v2b;
+ _vid->_charShadowColor = v3b;
+}
+
+void Menu::drawString2(const char *str, int16_t y, int16_t x) {
+ debug(DBG_MENU, "Menu::drawString2()");
+ int len = 0;
+ while (*str) {
+ _vid->PC_drawChar((uint8_t)*str, y, x + len);
+ ++str;
+ ++len;
+ }
+ _vid->markBlockAsDirty(x * 8, y * 8, len * 8, 8);
+}
+
+void Menu::loadPicture(const char *prefix) {
+ debug(DBG_MENU, "Menu::loadPicture('%s')", prefix);
+ _res->load_MAP_menu(prefix, _res->_memBuf);
+ for (int i = 0; i < 4; ++i) {
+ for (int y = 0; y < 224; ++y) {
+ for (int x = 0; x < 64; ++x) {
+ _vid->_frontLayer[i + x * 4 + 256 * y] = _res->_memBuf[0x3800 * i + x + 64 * y];
+ }
+ }
+ }
+ _res->load_PAL_menu(prefix, _res->_memBuf);
+ _stub->setPalette(_res->_memBuf, 256);
+}
+
+void Menu::handleInfoScreen() {
+ debug(DBG_MENU, "Menu::handleInfoScreen()");
+ _vid->fadeOut();
+ switch (_res->_lang) {
+ case LANG_FR:
+ loadPicture("instru_f");
+ break;
+ case LANG_EN:
+ case LANG_DE:
+ case LANG_SP:
+ case LANG_IT:
+ loadPicture("instru_e");
+ break;
+ }
+ _vid->fullRefresh();
+ _vid->updateScreen();
+ do {
+ _stub->sleep(EVENTS_DELAY);
+ _stub->processEvents();
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ break;
+ }
+ } while (!_stub->_pi.quit);
+}
+
+void Menu::handleSkillScreen(uint8_t &new_skill) {
+ debug(DBG_MENU, "Menu::handleSkillScreen()");
+ static const uint8_t option_colors[3][3] = { { 2, 3, 3 }, { 3, 2, 3}, { 3, 3, 2 } };
+ _vid->fadeOut();
+ loadPicture("menu3");
+ _vid->fullRefresh();
+ drawString(_res->getMenuString(LocaleData::LI_12_SKILL_LEVEL), 12, 4, 3);
+ int skill_level = new_skill;
+ do {
+ drawString(_res->getMenuString(LocaleData::LI_13_EASY), 15, 14, option_colors[skill_level][0]);
+ drawString(_res->getMenuString(LocaleData::LI_14_NORMAL), 17, 14, option_colors[skill_level][1]);
+ drawString(_res->getMenuString(LocaleData::LI_15_EXPERT), 19, 14, option_colors[skill_level][2]);
+
+ _vid->updateScreen();
+ _stub->sleep(EVENTS_DELAY);
+ _stub->processEvents();
+
+ if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
+ if (skill_level != 0) {
+ --skill_level;
+ } else {
+ skill_level = 2;
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
+ if (skill_level != 2) {
+ ++skill_level;
+ } else {
+ skill_level = 0;
+ }
+ }
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ new_skill = skill_level;
+ return;
+ }
+ } while (!_stub->_pi.quit);
+ new_skill = 1;
+}
+
+bool Menu::handlePasswordScreen(uint8_t &new_skill, uint8_t &new_level) {
+ debug(DBG_MENU, "Menu::handlePasswordScreen()");
+ _vid->fadeOut();
+ _vid->_charShadowColor = _charVar1;
+ _vid->_charTransparentColor = 0xFF;
+ _vid->_charFrontColor = _charVar4;
+ _vid->fullRefresh();
+ char password[7];
+ int len = 0;
+ do {
+ loadPicture("menu2");
+ drawString2(_res->getMenuString(LocaleData::LI_16_ENTER_PASSWORD1), 15, 3);
+ drawString2(_res->getMenuString(LocaleData::LI_17_ENTER_PASSWORD2), 17, 3);
+
+ for (int i = 0; i < len; ++i) {
+ _vid->PC_drawChar((uint8_t)password[i], 21, i + 15);
+ }
+ _vid->PC_drawChar(0x20, 21, len + 15);
+
+ _vid->markBlockAsDirty(15 * 8, 21 * 8, (len + 1) * 8, 8);
+ _vid->updateScreen();
+ _stub->sleep(EVENTS_DELAY);
+ _stub->processEvents();
+ char c = _stub->_pi.lastChar;
+ if (c != 0) {
+ _stub->_pi.lastChar = 0;
+ if (len < 6) {
+ if (c >= 'a' && c <= 'z') {
+ c &= ~0x20;
+ }
+ if ((c >= 'A' && c <= 'Z') || (c == 0x20)) {
+ password[len] = c;
+ ++len;
+ }
+ }
+ }
+ if (_stub->_pi.backspace) {
+ _stub->_pi.backspace = false;
+ if (len > 0) {
+ --len;
+ }
+ }
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ password[len] = '\0';
+ for (int level = 0; level < 8; ++level) {
+ for (int skill = 0; skill < 3; ++skill) {
+ if (strcmp(_passwords[level][skill], password) == 0) {
+ new_level = level;
+ new_skill = skill;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ } while (!_stub->_pi.quit);
+ return false;
+}
+
+bool Menu::handleLevelScreen(uint8_t &new_skill, uint8_t &new_level) {
+ debug(DBG_MENU, "Menu::handleLevelScreen()");
+ _vid->fadeOut();
+ loadPicture("menu2");
+ _vid->fullRefresh();
+ uint8_t currentSkill = new_skill;
+ uint8_t currentLevel = new_level;
+ do {
+ static const char *levelTitles[] = {
+ "Titan / The Jungle",
+ "Titan / New Washington",
+ "Titan / Death Tower Show",
+ "Earth / Surface",
+ "Earth / Paradise Club",
+ "Planet Morphs / Surface",
+ "Planet Morphs / Inner Core"
+ };
+ for (int i = 0; i < 7; ++i) {
+ drawString(levelTitles[i], 7 + i * 2, 4, (currentLevel == i) ? 2 : 3);
+ }
+ _vid->markBlockAsDirty(4 * 8, 7 * 8, 192, 7 * 8);
+
+ drawString(_res->getMenuString(LocaleData::LI_13_EASY), 23, 4, (currentSkill == 0) ? 2 : 3);
+ drawString(_res->getMenuString(LocaleData::LI_14_NORMAL), 23, 14, (currentSkill == 1) ? 2 : 3);
+ drawString(_res->getMenuString(LocaleData::LI_15_EXPERT), 23, 24, (currentSkill == 2) ? 2 : 3);
+ _vid->markBlockAsDirty(4 * 8, 23 * 8, 192, 8);
+
+ _vid->updateScreen();
+ _stub->sleep(EVENTS_DELAY);
+ _stub->processEvents();
+
+ if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
+ if (currentLevel != 0) {
+ --currentLevel;
+ } else {
+ currentLevel = 6;
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
+ if (currentLevel != 6) {
+ ++currentLevel;
+ } else {
+ currentLevel = 0;
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_LEFT) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_LEFT;
+ if (currentSkill != 0) {
+ --currentSkill;
+ } else {
+ currentSkill = 2;
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_RIGHT) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
+ if (currentSkill != 2) {
+ ++currentSkill;
+ } else {
+ currentSkill = 0;
+ }
+ }
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ new_skill = currentSkill;
+ new_level = currentLevel;
+ return true;
+ }
+ } while (!_stub->_pi.quit);
+ return false;
+}
+
+bool Menu::handleTitleScreen(uint8_t &new_skill, uint8_t &new_level) {
+ debug(DBG_MENU, "Menu::handleTitleScreen()");
+ bool quit_loop = false;
+ int menu_entry = 0;
+ bool reinit_screen = true;
+ bool continue_game = true;
+ _charVar1 = 0;
+ _charVar2 = 0;
+ _charVar3 = 0;
+ _charVar4 = 0;
+ _charVar5 = 0;
+ static const struct {
+ int str;
+ int opt;
+ } menu_items[] = {
+ { LocaleData::LI_07_START, MENU_OPTION_ITEM_START },
+#ifdef ENABLE_PASSWORD_MENU
+ { LocaleData::LI_08_SKILL, MENU_OPTION_ITEM_SKILL },
+ { LocaleData::LI_09_PASSWORD, MENU_OPTION_ITEM_PASSWORD },
+#else
+ { LocaleData::LI_06_LEVEL, MENU_OPTION_ITEM_LEVEL },
+#endif
+ { LocaleData::LI_10_INFO, MENU_OPTION_ITEM_INFO },
+ { LocaleData::LI_11_QUIT, MENU_OPTION_ITEM_QUIT }
+ };
+ static const int menu_items_count = ARRAYSIZE(menu_items);
+ while (!quit_loop) {
+ if (reinit_screen) {
+ _vid->fadeOut();
+ loadPicture("menu1");
+ _vid->fullRefresh();
+ _charVar3 = 1;
+ _charVar4 = 2;
+ menu_entry = 0;
+ reinit_screen = false;
+ }
+ int selected_menu_entry = -1;
+ const int y_start = 26 - menu_items_count * 2;
+ for (int i = 0; i < menu_items_count; ++i) {
+ drawString(_res->getMenuString(menu_items[i].str), y_start + i * 2, 20, (i == menu_entry) ? 2 : 3);
+ }
+
+ _vid->updateScreen();
+ _stub->sleep(EVENTS_DELAY);
+ _stub->processEvents();
+
+ if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
+ if (menu_entry != 0) {
+ --menu_entry;
+ } else {
+ menu_entry = menu_items_count - 1;
+ }
+ }
+ if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
+ _stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
+ if (menu_entry != menu_items_count - 1) {
+ ++menu_entry;
+ } else {
+ menu_entry = 0;
+ }
+ }
+ if (_stub->_pi.enter) {
+ _stub->_pi.enter = false;
+ selected_menu_entry = menu_entry;
+ }
+
+ if (selected_menu_entry != -1) {
+ switch (menu_items[selected_menu_entry].opt) {
+ case MENU_OPTION_ITEM_START:
+ quit_loop = true;
+ break;
+ case MENU_OPTION_ITEM_SKILL:
+ handleSkillScreen(new_skill);
+ reinit_screen = true;
+ break;
+ case MENU_OPTION_ITEM_PASSWORD:
+ if (handlePasswordScreen(new_skill, new_level)) {
+ quit_loop = true;
+ } else {
+ reinit_screen = true;
+ }
+ break;
+ case MENU_OPTION_ITEM_LEVEL:
+ if (handleLevelScreen(new_skill, new_level)) {
+ quit_loop = true;
+ } else {
+ reinit_screen = true;
+ }
+ break;
+ case MENU_OPTION_ITEM_INFO:
+ handleInfoScreen();
+ reinit_screen = true;
+ break;
+ case MENU_OPTION_ITEM_QUIT:
+ continue_game = false;
+ quit_loop = true;
+ break;
+ }
+ }
+ if (_stub->_pi.quit) {
+ continue_game = false;
+ quit_loop = true;
+ break;
+ }
+ }
+ return continue_game;
+}
diff --git a/menu.h b/menu.h
new file mode 100644
index 0000000..f52f8ec
--- /dev/null
+++ b/menu.h
@@ -0,0 +1,66 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 MENU_H__
+#define MENU_H__
+
+#include "intern.h"
+
+struct Resource;
+struct SystemStub;
+struct Video;
+
+struct Menu {
+ enum {
+ MENU_OPTION_ITEM_START,
+ MENU_OPTION_ITEM_SKILL,
+ MENU_OPTION_ITEM_PASSWORD,
+ MENU_OPTION_ITEM_LEVEL,
+ MENU_OPTION_ITEM_INFO,
+ MENU_OPTION_ITEM_QUIT
+ };
+
+ enum {
+ EVENTS_DELAY = 80
+ };
+
+ static const char *_passwords[8][3];
+
+ Resource *_res;
+ SystemStub *_stub;
+ Video *_vid;
+
+ const char **_textOptions;
+ uint8_t _charVar1;
+ uint8_t _charVar2;
+ uint8_t _charVar3;
+ uint8_t _charVar4;
+ uint8_t _charVar5;
+
+ Menu(Resource *res, SystemStub *stub, Video *vid);
+
+ void drawString(const char *str, int16_t y, int16_t x, uint8_t color);
+ void drawString2(const char *str, int16_t y, int16_t x);
+ void loadPicture(const char *prefix);
+ void handleInfoScreen();
+ void handleSkillScreen(uint8_t &new_skill);
+ bool handlePasswordScreen(uint8_t &new_skill, uint8_t &new_level);
+ bool handleLevelScreen(uint8_t &new_skill, uint8_t &new_level);
+ bool handleTitleScreen(uint8_t &new_skill, uint8_t &new_level);
+};
+
+#endif // MENU_H__
diff --git a/mixer.cpp b/mixer.cpp
new file mode 100644
index 0000000..3380a0c
--- /dev/null
+++ b/mixer.cpp
@@ -0,0 +1,183 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "mixer.h"
+#include "systemstub.h"
+
+
+Mixer::Mixer(FileSystem *fs, SystemStub *stub)
+ : _stub(stub), _musicType(MT_NONE), _mod(this, fs), _ogg(this, fs), _sfx(this) {
+ _musicTrack = -1;
+}
+
+void Mixer::init() {
+ memset(_channels, 0, sizeof(_channels));
+ _premixHook = 0;
+ _stub->startAudio(Mixer::mixCallback, this);
+}
+
+void Mixer::free() {
+ setPremixHook(0, 0);
+ stopAll();
+ _stub->stopAudio();
+}
+
+void Mixer::setPremixHook(PremixHook premixHook, void *userData) {
+ debug(DBG_SND, "Mixer::setPremixHook()");
+ LockAudioStack las(_stub);
+ _premixHook = premixHook;
+ _premixHookData = userData;
+}
+
+void Mixer::play(const MixerChunk *mc, uint16_t freq, uint8_t volume) {
+ debug(DBG_SND, "Mixer::play(%d, %d)", freq, volume);
+ LockAudioStack las(_stub);
+ MixerChannel *ch = 0;
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ MixerChannel *cur = &_channels[i];
+ if (cur->active) {
+ if (cur->chunk.data == mc->data) {
+ cur->chunkPos = 0;
+ return;
+ }
+ } else {
+ ch = cur;
+ break;
+ }
+ }
+ if (ch) {
+ ch->active = true;
+ ch->volume = volume;
+ ch->chunk = *mc;
+ ch->chunkPos = 0;
+ ch->chunkInc = (freq << FRAC_BITS) / _stub->getOutputSampleRate();
+ }
+}
+
+bool Mixer::isPlaying(const MixerChunk *mc) const {
+ debug(DBG_SND, "Mixer::isPlaying");
+ LockAudioStack las(_stub);
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ const MixerChannel *ch = &_channels[i];
+ if (ch->active && ch->chunk.data == mc->data) {
+ return true;
+ }
+ }
+ return false;
+}
+
+uint32_t Mixer::getSampleRate() const {
+ return _stub->getOutputSampleRate();
+}
+
+void Mixer::stopAll() {
+ debug(DBG_SND, "Mixer::stopAll()");
+ LockAudioStack las(_stub);
+ for (uint8_t i = 0; i < NUM_CHANNELS; ++i) {
+ _channels[i].active = false;
+ }
+}
+
+static bool isMusicSfx(int num) {
+ return (num >= 68 && num <= 75);
+}
+
+void Mixer::playMusic(int num) {
+ debug(DBG_SND, "Mixer::playMusic(%d)", num);
+ if (num > MUSIC_TRACK && num != _musicTrack) {
+ if (_ogg.playTrack(num - MUSIC_TRACK)) {
+ _musicType = MT_OGG;
+ _musicTrack = num;
+ return;
+ }
+ }
+ if (num == 1) { // menu screen
+ if (_ogg.playTrack(2)) {
+ _musicType = MT_OGG;
+ _musicTrack = 2;
+ return;
+ }
+ }
+ if (isMusicSfx(num)) { // level action sequence
+ _sfx.play(num);
+ _musicType = MT_SFX;
+ } else { // cutscene
+ _mod.play(num);
+ _musicType = MT_MOD;
+ }
+}
+
+void Mixer::stopMusic() {
+ debug(DBG_SND, "Mixer::stopMusic()");
+ switch (_musicType) {
+ case MT_NONE:
+ break;
+ case MT_MOD:
+ _mod.stop();
+ break;
+ case MT_OGG:
+ _ogg.stopTrack();
+ _musicTrack = -1;
+ break;
+ case MT_SFX:
+ _sfx.stop();
+ break;
+ }
+ _musicType = MT_NONE;
+ if (_musicTrack != -1) {
+ _ogg.resumeTrack();
+ _musicType = MT_OGG;
+ }
+}
+
+void Mixer::mix(int8_t *buf, int len) {
+ memset(buf, 0, len);
+ if (_premixHook) {
+ if (!_premixHook(_premixHookData, buf, len)) {
+ _premixHook = 0;
+ _premixHookData = 0;
+ }
+ }
+ for (uint8_t i = 0; i < NUM_CHANNELS; ++i) {
+ MixerChannel *ch = &_channels[i];
+ if (ch->active) {
+ for (int pos = 0; pos < len; ++pos) {
+ if ((ch->chunkPos >> FRAC_BITS) >= (ch->chunk.len - 1)) {
+ ch->active = false;
+ break;
+ }
+ int out = resampleLinear(&ch->chunk, ch->chunkPos, ch->chunkInc, FRAC_BITS);
+ addclamp(buf[pos], out * ch->volume / Mixer::MAX_VOLUME);
+ ch->chunkPos += ch->chunkInc;
+ }
+ }
+ }
+}
+
+void Mixer::addclamp(int8_t& a, int b) {
+ int add = a + b;
+ if (add < -128) {
+ add = -128;
+ } else if (add > 127) {
+ add = 127;
+ }
+ a = add;
+}
+
+void Mixer::mixCallback(void *param, int8_t *buf, int len) {
+ ((Mixer *)param)->mix(buf, len);
+}
diff --git a/mixer.h b/mixer.h
new file mode 100644
index 0000000..4a2397e
--- /dev/null
+++ b/mixer.h
@@ -0,0 +1,108 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 MIXER_H__
+#define MIXER_H__
+
+#include "intern.h"
+#include "mod_player.h"
+#include "ogg_player.h"
+#include "sfx_player.h"
+
+struct MixerChunk {
+ uint8_t *data;
+ uint32_t len;
+
+ MixerChunk()
+ : data(0), len(0) {
+ }
+
+ int8_t getPCM(int offset) const {
+ if (offset < 0) {
+ offset = 0;
+ } else if (offset >= (int)len) {
+ offset = len - 1;
+ }
+ return (int8_t)data[offset];
+ }
+};
+
+struct MixerChannel {
+ uint8_t active;
+ uint8_t volume;
+ MixerChunk chunk;
+ uint32_t chunkPos;
+ uint32_t chunkInc;
+};
+
+struct FileSystem;
+struct SystemStub;
+
+struct Mixer {
+ typedef bool (*PremixHook)(void *userData, int8_t *buf, int len);
+
+ enum MusicType {
+ MT_NONE,
+ MT_MOD,
+ MT_OGG,
+ MT_SFX,
+ };
+
+ enum {
+ MUSIC_TRACK = 1000,
+ NUM_CHANNELS = 4,
+ FRAC_BITS = 12,
+ MAX_VOLUME = 64
+ };
+
+ FileSystem *_fs;
+ SystemStub *_stub;
+ MixerChannel _channels[NUM_CHANNELS];
+ PremixHook _premixHook;
+ void *_premixHookData;
+ MusicType _musicType;
+ ModPlayer _mod;
+ OggPlayer _ogg;
+ SfxPlayer _sfx;
+ int _musicTrack;
+
+ Mixer(FileSystem *fs, SystemStub *stub);
+ void init();
+ void free();
+ void setPremixHook(PremixHook premixHook, void *userData);
+ void play(const MixerChunk *mc, uint16_t freq, uint8_t volume);
+ bool isPlaying(const MixerChunk *mc) const;
+ uint32_t getSampleRate() const;
+ void stopAll();
+ void playMusic(int num);
+ void stopMusic();
+ void mix(int8_t *buf, int len);
+
+ static void addclamp(int8_t &a, int b);
+ static void mixCallback(void *param, int8_t *buf, int len);
+};
+
+template
+int resampleLinear(T *sample, int pos, int step, int fracBits) {
+ const int inputPos = pos >> fracBits;
+ const int inputFrac = pos & ((1 << fracBits) - 1);
+ int out = sample->getPCM(inputPos);
+ out += (sample->getPCM(inputPos + 1) - out) * inputFrac >> fracBits;
+ return out;
+}
+
+#endif // MIXER_H__
diff --git a/mod_player.cpp b/mod_player.cpp
new file mode 100644
index 0000000..3df55bf
--- /dev/null
+++ b/mod_player.cpp
@@ -0,0 +1,522 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "file.h"
+#include "mixer.h"
+#include "mod_player.h"
+
+
+ModPlayer::ModPlayer(Mixer *mixer, FileSystem *fs)
+ : _playing(false), _mix(mixer), _fs(fs) {
+ memset(&_modInfo, 0, sizeof(_modInfo));
+}
+
+uint16_t ModPlayer::findPeriod(uint16_t period, uint8_t fineTune) const {
+ for (int p = 0; p < 36; ++p) {
+ if (_periodTable[p] == period) {
+ return fineTune * 36 + p;
+ }
+ }
+ error("Invalid period=%d", period);
+ return 0;
+}
+
+void ModPlayer::load(File *f) {
+ f->read(_modInfo.songName, 20);
+ _modInfo.songName[20] = 0;
+ debug(DBG_MOD, "songName = '%s'", _modInfo.songName);
+
+ for (int s = 0; s < NUM_SAMPLES; ++s) {
+ SampleInfo *si = &_modInfo.samples[s];
+ f->read(si->name, 22);
+ si->name[22] = 0;
+ si->len = f->readUint16BE() * 2;
+ si->fineTune = f->readByte();
+ si->volume = f->readByte();
+ si->repeatPos = f->readUint16BE() * 2;
+ si->repeatLen = f->readUint16BE() * 2;
+ si->data = 0;
+ assert(si->len == 0 || si->repeatPos + si->repeatLen <= si->len);
+ debug(DBG_MOD, "sample=%d name='%s' len=%d vol=%d", s, si->name, si->len, si->volume);
+ }
+ _modInfo.numPatterns = f->readByte();
+ assert(_modInfo.numPatterns < NUM_PATTERNS);
+ f->readByte(); // 0x7F
+ f->read(_modInfo.patternOrderTable, NUM_PATTERNS);
+ f->readUint32BE(); // 'M.K.', Protracker, 4 channels
+
+ uint16_t n = 0;
+ for (int i = 0; i < NUM_PATTERNS; ++i) {
+ if (_modInfo.patternOrderTable[i] != 0) {
+ n = MAX(n, _modInfo.patternOrderTable[i]);
+ }
+ }
+ debug(DBG_MOD, "numPatterns=%d",n + 1);
+ n = (n + 1) * 64 * 4 * 4; // 64 lines of 4 notes per channel
+ _modInfo.patternsTable = (uint8_t *)malloc(n);
+ assert(_modInfo.patternsTable);
+ f->read(_modInfo.patternsTable, n);
+
+ for (int s = 0; s < NUM_SAMPLES; ++s) {
+ SampleInfo *si = &_modInfo.samples[s];
+ if (si->len != 0) {
+ si->data = (int8_t *)malloc(si->len);
+ if (si->data) {
+ f->read(si->data, si->len);
+ }
+ }
+ }
+}
+
+void ModPlayer::unload() {
+ if (_modInfo.songName[0]) {
+ free(_modInfo.patternsTable);
+ for (int s = 0; s < NUM_SAMPLES; ++s) {
+ free(_modInfo.samples[s].data);
+ }
+ memset(&_modInfo, 0, sizeof(_modInfo));
+ }
+}
+
+void ModPlayer::play(uint8_t num) {
+ if (!_playing && num < _modulesFilesCount) {
+ File f;
+ bool found = false;
+ for (uint8_t i = 0; i < ARRAYSIZE(_modulesFiles[num]); ++i) {
+ if (f.open(_modulesFiles[num][i], "rb", _fs)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ warning("Can't find music file %d", num);
+ } else {
+ load(&f);
+ _currentPatternOrder = 0;
+ _currentPatternPos = 0;
+ _currentTick = 0;
+ _patternDelay = 0;
+ _songSpeed = 6;
+ _songTempo = 125;
+ _patternLoopPos = 0;
+ _patternLoopCount = -1;
+ _samplesLeft = 0;
+ _songNum = num;
+ _introSongHack = false;
+ memset(_tracks, 0, sizeof(_tracks));
+ _mix->setPremixHook(mixCallback, this);
+ _playing = true;
+ }
+ }
+}
+
+void ModPlayer::stop() {
+ if (_playing) {
+ _mix->setPremixHook(0, 0);
+ _playing = false;
+ }
+ unload();
+}
+
+void ModPlayer::handleNote(int trackNum, uint32_t noteData) {
+ Track *tk = &_tracks[trackNum];
+ uint16_t sampleNum = ((noteData >> 24) & 0xF0) | ((noteData >> 12) & 0xF);
+ uint16_t samplePeriod = (noteData >> 16) & 0xFFF;
+ uint16_t effectData = noteData & 0xFFF;
+ debug(DBG_MOD, "ModPlayer::handleNote(%d) p=%d/%d sampleNumber=0x%X samplePeriod=0x%X effectData=0x%X tk->period=%d", trackNum, _currentPatternPos, _currentPatternOrder, sampleNum, samplePeriod, effectData, tk->period);
+ if (sampleNum != 0) {
+ tk->sample = &_modInfo.samples[sampleNum - 1];
+ tk->volume = tk->sample->volume;
+ tk->pos = 0;
+ }
+ if (samplePeriod != 0) {
+ tk->periodIndex = findPeriod(samplePeriod, tk->sample->fineTune);
+ if ((effectData >> 8) != 0x3 && (effectData >> 8) != 0x5) {
+ tk->period = _periodTable[tk->periodIndex];
+ tk->freq = PAULA_FREQ / tk->period;
+ } else {
+ tk->portamento = _periodTable[tk->periodIndex];
+ }
+ tk->vibratoAmp = 0;
+ tk->vibratoSpeed = 0;
+ tk->vibratoPos = 0;
+ }
+ tk->effectData = effectData;
+}
+
+void ModPlayer::applyVolumeSlide(int trackNum, int amount) {
+ debug(DBG_MOD, "ModPlayer::applyVolumeSlide(%d, %d)", trackNum, amount);
+ Track *tk = &_tracks[trackNum];
+ int vol = tk->volume + amount;
+ if (vol < 0) {
+ vol = 0;
+ } else if (vol > 64) {
+ vol = 64;
+ }
+ tk->volume = vol;
+}
+
+void ModPlayer::applyVibrato(int trackNum) {
+ debug(DBG_MOD, "ModPlayer::applyVibrato(%d)", trackNum);
+ Track *tk = &_tracks[trackNum];
+ int vib = tk->vibratoAmp * _sineWaveTable[tk->vibratoPos] / 128;
+ if (tk->period + vib != 0) {
+ tk->freq = PAULA_FREQ / (tk->period + vib);
+ }
+ tk->vibratoPos += tk->vibratoSpeed;
+ if (tk->vibratoPos >= 64) {
+ tk->vibratoPos = 0;
+ }
+}
+
+void ModPlayer::applyPortamento(int trackNum) {
+ debug(DBG_MOD, "ModPlayer::applyPortamento(%d)", trackNum);
+ Track *tk = &_tracks[trackNum];
+ if (tk->period < tk->portamento) {
+ tk->period = MIN(tk->period + tk->portamentoSpeed, tk->portamento);
+ } else if (tk->period > tk->portamento) {
+ tk->period = MAX(tk->period - tk->portamentoSpeed, tk->portamento);
+ }
+ if (tk->period != 0) {
+ tk->freq = PAULA_FREQ / tk->period;
+ }
+}
+
+void ModPlayer::handleEffect(int trackNum, bool tick) {
+ Track *tk = &_tracks[trackNum];
+ uint8_t effectNum = tk->effectData >> 8;
+ uint8_t effectXY = tk->effectData & 0xFF;
+ uint8_t effectX = effectXY >> 4;
+ uint8_t effectY = effectXY & 0xF;
+ debug(DBG_MOD, "ModPlayer::handleEffect(%d) effectNum=0x%X effectXY=0x%X", trackNum, effectNum, effectXY);
+ switch (effectNum) {
+ case 0x0: // arpeggio
+ if (tick && effectXY != 0) {
+ uint16_t period = tk->period;
+ switch (_currentTick & 3) {
+ case 1:
+ period = _periodTable[tk->periodIndex + effectX];
+ break;
+ case 2:
+ period = _periodTable[tk->periodIndex + effectY];
+ break;
+ }
+ tk->freq = PAULA_FREQ / period;
+ }
+ break;
+ case 0x1: // portamento up
+ if (tick) {
+ tk->period -= effectXY;
+ if (tk->period < 113) { // note B-3
+ tk->period = 113;
+ }
+ tk->freq = PAULA_FREQ / tk->period;
+ }
+ break;
+ case 0x2: // portamento down
+ if (tick) {
+ tk->period += effectXY;
+ if (tk->period > 856) { // note C-1
+ tk->period = 856;
+ }
+ tk->freq = PAULA_FREQ / tk->period;
+ }
+ break;
+ case 0x3: // tone portamento
+ if (!tick) {
+ if (effectXY != 0) {
+ tk->portamentoSpeed = effectXY;
+ }
+ } else {
+ applyPortamento(trackNum);
+ }
+ break;
+ case 0x4: // vibrato
+ if (!tick) {
+ if (effectX != 0) {
+ tk->vibratoSpeed = effectX;
+ }
+ if (effectY != 0) {
+ tk->vibratoAmp = effectY;
+ }
+ } else {
+ applyVibrato(trackNum);
+ }
+ break;
+ case 0x5: // tone portamento + volume slide
+ if (tick) {
+ applyPortamento(trackNum);
+ applyVolumeSlide(trackNum, effectX - effectY);
+ }
+ break;
+ case 0x6: // vibrato + volume slide
+ if (tick) {
+ applyVibrato(trackNum);
+ applyVolumeSlide(trackNum, effectX - effectY);
+ }
+ break;
+ case 0x9: // set sample offset
+ if (!tick) {
+ tk->pos = effectXY << (8 + FRAC_BITS);
+ }
+ break;
+ case 0xA: // volume slide
+ if (tick) {
+ applyVolumeSlide(trackNum, effectX - effectY);
+ }
+ break;
+ case 0xB: // position jump
+ if (!tick) {
+ _currentPatternOrder = effectXY;
+ _currentPatternPos = 0;
+ assert(_currentPatternOrder < _modInfo.numPatterns);
+ }
+ break;
+ case 0xC: // set volume
+ if (!tick) {
+ assert(effectXY <= 64);
+ tk->volume = effectXY;
+ }
+ break;
+ case 0xD: // pattern break
+ if (!tick) {
+ _currentPatternPos = effectX * 10 + effectY;
+ assert(_currentPatternPos < 64);
+ ++_currentPatternOrder;
+ debug(DBG_MOD, "_currentPatternPos = %d _currentPatternOrder = %d", _currentPatternPos, _currentPatternOrder);
+ }
+ break;
+ case 0xE: // extended effects
+ switch (effectX) {
+ case 0x0: // set filter, ignored
+ break;
+ case 0x1: // fineslide up
+ if (!tick) {
+ tk->period -= effectY;
+ if (tk->period < 113) { // B-3 note
+ tk->period = 113;
+ }
+ tk->freq = PAULA_FREQ / tk->period;
+ }
+ break;
+ case 0x2: // fineslide down
+ if (!tick) {
+ tk->period += effectY;
+ if (tk->period > 856) { // C-1 note
+ tk->period = 856;
+ }
+ tk->freq = PAULA_FREQ / tk->period;
+ }
+ break;
+ case 0x6: // loop pattern
+ if (!tick) {
+ if (effectY == 0) {
+ _patternLoopPos = _currentPatternPos | (_currentPatternOrder << 8);
+ debug(DBG_MOD, "_patternLoopPos=%d/%d", _currentPatternPos, _currentPatternOrder);
+ } else {
+ if (_patternLoopCount == -1) {
+ _patternLoopCount = effectY;
+ _currentPatternPos = _patternLoopPos & 0xFF;
+ _currentPatternOrder = _patternLoopPos >> 8;
+ } else {
+ --_patternLoopCount;
+ if (_patternLoopCount != 0) {
+ _currentPatternPos = _patternLoopPos & 0xFF;
+ _currentPatternOrder = _patternLoopPos >> 8;
+ } else {
+ _patternLoopCount = -1;
+ }
+ }
+ debug(DBG_MOD, "_patternLoopCount=%d", _patternLoopCount);
+ }
+ }
+ break;
+ case 0x9: // retrigger sample
+ if (tick) {
+ tk->retriggerCounter = effectY;
+ } else {
+ if (tk->retriggerCounter == 0) {
+ tk->pos = 0;
+ tk->retriggerCounter = effectY;
+ debug(DBG_MOD, "retrigger sample=%d _songSpeed=%d", effectY, _songSpeed);
+ }
+ --tk->retriggerCounter;
+ }
+ break;
+ case 0xA: // fine volume slide up
+ if (!tick) {
+ applyVolumeSlide(trackNum, effectY);
+ }
+ break;
+ case 0xB: // fine volume slide down
+ if (!tick) {
+ applyVolumeSlide(trackNum, -effectY);
+ }
+ break;
+ case 0xC: // cut sample
+ if (!tick) {
+ tk->cutCounter = effectY;
+ } else {
+ --tk->cutCounter;
+ if (tk->cutCounter == 0) {
+ tk->volume = 0;
+ }
+ }
+ case 0xD: // delay sample
+ if (!tick) {
+ tk->delayCounter = effectY;
+ } else {
+ if (tk->delayCounter != 0) {
+ --tk->delayCounter;
+ }
+ }
+ break;
+ case 0xE: // delay pattern
+ if (!tick) {
+ debug(DBG_MOD, "ModPlayer::handleEffect() _currentTick=%d delay pattern=%d", _currentTick, effectY);
+ _patternDelay = effectY;
+ }
+ break;
+ default:
+ warning("Unhandled extended effect 0x%X params=0x%X", effectX, effectY);
+ break;
+ }
+ break;
+ case 0xF: // set speed
+ if (!tick) {
+ if (effectXY < 0x20) {
+ _songSpeed = effectXY;
+ } else {
+ _songTempo = effectXY;
+ }
+ }
+ break;
+ default:
+ warning("Unhandled effect 0x%X params=0x%X", effectNum, effectXY);
+ break;
+ }
+}
+
+void ModPlayer::handleTick() {
+ if (!_playing) {
+ return;
+ }
+// if (_patternDelay != 0) {
+// --_patternDelay;
+// return;
+// }
+ if (_currentTick == 0) {
+ debug(DBG_MOD, "_currentPatternOrder=%d _currentPatternPos=%d", _currentPatternOrder, _currentPatternPos);
+ uint8_t currentPattern = _modInfo.patternOrderTable[_currentPatternOrder];
+ const uint8_t *p = _modInfo.patternsTable + (currentPattern * 64 + _currentPatternPos) * 16;
+ for (int i = 0; i < NUM_TRACKS; ++i) {
+ uint32_t noteData = READ_BE_UINT32(p);
+ handleNote(i, noteData);
+ p += 4;
+ }
+ ++_currentPatternPos;
+ if (_currentPatternPos == 64) {
+ ++_currentPatternOrder;
+ _currentPatternPos = 0;
+ debug(DBG_MOD, "ModPlayer::handleTick() _currentPatternOrder = %d/%d", _currentPatternOrder, _modInfo.numPatterns);
+ // On the amiga version, the introduction cutscene is shorter than the PC version ;
+ // so the music module doesn't synchronize at all with the PC datafiles, here we
+ // add a hack to let the music play longer
+ if (_songNum == 0 && _currentPatternOrder == 3 && !_introSongHack) {
+ _currentPatternOrder = 1;
+ _introSongHack = true;
+// warning("Introduction module synchronization hack");
+ }
+ }
+ }
+ for (int i = 0; i < NUM_TRACKS; ++i) {
+ handleEffect(i, (_currentTick != 0));
+ }
+ ++_currentTick;
+ if (_currentTick == _songSpeed) {
+ _currentTick = 0;
+ }
+ if (_currentPatternOrder == _modInfo.numPatterns) {
+ debug(DBG_MOD, "ModPlayer::handleEffect() _currentPatternOrder == _modInfo.numPatterns");
+ _playing = false;
+ }
+}
+
+void ModPlayer::mixSamples(int8_t *buf, int samplesLen) {
+ for (int i = 0; i < NUM_TRACKS; ++i) {
+ Track *tk = &_tracks[i];
+ if (tk->sample != 0 && tk->delayCounter == 0) {
+ int8_t *mixbuf = buf;
+ SampleInfo *si = tk->sample;
+ int len = si->len << FRAC_BITS;
+ int loopLen = si->repeatLen << FRAC_BITS;
+ int loopPos = si->repeatPos << FRAC_BITS;
+ int deltaPos = (tk->freq << FRAC_BITS) / _mix->getSampleRate();
+ int curLen = samplesLen;
+ int pos = tk->pos;
+ while (curLen != 0) {
+ int count;
+ if (loopLen > (2 << FRAC_BITS)) {
+ if (pos >= loopPos + loopLen) {
+ pos -= loopLen;
+ }
+ count = MIN(curLen, (loopPos + loopLen - pos - 1) / deltaPos + 1);
+ curLen -= count;
+ } else {
+ if (pos >= len) {
+ count = 0;
+ } else {
+ count = MIN(curLen, (len - pos - 1) / deltaPos + 1);
+ }
+ curLen = 0;
+ }
+ while (count--) {
+ int out = resampleLinear(si, pos, deltaPos, FRAC_BITS);
+ Mixer::addclamp(*mixbuf++, out * tk->volume / 64);
+ pos += deltaPos;
+ }
+ }
+ tk->pos = pos;
+ }
+ }
+}
+
+bool ModPlayer::mix(int8_t *buf, int len) {
+ if (_playing) {
+ memset(buf, 0, len);
+ const int samplesPerTick = _mix->getSampleRate() / (50 * _songTempo / 125);
+ while (len != 0) {
+ if (_samplesLeft == 0) {
+ handleTick();
+ _samplesLeft = samplesPerTick;
+ }
+ int count = _samplesLeft;
+ if (count > len) {
+ count = len;
+ }
+ _samplesLeft -= count;
+ len -= count;
+ mixSamples(buf, count);
+ buf += count;
+ }
+ }
+ return _playing;
+}
+
+bool ModPlayer::mixCallback(void *param, int8_t *buf, int len) {
+ return ((ModPlayer *)param)->mix(buf, len);
+}
diff --git a/mod_player.h b/mod_player.h
new file mode 100644
index 0000000..4ae6683
--- /dev/null
+++ b/mod_player.h
@@ -0,0 +1,122 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 MOD_PLAYER_H__
+#define MOD_PLAYER_H__
+
+#include "intern.h"
+
+struct File;
+struct FileSystem;
+struct Mixer;
+
+struct ModPlayer {
+ enum {
+ NUM_SAMPLES = 31,
+ NUM_TRACKS = 4,
+ NUM_PATTERNS = 128,
+ FRAC_BITS = 12,
+ PAULA_FREQ = 3546897
+ };
+
+ struct SampleInfo {
+ char name[23];
+ uint16_t len;
+ uint8_t fineTune;
+ uint8_t volume;
+ uint16_t repeatPos;
+ uint16_t repeatLen;
+ int8_t *data;
+
+ int8_t getPCM(int offset) const {
+ if (offset < 0) {
+ offset = 0;
+ } else if (offset >= (int)len) {
+ offset = len - 1;
+ }
+ return data[offset];
+ }
+ };
+
+ struct ModuleInfo {
+ char songName[21];
+ SampleInfo samples[NUM_SAMPLES];
+ uint8_t numPatterns;
+ uint8_t patternOrderTable[NUM_PATTERNS];
+ uint8_t *patternsTable;
+ };
+
+ struct Track {
+ SampleInfo *sample;
+ uint8_t volume;
+ int pos;
+ int freq;
+ uint16_t period;
+ uint16_t periodIndex;
+ uint16_t effectData;
+ int vibratoSpeed;
+ int vibratoAmp;
+ int vibratoPos;
+ int portamento;
+ int portamentoSpeed;
+ int retriggerCounter;
+ int delayCounter;
+ int cutCounter;
+ };
+
+ static const int8_t _sineWaveTable[];
+ static const uint16_t _periodTable[];
+ static const char *_modulesFiles[][2];
+ static const int _modulesFilesCount;
+
+ ModuleInfo _modInfo;
+ uint8_t _currentPatternOrder;
+ uint8_t _currentPatternPos;
+ uint8_t _currentTick;
+ uint8_t _songSpeed;
+ uint8_t _songTempo;
+ int _patternDelay;
+ int _patternLoopPos;
+ int _patternLoopCount;
+ int _samplesLeft;
+ uint8_t _songNum;
+ bool _introSongHack;
+ bool _playing;
+ Track _tracks[NUM_TRACKS];
+ Mixer *_mix;
+ FileSystem *_fs;
+
+ ModPlayer(Mixer *mixer, FileSystem *fs);
+
+ uint16_t findPeriod(uint16_t period, uint8_t fineTune) const;
+ void load(File *f);
+ void unload();
+ void play(uint8_t num);
+ void stop();
+ void handleNote(int trackNum, uint32_t noteData);
+ void handleTick();
+ void applyVolumeSlide(int trackNum, int amount);
+ void applyVibrato(int trackNum);
+ void applyPortamento(int trackNum);
+ void handleEffect(int trackNum, bool tick);
+ void mixSamples(int8_t *buf, int len);
+ bool mix(int8_t *buf, int len);
+
+ static bool mixCallback(void *param, int8_t *buf, int len);
+};
+
+#endif // MOD_PLAYER_H__
diff --git a/ogg_player.cpp b/ogg_player.cpp
new file mode 100644
index 0000000..0daf5f7
--- /dev/null
+++ b/ogg_player.cpp
@@ -0,0 +1,214 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 .
+ */
+
+#ifdef USE_TREMOR
+#include
+#endif
+#include "file.h"
+#include "mixer.h"
+#include "ogg_player.h"
+
+#ifdef USE_TREMOR
+struct VorbisFile: File {
+ uint32_t offset;
+
+ static size_t readHelper(void *ptr, size_t size, size_t nmemb, void *datasource) {
+ VorbisFile *vf = (VorbisFile *)datasource;
+ if (size != 0 && nmemb != 0) {
+ const int n = vf->read(ptr, size * nmemb);
+ if (n > 0) {
+ vf->offset += n;
+ return n / size;
+ }
+ }
+ return 0;
+ }
+ static int seekHelper(void *datasource, ogg_int64_t offset, int whence) {
+ VorbisFile *vf = (VorbisFile *)datasource;
+ switch (whence) {
+ case SEEK_SET:
+ vf->offset = offset;
+ break;
+ case SEEK_CUR:
+ vf->offset += offset;
+ break;
+ case SEEK_END:
+ vf->offset = vf->size() + offset;
+ break;
+ }
+ vf->seek(vf->offset);
+ return 0;
+ }
+ static int closeHelper(void *datasource) {
+ VorbisFile *vf = (VorbisFile *)datasource;
+ vf->close();
+ delete vf;
+ return 0;
+ }
+ static long tellHelper(void *datasource) {
+ VorbisFile *vf = (VorbisFile *)datasource;
+ return vf->offset;
+ }
+};
+
+struct OggDecoder_impl {
+ OggDecoder_impl()
+ : _open(false), _readBuf(0), _readBufSize(0) {
+ }
+ ~OggDecoder_impl() {
+ free(_readBuf);
+ _readBuf = 0;
+ if (_open) {
+ ov_clear(&_ovf);
+ }
+ }
+
+ bool load(VorbisFile *f, int mixerSampleRate) {
+ ov_callbacks ovcb;
+ ovcb.read_func = VorbisFile::readHelper;
+ ovcb.seek_func = VorbisFile::seekHelper;
+ ovcb.close_func = VorbisFile::closeHelper;
+ ovcb.tell_func = VorbisFile::tellHelper;
+ if (ov_open_callbacks(f, &_ovf, 0, 0, ovcb) < 0) {
+ warning("Invalid .ogg file");
+ return false;
+ }
+ _open = true;
+ vorbis_info *vi = ov_info(&_ovf, -1);
+ if ((vi->channels != 1 && vi->channels != 2) || vi->rate != mixerSampleRate) {
+ warning("Unhandled ogg/pcm format ch %d rate %d", vi->channels, vi->rate);
+ return false;
+ }
+ _channels = vi->channels;
+ return true;
+ }
+ int read(int8_t *dst, int samples) {
+ int size = samples * _channels * sizeof(int16_t);
+ if (size > _readBufSize) {
+ _readBufSize = size;
+ free(_readBuf);
+ _readBuf = (int16_t *)malloc(_readBufSize);
+ if (!_readBuf) {
+ return 0;
+ }
+ }
+ int count = 0;
+ while (size > 0) {
+ const int len = ov_read(&_ovf, (char *)_readBuf, size, 0);
+ if (len < 0) {
+ // error in decoder
+ return 0;
+ } else if (len == 0) {
+ // loop
+ ov_raw_seek(&_ovf, 0);
+ continue;
+ }
+ switch (_channels) {
+ case 2:
+ assert((len & 1) == 0);
+ for (int i = 0; i < len / 2; i += 2) {
+ Mixer::addclamp(*dst++, ((_readBuf[i] + _readBuf[i + 1]) / 2) >> 8);
+ }
+ break;
+ case 1:
+ for (int i = 0; i < len / 2; ++i) {
+ Mixer::addclamp(*dst++, _readBuf[i] >> 8);
+ }
+ break;
+ }
+ size -= len;
+ count += len;
+ }
+ assert(size == 0);
+ return count;
+ }
+
+ OggVorbis_File _ovf;
+ int _channels;
+ bool _open;
+ int16_t *_readBuf;
+ int _readBufSize;
+};
+#endif
+
+OggPlayer::OggPlayer(Mixer *mixer, FileSystem *fs)
+ : _mix(mixer), _fs(fs), _impl(0) {
+}
+
+OggPlayer::~OggPlayer() {
+#ifdef USE_TREMOR
+ delete _impl;
+#endif
+}
+
+bool OggPlayer::playTrack(int num) {
+#ifdef USE_TREMOR
+ stopTrack();
+ char buf[16];
+ snprintf(buf, sizeof(buf), "track%02d.ogg", num);
+ VorbisFile *vf = new VorbisFile;
+ if (vf->open(buf, "rb", _fs)) {
+ vf->offset = 0;
+ _impl = new OggDecoder_impl();
+ if (_impl->load(vf, _mix->getSampleRate())) {
+ debug(DBG_INFO, "Playing '%s'", buf);
+ _mix->setPremixHook(mixCallback, this);
+ return true;
+ }
+ }
+ delete vf;
+#endif
+ return false;
+}
+
+void OggPlayer::stopTrack() {
+#ifdef USE_TREMOR
+ _mix->setPremixHook(0, 0);
+ delete _impl;
+ _impl = 0;
+#endif
+}
+
+void OggPlayer::pauseTrack() {
+#ifdef USE_TREMOR
+ if (_impl) {
+ _mix->setPremixHook(0, 0);
+ }
+#endif
+}
+
+void OggPlayer::resumeTrack() {
+#ifdef USE_TREMOR
+ if (_impl) {
+ _mix->setPremixHook(mixCallback, this);
+ }
+#endif
+}
+
+bool OggPlayer::mix(int8_t *buf, int len) {
+#ifdef USE_TREMOR
+ if (_impl) {
+ return _impl->read(buf, len) != 0;
+ }
+#endif
+ return false;
+}
+
+bool OggPlayer::mixCallback(void *param, int8_t *buf, int len) {
+ return ((OggPlayer *)param)->mix(buf, len);
+}
+
diff --git a/ogg_player.h b/ogg_player.h
new file mode 100644
index 0000000..9d11d7e
--- /dev/null
+++ b/ogg_player.h
@@ -0,0 +1,45 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 OGG_PLAYER_H__
+#define OGG_PLAYER_H__
+
+#include "intern.h"
+
+struct FileSystem;
+struct Mixer;
+struct OggDecoder_impl;
+
+struct OggPlayer {
+ OggPlayer(Mixer *mixer, FileSystem *fs);
+ ~OggPlayer();
+
+ bool playTrack(int num);
+ void stopTrack();
+ void pauseTrack();
+ void resumeTrack();
+ bool isPlaying() const { return _impl != 0; }
+ bool mix(int8_t *buf, int len);
+ static bool mixCallback(void *param, int8_t *buf, int len);
+
+ Mixer *_mix;
+ FileSystem *_fs;
+ OggDecoder_impl *_impl;
+};
+
+#endif // OGG_PLAYER_H__
+
diff --git a/piege.cpp b/piege.cpp
new file mode 100644
index 0000000..1ebe781
--- /dev/null
+++ b/piege.cpp
@@ -0,0 +1,2264 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "cutscene.h"
+#include "resource.h"
+#include "systemstub.h"
+#include "game.h"
+
+
+void Game::pge_resetGroups() {
+ memset(_pge_groupsTable, 0, sizeof(_pge_groupsTable));
+ GroupPGE *le = &_pge_groups[0];
+ _pge_nextFreeGroup = le;
+ int n = 0xFF;
+ while (n--) {
+ le->next_entry = le + 1;
+ le->index = 0;
+ le->group_id = 0;
+ ++le;
+ }
+ le->next_entry = 0;
+ le->index = 0;
+ le->group_id = 0;
+}
+
+void Game::pge_removeFromGroup(uint8_t idx) {
+ GroupPGE *le = _pge_groupsTable[idx];
+ if (le) {
+ _pge_groupsTable[idx] = 0;
+ GroupPGE *next = _pge_nextFreeGroup;
+ while (le) {
+ GroupPGE *cur = le->next_entry;
+ le->next_entry = next;
+ le->index = 0;
+ le->group_id = 0;
+ next = le;
+ le = cur;
+ }
+ _pge_nextFreeGroup = next;
+ }
+}
+
+int Game::pge_isInGroup(LivePGE *pge_dst, uint16_t group_id, uint16_t counter) {
+ assert(counter >= 1 && counter <= 4);
+ uint16_t c = pge_dst->init_PGE->counter_values[counter - 1];
+ GroupPGE *le = _pge_groupsTable[pge_dst->index];
+ while (le) {
+ if (le->group_id == group_id && le->index == c)
+ return 1;
+ le = le->next_entry;
+ }
+ return 0;
+}
+
+void Game::pge_loadForCurrentLevel(uint16_t idx) {
+ debug(DBG_PGE, "Game::pge_loadForCurrentLevel() idx=%d", idx);
+
+ LivePGE *live_pge = &_pgeLive[idx];
+ InitPGE *init_pge = &_res._pgeInit[idx];
+
+ live_pge->init_PGE = init_pge;
+ live_pge->obj_type = init_pge->type;
+ live_pge->pos_x = init_pge->pos_x;
+ live_pge->pos_y = init_pge->pos_y;
+ live_pge->anim_seq = 0;
+ live_pge->room_location = init_pge->init_room;
+
+ live_pge->life = init_pge->life;
+ if (_skillLevel >= 2 && init_pge->object_type == 10) {
+ live_pge->life *= 2;
+ }
+ live_pge->counter_value = 0;
+ live_pge->collision_slot = 0xFF;
+ live_pge->next_inventory_PGE = 0xFF;
+ live_pge->current_inventory_PGE = 0xFF;
+ live_pge->unkF = 0xFF;
+ live_pge->anim_number = 0;
+ live_pge->index = idx;
+ live_pge->next_PGE_in_room = 0;
+
+ uint16_t flags = 0;
+ if (init_pge->skill <= _skillLevel) {
+ if (init_pge->room_location != 0 || ((init_pge->flags & 4) && (_currentRoom == init_pge->init_room))) {
+ flags |= 4;
+ _pge_liveTable2[idx] = live_pge;
+ }
+ if (init_pge->mirror_x != 0) {
+ flags |= 1;
+ }
+ if (init_pge->init_flags & 8) {
+ flags |= 0x10;
+ }
+ flags |= (init_pge->init_flags & 3) << 5;
+ if (init_pge->flags & 2) {
+ flags |= 0x80;
+ }
+ live_pge->flags = flags;
+ assert(init_pge->obj_node_number < _res._numObjectNodes);
+ ObjectNode *on = _res._objectNodesMap[init_pge->obj_node_number];
+ Object *obj = on->objects;
+ int i = 0;
+ while (obj->type != live_pge->obj_type) {
+ ++i;
+ ++obj;
+ }
+ assert(i < on->num_objects);
+ live_pge->first_obj_number = i;
+ pge_setupDefaultAnim(live_pge);
+ }
+}
+
+void Game::pge_process(LivePGE *pge) {
+ debug(DBG_PGE, "Game::pge_process() pge_num=%d", pge - &_pgeLive[0]);
+ _pge_playAnimSound = true;
+ _pge_currentPiegeFacingDir = (pge->flags & 1) != 0;
+ _pge_currentPiegeRoom = pge->room_location;
+ GroupPGE *le = _pge_groupsTable[pge->index];
+ if (le) {
+ pge_setupNextAnimFrame(pge, le);
+ }
+ const uint8_t *anim_data = _res.getAniData(pge->obj_type);
+ if (READ_LE_UINT16(anim_data) <= pge->anim_seq) {
+ InitPGE *init_pge = pge->init_PGE;
+ assert(init_pge->obj_node_number < _res._numObjectNodes);
+ ObjectNode *on = _res._objectNodesMap[init_pge->obj_node_number];
+ Object *obj = &on->objects[pge->first_obj_number];
+ while (1) {
+ if (obj->type != pge->obj_type) {
+ pge_removeFromGroup(pge->index);
+ return;
+ }
+ uint16_t _ax = pge_execute(pge, init_pge, obj);
+ if (_ax != 0) {
+ anim_data = _res.getAniData(pge->obj_type);
+ uint8_t snd = anim_data[2];
+ if (snd) {
+ pge_playAnimSound(pge, snd);
+ }
+ pge_setupOtherPieges(pge, init_pge);
+ break;
+ }
+ ++obj;
+ }
+ }
+ pge_setupAnim(pge);
+ ++pge->anim_seq;
+ pge_removeFromGroup(pge->index);
+}
+
+void Game::pge_setupNextAnimFrame(LivePGE *pge, GroupPGE *le) {
+ InitPGE *init_pge = pge->init_PGE;
+ assert(init_pge->obj_node_number < _res._numObjectNodes);
+ ObjectNode *on = _res._objectNodesMap[init_pge->obj_node_number];
+ Object *obj = &on->objects[pge->first_obj_number];
+ int i = pge->first_obj_number;
+ while (i < on->last_obj_number && pge->obj_type == obj->type) {
+ GroupPGE *next_le = le;
+ while (next_le) {
+ uint16_t groupId = next_le->group_id;
+ if (obj->opcode2 == 0x6B) { // pge_op_isInGroupSlice
+ if (obj->opcode_arg2 == 0) {
+ if (groupId == 1 || groupId == 2) goto set_anim;
+ }
+ if (obj->opcode_arg2 == 1) {
+ if (groupId == 3 || groupId == 4) goto set_anim;
+ }
+ } else if (groupId == obj->opcode_arg2) {
+ if (obj->opcode2 == 0x22 || obj->opcode2 == 0x6F) goto set_anim;
+ }
+ if (obj->opcode1 == 0x6B) { // pge_op_isInGroupSlice
+ if (obj->opcode_arg1 == 0) {
+ if (groupId == 1 || groupId == 2) goto set_anim;
+ }
+ if (obj->opcode_arg1 == 1) {
+ if (groupId == 3 || groupId == 4) goto set_anim;
+ }
+ } else if (groupId == obj->opcode_arg1) {
+ if (obj->opcode1 == 0x22 || obj->opcode1 == 0x6F) goto set_anim;
+ }
+ next_le = next_le->next_entry;
+ }
+ ++obj;
+ ++i;
+ }
+ return;
+
+set_anim:
+ const uint8_t *anim_data = _res.getAniData(pge->obj_type);
+ uint8_t _dh = READ_LE_UINT16(anim_data);
+ uint8_t _dl = pge->anim_seq;
+ const uint8_t *anim_frame = anim_data + 6 + _dl * 4;
+ while (_dh > _dl) {
+ if (READ_LE_UINT16(anim_frame) != 0xFFFF) {
+ if (_pge_currentPiegeFacingDir) {
+ pge->pos_x -= (int8_t)anim_frame[2];
+ } else {
+ pge->pos_x += (int8_t)anim_frame[2];
+ }
+ pge->pos_y += (int8_t)anim_frame[3];
+ }
+ anim_frame += 4;
+ ++_dl;
+ }
+ pge->anim_seq = _dh;
+ _col_currentPiegeGridPosY = (pge->pos_y / 36) & ~1;
+ _col_currentPiegeGridPosX = (pge->pos_x + 8) >> 4;
+}
+
+void Game::pge_playAnimSound(LivePGE *pge, uint16_t arg2) {
+ if ((pge->flags & 4) && _pge_playAnimSound) {
+ uint8_t sfxId = (arg2 & 0xFF) - 1;
+ if (_currentRoom == pge->room_location) {
+ playSound(sfxId, 0);
+ } else {
+ if (_res._ctData[CT_DOWN_ROOM + _currentRoom] == pge->room_location ||
+ _res._ctData[CT_UP_ROOM + _currentRoom] == pge->room_location ||
+ _res._ctData[CT_RIGHT_ROOM + _currentRoom] == pge->room_location ||
+ _res._ctData[CT_LEFT_ROOM + _currentRoom] == pge->room_location) {
+ playSound(sfxId, 1);
+ }
+ }
+ }
+}
+
+void Game::pge_setupAnim(LivePGE *pge) {
+ debug(DBG_PGE, "Game::pge_setupAnim() pgeNum=%d", pge - &_pgeLive[0]);
+ const uint8_t *anim_data = _res.getAniData(pge->obj_type);
+ if (READ_LE_UINT16(anim_data) < pge->anim_seq) {
+ pge->anim_seq = 0;
+ }
+ const uint8_t *anim_frame = anim_data + 6 + pge->anim_seq * 4;
+ if (READ_LE_UINT16(anim_frame) != 0xFFFF) {
+ uint16_t fl = READ_LE_UINT16(anim_frame);
+ if (pge->flags & 1) {
+ fl ^= 0x8000;
+ pge->pos_x -= (int8_t)anim_frame[2];
+ } else {
+ pge->pos_x += (int8_t)anim_frame[2];
+ }
+ pge->pos_y += (int8_t)anim_frame[3];
+ pge->flags &= ~2;
+ if (fl & 0x8000) {
+ pge->flags |= 2;
+ }
+ pge->flags &= ~8;
+ if (READ_LE_UINT16(anim_data + 4) & 0xFFFF) {
+ pge->flags |= 8;
+ }
+ pge->anim_number = READ_LE_UINT16(anim_frame) & 0x7FFF;
+ }
+}
+
+int Game::pge_execute(LivePGE *live_pge, InitPGE *init_pge, const Object *obj) {
+ debug(DBG_PGE, "Game::pge_execute() pge_num=%d op1=0x%X op2=0x%X op3=0x%X", live_pge - &_pgeLive[0], obj->opcode1, obj->opcode2, obj->opcode3);
+ pge_OpcodeProc op;
+ ObjectOpcodeArgs args;
+ if (obj->opcode1) {
+ args.pge = live_pge;
+ args.a = obj->opcode_arg1;
+ args.b = 0;
+ debug(DBG_PGE, "pge_execute op1=0x%X", obj->opcode1);
+ op = _pge_opcodeTable[obj->opcode1];
+ if (!op) {
+ warning("Game::pge_execute() missing call to pge_opcode 0x%X", obj->opcode1);
+ return 0;
+ }
+ if (!((this->*op)(&args) & 0xFF))
+ return 0;
+ }
+ if (obj->opcode2) {
+ args.pge = live_pge;
+ args.a = obj->opcode_arg2;
+ args.b = obj->opcode_arg1;
+ debug(DBG_PGE, "pge_execute op2=0x%X", obj->opcode2);
+ op = _pge_opcodeTable[obj->opcode2];
+ if (!op) {
+ warning("Game::pge_execute() missing call to pge_opcode 0x%X", obj->opcode2);
+ return 0;
+ }
+ if (!((this->*op)(&args) & 0xFF))
+ return 0;
+ }
+ if (obj->opcode3) {
+ args.pge = live_pge;
+ args.a = obj->opcode_arg3;
+ args.b = 0;
+ debug(DBG_PGE, "pge_execute op3=0x%X", obj->opcode3);
+ op = _pge_opcodeTable[obj->opcode3];
+ if (op) {
+ (this->*op)(&args);
+ } else {
+ warning("Game::pge_execute() missing call to pge_opcode 0x%X", obj->opcode3);
+ }
+ }
+ live_pge->obj_type = obj->init_obj_type;
+ live_pge->first_obj_number = obj->init_obj_number;
+ live_pge->anim_seq = 0;
+ if (obj->flags & 0xF0) {
+ _score += _scoreTable[obj->flags >> 4];
+ }
+ if (obj->flags & 1) {
+ live_pge->flags ^= 1;
+ }
+ if (obj->flags & 2) {
+ --live_pge->life;
+ if (init_pge->object_type == 1) {
+ _pge_processOBJ = true;
+ } else if (init_pge->object_type == 10) {
+ _score += 100;
+ }
+ }
+ if (obj->flags & 4) {
+ ++live_pge->life;
+ }
+ if (obj->flags & 8) {
+ live_pge->life = 0xFFFF;
+ }
+
+ if (live_pge->flags & 1) {
+ live_pge->pos_x -= obj->dx;
+ } else {
+ live_pge->pos_x += obj->dx;
+ }
+ live_pge->pos_y += obj->dy;
+
+ if (_pge_processOBJ) {
+ if (init_pge->object_type == 1) {
+ if (pge_processOBJ(live_pge) != 0) {
+ _blinkingConradCounter = 60;
+ _pge_processOBJ = false;
+ }
+ }
+ }
+ return 0xFFFF;
+}
+
+void Game::pge_prepare() {
+ col_clearState();
+ if (!(_currentRoom & 0x80)) {
+ LivePGE *pge = _pge_liveTable1[_currentRoom];
+ while (pge) {
+ col_preparePiegeState(pge);
+ if (!(pge->flags & 4) && (pge->init_PGE->flags & 4)) {
+ _pge_liveTable2[pge->index] = pge;
+ pge->flags |= 4;
+ }
+ pge = pge->next_PGE_in_room;
+ }
+ }
+ for (uint16_t i = 0; i < _res._pgeNum; ++i) {
+ LivePGE *pge = _pge_liveTable2[i];
+ if (pge && _currentRoom != pge->room_location) {
+ col_preparePiegeState(pge);
+ }
+ }
+}
+
+void Game::pge_setupDefaultAnim(LivePGE *pge) {
+ const uint8_t *anim_data = _res.getAniData(pge->obj_type);
+ if (pge->anim_seq < READ_LE_UINT16(anim_data)) {
+ pge->anim_seq = 0;
+ }
+ const uint8_t *anim_frame = anim_data + 6 + pge->anim_seq * 4;
+ if (READ_LE_UINT16(anim_frame) != 0xFFFF) {
+ uint16_t f = READ_LE_UINT16(anim_data);
+ if (pge->flags & 1) {
+ f ^= 0x8000;
+ }
+ pge->flags &= ~2;
+ if (f & 0x8000) {
+ pge->flags |= 2;
+ }
+ pge->flags &= ~8;
+ if (READ_LE_UINT16(anim_data + 4) & 0xFFFF) {
+ pge->flags |= 8;
+ }
+ pge->anim_number = READ_LE_UINT16(anim_frame) & 0x7FFF;
+ debug(DBG_PGE, "Game::pge_setupDefaultAnim() pgeNum=%d pge->flags=0x%X pge->anim_number=0x%X pge->anim_seq=0x%X", pge - &_pgeLive[0], pge->flags, pge->anim_number, pge->anim_seq);
+ }
+}
+
+uint16_t Game::pge_processOBJ(LivePGE *pge) {
+ InitPGE *init_pge = pge->init_PGE;
+ assert(init_pge->obj_node_number < _res._numObjectNodes);
+ ObjectNode *on = _res._objectNodesMap[init_pge->obj_node_number];
+ Object *obj = &on->objects[pge->first_obj_number];
+ int i = pge->first_obj_number;
+ while (i < on->last_obj_number && pge->obj_type == obj->type) {
+ if (obj->opcode2 == 0x6B) return 0xFFFF;
+ if (obj->opcode2 == 0x22 && obj->opcode_arg2 <= 4) return 0xFFFF;
+
+ if (obj->opcode1 == 0x6B) return 0xFFFF;
+ if (obj->opcode1 == 0x22 && obj->opcode_arg1 <= 4) return 0xFFFF;
+
+ ++obj;
+ ++i;
+ }
+ return 0;
+}
+
+void Game::pge_setupOtherPieges(LivePGE *pge, InitPGE *init_pge) {
+ const int8_t *room_ct_data = 0;
+ if (pge->pos_x <= -10) {
+ pge->pos_x += 256;
+ room_ct_data = &_res._ctData[CT_LEFT_ROOM];
+ } else if (pge->pos_x >= 256) {
+ pge->pos_x -= 256;
+ room_ct_data = &_res._ctData[CT_RIGHT_ROOM];
+ } else if (pge->pos_y < 0) {
+ pge->pos_y += 216;
+ room_ct_data = &_res._ctData[CT_UP_ROOM];
+ } else if (pge->pos_y >= 216) {
+ pge->pos_y -= 216;
+ room_ct_data = &_res._ctData[CT_DOWN_ROOM];
+ }
+ if (room_ct_data) {
+ int8_t room = pge->room_location;
+ if (room >= 0) {
+ room = room_ct_data[room];
+ pge->room_location = room;
+ }
+ if (init_pge->object_type == 1) {
+ _currentRoom = room;
+ col_prepareRoomState();
+ _loadMap = true;
+ if (!(_currentRoom & 0x80) && _currentRoom < 0x40) {
+ LivePGE *pge_it = _pge_liveTable1[_currentRoom];
+ while (pge_it) {
+ if (pge_it->init_PGE->flags & 4) {
+ _pge_liveTable2[pge_it->index] = pge_it;
+ pge_it->flags |= 4;
+ }
+ pge_it = pge_it->next_PGE_in_room;
+ }
+ room = _res._ctData[CT_UP_ROOM + _currentRoom];
+ if (room >= 0 && room < 0x40) {
+ pge_it = _pge_liveTable1[room];
+ while (pge_it) {
+ if (pge_it->init_PGE->object_type != 10 && pge_it->pos_y >= 48 && (pge_it->init_PGE->flags & 4)) {
+ _pge_liveTable2[pge_it->index] = pge_it;
+ pge_it->flags |= 4;
+ }
+ pge_it = pge_it->next_PGE_in_room;
+ }
+ }
+ room = _res._ctData[CT_DOWN_ROOM + _currentRoom];
+ if (room >= 0 && room < 0x40) {
+ pge_it = _pge_liveTable1[room];
+ while (pge_it) {
+ if (pge_it->init_PGE->object_type != 10 && pge_it->pos_y >= 176 && (pge_it->init_PGE->flags & 4)) {
+ _pge_liveTable2[pge_it->index] = pge_it;
+ pge_it->flags |= 4;
+ }
+ pge_it = pge_it->next_PGE_in_room;
+ }
+ }
+ }
+ }
+ }
+ pge_addToCurrentRoomList(pge, _pge_currentPiegeRoom);
+}
+
+void Game::pge_addToCurrentRoomList(LivePGE *pge, uint8_t room) {
+ debug(DBG_PGE, "Game::pge_addToCurrentRoomList() pgeNum=%d room=%d", pge - &_pgeLive[0], room);
+ if (room != pge->room_location) {
+ LivePGE *cur_pge = _pge_liveTable1[room];
+ LivePGE *prev_pge = 0;
+ while (cur_pge && cur_pge != pge) {
+ prev_pge = cur_pge;
+ cur_pge = cur_pge->next_PGE_in_room;
+ }
+ if (cur_pge) {
+ if (!prev_pge) {
+ _pge_liveTable1[room] = pge->next_PGE_in_room;
+ } else {
+ prev_pge->next_PGE_in_room = cur_pge->next_PGE_in_room;
+ }
+ LivePGE *temp = _pge_liveTable1[pge->room_location];
+ pge->next_PGE_in_room = temp;
+ _pge_liveTable1[pge->room_location] = pge;
+ }
+ }
+}
+
+void Game::pge_getInput() {
+ inp_update();
+ _inp_lastKeysHit = _stub->_pi.dirMask;
+ if (_stub->_pi.mirrorMode && (_inp_lastKeysHit & 0xC)) {
+ _inp_lastKeysHit ^= 0xC; // invert left/right
+ }
+ if ((_inp_lastKeysHit & 0xC) && (_inp_lastKeysHit & 0x3)) {
+ const uint8_t mask = (_inp_lastKeysHit & 0xF0) | (_inp_lastKeysHitLeftRight & 0xF);
+ _pge_inpKeysMask = mask;
+ _inp_lastKeysHit = mask;
+ } else {
+ _pge_inpKeysMask = _inp_lastKeysHit;
+ _inp_lastKeysHitLeftRight = _inp_lastKeysHit;
+ }
+ if (_stub->_pi.enter) {
+ _pge_inpKeysMask |= 0x10;
+ }
+ if (_stub->_pi.space) {
+ _pge_inpKeysMask |= 0x20;
+ }
+ if (_stub->_pi.shift) {
+ _pge_inpKeysMask |= 0x40;
+ }
+}
+
+int Game::pge_op_isInpUp(ObjectOpcodeArgs *args) {
+ if (1 == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_isInpBackward(ObjectOpcodeArgs *args) {
+ uint8_t mask = 8; // right
+ if (_pge_currentPiegeFacingDir) {
+ mask = 4; // left
+ }
+ if (mask == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_isInpDown(ObjectOpcodeArgs *args) {
+ if (2 == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_isInpForward(ObjectOpcodeArgs *args) {
+ uint8_t mask = 4;
+ if (_pge_currentPiegeFacingDir) {
+ mask = 8;
+ }
+ if (mask == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_isInpUpMod(ObjectOpcodeArgs *args) {
+ assert(args->a < 3);
+ uint8_t mask = _pge_modKeysTable[args->a] | 1;
+ if (mask == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_isInpBackwardMod(ObjectOpcodeArgs *args) {
+ assert(args->a < 3);
+ uint8_t mask = _pge_modKeysTable[args->a];
+ if (_pge_currentPiegeFacingDir) {
+ mask |= 4;
+ } else {
+ mask |= 8;
+ }
+ if (mask == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_isInpDownMod(ObjectOpcodeArgs *args) {
+ assert(args->a < 3);
+ uint8_t mask = _pge_modKeysTable[args->a] | 2;
+ if (mask == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_isInpForwardMod(ObjectOpcodeArgs *args) {
+ assert(args->a < 3);
+ uint8_t mask = _pge_modKeysTable[args->a];
+ if (_pge_currentPiegeFacingDir) {
+ mask |= 8;
+ } else {
+ mask |= 4;
+ }
+ if (mask == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_isInpIdle(ObjectOpcodeArgs *args) {
+ if (_pge_inpKeysMask == 0) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_isInpNoMod(ObjectOpcodeArgs *args) {
+ assert(args->a < 3);
+ uint8_t mask = _pge_modKeysTable[args->a];
+ if (((_pge_inpKeysMask & 0xF) | mask) == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_getCollision0u(ObjectOpcodeArgs *args) {
+ return col_getGridData(args->pge, 0, -args->a);
+}
+
+int Game::pge_op_getCollision00(ObjectOpcodeArgs *args) {
+ return col_getGridData(args->pge, 0, 0);
+}
+
+int Game::pge_op_getCollision0d(ObjectOpcodeArgs *args) {
+ return col_getGridData(args->pge, 0, args->a);
+}
+
+int Game::pge_op_getCollision1u(ObjectOpcodeArgs *args) {
+ return col_getGridData(args->pge, 1, -args->a);
+}
+
+int Game::pge_op_getCollision10(ObjectOpcodeArgs *args) {
+ return col_getGridData(args->pge, 1, 0);
+}
+
+int Game::pge_op_getCollision1d(ObjectOpcodeArgs *args) {
+ return col_getGridData(args->pge, 1, args->a);
+}
+
+int Game::pge_op_getCollision2u(ObjectOpcodeArgs *args) {
+ return col_getGridData(args->pge, 2, -args->a);
+}
+
+int Game::pge_op_getCollision20(ObjectOpcodeArgs *args) {
+ return col_getGridData(args->pge, 2, 0);
+}
+
+int Game::pge_op_getCollision2d(ObjectOpcodeArgs *args) {
+ return col_getGridData(args->pge, 2, args->a);
+}
+
+int Game::pge_op_doesNotCollide0u(ObjectOpcodeArgs *args) {
+ int16_t r = col_getGridData(args->pge, 0, -args->a);
+ if (r & 0xFFFF) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_op_doesNotCollide00(ObjectOpcodeArgs *args) {
+ int16_t r = col_getGridData(args->pge, 0, 0);
+ if (r & 0xFFFF) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_op_doesNotCollide0d(ObjectOpcodeArgs *args) {
+ int16_t r = col_getGridData(args->pge, 0, args->a);
+ if (r & 0xFFFF) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_op_doesNotCollide1u(ObjectOpcodeArgs *args) {
+ int16_t r = col_getGridData(args->pge, 1, -args->a);
+ if (r & 0xFFFF) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_op_doesNotCollide10(ObjectOpcodeArgs *args) {
+ int16_t r = col_getGridData(args->pge, 1, 0);
+ if (r & 0xFFFF) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_op_doesNotCollide1d(ObjectOpcodeArgs *args) {
+ int16_t r = col_getGridData(args->pge, 1, args->a);
+ if (r & 0xFFFF) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_op_doesNotCollide2u(ObjectOpcodeArgs *args) {
+ int16_t r = col_getGridData(args->pge, 2, -args->a);
+ if (r & 0xFFFF) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_op_doesNotCollide20(ObjectOpcodeArgs *args) {
+ int16_t r = col_getGridData(args->pge, 2, 0);
+ if (r & 0xFFFF) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_op_doesNotCollide2d(ObjectOpcodeArgs *args) {
+ int16_t r = col_getGridData(args->pge, 2, args->a);
+ if (r & 0xFFFF) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_op_collides0o0d(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 0, args->a) & 0xFFFF) {
+ if (col_getGridData(args->pge, 0, args->a + 1) == 0) {
+ if (col_getGridData(args->pge, -1, args->a) == 0) {
+ return 0xFFFF;
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_collides2o2d(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 2, args->a) & 0xFFFF) {
+ if (col_getGridData(args->pge, 2, args->a + 1) == 0) {
+ if (col_getGridData(args->pge, 1, args->a) == 0) {
+ return 0xFFFF;
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_collides0o0u(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 0, args->a) & 0xFFFF) {
+ if (col_getGridData(args->pge, 0, args->a - 1) == 0) {
+ if (col_getGridData(args->pge, -1, args->a) == 0) {
+ return 0xFFFF;
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_collides2o2u(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 2, args->a) & 0xFFFF) {
+ if (col_getGridData(args->pge, 2, args->a - 1) == 0) {
+ if (col_getGridData(args->pge, 1, args->a) == 0) {
+ return 0xFFFF;
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_collides2u2o(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 2, args->a - 1) & 0xFFFF) {
+ if (col_getGridData(args->pge, 2, args->a) == 0) {
+ if (col_getGridData(args->pge, 1, args->a - 1) == 0) {
+ return 0xFFFF;
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_isInGroup(ObjectOpcodeArgs *args) {
+ GroupPGE *le = _pge_groupsTable[args->pge->index];
+ while (le) {
+ if (le->group_id == args->a) {
+ return 0xFFFF;
+ }
+ le = le->next_entry;
+ }
+ return 0;
+}
+
+int Game::pge_op_updateGroup0(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ pge_updateGroup(pge->index, pge->init_PGE->counter_values[0], args->a);
+ return 0xFFFF;
+}
+
+int Game::pge_op_updateGroup1(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ pge_updateGroup(pge->index, pge->init_PGE->counter_values[1], args->a);
+ return 0xFFFF;
+}
+
+int Game::pge_op_updateGroup2(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ pge_updateGroup(pge->index, pge->init_PGE->counter_values[2], args->a);
+ return 0xFFFF;
+}
+
+int Game::pge_op_updateGroup3(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ pge_updateGroup(pge->index, pge->init_PGE->counter_values[3], args->a);
+ return 0xFFFF;
+}
+
+int Game::pge_op_isPiegeDead(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ if (pge->life <= 0) {
+ if (pge->init_PGE->object_type == 10) {
+ _score += 100;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+int Game::pge_op_collides1u2o(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 1, args->a - 1) & 0xFFFF) {
+ if (col_getGridData(args->pge, 2, args->a) == 0) {
+ return 0xFFFF;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_collides1u1o(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 1, args->a - 1) & 0xFFFF) {
+ if (col_getGridData(args->pge, 1, args->a) == 0) {
+ return 0xFFFF;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_collides1o1u(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 1, args->a - 1) == 0) {
+ if (col_getGridData(args->pge, 1, args->a) & 0xFFFF) {
+ return 0xFFFF;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_o_unk0x2B(ObjectOpcodeArgs *args) {
+ return pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderIfTypeAndDifferentDirection, 0);
+}
+
+int Game::pge_o_unk0x2C(ObjectOpcodeArgs *args) {
+ return pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderIfTypeAndSameDirection, 0);
+}
+
+int Game::pge_o_unk0x2D(ObjectOpcodeArgs *args) {
+ return pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderByObj, 0) ^ 1;
+}
+
+int Game::pge_op_nop(ObjectOpcodeArgs *args) {
+ return 1;
+}
+
+int Game::pge_op_pickupObject(ObjectOpcodeArgs *args) {
+ LivePGE *pge = col_findPiege(args->pge, 3);
+ if (pge) {
+ pge_updateGroup(args->pge->index, pge->index, args->a);
+ return 0xFFFF;
+ }
+ return 0;
+}
+
+int Game::pge_op_addItemToInventory(ObjectOpcodeArgs *args) {
+ pge_updateInventory(&_pgeLive[args->a], args->pge);
+ args->pge->room_location = 0xFF;
+ return 0xFFFF;
+}
+
+int Game::pge_op_copyPiege(ObjectOpcodeArgs *args) {
+ LivePGE *src = &_pgeLive[args->a];
+ LivePGE *dst = args->pge;
+
+ dst->pos_x = src->pos_x;
+ dst->pos_y = src->pos_y;
+ dst->room_location = src->room_location;
+
+ dst->flags &= 0xFE;
+ if (src->flags & 1) {
+ dst->flags |= 1;
+ }
+ pge_reorderInventory(args->pge);
+ return 0xFFFF;
+}
+
+int Game::pge_op_removeItemFromInventory(ObjectOpcodeArgs *args) {
+ if (args->pge->current_inventory_PGE != 0xFF) {
+ pge_updateGroup(args->pge->index, args->pge->current_inventory_PGE, args->a);
+ }
+ return 1;
+}
+
+int Game::pge_op_canUseCurrentInventoryItem(ObjectOpcodeArgs *args) {
+ LivePGE *pge = &_pgeLive[0];
+ if (pge->current_inventory_PGE != 0xFF && _res._pgeInit[pge->current_inventory_PGE].object_id == args->a) {
+ return 1;
+ }
+ return 0;
+}
+
+// useObject related
+int Game::pge_o_unk0x34(ObjectOpcodeArgs *args) {
+ uint8_t mask = (_pge_inpKeysMask & 0xF) | _pge_modKeysTable[0];
+ if (mask == _pge_inpKeysMask) {
+ if (col_getGridData(args->pge, 2, -args->a) == 0) {
+ return 0xFFFF;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_isInpMod(ObjectOpcodeArgs *args) {
+ assert(args->a < 3);
+ uint8_t mask = _pge_modKeysTable[args->a];
+ if (mask == _pge_inpKeysMask) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_op_setCollisionState1(ObjectOpcodeArgs *args) {
+ return pge_updateCollisionState(args->pge, args->a, 1);
+}
+
+int Game::pge_op_setCollisionState0(ObjectOpcodeArgs *args) {
+ return pge_updateCollisionState(args->pge, args->a, 0);
+}
+
+int Game::pge_op_isInGroup1(ObjectOpcodeArgs *args) {
+ return pge_isInGroup(args->pge, args->a, 1);
+}
+
+int Game::pge_op_isInGroup2(ObjectOpcodeArgs *args) {
+ return pge_isInGroup(args->pge, args->a, 2);
+}
+
+int Game::pge_op_isInGroup3(ObjectOpcodeArgs *args) {
+ return pge_isInGroup(args->pge, args->a, 3);
+}
+
+int Game::pge_op_isInGroup4(ObjectOpcodeArgs *args) {
+ return pge_isInGroup(args->pge, args->a, 4);
+}
+
+int Game::pge_o_unk0x3C(ObjectOpcodeArgs *args) {
+ return pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderByAnimYIfType, args->b);
+}
+
+int Game::pge_o_unk0x3D(ObjectOpcodeArgs *args) {
+ return pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderByAnimY, 0);
+}
+
+int Game::pge_op_setPiegeCounter(ObjectOpcodeArgs *args) {
+ args->pge->counter_value = args->a;
+ return 1;
+}
+
+int Game::pge_op_decPiegeCounter(ObjectOpcodeArgs *args) {
+ args->pge->counter_value -= 1;
+ if (args->a == args->pge->counter_value) {
+ return 0xFFFF;
+ } else {
+ return 0;
+ }
+}
+
+int Game::pge_o_unk0x40(ObjectOpcodeArgs *args) {
+ int8_t pge_room = args->pge->room_location;
+ if (pge_room < 0 || pge_room >= 0x40) return 0;
+ int col_area;
+ if (_currentRoom == pge_room) {
+ col_area = 1;
+ } else if (_col_currentLeftRoom == pge_room) {
+ col_area = 0;
+ } else if (_col_currentRightRoom == pge_room) {
+ col_area = 2;
+ } else {
+ return 0;
+ }
+ int16_t grid_pos_x = (args->pge->pos_x + 8) >> 4;
+ int16_t grid_pos_y = args->pge->pos_y / 72;
+ if (grid_pos_y >= 0 && grid_pos_y <= 2) {
+ grid_pos_y *= 16;
+ int16_t _cx = args->a;
+ if (_pge_currentPiegeFacingDir) {
+ _cx = -_cx;
+ }
+ int8_t _bl;
+ if (_cx >= 0) {
+ if (_cx > 0x10) {
+ _cx = 0x10;
+ }
+ int8_t *var2 = &_res._ctData[0x100] + pge_room * 0x70 + grid_pos_y * 2 + 0x10 + grid_pos_x;
+ uint8_t *var4 = _col_activeCollisionSlots + col_area * 0x30 + grid_pos_y + grid_pos_x;
+ int16_t var12 = grid_pos_x;
+ --_cx;
+ do {
+ --var12;
+ if (var12 < 0) {
+ --col_area;
+ if (col_area < 0) return 0;
+ pge_room = _res._ctData[CT_LEFT_ROOM + pge_room];
+ if (pge_room < 0) return 0;
+ var12 = 15;
+ var2 = &_res._ctData[0x101] + pge_room * 0x70 + grid_pos_y * 2 + 15 + 0x10;
+ var4 = var4 - 31;
+ }
+ --var4;
+ _bl = *var4;
+ if (_bl >= 0) {
+ CollisionSlot *col_slot = _col_slotsTable[_bl];
+ do {
+ if (args->pge != col_slot->live_pge && (col_slot->live_pge->flags & 4)) {
+ if (col_slot->live_pge->init_PGE->object_type == args->b) {
+ return 1;
+ }
+ }
+ col_slot = col_slot->prev_slot;
+ } while (col_slot);
+ }
+ --var2;
+ if (*var2 != 0) return 0;
+ --_cx;
+ } while (_cx >= 0);
+ } else {
+ _cx = -_cx;
+ if (_cx > 0x10) {
+ _cx = 0x10;
+ }
+ int8_t *var2 = &_res._ctData[0x101] + pge_room * 0x70 + grid_pos_y * 2 + 0x10 + grid_pos_x;
+ uint8_t *var4 = _col_activeCollisionSlots + 1 + col_area * 0x30 + grid_pos_y + grid_pos_x;
+ int16_t var12 = grid_pos_x;
+ --_cx;
+ do {
+ ++var12;
+ if (var12 == 0x10) {
+ ++col_area;
+ if (col_area > 2) return 0;
+ pge_room = _res._ctData[CT_RIGHT_ROOM + pge_room];
+ if (pge_room < 0) return 0;
+
+ var12 = 0;
+ var2 = &_res._ctData[0x101] + pge_room * 0x70 + grid_pos_y * 2 + 0x10;
+ var4 += 32;
+ }
+ var4++;
+ _bl = *var4;
+ if (_bl >= 0) {
+ CollisionSlot *col_slot = _col_slotsTable[_bl];
+ do {
+ if (args->pge != col_slot->live_pge && (col_slot->live_pge->flags & 4)) {
+ if (col_slot->live_pge->init_PGE->object_type == args->b) {
+ return 1;
+ }
+ }
+ col_slot = col_slot->prev_slot;
+ } while (col_slot);
+ }
+ _bl = *var2;
+ ++var2;
+ if (_bl != 0) return 0;
+ --_cx;
+ } while (_cx >= 0);
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_wakeUpPiege(ObjectOpcodeArgs *args) {
+ if (args->a <= 3) {
+ int16_t num = args->pge->init_PGE->counter_values[args->a];
+ if (num >= 0) {
+ LivePGE *pge = &_pgeLive[num];
+ pge->flags |= 4;
+ _pge_liveTable2[num] = pge;
+ }
+ }
+ return 1;
+}
+
+int Game::pge_op_removePiege(ObjectOpcodeArgs *args) {
+ if (args->a <= 3) {
+ int16_t num = args->pge->init_PGE->counter_values[args->a];
+ if (num >= 0) {
+ _pge_liveTable2[num] = 0;
+ _pgeLive[num].flags &= ~4;
+ }
+ }
+ return 1;
+}
+
+int Game::pge_op_removePiegeIfNotNear(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ if (!(pge->init_PGE->flags & 4)) goto kill_pge;
+ if (_currentRoom & 0x80) goto skip_pge;
+ if (pge->room_location & 0x80) goto kill_pge;
+ if (pge->room_location > 0x3F) goto kill_pge;
+ if (pge->room_location == _currentRoom) goto skip_pge;
+ if (pge->room_location == _res._ctData[CT_UP_ROOM + _currentRoom]) goto skip_pge;
+ if (pge->room_location == _res._ctData[CT_DOWN_ROOM + _currentRoom]) goto skip_pge;
+ if (pge->room_location == _res._ctData[CT_RIGHT_ROOM + _currentRoom]) goto skip_pge;
+ if (pge->room_location == _res._ctData[CT_LEFT_ROOM + _currentRoom]) goto skip_pge;
+
+kill_pge:
+ pge->flags &= ~4;
+ pge->collision_slot = 0xFF;
+ _pge_liveTable2[pge->index] = 0;
+
+skip_pge:
+ _pge_playAnimSound = false;
+ return 1;
+}
+
+int Game::pge_op_loadPiegeCounter(ObjectOpcodeArgs *args) {
+ args->pge->counter_value = args->pge->init_PGE->counter_values[args->a];
+ return 1;
+}
+
+int Game::pge_o_unk0x45(ObjectOpcodeArgs *args) {
+ return pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderByNumber, 0);
+}
+
+int Game::pge_o_unk0x46(ObjectOpcodeArgs *args) {
+ _pge_compareVar1 = 0;
+ pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderIfDifferentDirection, 0);
+ return _pge_compareVar1;
+}
+
+int Game::pge_o_unk0x47(ObjectOpcodeArgs *args) {
+ _pge_compareVar2 = 0;
+ pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderIfSameDirection, 0);
+ return _pge_compareVar2;
+}
+
+// used with Ian in level2
+int Game::pge_o_unk0x48(ObjectOpcodeArgs *args) {
+ LivePGE *pge = col_findPiege(&_pgeLive[0], args->pge->init_PGE->counter_values[0]);
+ if (pge && pge->life == args->pge->life) {
+ pge_updateGroup(args->pge->index, pge->index, args->a);
+ return 1;
+ }
+ return 0;
+}
+
+int Game::pge_o_unk0x49(ObjectOpcodeArgs *args) {
+ return pge_ZOrder(&_pgeLive[0], args->a, &Game::pge_ZOrderIfIndex, args->pge->init_PGE->counter_values[0]);
+}
+
+int Game::pge_o_unk0x4A(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ pge->room_location = 0xFE;
+ pge->flags &= ~4;
+ _pge_liveTable2[pge->index] = 0;
+ LivePGE *inv_pge = pge_getInventoryItemBefore(&_pgeLive[args->a], pge);
+ if (inv_pge == &_pgeLive[args->a]) {
+ if (pge->index != inv_pge->current_inventory_PGE) {
+ return 1;
+ }
+ } else {
+ if (pge->index != inv_pge->next_inventory_PGE) {
+ return 1;
+ }
+ }
+ pge_removeFromInventory(inv_pge, pge, &_pgeLive[args->a]);
+ return 1;
+}
+
+int Game::pge_op_killPiege(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ pge->room_location = 0xFE;
+ pge->flags &= ~4;
+ _pge_liveTable2[pge->index] = 0;
+ if (pge->init_PGE->object_type == 10) {
+ _score += 200;
+ }
+ return 0xFFFF;
+}
+
+int Game::pge_op_isInCurrentRoom(ObjectOpcodeArgs *args) {
+ return (args->pge->room_location == _currentRoom) ? 1 : 0;
+}
+
+int Game::pge_op_isNotInCurrentRoom(ObjectOpcodeArgs *args) {
+ return (args->pge->room_location == _currentRoom) ? 0 : 1;
+}
+
+int Game::pge_op_scrollPosY(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ args->pge->pos_y += args->a;
+ uint8_t pge_num = pge->current_inventory_PGE;
+ while (pge_num != 0xFF) {
+ pge = &_pgeLive[pge_num];
+ pge->pos_y += args->a;
+ pge_num = pge->next_inventory_PGE;
+ }
+ return 1;
+}
+
+int Game::pge_op_playDefaultDeathCutscene(ObjectOpcodeArgs *args) {
+ if (_deathCutsceneCounter == 0) {
+ _deathCutsceneCounter = args->a;
+ }
+ return 1;
+}
+
+int Game::pge_o_unk0x50(ObjectOpcodeArgs *args) {
+ return pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderByObj, 0);
+}
+
+int Game::pge_o_unk0x52(ObjectOpcodeArgs *args) {
+ return col_detectHit(args->pge, args->a, args->b, &Game::col_detectHitCallback4, &Game::col_detectHitCallback1, 0, 0);
+}
+
+int Game::pge_o_unk0x53(ObjectOpcodeArgs *args) {
+ return col_detectHit(args->pge, args->a, args->b, &Game::col_detectHitCallback5, &Game::col_detectHitCallback1, 0, 0);
+}
+
+int Game::pge_op_isPiegeNear(ObjectOpcodeArgs *args) {
+ if (col_findPiege(&_pgeLive[0], args->a) != 0) {
+ return 1;
+ }
+ return 0;
+}
+
+int Game::pge_op_setLife(ObjectOpcodeArgs *args) {
+ args->pge->life = args->a;
+ return 1;
+}
+
+int Game::pge_op_incLife(ObjectOpcodeArgs *args) {
+ args->pge->life += args->a;
+ return 1;
+}
+
+// level2, Ian
+int Game::pge_op_setPiegeDefaultAnim(ObjectOpcodeArgs *args) {
+ assert(args->a >= 0 && args->a < 4);
+ int16_t r = args->pge->init_PGE->counter_values[args->a];
+ args->pge->room_location = r;
+ if (r == 1) {
+ warning("setting _loadMap to true");
+ _loadMap = true;
+ }
+ pge_setupDefaultAnim(args->pge);
+ return 1;
+}
+
+int Game::pge_op_setLifeCounter(ObjectOpcodeArgs *args) {
+ _pgeLive[args->a].life = args->pge->init_PGE->counter_values[0];
+ return 1;
+}
+
+int Game::pge_op_decLifeCounter(ObjectOpcodeArgs *args) {
+ args->pge->life = _pgeLive[args->a].life - 1;
+ return 1;
+}
+
+int Game::pge_op_playCutscene(ObjectOpcodeArgs *args) {
+ if (_deathCutsceneCounter == 0) {
+ _cut._id = args->a;
+ }
+ return 1;
+}
+
+int Game::pge_op_isTempVar2Set(ObjectOpcodeArgs *args) {
+ if (_pge_opTempVar2 == args->a) {
+ return 1;
+ }
+ return 0;
+}
+
+int Game::pge_op_playDeathCutscene(ObjectOpcodeArgs *args) {
+ if (_deathCutsceneCounter == 0) {
+ _deathCutsceneCounter = args->pge->init_PGE->counter_values[3] + 1;
+ _cut._deathCutsceneId = args->a;
+ }
+ return 1;
+}
+
+int Game::pge_o_unk0x5D(ObjectOpcodeArgs *args) {
+ return col_detectHit(args->pge, args->a, args->b, &Game::col_detectHitCallback4, &Game::col_detectHitCallback6, 0, 0);
+}
+
+int Game::pge_o_unk0x5E(ObjectOpcodeArgs *args) {
+ return col_detectHit(args->pge, args->a, args->b, &Game::col_detectHitCallback5, &Game::col_detectHitCallback6, 0, 0);
+}
+
+int Game::pge_o_unk0x5F(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+
+ int8_t pge_room = pge->room_location;
+ if (pge_room < 0 || pge_room >= 0x40) return 0;
+
+ int16_t dx;
+ int16_t _cx = pge->init_PGE->counter_values[0];
+ if (_cx <= 0) {
+ dx = 1;
+ _cx = -_cx;
+ } else {
+ dx = -1;
+ }
+ if (_pge_currentPiegeFacingDir) {
+ dx = -dx;
+ }
+ int16_t grid_pos_x = (pge->pos_x + 8) >> 4;
+ int16_t grid_pos_y = 0;
+ do {
+ int16_t _ax = col_getGridData(pge, 1, -grid_pos_y);
+ if (_ax != 0) {
+ if (!(_ax & 2) || args->a != 1) {
+ pge->room_location = pge_room;
+ pge->pos_x = grid_pos_x * 16;
+ return 1;
+ }
+ }
+ if (grid_pos_x < 0) {
+ pge_room = _res._ctData[CT_LEFT_ROOM + pge_room];
+ if (pge_room < 0 || pge_room >= 0x40) return 0;
+ grid_pos_x += 16;
+ } else if (grid_pos_x > 15) {
+ pge_room = _res._ctData[CT_RIGHT_ROOM + pge_room];
+ if (pge_room < 0 || pge_room >= 0x40) return 0;
+ grid_pos_x -= 16;
+ }
+ grid_pos_x += dx;
+ ++grid_pos_y;
+ } while (grid_pos_y <= _cx);
+ return 0;
+}
+
+int Game::pge_op_findAndCopyPiege(ObjectOpcodeArgs *args) {
+ GroupPGE *le = _pge_groupsTable[args->pge->index];
+ while (le) {
+ if (le->group_id == args->a) {
+ args->a = le->index;
+ args->b = 0;
+ pge_op_copyPiege(args);
+ return 1;
+ }
+ le = le->next_entry;
+ }
+ return 0;
+}
+
+int Game::pge_op_isInRandomRange(ObjectOpcodeArgs *args) {
+ uint16_t n = args->a;
+ if (n != 0) {
+ if ((getRandomNumber() % n) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_o_unk0x62(ObjectOpcodeArgs *args) {
+ return col_detectHit(args->pge, args->a, args->b, &Game::col_detectHitCallback3, &Game::col_detectHitCallback1, 0, -1);
+}
+
+int Game::pge_o_unk0x63(ObjectOpcodeArgs *args) {
+ return col_detectHit(args->pge, args->a, args->b, &Game::col_detectHitCallback2, &Game::col_detectHitCallback1, 0, -1);
+}
+
+int Game::pge_o_unk0x64(ObjectOpcodeArgs *args) {
+ return col_detectGunHit(args->pge, args->a, args->b, &Game::col_detectGunHitCallback3, &Game::col_detectGunHitCallback1, 1, -1);
+}
+
+int Game::pge_op_addToCredits(ObjectOpcodeArgs *args) {
+ assert(args->a >= 0 && args->a < 3);
+ uint8_t pge = args->pge->init_PGE->counter_values[args->a];
+ int16_t val = args->pge->init_PGE->counter_values[args->a + 1];
+ _pgeLive[pge].life += val;
+ return 1;
+}
+
+int Game::pge_op_subFromCredits(ObjectOpcodeArgs *args) {
+ assert(args->a >= 0 && args->a < 3);
+ uint8_t pge = args->pge->init_PGE->counter_values[args->a];
+ int16_t val = args->pge->init_PGE->counter_values[args->a + 1];
+ _pgeLive[pge].life -= val;
+ return 1;
+}
+
+int Game::pge_o_unk0x67(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 1, -args->a) & 2) {
+ return 0xFFFF;
+ }
+ return 0;
+}
+
+int Game::pge_op_setCollisionState2(ObjectOpcodeArgs *args) {
+ return pge_updateCollisionState(args->pge, args->a, 2);
+}
+
+int Game::pge_op_saveState(ObjectOpcodeArgs *args) {
+ _saveStateCompleted = true;
+ _validSaveState = saveGameState(0);
+ return 0xFFFF;
+}
+
+// useGun related
+int Game::pge_o_unk0x6A(ObjectOpcodeArgs *args) {
+ LivePGE *_si = args->pge;
+ int8_t pge_room = _si->room_location;
+ if (pge_room < 0 || pge_room >= 0x40) return 0;
+ int8_t _bl;
+ int col_area = 0;
+ int8_t *ct_data;
+ if (_currentRoom == pge_room) {
+ col_area = 1;
+ } else if (_col_currentLeftRoom == pge_room) {
+ col_area = 0;
+ } else if (_col_currentRightRoom == pge_room) {
+ col_area = 2;
+ } else {
+ return 0;
+ }
+ int16_t grid_pos_x = (_si->pos_x + 8) >> 4;
+ int16_t grid_pos_y = (_si->pos_y / 72);
+ if (grid_pos_y >= 0 && grid_pos_y <= 2) {
+ grid_pos_y *= 16;
+ int16_t _cx = args->a;
+ if (_pge_currentPiegeFacingDir) {
+ _cx = -_cx;
+ }
+ if (_cx >= 0) {
+ if (_cx > 0x10) {
+ _cx = 0x10;
+ }
+ ct_data = &_res._ctData[0x100] + pge_room * 0x70 + grid_pos_y * 2 + 0x10 + grid_pos_x;
+ uint8_t *var4 = _col_activeCollisionSlots + col_area * 0x30 + grid_pos_y + grid_pos_x;
+ ++var4;
+ ++ct_data;
+ int16_t varA = grid_pos_x;
+ do {
+ --varA;
+ if (varA < 0) {
+ --col_area;
+ if (col_area < 0) return 0;
+ pge_room = _res._ctData[CT_LEFT_ROOM + pge_room];
+ if (pge_room < 0) return 0;
+ varA = 0xF;
+ ct_data = &_res._ctData[0x101] + pge_room * 0x70 + grid_pos_y * 2 + 0x10 + varA;
+ var4 -= 0x1F;
+ }
+ --var4;
+ _bl = *var4;
+ if (_bl >= 0) {
+ CollisionSlot *collision_slot = _col_slotsTable[_bl];
+ do {
+ _si = collision_slot->live_pge;
+ if (args->pge != _si && (_si->flags & 4) && _si->life >= 0) {
+ if (_si->init_PGE->object_type == 1 || _si->init_PGE->object_type == 10) {
+ return 1;
+ }
+ }
+ collision_slot = collision_slot->prev_slot;
+ } while (collision_slot);
+ }
+ --ct_data;
+ if (*ct_data != 0) return 0;
+ --_cx;
+ } while (_cx >= 0);
+
+ } else {
+ _cx = -_cx;
+ if (_cx > 0x10) {
+ _cx = 0x10;
+ }
+ ct_data = &_res._ctData[0x101] + pge_room * 0x70 + grid_pos_y * 2 + 0x10 + grid_pos_x;
+ uint8_t *var4 = _col_activeCollisionSlots + 1 + col_area * 0x30 + grid_pos_y + grid_pos_x;
+ int16_t varA = grid_pos_x;
+ goto loc_0_15446;
+ do {
+ ++varA;
+ if (varA == 0x10) {
+ ++col_area;
+ if (col_area > 2) return 0;
+ pge_room = _res._ctData[CT_RIGHT_ROOM + pge_room];
+ if (pge_room < 0) return 0;
+ varA = 0;
+ ct_data = &_res._ctData[0x100] + pge_room * 0x70 + grid_pos_y * 2 + 0x10 + varA;
+ var4 += 0x20;
+ }
+loc_0_15446:
+ _bl = *var4;
+ ++var4;
+ if (_bl >= 0) {
+ CollisionSlot *collision_slot = _col_slotsTable[_bl];
+ do {
+ _si = collision_slot->live_pge;
+ if (args->pge != _si && (_si->flags & 4) && _si->life >= 0) {
+ if (_si->init_PGE->object_type == 1 || _si->init_PGE->object_type == 10) {
+ return 1;
+ }
+ }
+ collision_slot = collision_slot->prev_slot;
+ } while (collision_slot);
+ }
+ _bl = *ct_data;
+ ++ct_data;
+ if (_bl != 0) return 0;
+ --_cx;
+ } while (_cx >= 0);
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_isInGroupSlice(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ GroupPGE *le = _pge_groupsTable[pge->index];
+ if (le) {
+ if (args->a == 0) {
+ do {
+ if (le->group_id == 1 || le->group_id == 2) {
+ return 1;
+ }
+ le = le->next_entry;
+ } while (le);
+ } else {
+ do {
+ if (le->group_id == 3 || le->group_id == 4) {
+ return 1;
+ }
+ le = le->next_entry;
+ } while (le);
+ }
+ }
+ return 0;
+}
+
+int Game::pge_o_unk0x6C(ObjectOpcodeArgs *args) {
+ LivePGE *pge = col_findPiege(&_pgeLive[0], args->pge->init_PGE->counter_values[0]);
+ if (pge) {
+ if (pge->life <= args->pge->life) {
+ pge_updateGroup(args->pge->index, pge->index, args->a);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_isCollidingObject(ObjectOpcodeArgs *args) {
+ uint8_t r = col_findCurrentCollidingObject(args->pge, 3, 0xFF, 0xFF, 0);
+ if (r == args->a) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+// elevator
+int Game::pge_o_unk0x6E(ObjectOpcodeArgs *args) {
+ GroupPGE *le = _pge_groupsTable[args->pge->index];
+ while (le) {
+ if (args->a == le->group_id) {
+ pge_updateInventory(&_pgeLive[le->index], args->pge);
+ return 0xFFFF;
+ }
+ le = le->next_entry;
+ }
+ return 0;
+}
+
+
+int Game::pge_o_unk0x6F(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ GroupPGE *le = _pge_groupsTable[pge->index];
+ while (le) {
+ if (args->a == le->group_id) {
+ pge_updateGroup(pge->index, le->index, 0xC);
+ return 1;
+ }
+ le = le->next_entry;
+ }
+ return 0;
+}
+
+int Game::pge_o_unk0x70(ObjectOpcodeArgs *args) {
+ uint8_t pge_num = args->pge->current_inventory_PGE;
+ while (pge_num != 0xFF) {
+ pge_updateGroup(args->pge->index, _pgeLive[pge_num].index, args->a);
+ pge_num = _pgeLive[pge_num].next_inventory_PGE;
+ }
+ return 1;
+}
+
+// elevator
+int Game::pge_o_unk0x71(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ GroupPGE *le = _pge_groupsTable[pge->index];
+ while (le) {
+ if (le->group_id == args->a) {
+ pge_reorderInventory(args->pge);
+ return 1;
+ }
+ le = le->next_entry;
+ }
+ return 0;
+}
+
+int Game::pge_o_unk0x72(ObjectOpcodeArgs *args) {
+ int8_t *var4 = &_res._ctData[0x100] + args->pge->room_location * 0x70;
+ var4 += (((args->pge->pos_y / 36) & ~1) + args->a) * 16 + (args->pge->pos_x + 8) / 16;
+
+ CollisionSlot2 *_di = _col_slots2Next;
+ int _cx = 0x100;
+ while (_di && _cx != 0) {
+ if (_di->unk2 != var4) {
+ _di = _di->next_slot;
+ --_cx;
+ } else {
+ memcpy(_di->unk2, _di->data_buf, _di->data_size + 1);
+ break;
+ }
+ }
+ return 0xFFFF; // XXX var4;
+}
+
+int Game::pge_o_unk0x73(ObjectOpcodeArgs *args) {
+ LivePGE *pge = col_findPiege(args->pge, args->a);
+ if (pge != 0) {
+ pge_updateInventory(pge, args->pge);
+ return 0xFFFF;
+ }
+ return 0;
+}
+
+int Game::pge_op_collides4u(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 4, -args->a) != 0) {
+ return 0xFFFF;
+ }
+ return 0;
+}
+
+int Game::pge_op_doesNotCollide4u(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 4, -args->a) == 0) {
+ return 0xFFFF;
+ }
+ return 0;
+}
+
+int Game::pge_op_isBelowConrad(ObjectOpcodeArgs *args) {
+ LivePGE *_si = args->pge;
+ LivePGE *pge_conrad = &_pgeLive[0];
+ if (pge_conrad->room_location == _si->room_location) {
+ if ((pge_conrad->pos_y - 8) / 72 < _si->pos_y / 72) {
+ return 0xFFFF;
+ }
+ } else if (!(_si->room_location & 0x80) && _si->room_location < 0x40) {
+ if (pge_conrad->room_location == _res._ctData[CT_UP_ROOM + _si->room_location]) {
+ return 0xFFFF;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_isAboveConrad(ObjectOpcodeArgs *args) {
+ LivePGE *_si = args->pge;
+ LivePGE *pge_conrad = &_pgeLive[0];
+ if (pge_conrad->room_location == _si->room_location) {
+ if ((pge_conrad->pos_y - 8) / 72 > _si->pos_y / 72) {
+ return 0xFFFF;
+ }
+ } else if (!(_si->room_location & 0x80) && _si->room_location < 0x40) {
+ if (pge_conrad->room_location == _res._ctData[CT_DOWN_ROOM + _si->room_location]) {
+ return 0xFFFF;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_isNotFacingConrad(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ LivePGE *pge_conrad = &_pgeLive[0];
+ if (pge->pos_y / 72 == (pge_conrad->pos_y - 8) / 72) { // same grid cell
+ if (pge->room_location == pge_conrad->room_location) {
+ if (args->a == 0) {
+ if (_pge_currentPiegeFacingDir) {
+ if (pge->pos_x < pge_conrad->pos_x) {
+ return 0xFFFF;
+ }
+ } else {
+ if (pge->pos_x > pge_conrad->pos_x) {
+ return 0xFFFF;
+ }
+ }
+ } else {
+ int16_t dx;
+ if (_pge_currentPiegeFacingDir) {
+ dx = pge_conrad->pos_x - pge->pos_x;
+ } else {
+ dx = pge->pos_x - pge_conrad->pos_x;
+ }
+ if (dx > 0 && dx < args->a * 16) {
+ return 0xFFFF;
+ }
+ }
+ } else if (args->a == 0) {
+ if (!(pge->room_location & 0x80) && pge->room_location < 0x40) {
+ if (_pge_currentPiegeFacingDir) {
+ if (pge_conrad->room_location == _res._ctData[CT_RIGHT_ROOM + pge->room_location])
+ return 0xFFFF;
+ } else {
+ if (pge_conrad->room_location == _res._ctData[CT_LEFT_ROOM + pge->room_location])
+ return 0xFFFF;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_isFacingConrad(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ LivePGE *pge_conrad = &_pgeLive[0];
+ if (pge->pos_y / 72 == (pge_conrad->pos_y - 8) / 72) {
+ if (pge->room_location == pge_conrad->room_location) {
+ if (args->a == 0) {
+ if (_pge_currentPiegeFacingDir) {
+ if (pge->pos_x > pge_conrad->pos_x) {
+ return 0xFFFF;
+ }
+ } else {
+ if (pge->pos_x <= pge_conrad->pos_x) {
+ return 0xFFFF;
+ }
+ }
+ } else {
+ int16_t dx;
+ if (_pge_currentPiegeFacingDir) {
+ dx = pge->pos_x - pge_conrad->pos_x;
+ } else {
+ dx = pge_conrad->pos_x - pge->pos_x;
+ }
+ if (dx > 0 && dx < args->a * 16) {
+ return 0xFFFF;
+ }
+ }
+ } else if (args->a == 0) {
+ if (!(pge->room_location & 0x80) && pge->room_location < 0x40) {
+ if (_pge_currentPiegeFacingDir) {
+ if (pge_conrad->room_location == _res._ctData[CT_LEFT_ROOM + pge->room_location])
+ return 0xFFFF;
+ } else {
+ if (pge_conrad->room_location == _res._ctData[CT_RIGHT_ROOM + pge->room_location])
+ return 0xFFFF;
+ }
+ }
+
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_collides2u1u(ObjectOpcodeArgs *args) {
+ if (col_getGridData(args->pge, 1, -args->a) == 0) {
+ if (col_getGridData(args->pge, 2, -(args->a + 1)) & 0xFFFF) {
+ return 0xFFFF;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_op_displayText(ObjectOpcodeArgs *args) {
+ _textToDisplay = args->a;
+ return 0xFFFF;
+}
+
+int Game::pge_o_unk0x7C(ObjectOpcodeArgs *args) {
+ LivePGE *pge = col_findPiege(args->pge, 3);
+ if (pge == 0) {
+ pge = col_findPiege(args->pge, 5);
+ if (pge == 0) {
+ pge = col_findPiege(args->pge, 9);
+ if (pge == 0) {
+ pge = col_findPiege(args->pge, 0xFFFF);
+ }
+ }
+ }
+ if (pge != 0) {
+ pge_updateGroup(args->pge->index, pge->index, args->a);
+ }
+ return 0;
+}
+
+int Game::pge_op_playSound(ObjectOpcodeArgs *args) {
+ uint8_t sfxId = args->a & 0xFF;
+ uint8_t softVol = args->a >> 8;
+ playSound(sfxId, softVol);
+ return 0xFFFF;
+}
+
+int Game::pge_o_unk0x7E(ObjectOpcodeArgs *args) {
+ _pge_compareVar1 = 0;
+ pge_ZOrder(args->pge, args->a, &Game::pge_ZOrderByIndex, 0);
+ return _pge_compareVar1;
+}
+
+int Game::pge_o_unk0x7F(ObjectOpcodeArgs *args) {
+ LivePGE *_si = args->pge;
+ uint8_t var4 = _si->collision_slot;
+ uint8_t var2 = _si->index;
+ while (var4 != 0xFF) {
+ CollisionSlot *slot = _col_slotsTable[var4];
+ while (slot) {
+ if (slot->live_pge != args->pge) {
+ if (slot->live_pge->init_PGE->object_type == 3 && var2 != slot->live_pge->unkF) {
+ return 0;
+ }
+ }
+ if (slot->live_pge == args->pge) {
+ var4 = slot->index;
+ }
+ slot = slot->prev_slot;
+ }
+ }
+ return 0xFFFF;
+}
+
+int Game::pge_op_setPiegePosX(ObjectOpcodeArgs *args) {
+ uint8_t pge_num = args->pge->unkF;
+ if (pge_num != 0xFF) {
+ args->pge->pos_x = _pgeLive[pge_num].pos_x;
+ }
+ return 0xFFFF;
+}
+
+int Game::pge_op_setPiegePosModX(ObjectOpcodeArgs *args) {
+ uint8_t pge_num = args->pge->unkF;
+ if (pge_num != 0xFF) {
+ int16_t dx = _pgeLive[pge_num].pos_x % 256;
+ if (dx >= args->pge->pos_x) {
+ dx -= args->pge->pos_x;
+ }
+ args->pge->pos_x += dx;
+ }
+ return 0xFFFF;
+}
+
+// taxi, level4
+int Game::pge_op_changeRoom(ObjectOpcodeArgs *args) {
+ InitPGE *init_pge_1 = args->pge->init_PGE;
+ assert(args->a >= 0 && args->a < 3);
+ int16_t _ax = init_pge_1->counter_values[args->a];
+ int16_t _bx = init_pge_1->counter_values[args->a + 1];
+ LivePGE *live_pge_1 = &_pgeLive[_bx];
+ LivePGE *live_pge_2 = &_pgeLive[_ax];
+ int8_t pge_room = live_pge_1->room_location;
+ if (pge_room >= 0 && pge_room < 0x40) {
+ int8_t _al = live_pge_2->room_location;
+ live_pge_2->pos_x = live_pge_1->pos_x;
+ live_pge_2->pos_y = live_pge_1->pos_y;
+ live_pge_2->room_location = live_pge_1->room_location;
+ pge_addToCurrentRoomList(live_pge_2, _al);
+ InitPGE *init_pge_2 = live_pge_2->init_PGE;
+ init_pge_1 = live_pge_1->init_PGE;
+ if (init_pge_2->obj_node_number == init_pge_1->obj_node_number) {
+ live_pge_2->flags &= 0xFE;
+ if (live_pge_1->flags & 1) {
+ live_pge_2->flags |= 1;
+ }
+ live_pge_2->obj_type = live_pge_1->obj_type;
+ live_pge_2->anim_seq = 0;
+ assert(init_pge_2->obj_node_number < _res._numObjectNodes);
+ ObjectNode *on = _res._objectNodesMap[init_pge_2->obj_node_number];
+ Object *obj = on->objects;
+ int i = 0;
+ while (obj->type != live_pge_2->obj_type) {
+ ++i;
+ ++obj;
+ }
+ live_pge_2->first_obj_number = i;
+ }
+ if (init_pge_2->object_type == 1) {
+ if (_currentRoom != live_pge_2->room_location) {
+ _currentRoom = live_pge_2->room_location;
+ loadLevelMap();
+ _vid.fullRefresh();
+ }
+ }
+ pge_setupDefaultAnim(live_pge_2);
+ }
+ return 0xFFFF;
+}
+
+// called for example before using gun, to check its presence
+int Game::pge_op_hasInventoryItem(ObjectOpcodeArgs *args) {
+ LivePGE *pge = &_pgeLive[0];
+ uint8_t _dl = pge->current_inventory_PGE;
+ while (_dl != 0xFF) {
+ pge = &_pgeLive[_dl];
+ if (pge->init_PGE->object_id == args->a) {
+ return 0xFFFF;
+ }
+ _dl = pge->next_inventory_PGE;
+ }
+ return 0;
+}
+
+int Game::pge_op_changeLevel(ObjectOpcodeArgs *args) {
+ _currentLevel = args->a - 1;
+ return _currentLevel;
+}
+
+int Game::pge_op_shakeScreen(ObjectOpcodeArgs *args) {
+ _vid._shakeOffset = getRandomNumber() & 7;
+ return 0xFFFF;
+}
+
+int Game::pge_o_unk0x86(ObjectOpcodeArgs *args) {
+ return col_detectGunHit(args->pge, args->a, args->b, &Game::col_detectGunHitCallback2, &Game::col_detectGunHitCallback1, 1, 0);
+}
+
+int Game::pge_op_playSoundGroup(ObjectOpcodeArgs *args) {
+ assert(args->a < 4);
+ uint16_t c = args->pge->init_PGE->counter_values[args->a];
+ uint8_t sfxId = c & 0xFF;
+ uint8_t softVol = c >> 8;
+ playSound(sfxId, softVol);
+ return 0xFFFF;
+}
+
+int Game::pge_op_adjustPos(ObjectOpcodeArgs *args) {
+ LivePGE *pge = args->pge;
+ pge->pos_x &= 0xFFF0;
+ if (pge->pos_y != 70 && pge->pos_y != 142 && pge->pos_y != 214) {
+ pge->pos_y = ((pge->pos_y / 72) + 1) * 72 - 2;
+ }
+ return 0xFFFF;
+}
+
+int Game::pge_op_setTempVar1(ObjectOpcodeArgs *args) {
+ _pge_opTempVar1 = args->a;
+ return 0xFFFF;
+}
+
+int Game::pge_op_isTempVar1Set(ObjectOpcodeArgs *args) {
+ if (_pge_opTempVar1 != args->a) {
+ return 0;
+ } else {
+ return 0xFFFF;
+ }
+}
+
+int Game::pge_setCurrentInventoryObject(LivePGE *pge) {
+ LivePGE *_bx = pge_getInventoryItemBefore(&_pgeLive[0], pge);
+ if (_bx == &_pgeLive[0]) {
+ if (_bx->current_inventory_PGE != pge->index) {
+ return 0;
+ }
+ } else {
+ if (_bx->next_inventory_PGE != pge->index) {
+ return 0;
+ }
+ }
+ pge_removeFromInventory(_bx, pge, &_pgeLive[0]);
+ pge_addToInventory(&_pgeLive[0], pge, &_pgeLive[0]);
+ return 0xFFFF;
+}
+
+void Game::pge_updateInventory(LivePGE *pge1, LivePGE *pge2) {
+ if (pge2->unkF != 0xFF) {
+ pge_reorderInventory(pge2);
+ }
+ LivePGE *_ax = pge_getInventoryItemBefore(pge1, 0);
+ pge_addToInventory(_ax, pge2, pge1);
+}
+
+void Game::pge_reorderInventory(LivePGE *pge) {
+ if (pge->unkF != 0xFF) {
+ LivePGE *_bx = &_pgeLive[pge->unkF];
+ LivePGE *_di = pge_getInventoryItemBefore(_bx, pge);
+ if (_di == _bx) {
+ if (_di->current_inventory_PGE == pge->index) {
+ pge_removeFromInventory(_di, pge, _bx);
+ }
+ } else {
+ if (_di->next_inventory_PGE == pge->index) {
+ pge_removeFromInventory(_di, pge, _bx);
+ }
+ }
+ }
+}
+
+LivePGE *Game::pge_getInventoryItemBefore(LivePGE *pge, LivePGE *last_pge) {
+ LivePGE *_di = pge;
+ uint8_t n = _di->current_inventory_PGE;
+ while (n != 0xFF) {
+ LivePGE *_si = &_pgeLive[n];
+ if (_si == last_pge) {
+ break;
+ } else {
+ _di = _si;
+ n = _di->next_inventory_PGE;
+ }
+ }
+ return _di;
+}
+
+void Game::pge_addToInventory(LivePGE *pge1, LivePGE *pge2, LivePGE *pge3) {
+ pge2->unkF = pge3->index;
+ if (pge1 == pge3) {
+ pge2->next_inventory_PGE = pge1->current_inventory_PGE;
+ pge1->current_inventory_PGE = pge2->index;
+ } else {
+ pge2->next_inventory_PGE = pge1->next_inventory_PGE;
+ pge1->next_inventory_PGE = pge2->index;
+ }
+}
+
+int Game::pge_updateCollisionState(LivePGE *pge, int16_t pge_dy, uint8_t var8) {
+ uint8_t pge_unk1C = pge->init_PGE->unk1C;
+ if (!(pge->room_location & 0x80) && pge->room_location < 0x40) {
+ int8_t *grid_data = &_res._ctData[0x100] + 0x70 * pge->room_location;
+ int16_t pge_pos_y = ((pge->pos_y / 36) & ~1) + pge_dy;
+ int16_t pge_pos_x = (pge->pos_x + 8) >> 4;
+
+ grid_data += pge_pos_x + pge_pos_y * 16;
+
+ CollisionSlot2 *slot1 = _col_slots2Next;
+ int16_t i = 255;
+ pge_pos_x = i;
+ if (_pge_currentPiegeFacingDir) {
+ i = pge_unk1C - 1;
+ grid_data -= i;
+ }
+ while (slot1) {
+ if (slot1->unk2 == grid_data) {
+ slot1->data_size = pge_unk1C - 1;
+ assert(pge_unk1C < 0x70);
+ memset(grid_data, var8, pge_unk1C);
+ grid_data += pge_unk1C;
+ return 1;
+ } else {
+ ++i;
+ slot1 = slot1->next_slot;
+ if (--i == 0) {
+ break;
+ }
+ }
+ }
+ if (_col_slots2Cur < &_col_slots2[255]) {
+ slot1 = _col_slots2Cur;
+ slot1->unk2 = grid_data;
+ slot1->data_size = pge_unk1C - 1;
+ uint8_t *dst = &slot1->data_buf[0];
+ int8_t *src = grid_data;
+ int n = pge_unk1C;
+ assert(n < 0x10);
+ while (n--) {
+ *dst++ = *src;
+ *src++ = var8;
+ }
+ ++_col_slots2Cur;
+ slot1->next_slot = _col_slots2Next;
+ _col_slots2Next = slot1;
+ }
+ }
+ return 1;
+}
+
+int Game::pge_ZOrder(LivePGE *pge, int16_t num, pge_ZOrderCallback compare, uint16_t unk) {
+ uint8_t slot = pge->collision_slot;
+ while (slot != 0xFF) {
+ CollisionSlot *cs = _col_slotsTable[slot];
+ if (cs == 0) {
+ return 0;
+ }
+ uint8_t slot_bak = slot;
+ slot = 0xFF;
+ while (cs != 0) {
+ if ((this->*compare)(cs->live_pge, pge, num, unk) != 0) {
+ return 1;
+ }
+ if (pge == cs->live_pge) {
+ slot = cs->index;
+ }
+ cs = cs->prev_slot;
+ if (slot == slot_bak) {
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+void Game::pge_updateGroup(uint8_t idx, uint8_t unk1, int16_t unk2) {
+ debug(DBG_GAME, "Game::pge_updateGroup() idx=0x%X unk1=0x%X unk2=0x%X", idx, unk1, unk2);
+ LivePGE *pge = &_pgeLive[unk1];
+ if (!(pge->flags & 4)) {
+ if (!(pge->init_PGE->flags & 1)) {
+ return;
+ }
+ pge->flags |= 4;
+ _pge_liveTable2[unk1] = pge;
+ }
+ if (unk2 <= 4) {
+ uint8_t pge_room = pge->room_location;
+ pge = &_pgeLive[idx];
+ if (pge_room != pge->room_location) {
+ return;
+ }
+ if (unk1 == 0 && _blinkingConradCounter != 0) {
+ return;
+ }
+ // XXX
+ }
+ GroupPGE *le = _pge_nextFreeGroup;
+ if (le) {
+ // append to the list
+ _pge_nextFreeGroup = le->next_entry;
+ GroupPGE *_ax = _pge_groupsTable[unk1];
+ _pge_groupsTable[unk1] = le;
+ le->next_entry = _ax;
+ le->index = idx;
+ le->group_id = unk2;
+ }
+}
+
+void Game::pge_removeFromInventory(LivePGE *pge1, LivePGE *pge2, LivePGE *pge3) {
+ pge2->unkF = 0xFF;
+ if (pge3 == pge1) {
+ pge3->current_inventory_PGE = pge2->next_inventory_PGE;
+ pge2->next_inventory_PGE = 0xFF;
+ } else {
+ pge1->next_inventory_PGE = pge2->next_inventory_PGE;
+ pge2->next_inventory_PGE = 0xFF;
+ }
+}
+
+int Game::pge_ZOrderByAnimY(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ if (pge1 != pge2) {
+ if (_res.getAniData(pge1->obj_type)[3] == comp) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_ZOrderByAnimYIfType(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ if (pge1->init_PGE->object_type == comp2) {
+ if (_res.getAniData(pge1->obj_type)[3] == comp) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_ZOrderIfIndex(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ if (pge1->index != comp2) {
+ pge_updateGroup(pge2->index, pge1->index, comp);
+ return 1;
+ }
+ return 0;
+}
+
+int Game::pge_ZOrderByIndex(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ if (pge1 != pge2) {
+ pge_updateGroup(pge2->index, pge1->index, comp);
+ _pge_compareVar1 = 0xFFFF;
+ }
+ return 0;
+}
+
+int Game::pge_ZOrderByObj(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ if (comp == 10) {
+ if (pge1->init_PGE->object_type == comp && pge1->life >= 0) {
+ return 1;
+ }
+ } else {
+ if (pge1->init_PGE->object_type == comp) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_ZOrderIfDifferentDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ if (pge1 != pge2) {
+ if ((pge1->flags & 1) != (pge2->flags & 1)) {
+ _pge_compareVar1 = 1;
+ pge_updateGroup(pge2->index, pge1->index, comp);
+ if (pge2->index == 0) {
+ return 0xFFFF;
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::pge_ZOrderIfSameDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ if (pge1 != pge2) {
+ if ((pge1->flags & 1) == (pge2->flags & 1)) {
+ _pge_compareVar2 = 1;
+ pge_updateGroup(pge2->index, pge1->index, comp);
+ if (pge2->index == 0) {
+ return 0xFFFF;
+ }
+ }
+ }
+ return 0;
+}
+
+int Game::pge_ZOrderIfTypeAndSameDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ if (pge1->init_PGE->object_type == comp) {
+ if ((pge1->flags & 1) == (pge2->flags & 1)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_ZOrderIfTypeAndDifferentDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ if (pge1->init_PGE->object_type == comp) {
+ if ((pge1->flags & 1) != (pge2->flags & 1)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Game::pge_ZOrderByNumber(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2) {
+ return pge1 - pge2;
+}
diff --git a/resource.cpp b/resource.cpp
new file mode 100644
index 0000000..3d60eed
--- /dev/null
+++ b/resource.cpp
@@ -0,0 +1,1130 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "file.h"
+#include "unpack.h"
+#include "resource.h"
+
+
+Resource::Resource(FileSystem *fs, ResourceType ver, Language lang) {
+ memset(this, 0, sizeof(Resource));
+ _type = ver;
+ _lang = lang;
+ _fs = fs;
+ _memBuf = (uint8_t *)malloc(256 * 224);
+ if (!_memBuf) {
+ error("Unable to allocate temporary memory buffer");
+ }
+ static const int kBankDataSize = 0x7000;
+ _bankData = (uint8_t *)malloc(kBankDataSize);
+ if (!_bankData) {
+ error("Unable to allocate bank data buffer");
+ }
+ _bankDataTail = _bankData + kBankDataSize;
+ clearBankData();
+}
+
+Resource::~Resource() {
+ clearLevelRes();
+ free(_fnt);
+ free(_icn); _icn = 0;
+ _icnLen = 0;
+ free(_tab);
+ free(_spc);
+ free(_spr1);
+ free(_memBuf);
+ free(_cmd);
+ free(_pol);
+ free(_cine_off);
+ free(_cine_txt);
+ for (int i = 0; i < _numSfx; ++i) {
+ free(_sfxList[i].data);
+ }
+ free(_sfxList);
+ free(_bankData);
+}
+
+void Resource::clearLevelRes() {
+ free(_tbn); _tbn = 0;
+ free(_mbk); _mbk = 0;
+ free(_pal); _pal = 0;
+ free(_map); _map = 0;
+ free(_lev); _lev = 0;
+ _levNum = -1;
+ free(_sgd); _sgd = 0;
+ free(_ani); _ani = 0;
+ free_OBJ();
+}
+
+void Resource::load_FIB(const char *fileName) {
+ debug(DBG_RES, "Resource::load_FIB('%s')", fileName);
+ static const uint8_t fibonacciTable[] = {
+ 0xDE, 0xEB, 0xF3, 0xF8, 0xFB, 0xFD, 0xFE, 0xFF,
+ 0x00, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15
+ };
+ snprintf(_entryName, sizeof(_entryName), "%s.FIB", fileName);
+ File f;
+ if (f.open(_entryName, "rb", _fs)) {
+ _numSfx = f.readUint16LE();
+ _sfxList = (SoundFx *)malloc(_numSfx * sizeof(SoundFx));
+ if (!_sfxList) {
+ error("Unable to allocate SoundFx table");
+ }
+ int i;
+ for (i = 0; i < _numSfx; ++i) {
+ SoundFx *sfx = &_sfxList[i];
+ sfx->offset = f.readUint32LE();
+ sfx->len = f.readUint16LE();
+ sfx->data = 0;
+ }
+ for (i = 0; i < _numSfx; ++i) {
+ SoundFx *sfx = &_sfxList[i];
+ if (sfx->len == 0) {
+ continue;
+ }
+ f.seek(sfx->offset);
+ uint8_t *data = (uint8_t *)malloc(sfx->len * 2);
+ if (!data) {
+ error("Unable to allocate SoundFx data buffer");
+ }
+ sfx->data = data;
+ uint8_t c = f.readByte();
+ *data++ = c;
+ *data++ = c;
+ uint16_t sz = sfx->len - 1;
+ while (sz--) {
+ uint8_t d = f.readByte();
+ c += fibonacciTable[d >> 4];
+ *data++ = c;
+ c += fibonacciTable[d & 15];
+ *data++ = c;
+ }
+ sfx->len *= 2;
+ }
+ if (f.ioErr()) {
+ error("I/O error when reading '%s'", _entryName);
+ }
+ } else {
+ error("Can't open '%s'", _entryName);
+ }
+}
+
+void Resource::load_SPL_demo() {
+ _numSfx = NUM_SFXS;
+ _sfxList = (SoundFx *)calloc(_numSfx, sizeof(SoundFx));
+ if (!_sfxList) {
+ return;
+ }
+ for (int i = 0; _splNames[i] && i < NUM_SFXS; ++i) {
+ File f;
+ if (f.open(_splNames[i], "rb", _fs)) {
+ SoundFx *sfx = &_sfxList[i];
+ const int size = f.size();
+ sfx->data = (uint8_t *)malloc(size);
+ if (sfx->data) {
+ f.read(sfx->data, size);
+ sfx->offset = 0;
+ sfx->len = size;
+ }
+ }
+ }
+}
+
+void Resource::load_MAP_menu(const char *fileName, uint8_t *dstPtr) {
+ debug(DBG_RES, "Resource::load_MAP_menu('%s')", fileName);
+ snprintf(_entryName, sizeof(_entryName), "%s.MAP", fileName);
+ File f;
+ if (f.open(_entryName, "rb", _fs)) {
+ if (f.size() != 0x3800 * 4) {
+ error("Wrong file size for '%s', %d", _entryName, f.size());
+ }
+ f.read(dstPtr, 0x3800 * 4);
+ if (f.ioErr()) {
+ error("I/O error when reading '%s'", _entryName);
+ }
+ } else {
+ error("Can't open '%s'", _entryName);
+ }
+}
+
+void Resource::load_PAL_menu(const char *fileName, uint8_t *dstPtr) {
+ debug(DBG_RES, "Resource::load_PAL_menu('%s')", fileName);
+ snprintf(_entryName, sizeof(_entryName), "%s.PAL", fileName);
+ File f;
+ if (f.open(_entryName, "rb", _fs)) {
+ if (f.size() != 768) {
+ error("Wrong file size for '%s', %d", _entryName, f.size());
+ }
+ f.read(dstPtr, 768);
+ if (f.ioErr()) {
+ error("I/O error when reading '%s'", _entryName);
+ }
+ } else {
+ error("Can't open '%s'", _entryName);
+ }
+}
+
+void Resource::load_SPR_OFF(const char *fileName, uint8_t *sprData) {
+ debug(DBG_RES, "Resource::load_SPR_OFF('%s')", fileName);
+ snprintf(_entryName, sizeof(_entryName), "%s.OFF", fileName);
+ File f;
+ if (f.open(_entryName, "rb", _fs)) {
+ int len = f.size();
+ uint8_t *offData = (uint8_t *)malloc(len);
+ if (!offData) {
+ error("Unable to allocate sprite offsets");
+ }
+ f.read(offData, len);
+ if (f.ioErr()) {
+ error("I/O error when reading '%s'", _entryName);
+ }
+ const uint8_t *p = offData;
+ uint16_t pos;
+ while ((pos = READ_LE_UINT16(p)) != 0xFFFF) {
+ assert(pos < NUM_SPRITES);
+ uint32_t off = READ_LE_UINT32(p + 2);
+ if (off == 0xFFFFFFFF) {
+ _sprData[pos] = 0;
+ } else {
+ _sprData[pos] = sprData + off;
+ }
+ p += 6;
+ }
+ free(offData);
+ } else {
+ error("Can't open '%s'", _entryName);
+ }
+}
+
+void Resource::load_CINE() {
+ const char *baseName = 0;
+ switch (_lang) {
+ case LANG_FR:
+ baseName = "FR_CINE";
+ break;
+ case LANG_EN:
+ baseName = "ENGCINE";
+ break;
+ case LANG_DE:
+ baseName = "GERCINE";
+ break;
+ case LANG_SP:
+ baseName = "SPACINE";
+ break;
+ case LANG_IT:
+ baseName = "ITACINE";
+ break;
+ }
+ debug(DBG_RES, "Resource::load_CINE('%s')", baseName);
+ if (_cine_off == 0) {
+ snprintf(_entryName, sizeof(_entryName), "%s.BIN", baseName);
+ File f;
+ if (f.open(_entryName, "rb", _fs)) {
+ int len = f.size();
+ _cine_off = (uint8_t *)malloc(len);
+ if (!_cine_off) {
+ error("Unable to allocate cinematics offsets");
+ }
+ f.read(_cine_off, len);
+ if (f.ioErr()) {
+ error("I/O error when reading '%s'", _entryName);
+ }
+ } else {
+ error("Can't open '%s'", _entryName);
+ }
+ }
+ if (_cine_txt == 0) {
+ snprintf(_entryName, sizeof(_entryName), "%s.TXT", baseName);
+ File f;
+ if (f.open(_entryName, "rb", _fs)) {
+ int len = f.size();
+ _cine_txt = (uint8_t *)malloc(len);
+ if (!_cine_txt) {
+ error("Unable to allocate cinematics text data");
+ }
+ f.read(_cine_txt, len);
+ if (f.ioErr()) {
+ error("I/O error when reading '%s'", _entryName);
+ }
+ } else {
+ error("Can't open '%s'", _entryName);
+ }
+ }
+}
+
+void Resource::load_TEXT() {
+ File f;
+ // Load game strings
+ _stringsTable = 0;
+ if (f.open("STRINGS.TXT", "rb", _fs)) {
+ const int sz = f.size();
+ _extStringsTable = (uint8_t *)malloc(sz);
+ if (_extStringsTable) {
+ f.read(_extStringsTable, sz);
+ _stringsTable = _extStringsTable;
+ }
+ f.close();
+ }
+ if (!_stringsTable) {
+ switch (_lang) {
+ case LANG_FR:
+ _stringsTable = LocaleData::_stringsTableFR;
+ break;
+ case LANG_EN:
+ _stringsTable = LocaleData::_stringsTableEN;
+ break;
+ case LANG_DE:
+ _stringsTable = LocaleData::_stringsTableDE;
+ break;
+ case LANG_SP:
+ _stringsTable = LocaleData::_stringsTableSP;
+ break;
+ case LANG_IT:
+ _stringsTable = LocaleData::_stringsTableIT;
+ break;
+ }
+ }
+ // Load menu strings
+ _textsTable = 0;
+ if (f.open("MENUS.TXT", "rb", _fs)) {
+ const int offs = LocaleData::LI_NUM * sizeof(char *);
+ const int sz = f.size() + 1;
+ _extTextsTable = (char **)malloc(offs + sz);
+ if (_extTextsTable) {
+ char *textData = (char *)_extTextsTable + offs;
+ f.read(textData, sz);
+ textData[sz] = 0;
+ int textsCount = 0;
+ for (char *eol; (eol = strpbrk(textData, "\r\n")) != 0; ) {
+ *eol++ = 0;
+ if (*eol == '\r' || *eol == '\n') {
+ *eol++ = 0;
+ }
+ if (textsCount < LocaleData::LI_NUM && textData[0] != 0) {
+ _extTextsTable[textsCount] = textData;
+ ++textsCount;
+ }
+ textData = eol;
+ }
+ if (textsCount < LocaleData::LI_NUM && textData[0] != 0) {
+ _extTextsTable[textsCount] = textData;
+ ++textsCount;
+ }
+ if (textsCount < LocaleData::LI_NUM) {
+ free(_extTextsTable);
+ _extTextsTable = 0;
+ } else {
+ _textsTable = (const char **)_extTextsTable;
+ }
+ }
+ }
+ if (!_textsTable) {
+ switch (_lang) {
+ case LANG_FR:
+ _textsTable = LocaleData::_textsTableFR;
+ break;
+ case LANG_EN:
+ _textsTable = LocaleData::_textsTableEN;
+ break;
+ case LANG_DE:
+ _textsTable = LocaleData::_textsTableDE;
+ break;
+ case LANG_SP:
+ _textsTable = LocaleData::_textsTableSP;
+ break;
+ case LANG_IT:
+ _textsTable = LocaleData::_textsTableIT;
+ break;
+ }
+ }
+}
+
+void Resource::free_TEXT() {
+ if (_extTextsTable) {
+ free(_extTextsTable);
+ _extTextsTable = 0;
+ }
+ _stringsTable = 0;
+ if (_extStringsTable) {
+ free(_extStringsTable);
+ _extStringsTable = 0;
+ }
+ _textsTable = 0;
+}
+
+void Resource::load(const char *objName, int objType, const char *ext) {
+ debug(DBG_RES, "Resource::load('%s', %d)", objName, objType);
+ LoadStub loadStub = 0;
+ switch (objType) {
+ case OT_MBK:
+ snprintf(_entryName, sizeof(_entryName), "%s.MBK", objName);
+ loadStub = &Resource::load_MBK;
+ break;
+ case OT_PGE:
+ snprintf(_entryName, sizeof(_entryName), "%s.PGE", objName);
+ loadStub = &Resource::load_PGE;
+ break;
+ case OT_PAL:
+ snprintf(_entryName, sizeof(_entryName), "%s.PAL", objName);
+ loadStub = &Resource::load_PAL;
+ break;
+ case OT_CT:
+ snprintf(_entryName, sizeof(_entryName), "%s.CT", objName);
+ loadStub = &Resource::load_CT;
+ break;
+ case OT_MAP:
+ snprintf(_entryName, sizeof(_entryName), "%s.MAP", objName);
+ loadStub = &Resource::load_MAP;
+ break;
+ case OT_SPC:
+ snprintf(_entryName, sizeof(_entryName), "%s.SPC", objName);
+ loadStub = &Resource::load_SPC;
+ break;
+ case OT_RP:
+ snprintf(_entryName, sizeof(_entryName), "%s.RP", objName);
+ loadStub = &Resource::load_RP;
+ break;
+ case OT_RPC:
+ snprintf(_entryName, sizeof(_entryName), "%s.RPC", objName);
+ loadStub = &Resource::load_RP;
+ break;
+ case OT_SPR:
+ snprintf(_entryName, sizeof(_entryName), "%s.SPR", objName);
+ loadStub = &Resource::load_SPR;
+ break;
+ case OT_SPRM:
+ snprintf(_entryName, sizeof(_entryName), "%s.SPR", objName);
+ loadStub = &Resource::load_SPRM;
+ break;
+ case OT_ICN:
+ snprintf(_entryName, sizeof(_entryName), "%s.ICN", objName);
+ loadStub = &Resource::load_ICN;
+ break;
+ case OT_FNT:
+ snprintf(_entryName, sizeof(_entryName), "%s.FNT", objName);
+ loadStub = &Resource::load_FNT;
+ break;
+ case OT_OBJ:
+ snprintf(_entryName, sizeof(_entryName), "%s.OBJ", objName);
+ loadStub = &Resource::load_OBJ;
+ break;
+ case OT_ANI:
+ snprintf(_entryName, sizeof(_entryName), "%s.ANI", objName);
+ loadStub = &Resource::load_ANI;
+ break;
+ case OT_TBN:
+ snprintf(_entryName, sizeof(_entryName), "%s.TBN", objName);
+ loadStub = &Resource::load_TBN;
+ break;
+ case OT_CMD:
+ snprintf(_entryName, sizeof(_entryName), "%s.CMD", objName);
+ loadStub = &Resource::load_CMD;
+ break;
+ case OT_POL:
+ snprintf(_entryName, sizeof(_entryName), "%s.POL", objName);
+ loadStub = &Resource::load_POL;
+ break;
+ case OT_CMP:
+ snprintf(_entryName, sizeof(_entryName), "%s.CMP", objName);
+ loadStub = &Resource::load_CMP;
+ break;
+ case OT_OBC:
+ snprintf(_entryName, sizeof(_entryName), "%s.OBC", objName);
+ loadStub = &Resource::load_OBC;
+ break;
+ case OT_SPL:
+ snprintf(_entryName, sizeof(_entryName), "%s.SPL", objName);
+ loadStub = &Resource::load_SPL;
+ break;
+ case OT_LEV:
+ snprintf(_entryName, sizeof(_entryName), "%s.LEV", objName);
+ loadStub = &Resource::load_LEV;
+ break;
+ case OT_SGD:
+ snprintf(_entryName, sizeof(_entryName), "%s.SGD", objName);
+ loadStub = &Resource::load_SGD;
+ break;
+ case OT_SPM:
+ snprintf(_entryName, sizeof(_entryName), "%s.SPM", objName);
+ loadStub = &Resource::load_SPM;
+ break;
+ default:
+ error("Unimplemented Resource::load() type %d", objType);
+ break;
+ }
+ if (ext) {
+ snprintf(_entryName, sizeof(_entryName), "%s.%s", objName, ext);
+ }
+ File f;
+ if (f.open(_entryName, "rb", _fs)) {
+ assert(loadStub);
+ (this->*loadStub)(&f);
+ if (f.ioErr()) {
+ error("I/O error when reading '%s'", _entryName);
+ }
+ } else {
+ error("Can't open '%s'", _entryName);
+ }
+}
+
+void Resource::load_CT(File *pf) {
+ debug(DBG_RES, "Resource::load_CT()");
+ int len = pf->size();
+ uint8_t *tmp = (uint8_t *)malloc(len);
+ if (!tmp) {
+ error("Unable to allocate CT buffer");
+ } else {
+ pf->read(tmp, len);
+ if (!delphine_unpack((uint8_t *)_ctData, tmp, len)) {
+ error("Bad CRC for collision data");
+ }
+ free(tmp);
+ }
+}
+
+void Resource::load_FNT(File *f) {
+ debug(DBG_RES, "Resource::load_FNT()");
+ int len = f->size();
+ _fnt = (uint8_t *)malloc(len);
+ if (!_fnt) {
+ error("Unable to allocate FNT buffer");
+ } else {
+ f->read(_fnt, len);
+ }
+}
+
+void Resource::load_MBK(File *f) {
+ debug(DBG_RES, "Resource::load_MBK()");
+ int len = f->size();
+ _mbk = (uint8_t *)malloc(len);
+ if (!_mbk) {
+ error("Unable to allocate MBK buffer");
+ } else {
+ f->read(_mbk, len);
+ }
+}
+
+void Resource::load_ICN(File *f) {
+ debug(DBG_RES, "Resource::load_ICN()");
+ int len = f->size();
+ if (_icnLen == 0) {
+ _icn = (uint8_t *)malloc(len);
+ } else {
+ _icn = (uint8_t *)realloc(_icn, _icnLen + len);
+ }
+ if (!_icn) {
+ error("Unable to allocate ICN buffer");
+ } else {
+ f->read(_icn + _icnLen, len);
+ }
+ _icnLen += len;
+}
+
+void Resource::load_SPR(File *f) {
+ debug(DBG_RES, "Resource::load_SPR()");
+ int len = f->size() - 12;
+ _spr1 = (uint8_t *)malloc(len);
+ if (!_spr1) {
+ error("Unable to allocate SPR1 buffer");
+ } else {
+ f->seek(12);
+ f->read(_spr1, len);
+ }
+}
+
+void Resource::load_SPRM(File *f) {
+ debug(DBG_RES, "Resource::load_SPRM()");
+ const uint32_t len = f->size() - 12;
+ assert(len <= sizeof(_sprm));
+ f->seek(12);
+ f->read(_sprm, len);
+}
+
+void Resource::load_RP(File *f) {
+ debug(DBG_RES, "Resource::load_RP()");
+ f->read(_rp, 0x4A);
+}
+
+void Resource::load_SPC(File *f) {
+ debug(DBG_RES, "Resource::load_SPC()");
+ int len = f->size();
+ _spc = (uint8_t *)malloc(len);
+ if (!_spc) {
+ error("Unable to allocate SPC buffer");
+ } else {
+ f->read(_spc, len);
+ _numSpc = READ_BE_UINT16(_spc) / 2;
+ }
+}
+
+void Resource::load_PAL(File *f) {
+ debug(DBG_RES, "Resource::load_PAL()");
+ int len = f->size();
+ _pal = (uint8_t *)malloc(len);
+ if (!_pal) {
+ error("Unable to allocate PAL buffer");
+ } else {
+ f->read(_pal, len);
+ }
+}
+
+void Resource::load_MAP(File *f) {
+ debug(DBG_RES, "Resource::load_MAP()");
+ int len = f->size();
+ _map = (uint8_t *)malloc(len);
+ if (!_map) {
+ error("Unable to allocate MAP buffer");
+ } else {
+ f->read(_map, len);
+ }
+}
+
+void Resource::load_OBJ(File *f) {
+ debug(DBG_RES, "Resource::load_OBJ()");
+ if (_type == kResourceTypeAmiga) { // demo has uncompressed objects data
+ const int size = f->size();
+ uint8_t *buf = (uint8_t *)malloc(size);
+ if (!buf) {
+ error("Unable to allocate OBJ buffer");
+ } else {
+ f->read(buf, size);
+ decodeOBJ(buf, size);
+ }
+ return;
+ }
+ _numObjectNodes = f->readUint16LE();
+ assert(_numObjectNodes < 255);
+ uint32_t offsets[256];
+ for (int i = 0; i < _numObjectNodes; ++i) {
+ offsets[i] = f->readUint32LE();
+ }
+ offsets[_numObjectNodes] = f->size() - 2;
+ int numObjectsCount = 0;
+ uint16_t objectsCount[256];
+ for (int i = 0; i < _numObjectNodes; ++i) {
+ int diff = offsets[i + 1] - offsets[i];
+ if (diff != 0) {
+ objectsCount[numObjectsCount] = (diff - 2) / 0x12;
+ debug(DBG_RES, "i=%d objectsCount[numObjectsCount]=%d", i, objectsCount[numObjectsCount]);
+ ++numObjectsCount;
+ }
+ }
+ uint32_t prevOffset = 0;
+ ObjectNode *prevNode = 0;
+ int iObj = 0;
+ for (int i = 0; i < _numObjectNodes; ++i) {
+ if (prevOffset != offsets[i]) {
+ ObjectNode *on = (ObjectNode *)malloc(sizeof(ObjectNode));
+ if (!on) {
+ error("Unable to allocate ObjectNode num=%d", i);
+ }
+ f->seek(offsets[i] + 2);
+ on->last_obj_number = f->readUint16LE();
+ on->num_objects = objectsCount[iObj];
+ debug(DBG_RES, "last=%d num=%d", on->last_obj_number, on->num_objects);
+ on->objects = (Object *)malloc(sizeof(Object) * on->num_objects);
+ for (int j = 0; j < on->num_objects; ++j) {
+ Object *obj = &on->objects[j];
+ obj->type = f->readUint16LE();
+ obj->dx = f->readByte();
+ obj->dy = f->readByte();
+ obj->init_obj_type = f->readUint16LE();
+ obj->opcode2 = f->readByte();
+ obj->opcode1 = f->readByte();
+ obj->flags = f->readByte();
+ obj->opcode3 = f->readByte();
+ obj->init_obj_number = f->readUint16LE();
+ obj->opcode_arg1 = f->readUint16LE();
+ obj->opcode_arg2 = f->readUint16LE();
+ obj->opcode_arg3 = f->readUint16LE();
+ debug(DBG_RES, "obj_node=%d obj=%d op1=0x%X op2=0x%X op3=0x%X", i, j, obj->opcode2, obj->opcode1, obj->opcode3);
+ }
+ ++iObj;
+ prevOffset = offsets[i];
+ prevNode = on;
+ }
+ _objectNodesMap[i] = prevNode;
+ }
+}
+
+void Resource::free_OBJ() {
+ debug(DBG_RES, "Resource::free_OBJ()");
+ ObjectNode *prevNode = 0;
+ for (int i = 0; i < _numObjectNodes; ++i) {
+ if (_objectNodesMap[i] != prevNode) {
+ ObjectNode *curNode = _objectNodesMap[i];
+ free(curNode->objects);
+ free(curNode);
+ prevNode = curNode;
+ }
+ _objectNodesMap[i] = 0;
+ }
+}
+
+void Resource::load_OBC(File *f) {
+ const int packedSize = f->readUint32BE();
+ uint8_t *packedData = (uint8_t *)malloc(packedSize);
+ if (!packedData) {
+ error("Unable to allocate OBC temporary buffer 1");
+ }
+ f->seek(packedSize);
+ const int unpackedSize = f->readUint32BE();
+ uint8_t *tmp = (uint8_t *)malloc(unpackedSize);
+ if (!tmp) {
+ error("Unable to allocate OBC temporary buffer 2");
+ }
+ f->seek(4);
+ f->read(packedData, packedSize);
+ if (!delphine_unpack(tmp, packedData, packedSize)) {
+ error("Bad CRC for compressed object data");
+ }
+ free(packedData);
+ decodeOBJ(tmp, unpackedSize);
+ free(tmp);
+}
+
+void Resource::decodeOBJ(const uint8_t *tmp, int size) {
+ uint32_t offsets[256];
+ int tmpOffset = 0;
+ _numObjectNodes = 230;
+ for (int i = 0; i < _numObjectNodes; ++i) {
+ offsets[i] = READ_BE_UINT32(tmp + tmpOffset); tmpOffset += 4;
+ }
+ offsets[_numObjectNodes] = size;
+ int numObjectsCount = 0;
+ uint16_t objectsCount[256];
+ for (int i = 0; i < _numObjectNodes; ++i) {
+ int diff = offsets[i + 1] - offsets[i];
+ if (diff != 0) {
+ objectsCount[numObjectsCount] = (diff - 2) / 0x12;
+ ++numObjectsCount;
+ }
+ }
+ uint32_t prevOffset = 0;
+ ObjectNode *prevNode = 0;
+ int iObj = 0;
+ for (int i = 0; i < _numObjectNodes; ++i) {
+ if (prevOffset != offsets[i]) {
+ ObjectNode *on = (ObjectNode *)malloc(sizeof(ObjectNode));
+ if (!on) {
+ error("Unable to allocate ObjectNode num=%d", i);
+ }
+ const uint8_t *objData = tmp + offsets[i];
+ on->last_obj_number = READ_BE_UINT16(objData); objData += 2;
+ on->num_objects = objectsCount[iObj];
+ on->objects = (Object *)malloc(sizeof(Object) * on->num_objects);
+ for (int j = 0; j < on->num_objects; ++j) {
+ Object *obj = &on->objects[j];
+ obj->type = READ_BE_UINT16(objData); objData += 2;
+ obj->dx = *objData++;
+ obj->dy = *objData++;
+ obj->init_obj_type = READ_BE_UINT16(objData); objData += 2;
+ obj->opcode2 = *objData++;
+ obj->opcode1 = *objData++;
+ obj->flags = *objData++;
+ obj->opcode3 = *objData++;
+ obj->init_obj_number = READ_BE_UINT16(objData); objData += 2;
+ obj->opcode_arg1 = READ_BE_UINT16(objData); objData += 2;
+ obj->opcode_arg2 = READ_BE_UINT16(objData); objData += 2;
+ obj->opcode_arg3 = READ_BE_UINT16(objData); objData += 2;
+ debug(DBG_RES, "obj_node=%d obj=%d op1=0x%X op2=0x%X op3=0x%X", i, j, obj->opcode2, obj->opcode1, obj->opcode3);
+ }
+ ++iObj;
+ prevOffset = offsets[i];
+ prevNode = on;
+ }
+ _objectNodesMap[i] = prevNode;
+ }
+}
+
+void Resource::load_PGE(File *f) {
+ debug(DBG_RES, "Resource::load_PGE()");
+ int len = f->size() - 2;
+ _pgeNum = f->readUint16LE();
+ if (_type == kResourceTypeAmiga) {
+ SWAP_UINT16(&_pgeNum);
+ }
+ memset(_pgeInit, 0, sizeof(_pgeInit));
+ debug(DBG_RES, "len=%d _pgeNum=%d", len, _pgeNum);
+ for (uint16_t i = 0; i < _pgeNum; ++i) {
+ InitPGE *pge = &_pgeInit[i];
+ pge->type = f->readUint16LE();
+ pge->pos_x = f->readUint16LE();
+ pge->pos_y = f->readUint16LE();
+ pge->obj_node_number = f->readUint16LE();
+ pge->life = f->readUint16LE();
+ for (int lc = 0; lc < 4; ++lc) {
+ pge->counter_values[lc] = f->readUint16LE();
+ }
+ pge->object_type = f->readByte();
+ pge->init_room = f->readByte();
+ pge->room_location = f->readByte();
+ pge->init_flags = f->readByte();
+ pge->colliding_icon_num = f->readByte();
+ pge->icon_num = f->readByte();
+ pge->object_id = f->readByte();
+ pge->skill = f->readByte();
+ pge->mirror_x = f->readByte();
+ pge->flags = f->readByte();
+ pge->unk1C = f->readByte();
+ f->readByte();
+ pge->text_num = f->readUint16LE();
+ }
+ if (_type == kResourceTypeAmiga) {
+ for (uint16_t i = 0; i < _pgeNum; ++i) {
+ InitPGE *pge = &_pgeInit[i];
+ SWAP_UINT16((uint16_t *)&pge->type);
+ SWAP_UINT16((uint16_t *)&pge->pos_x);
+ SWAP_UINT16((uint16_t *)&pge->pos_y);
+ SWAP_UINT16((uint16_t *)&pge->obj_node_number);
+ SWAP_UINT16((uint16_t *)&pge->life);
+ for (int lc = 0; lc < 4; ++lc) {
+ SWAP_UINT16((uint16_t *)&pge->counter_values[lc]);
+ }
+ SWAP_UINT16((uint16_t *)&pge->text_num);
+ }
+ }
+}
+
+void Resource::load_ANI(File *f) {
+ debug(DBG_RES, "Resource::load_ANI()");
+ int size = f->size() - 2;
+ _ani = (uint8_t *)malloc(size);
+ if (!_ani) {
+ error("Unable to allocate ANI buffer");
+ } else {
+ uint16_t count = f->readUint16LE();
+ f->read(_ani, size);
+ if (_type == kResourceTypeAmiga) {
+ const uint8_t *end = _ani + size;
+ SWAP_UINT16(&count);
+ // byte-swap animation data
+ for (uint16_t i = 0; i < count; ++i) {
+ uint8_t *p = _ani + READ_BE_UINT16(_ani + 2 * i);
+ // byte-swap offset
+ SWAP(_ani[2 * i], _ani[2 * i + 1]);
+ if (p >= end) {
+ continue;
+ }
+ const int frames = READ_BE_UINT16(p);
+ if (p[0] != 0) {
+ // byte-swap only once
+ continue;
+ }
+ // byte-swap anim count
+ SWAP(p[0], p[1]);
+ debug(DBG_RES, "ani=%d frames=%d", i, frames);
+ for (int j = 0; j < frames; ++j) {
+ // byte-swap next frame
+ SWAP(p[6 + j * 4], p[6 + j * 4 + 1]);
+ }
+ }
+ }
+ }
+}
+
+void Resource::load_TBN(File *f) {
+ debug(DBG_RES, "Resource::load_TBN()");
+ int len = f->size();
+ _tbn = (uint8_t *)malloc(len);
+ if (!_tbn) {
+ error("Unable to allocate TBN buffer");
+ } else {
+ f->read(_tbn, len);
+ }
+ if (_type == kResourceTypeAmiga) {
+ const int firstOffset = READ_BE_UINT16(_tbn);
+ for (int i = 0; i < firstOffset; i += 2) {
+ // byte-swap offset
+ SWAP(_tbn[i], _tbn[i + 1]);
+ }
+ }
+}
+
+void Resource::load_CMD(File *pf) {
+ debug(DBG_RES, "Resource::load_CMD()");
+ free(_cmd);
+ int len = pf->size();
+ _cmd = (uint8_t *)malloc(len);
+ if (!_cmd) {
+ error("Unable to allocate CMD buffer");
+ } else {
+ pf->read(_cmd, len);
+ }
+}
+
+void Resource::load_POL(File *pf) {
+ debug(DBG_RES, "Resource::load_POL()");
+ free(_pol);
+ int len = pf->size();
+ _pol = (uint8_t *)malloc(len);
+ if (!_pol) {
+ error("Unable to allocate POL buffer");
+ } else {
+ pf->read(_pol, len);
+ }
+}
+
+void Resource::load_CMP(File *pf) {
+ free(_pol);
+ free(_cmd);
+ int len = pf->size();
+ uint8_t *tmp = (uint8_t *)malloc(len);
+ if (!tmp) {
+ error("Unable to allocate CMP buffer");
+ }
+ pf->read(tmp, len);
+ struct {
+ int offset, packedSize, size;
+ } data[2];
+ int offset = 0;
+ for (int i = 0; i < 2; ++i) {
+ int packedSize = READ_BE_UINT32(tmp + offset); offset += 4;
+ assert((packedSize & 1) == 0);
+ if (packedSize < 0) {
+ data[i].size = packedSize = -packedSize;
+ } else {
+ data[i].size = READ_BE_UINT32(tmp + offset + packedSize - 4);
+ }
+ data[i].offset = offset;
+ data[i].packedSize = packedSize;
+ offset += packedSize;
+ }
+ _pol = (uint8_t *)malloc(data[0].size);
+ if (!_pol) {
+ error("Unable to allocate POL buffer");
+ }
+ if (data[0].packedSize == data[0].size) {
+ memcpy(_pol, tmp + data[0].offset, data[0].packedSize);
+ } else if (!delphine_unpack(_pol, tmp + data[0].offset, data[0].packedSize)) {
+ error("Bad CRC for cutscene polygon data");
+ }
+ _cmd = (uint8_t *)malloc(data[1].size);
+ if (!_cmd) {
+ error("Unable to allocate CMD buffer");
+ }
+ if (data[1].packedSize == data[1].size) {
+ memcpy(_cmd, tmp + data[1].offset, data[1].packedSize);
+ } else if (!delphine_unpack(_cmd, tmp + data[1].offset, data[1].packedSize)) {
+ error("Bad CRC for cutscene command data");
+ }
+ free(tmp);
+}
+
+void Resource::load_VCE(int num, int segment, uint8_t **buf, uint32_t *bufSize) {
+ *buf = 0;
+ int offset = _voicesOffsetsTable[num];
+ if (offset != 0xFFFF) {
+ const uint16_t *p = _voicesOffsetsTable + offset / 2;
+ offset = (*p++) * 2048;
+ int count = *p++;
+ if (segment < count) {
+ File f;
+ if (f.open("VOICE.VCE", "rb", _fs)) {
+ int voiceSize = p[segment] * 2048 / 5;
+ uint8_t *voiceBuf = (uint8_t *)malloc(voiceSize);
+ if (voiceBuf) {
+ uint8_t *dst = voiceBuf;
+ offset += 0x2000;
+ for (int s = 0; s < count; ++s) {
+ int len = p[s] * 2048;
+ for (int i = 0; i < len / (0x2000 + 2048); ++i) {
+ if (s == segment) {
+ f.seek(offset);
+ int n = 2048;
+ while (n--) {
+ int v = f.readByte();
+ if (v & 0x80) {
+ v = -(v & 0x7F);
+ }
+ *dst++ = (uint8_t)(v & 0xFF);
+ }
+ }
+ offset += 0x2000 + 2048;
+ }
+ if (s == segment) {
+ break;
+ }
+ }
+ *buf = voiceBuf;
+ *bufSize = voiceSize;
+ }
+ }
+ }
+ }
+}
+
+void Resource::load_SPL(File *f) {
+ for (int i = 0; i < _numSfx; ++i) {
+ free(_sfxList[i].data);
+ }
+ free(_sfxList);
+ _numSfx = NUM_SFXS;
+ _sfxList = (SoundFx *)calloc(_numSfx, sizeof(SoundFx));
+ if (!_sfxList) {
+ error("Unable to allocate SoundFx table");
+ }
+ int offset = 0;
+ for (int i = 0; i < _numSfx; ++i) {
+ const int size = f->readUint16BE(); offset += 2;
+ if ((size & 0x8000) != 0) {
+ continue;
+ }
+ debug(DBG_RES, "sfx=%d size=%d", i, size);
+ assert(size != 0 && (size & 1) == 0);
+ if (i != 64) {
+ _sfxList[i].offset = offset;
+ _sfxList[i].len = size;
+ _sfxList[i].data = (uint8_t *)malloc(size);
+ assert(_sfxList[i].data);
+ f->read(_sfxList[i].data, size);
+ } else {
+ f->seek(offset + size);
+ }
+ offset += size;
+ }
+}
+
+void Resource::load_LEV(File *f) {
+ const int len = f->size();
+ _lev = (uint8_t *)malloc(len);
+ if (!_lev) {
+ error("Unable to allocate LEV buffer");
+ } else {
+ f->read(_lev, len);
+ }
+}
+
+void Resource::load_SGD(File *f) {
+ const int len = f->size();
+ f->seek(len - 4);
+ int size = f->readUint32BE();
+ f->seek(0);
+ uint8_t *tmp = (uint8_t *)malloc(len);
+ if (!tmp) {
+ error("Unable to allocate SGD temporary buffer");
+ }
+ f->read(tmp, len);
+ _sgd = (uint8_t *)malloc(size);
+ if (!_sgd) {
+ error("Unable to allocate SGD buffer");
+ }
+ if (!delphine_unpack(_sgd, tmp, len)) {
+ error("Bad CRC for SGD data");
+ }
+ free(tmp);
+}
+
+void Resource::load_SPM(File *f) {
+ static const int kPersoDatSize = 178647;
+ const int len = f->size();
+ f->seek(len - 4);
+ const uint32_t size = f->readUint32BE();
+ f->seek(0);
+ uint8_t *tmp = (uint8_t *)malloc(len);
+ if (!tmp) {
+ error("Unable to allocate SPM temporary buffer");
+ }
+ f->read(tmp, len);
+ if (size == kPersoDatSize) {
+ _spr1 = (uint8_t *)malloc(size);
+ if (!_spr1) {
+ error("Unable to allocate SPR1 buffer");
+ }
+ if (!delphine_unpack(_spr1, tmp, len)) {
+ error("Bad CRC for SPM data");
+ }
+ } else {
+ assert(size <= sizeof(_sprm));
+ if (!delphine_unpack(_sprm, tmp, len)) {
+ error("Bad CRC for SPM data");
+ }
+ }
+ for (int i = 0; i < NUM_SPRITES; ++i) {
+ const uint32_t offset = _spmOffsetsTable[i];
+ if (offset >= kPersoDatSize) {
+ _sprData[i] = _sprm + offset - kPersoDatSize;
+ } else {
+ _sprData[i] = _spr1 + offset;
+ }
+ }
+ free(tmp);
+}
+
+void Resource::clearBankData() {
+ _bankBuffersCount = 0;
+ _bankDataHead = _bankData;
+}
+
+int Resource::getBankDataSize(uint16_t num) {
+ int len = READ_BE_UINT16(_mbk + num * 6 + 4);
+ int size = 0;
+ switch (_type) {
+ case kResourceTypeAmiga:
+ if (len & 0x8000) {
+ len = -(int16_t)len;
+ }
+ size = len * 32;
+ break;
+ case kResourceTypePC:
+ size = (len & 0x7FFF) * 32;
+ break;
+ }
+ return size;
+}
+
+uint8_t *Resource::findBankData(uint16_t num) {
+ for (int i = 0; i < _bankBuffersCount; ++i) {
+ if (_bankBuffers[i].entryNum == num) {
+ return _bankBuffers[i].ptr;
+ }
+ }
+ return 0;
+}
+
+uint8_t *Resource::loadBankData(uint16_t num) {
+ const uint8_t *ptr = _mbk + num * 6;
+ int dataOffset = READ_BE_UINT32(ptr);
+ if (_type == kResourceTypePC) {
+ // first byte of the data buffer corresponds
+ // to the total count of entries
+ dataOffset &= 0xFFFF;
+ }
+ const int size = getBankDataSize(num);
+ const int avail = _bankDataTail - _bankDataHead;
+ if (avail < size) {
+ clearBankData();
+ }
+ assert(_bankDataHead + size <= _bankDataTail);
+ assert(_bankBuffersCount < (int)ARRAYSIZE(_bankBuffers));
+ _bankBuffers[_bankBuffersCount].entryNum = num;
+ _bankBuffers[_bankBuffersCount].ptr = _bankDataHead;
+ const uint8_t *data = _mbk + dataOffset;
+ if (READ_BE_UINT16(ptr + 4) & 0x8000) {
+ memcpy(_bankDataHead, data, size);
+ } else {
+ assert(dataOffset > 4);
+ assert(size == (int)READ_BE_UINT32(data - 4));
+ if (!delphine_unpack(_bankDataHead, data, 0)) {
+ error("Bad CRC for bank data %d", num);
+ }
+ }
+ uint8_t *bankData = _bankDataHead;
+ _bankDataHead += size;
+ return bankData;
+}
+
diff --git a/resource.h b/resource.h
new file mode 100644
index 0000000..56406dc
--- /dev/null
+++ b/resource.h
@@ -0,0 +1,214 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 RESOURCE_H__
+#define RESOURCE_H__
+
+#include "intern.h"
+
+struct File;
+struct FileSystem;
+
+struct LocaleData {
+ enum Id {
+ LI_01_CONTINUE_OR_ABORT = 0,
+ LI_02_TIME,
+ LI_03_CONTINUE,
+ LI_04_ABORT,
+ LI_05_COMPLETED,
+ LI_06_LEVEL,
+ LI_07_START,
+ LI_08_SKILL,
+ LI_09_PASSWORD,
+ LI_10_INFO,
+ LI_11_QUIT,
+ LI_12_SKILL_LEVEL,
+ LI_13_EASY,
+ LI_14_NORMAL,
+ LI_15_EXPERT,
+ LI_16_ENTER_PASSWORD1,
+ LI_17_ENTER_PASSWORD2,
+ LI_18_RESUME_GAME,
+ LI_19_ABORT_GAME,
+ LI_20_LOAD_GAME,
+ LI_21_SAVE_GAME,
+ LI_22_SAVE_SLOT,
+
+ LI_NUM
+ };
+
+ static const char *_textsTableFR[];
+ static const char *_textsTableEN[];
+ static const char *_textsTableDE[];
+ static const char *_textsTableSP[];
+ static const char *_textsTableIT[];
+ static const uint8_t _stringsTableFR[];
+ static const uint8_t _stringsTableEN[];
+ static const uint8_t _stringsTableDE[];
+ static const uint8_t _stringsTableSP[];
+ static const uint8_t _stringsTableIT[];
+};
+
+struct Resource {
+ typedef void (Resource::*LoadStub)(File *);
+
+ enum ObjectType {
+ OT_MBK,
+ OT_PGE,
+ OT_PAL,
+ OT_CT,
+ OT_MAP,
+ OT_SPC,
+ OT_RP,
+ OT_RPC,
+ OT_DEMO,
+ OT_ANI,
+ OT_OBJ,
+ OT_TBN,
+ OT_SPR,
+ OT_TAB,
+ OT_ICN,
+ OT_FNT,
+ OT_TXTBIN,
+ OT_CMD,
+ OT_POL,
+ OT_SPRM,
+ OT_OFF,
+ OT_CMP,
+ OT_OBC,
+ OT_SPL,
+ OT_LEV,
+ OT_SGD,
+ OT_SPM
+ };
+
+ enum {
+ NUM_SFXS = 66,
+ NUM_SPRITES = 1287
+ };
+
+ static const uint16_t _voicesOffsetsTable[];
+ static const uint32_t _spmOffsetsTable[];
+ static const char *_splNames[];
+
+ FileSystem *_fs;
+ ResourceType _type;
+ Language _lang;
+ bool _hasSeqData;
+ char _entryName[32];
+ uint8_t *_fnt;
+ uint8_t *_mbk;
+ uint8_t *_icn;
+ int _icnLen;
+ uint8_t *_tab;
+ uint8_t *_spc; // BE
+ uint16_t _numSpc;
+ uint8_t _rp[0x4A];
+ uint8_t *_pal; // BE
+ uint8_t *_ani;
+ uint8_t *_tbn;
+ int8_t _ctData[0x1D00];
+ uint8_t *_spr1;
+ uint8_t *_sprData[NUM_SPRITES]; // 0-0x22F + 0x28E-0x2E9 ... conrad, 0x22F-0x28D : junkie
+ uint8_t _sprm[0x10000];
+ uint16_t _pgeNum;
+ InitPGE _pgeInit[256];
+ uint8_t *_map;
+ uint8_t *_lev;
+ int _levNum;
+ uint8_t *_sgd;
+ uint16_t _numObjectNodes;
+ ObjectNode *_objectNodesMap[255];
+ uint8_t *_memBuf;
+ SoundFx *_sfxList;
+ uint8_t _numSfx;
+ uint8_t *_cmd;
+ uint8_t *_pol;
+ uint8_t *_cine_off;
+ uint8_t *_cine_txt;
+ char **_extTextsTable;
+ const char **_textsTable;
+ uint8_t *_extStringsTable;
+ const uint8_t *_stringsTable;
+ uint8_t *_bankData;
+ uint8_t *_bankDataHead;
+ uint8_t *_bankDataTail;
+ BankSlot _bankBuffers[50];
+ int _bankBuffersCount;
+
+ Resource(FileSystem *fs, ResourceType type, Language lang);
+ ~Resource();
+
+ void clearLevelRes();
+ void load_FIB(const char *fileName);
+ void load_SPL_demo();
+ void load_MAP_menu(const char *fileName, uint8_t *dstPtr);
+ void load_PAL_menu(const char *fileName, uint8_t *dstPtr);
+ void load_SPR_OFF(const char *fileName, uint8_t *sprData);
+ void load_CINE();
+ void load_TEXT();
+ void free_TEXT();
+ void load(const char *objName, int objType, const char *ext = 0);
+ void load_CT(File *pf);
+ void load_FNT(File *pf);
+ void load_MBK(File *pf);
+ void load_ICN(File *pf);
+ void load_SPR(File *pf);
+ void load_SPRM(File *pf);
+ void load_RP(File *pf);
+ void load_SPC(File *pf);
+ void load_PAL(File *pf);
+ void load_MAP(File *pf);
+ void load_OBJ(File *pf);
+ void free_OBJ();
+ void load_OBC(File *pf);
+ void decodeOBJ(const uint8_t *, int);
+ void load_PGE(File *pf);
+ void load_ANI(File *pf);
+ void load_TBN(File *pf);
+ void load_CMD(File *pf);
+ void load_POL(File *pf);
+ void load_CMP(File *pf);
+ void load_VCE(int num, int segment, uint8_t **buf, uint32_t *bufSize);
+ void load_SPL(File *pf);
+ void load_LEV(File *pf);
+ void load_SGD(File *pf);
+ void load_SPM(File *f);
+ const uint8_t *getAniData(int num) const {
+ const int offset = READ_LE_UINT16(_ani + num * 2);
+ return _ani + offset;
+ }
+ const uint8_t *getGameString(int num) {
+ return _stringsTable + READ_LE_UINT16(_stringsTable + num * 2);
+ }
+ const uint8_t *getCineString(int num) {
+ if (_cine_off) {
+ const int offset = READ_BE_UINT16(_cine_off + num * 2);
+ return _cine_txt + offset;
+ }
+ return 0;
+ }
+ const char *getMenuString(int num) {
+ return (num >= 0 && num < LocaleData::LI_NUM) ? _textsTable[num] : "";
+ }
+ void clearBankData();
+ int getBankDataSize(uint16_t num);
+ uint8_t *findBankData(uint16_t num);
+ uint8_t *loadBankData(uint16_t num);
+};
+
+#endif // RESOURCE_H__
diff --git a/scaler.cpp b/scaler.cpp
new file mode 100644
index 0000000..8edb46c
--- /dev/null
+++ b/scaler.cpp
@@ -0,0 +1,192 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "scaler.h"
+
+
+static void point1x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
+ dstPitch >>= 1;
+ while (h--) {
+ memcpy(dst, src, w * 2);
+ dst += dstPitch;
+ src += srcPitch;
+ }
+}
+
+static void point2x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
+ dstPitch >>= 1;
+ const int dstPitch2 = dstPitch * 2;
+ while (h--) {
+ uint16_t *p = dst;
+ for (int i = 0; i < w; ++i, p += 2) {
+ const uint16_t c = *(src + i);
+ for (int j = 0; j < 2; ++j) {
+ *(p + j) = *(p + dstPitch + j) = c;
+ }
+ }
+ dst += dstPitch2;
+ src += srcPitch;
+ }
+}
+
+static void point3x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
+ dstPitch >>= 1;
+ const int dstPitch2 = dstPitch * 2;
+ const int dstPitch3 = dstPitch * 3;
+ while (h--) {
+ uint16_t *p = dst;
+ for (int i = 0; i < w; ++i, p += 3) {
+ const uint16_t c = *(src + i);
+ for (int j = 0; j < 3; ++j) {
+ *(p + j) = *(p + dstPitch + j) = *(p + dstPitch2 + j) = c;
+ }
+ }
+ dst += dstPitch3;
+ src += srcPitch;
+ }
+}
+
+static void point4x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
+ dstPitch >>= 1;
+ const int dstPitch2 = dstPitch * 2;
+ const int dstPitch3 = dstPitch * 3;
+ const int dstPitch4 = dstPitch * 4;
+ while (h--) {
+ uint16_t *p = dst;
+ for (int i = 0; i < w; ++i, p += 4) {
+ const uint16_t c = *(src + i);
+ for (int j = 0; j < 4; ++j) {
+ *(p + j) = *(p + dstPitch + j) = *(p + dstPitch2 + j) = *(p + dstPitch3 + j) = c;
+ }
+ }
+ dst += dstPitch4;
+ src += srcPitch;
+ }
+}
+
+static void scale2x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
+ dstPitch >>= 1;
+ const int dstPitch2 = dstPitch * 2;
+ while (h--) {
+ uint16_t *p = dst;
+ uint16_t D = *(src - 1);
+ uint16_t E = *(src);
+ for (int i = 0; i < w; ++i, p += 2) {
+ uint16_t B = *(src + i - srcPitch);
+ uint16_t F = *(src + i + 1);
+ uint16_t H = *(src + i + srcPitch);
+ if (B != H && D != F) {
+ *(p) = D == B ? D : E;
+ *(p + 1) = B == F ? F : E;
+ *(p + dstPitch) = D == H ? D : E;
+ *(p + dstPitch + 1) = H == F ? F : E;
+ } else {
+ *(p) = E;
+ *(p + 1) = E;
+ *(p + dstPitch) = E;
+ *(p + dstPitch + 1) = E;
+ }
+ D = E;
+ E = F;
+ }
+ dst += dstPitch2;
+ src += srcPitch;
+ }
+}
+
+static void scale3x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
+ dstPitch >>= 1;
+ const int dstPitch2 = dstPitch * 2;
+ const int dstPitch3 = dstPitch * 3;
+ while (h--) {
+ uint16_t *p = dst;
+ uint16_t A = *(src - srcPitch - 1);
+ uint16_t B = *(src - srcPitch);
+ uint16_t D = *(src - 1);
+ uint16_t E = *(src);
+ uint16_t G = *(src + srcPitch - 1);
+ uint16_t H = *(src + srcPitch);
+ for (int i = 0; i < w; ++i, p += 3) {
+ uint16_t C = *(src + i - srcPitch + 1);
+ uint16_t F = *(src + i + 1);
+ uint16_t I = *(src + i + srcPitch + 1);
+ if (B != H && D != F) {
+ *(p) = D == B ? D : E;
+ *(p + 1) = (D == B && E != C) || (B == F && E != A) ? B : E;
+ *(p + 2) = B == F ? F : E;
+ *(p + dstPitch) = (D == B && E != G) || (D == B && E != A) ? D : E;
+ *(p + dstPitch + 1) = E;
+ *(p + dstPitch + 2) = (B == F && E != I) || (H == F && E != C) ? F : E;
+ *(p + dstPitch2) = D == H ? D : E;
+ *(p + dstPitch2 + 1) = (D == H && E != I) || (H == F && E != G) ? H : E;
+ *(p + dstPitch2 + 2) = H == F ? F : E;
+ } else {
+ *(p) = E;
+ *(p + 1) = E;
+ *(p + 2) = E;
+ *(p + dstPitch) = E;
+ *(p + dstPitch + 1) = E;
+ *(p + dstPitch + 2) = E;
+ *(p + dstPitch2) = E;
+ *(p + dstPitch2 + 1) = E;
+ *(p + dstPitch2 + 2) = E;
+ }
+ A = B;
+ B = C;
+ D = E;
+ E = F;
+ G = H;
+ H = I;
+ }
+ dst += dstPitch3;
+ src += srcPitch;
+ }
+}
+
+void scale4x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
+ static struct {
+ uint16_t *ptr;
+ int w, h, pitch;
+ int size;
+ } buf;
+ const int size = (w * 2 + 2) * (h * 2 + 2) * sizeof(uint16_t);
+ if (buf.size < size) {
+ free(buf.ptr);
+ buf.size = size;
+ buf.w = w * 2;
+ buf.h = h * 2;
+ buf.pitch = buf.w + 2;
+ buf.ptr = (uint16_t *)malloc(buf.size);
+ if (!buf.ptr) {
+ error("Unable to allocate scale4x intermediate buffer");
+ }
+ }
+ scale2x(buf.ptr + buf.pitch + 1, buf.pitch * sizeof(uint16_t), src, srcPitch, w, h);
+ scale2x(dst, dstPitch, buf.ptr + buf.pitch + 1, buf.pitch, w * 2, h * 2);
+}
+
+const Scaler _scalers[] = {
+ { "point1x", &point1x, 1 },
+ { "point2x", &point2x, 2 },
+ { "scale2x", &scale2x, 2 },
+ { "point3x", &point3x, 3 },
+ { "scale3x", &scale3x, 3 },
+ { "point4x", &point4x, 4 },
+ { "scale4x", &scale4x, 4 },
+ { 0, 0, 0 }
+};
+
diff --git a/scaler.h b/scaler.h
new file mode 100644
index 0000000..f6b4be2
--- /dev/null
+++ b/scaler.h
@@ -0,0 +1,44 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 SCALER_H__
+#define SCALER_H__
+
+#include "intern.h"
+
+typedef void (*ScaleProc)(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h);
+
+enum {
+ SCALER_POINT_1X = 0,
+ SCALER_POINT_2X,
+ SCALER_SCALE_2X,
+ SCALER_POINT_3X,
+ SCALER_SCALE_3X,
+ SCALER_POINT_4X,
+ SCALER_SCALE_4X,
+ NUM_SCALERS = 7
+};
+
+struct Scaler {
+ const char *name;
+ ScaleProc proc;
+ uint8_t factor;
+};
+
+extern const Scaler _scalers[];
+
+#endif // SCALER_H__
diff --git a/seq_player.cpp b/seq_player.cpp
new file mode 100644
index 0000000..77c6c10
--- /dev/null
+++ b/seq_player.cpp
@@ -0,0 +1,367 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "file.h"
+#include "fs.h"
+#include "mixer.h"
+#include "seq_player.h"
+#include "systemstub.h"
+
+
+bool SeqDemuxer::open(File *f) {
+ _f = f;
+ _fileSize = _f->size();
+ memset(_buffers, 0, sizeof(_buffers));
+ _frameOffset = 0;
+ return readHeader();
+}
+
+void SeqDemuxer::close() {
+ _f = 0;
+ for (int i = 0; i < kBuffersCount; ++i) {
+ free(_buffers[i].data);
+ }
+}
+
+bool SeqDemuxer::readHeader() {
+ for (int i = 0; i < 256; i += 4) {
+ if (_f->readUint32LE() != 0) {
+ return false;
+ }
+ }
+ for (int i = 0; i < kBuffersCount; ++i) {
+ const int size = _f->readUint16LE();
+ if (size != 0) {
+ _buffers[i].size = 0;
+ _buffers[i].avail = size;
+ _buffers[i].data = (uint8_t *)malloc(size);
+ if (!_buffers[i].data) {
+ error("Unable to allocate %d bytes for SEQ buffer %d", size, i);
+ }
+ }
+ }
+ for (int i = 1; i <= 100; ++i) {
+ readFrameData();
+ }
+ return true;
+}
+
+bool SeqDemuxer::readFrameData() {
+ _frameOffset += kFrameSize;
+ if (_frameOffset >= _fileSize) {
+ return false;
+ }
+ _f->seek(_frameOffset);
+ _audioDataOffset = _f->readUint16LE();
+ _audioDataSize = (_audioDataOffset != 0) ? kAudioBufferSize * 2 : 0;
+ _paletteDataOffset = _f->readUint16LE();
+ _paletteDataSize = (_paletteDataOffset != 0) ? 768 : 0;
+ uint8_t num[4];
+ for (int i = 0; i < 4; ++i) {
+ num[i] = _f->readByte();
+ }
+ uint16_t offsets[4];
+ for (int i = 0; i < 4; ++i) {
+ offsets[i] = _f->readUint16LE();
+ }
+ for (int i = 0; i < 3; ++i) {
+ if (offsets[i] != 0) {
+ int e = i + 1;
+ while (e < 3 && offsets[e] == 0) {
+ ++e;
+ }
+ fillBuffer(num[i + 1], offsets[i], offsets[e] - offsets[i]);
+ }
+ }
+ if (num[0] != 255) {
+ assert(num[0] < kBuffersCount);
+ _videoData = num[0];
+ } else {
+ _videoData = -1;
+ }
+ return !_f->ioErr();
+}
+
+void SeqDemuxer::fillBuffer(int num, int offset, int size) {
+ assert(num < kBuffersCount);
+ _f->seek(_frameOffset + offset);
+ assert(_buffers[num].size + size <= _buffers[num].avail);
+ _f->read(_buffers[num].data + _buffers[num].size, size);
+ _buffers[num].size += size;
+}
+
+void SeqDemuxer::clearBuffer(int num) {
+ _buffers[num].size = 0;
+}
+
+void SeqDemuxer::readPalette(uint8_t *dst) {
+ _f->seek(_frameOffset + _paletteDataOffset);
+ _f->read(dst, 256 * 3);
+}
+
+void SeqDemuxer::readAudioS8(uint8_t *dst) {
+ _f->seek(_frameOffset + _audioDataOffset);
+ for (int i = 0; i < kAudioBufferSize; ++i) {
+ dst[i] = _f->readUint16BE() >> 8;
+ }
+}
+
+struct BitStream {
+ BitStream(const uint8_t *src)
+ : _src(src) {
+ _bits = READ_LE_UINT16(_src); _src += 2;
+ _len = 16;
+ }
+ int getBits(int count) {
+ if (count > _len) {
+ _bits |= READ_LE_UINT16(_src) << _len; _src += 2;
+ _len += 16;
+ }
+ assert(count <= _len);
+ const int x = _bits & ((1 << count) - 1);
+ _bits >>= count;
+ _len -= count;
+ return x;
+ }
+ int getSignedBits(int count) {
+ const int32_t x = getBits(count);
+ return (x << (32 - count)) >> (32 - count);
+ }
+
+ const uint8_t *_src;
+ int _len;
+ uint32_t _bits;
+};
+
+static const uint8_t *decodeSeqOp1Helper(const uint8_t *src, uint8_t *dst, int dstSize) {
+ int codes[64], count = 0;
+ BitStream bs(src);
+ for (int i = 0, sz = 0; i < 64 && sz < 64; ++i) {
+ codes[i] = bs.getSignedBits(4);
+ sz += ABS(codes[i]);
+ count += 4;
+ }
+ src += (count + 7) / 8;
+ for (int i = 0; i < 64 && dstSize > 0; ++i) {
+ int len = codes[i];
+ if (len < 0) {
+ len = -len;
+ memset(dst, *src++, MIN(len, dstSize));
+ } else {
+ memcpy(dst, src, MIN(len, dstSize));
+ src += len;
+ }
+ dst += len;
+ dstSize -= len;
+ }
+ return src;
+}
+
+static const uint8_t *decodeSeqOp1(uint8_t *dst, int pitch, const uint8_t *src) {
+ const int len = *src++;
+ if (len & 0x80) {
+ uint8_t buf[8 * 8];
+ switch (len & 3) {
+ case 1:
+ src = decodeSeqOp1Helper(src, buf, sizeof(buf));
+ for (int y = 0; y < 8; ++y) {
+ memcpy(dst, buf + y * 8, 8);
+ dst += pitch;
+ }
+ break;
+ case 2:
+ src = decodeSeqOp1Helper(src, buf, sizeof(buf));
+ for (int i = 0; i < 8; i++) {
+ for (int y = 0; y < 8; ++y) {
+ dst[y * pitch] = buf[i * 8 + y];
+ }
+ ++dst;
+ }
+ break;
+ }
+ } else {
+ static const uint8_t log2_16[] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
+ BitStream bs(src + len);
+ assert(len <= 16);
+ const int bits = log2_16[len - 1] + 1;
+ for (int y = 0; y < 8; ++y) {
+ for (int x = 0; x < 8; ++x) {
+ dst[y * pitch + x] = src[bs.getBits(bits)];
+ }
+ }
+ src += len + bits * 8;
+ }
+ return src;
+}
+
+static const uint8_t *decodeSeqOp2(uint8_t *dst, int pitch, const uint8_t *src) {
+ for (int y = 0; y < 8; ++y) {
+ memcpy(dst + y * pitch, src, 8);
+ src += 8;
+ }
+ return src;
+}
+
+static const uint8_t *decodeSeqOp3(uint8_t *dst, int pitch, const uint8_t *src) {
+ int pos;
+ do {
+ pos = *src++;
+ const int offset = ((pos >> 3) & 7) * pitch + (pos & 7);
+ dst[offset] = *src++;
+ } while ((pos & 0x80) == 0);
+ return src;
+}
+
+SeqPlayer::SeqPlayer(SystemStub *stub, Mixer *mixer)
+ : _stub(stub), _buf(0), _mix(mixer) {
+ _soundQueuePreloadSize = 0;
+ _soundQueue = 0;
+}
+
+SeqPlayer::~SeqPlayer() {
+}
+
+void SeqPlayer::play(File *f) {
+ if (_demux.open(f)) {
+ Color pal[256];
+ for (int i = 0; i < 256; ++i) {
+ _stub->getPaletteEntry(i, &pal[i]);
+ }
+ _mix->setPremixHook(mixCallback, this);
+ memset(_buf, 0, 256 * 224);
+ bool clearScreen = true;
+ while (true) {
+ const uint32_t nextFrameTimeStamp = _stub->getTimeStamp() + 1000 / 25;
+ _stub->processEvents();
+ if (_stub->_pi.quit || _stub->_pi.backspace) {
+ _stub->_pi.backspace = false;
+ break;
+ }
+ if (!_demux.readFrameData()) {
+ break;
+ }
+ if (_demux._audioDataSize != 0) {
+ SoundBufferQueue *sbq = (SoundBufferQueue *)malloc(sizeof(SoundBufferQueue));
+ if (sbq) {
+ sbq->data = (uint8_t *)malloc(SeqDemuxer::kAudioBufferSize);
+ if (sbq->data) {
+ _demux.readAudioS8(sbq->data);
+ sbq->size = SeqDemuxer::kAudioBufferSize;
+ sbq->read = 0;
+ sbq->next = 0;
+ } else {
+ free(sbq);
+ sbq = 0;
+ }
+ }
+ if (sbq) {
+ LockAudioStack las(_stub);
+ if (!_soundQueue) {
+ _soundQueue = sbq;
+ } else {
+ SoundBufferQueue *p = _soundQueue;
+ while (p->next) {
+ p = p->next;
+ }
+ p->next = sbq;
+ }
+ if (_soundQueuePreloadSize < kSoundPreloadSize) {
+ ++_soundQueuePreloadSize;
+ }
+ }
+ }
+ if (_demux._paletteDataSize != 0) {
+ uint8_t buf[256 * 3];
+ _demux.readPalette(buf);
+ for (int i = 0; i < 256 * 3; ++i) {
+ buf[i] = (buf[i] << 2) | (buf[i] & 3);
+ }
+ _stub->setPalette(buf, 256);
+ }
+ if (_demux._videoData != -1) {
+ const int y0 = (224 - kVideoHeight) / 2;
+ const uint8_t *src = _demux._buffers[_demux._videoData].data;
+ _demux.clearBuffer(_demux._videoData);
+ BitStream bs(src); src += 128;
+ for (int y = 0; y < kVideoHeight; y += 8) {
+ for (int x = 0; x < kVideoWidth; x += 8) {
+ const int offset = (y0 + y) * 256 + x;
+ switch (bs.getBits(2)) {
+ case 1:
+ src = decodeSeqOp1(_buf + offset, 256, src);
+ break;
+ case 2:
+ src = decodeSeqOp2(_buf + offset, 256, src);
+ break;
+ case 3:
+ src = decodeSeqOp3(_buf + offset, 256, src);
+ break;
+ }
+ }
+ }
+ if (clearScreen) {
+ clearScreen = false;
+ _stub->copyRect(0, 0, kVideoWidth, 224, _buf, 256);
+ } else {
+ _stub->copyRect(0, y0, kVideoWidth, kVideoHeight, _buf, 256);
+ }
+ _stub->updateScreen(0);
+ }
+ const int diff = nextFrameTimeStamp - _stub->getTimeStamp();
+ if (diff > 0) {
+ _stub->sleep(diff);
+ }
+ }
+ for (int i = 0; i < 256; ++i) {
+ _stub->setPaletteEntry(i, &pal[i]);
+ }
+ _mix->setPremixHook(0, 0);
+ _demux.close();
+ // flush sound queue
+ LockAudioStack las(_stub);
+ while (_soundQueue) {
+ SoundBufferQueue *next = _soundQueue->next;
+ free(_soundQueue->data);
+ free(_soundQueue);
+ _soundQueue = next;
+ }
+ _soundQueuePreloadSize = 0;
+ }
+}
+
+bool SeqPlayer::mix(int8_t *buf, int samples) {
+ if (_soundQueuePreloadSize < kSoundPreloadSize) {
+ return true;
+ }
+ while (_soundQueue && samples > 0) {
+ *buf++ = _soundQueue->data[_soundQueue->read];
+ ++_soundQueue->read;
+ if (_soundQueue->read == _soundQueue->size) {
+ SoundBufferQueue *next = _soundQueue->next;
+ free(_soundQueue->data);
+ free(_soundQueue);
+ _soundQueue = next;
+ }
+ --samples;
+ }
+ return true;
+}
+
+bool SeqPlayer::mixCallback(void *param, int8_t *buf, int len) {
+ return ((SeqPlayer *)param)->mix(buf, len);
+}
+
diff --git a/seq_player.h b/seq_player.h
new file mode 100644
index 0000000..2bd42bc
--- /dev/null
+++ b/seq_player.h
@@ -0,0 +1,92 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 SEQ_PLAYER_H__
+#define SEQ_PLAYER_H__
+
+#include "intern.h"
+
+struct File;
+struct SystemStub;
+struct Mixer;
+
+struct SeqDemuxer {
+ enum {
+ kFrameSize = 6144,
+ kAudioBufferSize = 882,
+ kBuffersCount = 30
+ };
+
+ bool open(File *f);
+ void close();
+
+ bool readHeader();
+ bool readFrameData();
+ void fillBuffer(int num, int offset, int size);
+ void clearBuffer(int num);
+ void readPalette(uint8_t *dst);
+ void readAudioS8(uint8_t *dst);
+
+ int _frameOffset;
+ int _audioDataOffset;
+ int _audioDataSize;
+ int _paletteDataOffset;
+ int _paletteDataSize;
+ int _videoData;
+ struct {
+ int size;
+ int avail;
+ uint8_t *data;
+ } _buffers[kBuffersCount];
+ int _fileSize;
+ File *_f;
+};
+
+struct SeqPlayer {
+ enum {
+ kVideoWidth = 256,
+ kVideoHeight = 128,
+ kSoundPreloadSize = 4
+ };
+
+ static const char *_namesTable[];
+
+ struct SoundBufferQueue {
+ uint8_t *data;
+ int size;
+ int read;
+ SoundBufferQueue *next;
+ };
+
+ SeqPlayer(SystemStub *stub, Mixer *mixer);
+ ~SeqPlayer();
+
+ void setBackBuffer(uint8_t *buf) { _buf = buf; }
+ void play(File *f);
+ bool mix(int8_t *buf, int len);
+ static bool mixCallback(void *param, int8_t *buf, int len);
+
+ SystemStub *_stub;
+ uint8_t *_buf;
+ Mixer *_mix;
+ SeqDemuxer _demux;
+ int _soundQueuePreloadSize;
+ SoundBufferQueue *_soundQueue;
+};
+
+#endif // SEQ_PLAYER_H__
+
diff --git a/sfx_player.cpp b/sfx_player.cpp
new file mode 100644
index 0000000..bee8a2b
--- /dev/null
+++ b/sfx_player.cpp
@@ -0,0 +1,174 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "mixer.h"
+#include "sfx_player.h"
+
+
+SfxPlayer::SfxPlayer(Mixer *mixer)
+ : _mod(0), _playing(false), _mix(mixer) {
+}
+
+void SfxPlayer::play(uint8_t num) {
+ debug(DBG_SFX, "SfxPlayer::play(%d)", num);
+ if (!_playing) {
+ if (num >= 68 && num <= 75) {
+ static const Module *modTable[] = {
+ &_module68, &_module68, &_module70, &_module70,
+ &_module72, &_module73, &_module74, &_module75
+ };
+ _mod = modTable[num - 68];
+ _curOrder = 0;
+ _numOrders = READ_BE_UINT16(_mod->moduleData);
+ _orderDelay = 0;
+ _modData = _mod->moduleData + 0x22;
+ memset(_samples, 0, sizeof(_samples));
+ _samplesLeft = 0;
+ _mix->setPremixHook(mixCallback, this);
+ _playing = true;
+ }
+ }
+}
+
+void SfxPlayer::stop() {
+ if (_playing) {
+ _mix->setPremixHook(0, 0);
+ _playing = false;
+ }
+}
+
+void SfxPlayer::playSample(int channel, const uint8_t *sampleData, uint16_t period) {
+ assert(channel < NUM_CHANNELS);
+ SampleInfo *si = &_samples[channel];
+ si->len = READ_BE_UINT16(sampleData); sampleData += 2;
+ si->vol = READ_BE_UINT16(sampleData); sampleData += 2;
+ si->loopPos = READ_BE_UINT16(sampleData); sampleData += 2;
+ si->loopLen = READ_BE_UINT16(sampleData); sampleData += 2;
+ si->freq = PAULA_FREQ / period;
+ si->pos = 0;
+ si->data = sampleData;
+}
+
+void SfxPlayer::handleTick() {
+ if (!_playing) {
+ return;
+ }
+ if (_orderDelay != 0) {
+ --_orderDelay;
+ // check for end of song
+ if (_orderDelay == 0 && _modData == 0) {
+ _playing = false;
+ }
+ } else {
+ _orderDelay = READ_BE_UINT16(_mod->moduleData + 2);
+ debug(DBG_SFX, "curOrder=%d/%d _orderDelay=%d\n", _curOrder, _numOrders, _orderDelay);
+ int16_t period = 0;
+ for (int ch = 0; ch < 3; ++ch) {
+ const uint8_t *sampleData = 0;
+ uint8_t b = *_modData++;
+ if (b != 0) {
+ --b;
+ assert(b < 5);
+ period = READ_BE_UINT16(_mod->moduleData + 4 + b * 2);
+ sampleData = _mod->sampleData[b];
+ }
+ b = *_modData++;
+ if (b != 0) {
+ int16_t per = period + (b - 1);
+ if (per >= 0 && per < 40) {
+ per = _periodTable[per];
+ } else if (per == -3) {
+ per = 0xA0;
+ } else {
+ per = 0x71;
+ }
+ playSample(ch, sampleData, per);
+ }
+ }
+ ++_curOrder;
+ if (_curOrder >= _numOrders) {
+ debug(DBG_SFX, "End of song");
+ _orderDelay += 20;
+ _modData = 0;
+ }
+ }
+}
+
+void SfxPlayer::mixSamples(int8_t *buf, int samplesLen) {
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ SampleInfo *si = &_samples[i];
+ if (si->data) {
+ int8_t *mixbuf = buf;
+ int len = si->len << FRAC_BITS;
+ int loopLen = si->loopLen << FRAC_BITS;
+ int loopPos = si->loopPos << FRAC_BITS;
+ int deltaPos = (si->freq << FRAC_BITS) / _mix->getSampleRate();
+ int curLen = samplesLen;
+ int pos = si->pos;
+ while (curLen != 0) {
+ int count;
+ if (loopLen > (2 << FRAC_BITS)) {
+ assert(si->loopPos + si->loopLen <= si->len);
+ if (pos >= loopPos + loopLen) {
+ pos -= loopLen;
+ }
+ count = MIN(curLen, (loopPos + loopLen - pos - 1) / deltaPos + 1);
+ curLen -= count;
+ } else {
+ if (pos >= len) {
+ count = 0;
+ } else {
+ count = MIN(curLen, (len - pos - 1) / deltaPos + 1);
+ }
+ curLen = 0;
+ }
+ while (count--) {
+ int out = resampleLinear(si, pos, deltaPos, FRAC_BITS);
+ Mixer::addclamp(*mixbuf++, out * si->vol / 64);
+ pos += deltaPos;
+ }
+ }
+ si->pos = pos;
+ }
+ }
+}
+
+bool SfxPlayer::mix(int8_t *buf, int len) {
+ if (_playing) {
+ memset(buf, 0, len);
+ const int samplesPerTick = _mix->getSampleRate() / 50;
+ while (len != 0) {
+ if (_samplesLeft == 0) {
+ handleTick();
+ _samplesLeft = samplesPerTick;
+ }
+ int count = _samplesLeft;
+ if (count > len) {
+ count = len;
+ }
+ _samplesLeft -= count;
+ len -= count;
+ mixSamples(buf, count);
+ buf += count;
+ }
+ }
+ return _playing;
+}
+
+bool SfxPlayer::mixCallback(void *param, int8_t *buf, int len) {
+ return ((SfxPlayer *)param)->mix(buf, len);
+}
diff --git a/sfx_player.h b/sfx_player.h
new file mode 100644
index 0000000..588368f
--- /dev/null
+++ b/sfx_player.h
@@ -0,0 +1,101 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 SFX_PLAYER_H__
+#define SFX_PLAYER_H__
+
+#include "intern.h"
+
+struct Mixer;
+
+struct SfxPlayer {
+ enum {
+ NUM_SAMPLES = 5,
+ NUM_CHANNELS = 3,
+ FRAC_BITS = 12,
+ PAULA_FREQ = 3546897
+ };
+
+ struct Module {
+ const uint8_t *sampleData[NUM_SAMPLES];
+ const uint8_t *moduleData;
+ };
+
+ struct SampleInfo {
+ uint16_t len;
+ uint16_t vol;
+ uint16_t loopPos;
+ uint16_t loopLen;
+ int freq;
+ int pos;
+ const uint8_t *data;
+
+ int8_t getPCM(int offset) const {
+ if (offset < 0) {
+ offset = 0;
+ } else if (offset >= (int)len) {
+ offset = len - 1;
+ }
+ return (int8_t)data[offset];
+ }
+ };
+
+ static const uint8_t _musicData68[];
+ static const uint8_t _musicData70[];
+ static const uint8_t _musicData72[];
+ static const uint8_t _musicData73[];
+ static const uint8_t _musicData74[];
+ static const uint8_t _musicData75[];
+ static const uint8_t _musicDataSample1[];
+ static const uint8_t _musicDataSample2[]; // tick
+ static const uint8_t _musicDataSample3[]; // bell
+ static const uint8_t _musicDataSample4[];
+ static const uint8_t _musicDataSample5[];
+ static const uint8_t _musicDataSample6[];
+ static const uint8_t _musicDataSample7[];
+ static const uint8_t _musicDataSample8[];
+ static const Module _module68;
+ static const Module _module70;
+ static const Module _module72;
+ static const Module _module73;
+ static const Module _module74;
+ static const Module _module75;
+ static const uint16_t _periodTable[];
+
+ const Module *_mod;
+ bool _playing;
+ int _samplesLeft;
+ uint16_t _curOrder;
+ uint16_t _numOrders;
+ uint16_t _orderDelay;
+ const uint8_t *_modData;
+ SampleInfo _samples[NUM_CHANNELS];
+ Mixer *_mix;
+
+ SfxPlayer(Mixer *mixer);
+
+ void play(uint8_t num);
+ void stop();
+ void playSample(int channel, const uint8_t *sampleData, uint16_t period);
+ void handleTick();
+ bool mix(int8_t *buf, int len);
+ void mixSamples(int8_t *buf, int samplesLen);
+
+ static bool mixCallback(void *param, int8_t *buf, int len);
+};
+
+#endif // SFX_PLAYER_H__
diff --git a/staticres.cpp b/staticres.cpp
new file mode 100644
index 0000000..adfc41d
--- /dev/null
+++ b/staticres.cpp
@@ -0,0 +1,3972 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "game.h"
+#include "resource.h"
+
+
+const Cutscene::OpcodeStub Cutscene::_opcodeTable[] = {
+ /* 0x00 */
+ &Cutscene::op_markCurPos,
+ &Cutscene::op_refreshScreen,
+ &Cutscene::op_waitForSync,
+ &Cutscene::op_drawShape,
+ /* 0x04 */
+ &Cutscene::op_setPalette,
+ &Cutscene::op_markCurPos,
+ &Cutscene::op_drawStringAtBottom,
+ &Cutscene::op_nop,
+ /* 0x08 */
+ &Cutscene::op_skip3,
+ &Cutscene::op_refreshAll,
+ &Cutscene::op_drawShapeScale,
+ &Cutscene::op_drawShapeScaleRotate,
+ /* 0x0C */
+ &Cutscene::op_drawCreditsText,
+ &Cutscene::op_drawStringAtPos,
+ &Cutscene::op_handleKeys
+};
+
+const char *Cutscene::_namesTable[] = {
+ "DEBUT",
+ "OBJET",
+ "CARTE",
+ "GEN",
+ "CHUTE",
+ "CODE",
+ "DESINTEG",
+ "INTRO1",
+ "STREM",
+ "HOLOSEQ",
+ "CARTEID",
+ "PONT",
+ "ASC",
+ "MAP",
+ "METRO",
+ "MISSIONS",
+ "GENMIS",
+ "MEMO",
+ "TAXI",
+ "ACCROCHE",
+ "VOYAGE",
+ "TELEPORT",
+ "LIFT",
+ "ESPIONS",
+ "LOG",
+ "FIN",
+ "GENEXP",
+ "LOGOS",
+ "OVER",
+ "SCORE",
+ "INTRO2"
+};
+
+const uint16_t Cutscene::_offsetsTable[] = {
+ 0x0000, 0x0000, 0x0001, 0x0003, 0x0001, 0x0004, 0xFFFF, 0x0000, 0x0001, 0x0002,
+ 0x0003, 0x0000, 0x0004, 0x0000, 0xFFFF, 0x0100, 0xFFFF, 0x0000, 0x0006, 0x0000,
+ 0x0001, 0x0001, 0xFFFF, 0x0000, 0xFFFF, 0x0200, 0x8007, 0x0000, 0x0003, 0x0001,
+ 0x0001, 0x000B, 0x0001, 0x0005, 0x0009, 0x0000, 0x0001, 0x0006, 0xFFFF, 0x0000,
+ 0x000B, 0x0000, 0x0001, 0x000A, 0xFFFF, 0x0001, 0xFFFF, 0x0002, 0xFFFF, 0x0000,
+ 0x000D, 0x0004, 0x000D, 0x0000, 0x000D, 0x0001, 0x000D, 0x0002, 0x000D, 0x0003,
+ 0xFFFF, 0x0000, 0xFFFF, 0x0001, 0x0001, 0x000C, 0x0001, 0x000D, 0x0001, 0x000E,
+ 0x0001, 0x000F, 0x0001, 0x0010, 0x000F, 0x0000, 0x000F, 0x0001, 0x000F, 0x0001,
+ 0x000F, 0x0003, 0x000F, 0x0002, 0x000F, 0x0004, 0x0001, 0x0008, 0x0001, 0x0007,
+ 0x000F, 0x0005, 0xFFFF, 0x0000, 0x0004, 0x0001, 0x0011, 0x0000, 0x0001, 0x0009,
+ 0x0012, 0x0000, 0xFFFF, 0x0000, 0x0014, 0x0000, 0x0015, 0x0000, 0x0016, 0x0000,
+ 0x0016, 0x0001, 0xFFFF, 0x0012, 0x0017, 0x0000, 0x0001, 0x0011, 0x0018, 0x0000,
+ 0x0001, 0x0013, 0x0019, 0x0000, 0x001A, 0x0000, 0x0019, 0x0001, 0x001B, 0x0000,
+ 0x001C, 0x0000, 0x000F, 0x0006, 0x000F, 0x0006, 0x000F, 0x0007, 0x000F, 0x0008,
+ 0x000F, 0x0009, 0x000F, 0x000A, 0x001D, 0x0000, 0x001B, 0x0001, 0x001E, 0x0000,
+ 0xFFFF, 0x0000
+};
+
+const uint16_t Cutscene::_cosTable[] = {
+ 0x0100, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FE, 0x00FE,
+ 0x00FD, 0x00FC, 0x00FC, 0x00FB, 0x00FA, 0x00F9, 0x00F8, 0x00F7,
+ 0x00F6, 0x00F4, 0x00F3, 0x00F2, 0x00F0, 0x00EE, 0x00ED, 0x00EB,
+ 0x00E9, 0x00E8, 0x00E6, 0x00E4, 0x00E2, 0x00DF, 0x00DD, 0x00DB,
+ 0x00D9, 0x00D6, 0x00D4, 0x00D1, 0x00CF, 0x00CC, 0x00C9, 0x00C6,
+ 0x00C4, 0x00C1, 0x00BE, 0x00BB, 0x00B8, 0x00B5, 0x00B1, 0x00AE,
+ 0x00AB, 0x00A7, 0x00A4, 0x00A1, 0x009D, 0x009A, 0x0096, 0x0092,
+ 0x008F, 0x008B, 0x0087, 0x0083, 0x007F, 0x007C, 0x0078, 0x0074,
+ 0x0070, 0x006C, 0x0068, 0x0064, 0x005F, 0x005B, 0x0057, 0x0053,
+ 0x004F, 0x004A, 0x0046, 0x0042, 0x003D, 0x0039, 0x0035, 0x0030,
+ 0x002C, 0x0028, 0x0023, 0x001F, 0x001A, 0x0016, 0x0011, 0x000D,
+ 0x0008, 0x0004, 0x0000, 0xFFFC, 0xFFF8, 0xFFF3, 0xFFEF, 0xFFEA,
+ 0xFFE6, 0xFFE1, 0xFFDD, 0xFFD8, 0xFFD4, 0xFFD0, 0xFFCB, 0xFFC7,
+ 0xFFC3, 0xFFBE, 0xFFBA, 0xFFB6, 0xFFB1, 0xFFAD, 0xFFA9, 0xFFA5,
+ 0xFFA1, 0xFF9C, 0xFF98, 0xFF94, 0xFF90, 0xFF8C, 0xFF88, 0xFF84,
+ 0xFF80, 0xFF7D, 0xFF79, 0xFF75, 0xFF71, 0xFF6E, 0xFF6A, 0xFF66,
+ 0xFF63, 0xFF5F, 0xFF5C, 0xFF59, 0xFF55, 0xFF52, 0xFF4F, 0xFF4B,
+ 0xFF48, 0xFF45, 0xFF42, 0xFF3F, 0xFF3C, 0xFF3A, 0xFF37, 0xFF34,
+ 0xFF31, 0xFF2F, 0xFF2C, 0xFF2A, 0xFF27, 0xFF25, 0xFF23, 0xFF21,
+ 0xFF1E, 0xFF1C, 0xFF1A, 0xFF18, 0xFF17, 0xFF15, 0xFF13, 0xFF12,
+ 0xFF10, 0xFF0E, 0xFF0D, 0xFF0C, 0xFF0A, 0xFF09, 0xFF08, 0xFF07,
+ 0xFF06, 0xFF05, 0xFF04, 0xFF04, 0xFF03, 0xFF02, 0xFF02, 0xFF01,
+ 0xFF01, 0xFF01, 0xFF01, 0xFF01, 0xFF00, 0xFF01, 0xFF01, 0xFF01,
+ 0xFF01, 0xFF01, 0xFF02, 0xFF02, 0xFF03, 0xFF04, 0xFF04, 0xFF05,
+ 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFF0C, 0xFF0D, 0xFF0E,
+ 0xFF10, 0xFF12, 0xFF13, 0xFF15, 0xFF17, 0xFF18, 0xFF1A, 0xFF1C,
+ 0xFF1E, 0xFF21, 0xFF23, 0xFF25, 0xFF27, 0xFF2A, 0xFF2C, 0xFF2F,
+ 0xFF31, 0xFF34, 0xFF37, 0xFF3A, 0xFF3C, 0xFF3F, 0xFF42, 0xFF45,
+ 0xFF48, 0xFF4B, 0xFF4F, 0xFF52, 0xFF55, 0xFF59, 0xFF5C, 0xFF5F,
+ 0xFF63, 0xFF66, 0xFF6A, 0xFF6E, 0xFF71, 0xFF75, 0xFF79, 0xFF7D,
+ 0xFF81, 0xFF84, 0xFF88, 0xFF8C, 0xFF90, 0xFF94, 0xFF98, 0xFF9C,
+ 0xFFA1, 0xFFA5, 0xFFA9, 0xFFAD, 0xFFB1, 0xFFB6, 0xFFBA, 0xFFBE,
+ 0xFFC3, 0xFFC7, 0xFFCB, 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDD, 0xFFE1,
+ 0xFFE6, 0xFFEA, 0xFFEF, 0xFFF3, 0xFFF8, 0xFFFC, 0x0000, 0x0004,
+ 0x0008, 0x000D, 0x0011, 0x0016, 0x001A, 0x001F, 0x0023, 0x0028,
+ 0x002C, 0x0030, 0x0035, 0x0039, 0x003D, 0x0042, 0x0046, 0x004A,
+ 0x004F, 0x0053, 0x0057, 0x005B, 0x005F, 0x0064, 0x0068, 0x006C,
+ 0x0070, 0x0074, 0x0078, 0x007C, 0x0080, 0x0083, 0x0087, 0x008B,
+ 0x008F, 0x0092, 0x0096, 0x009A, 0x009D, 0x00A1, 0x00A4, 0x00A7,
+ 0x00AB, 0x00AE, 0x00B1, 0x00B5, 0x00B8, 0x00BB, 0x00BE, 0x00C1,
+ 0x00C4, 0x00C6, 0x00C9, 0x00CC, 0x00CF, 0x00D1, 0x00D4, 0x00D6,
+ 0x00D9, 0x00DB, 0x00DD, 0x00DF, 0x00E2, 0x00E4, 0x00E6, 0x00E8,
+ 0x00E9, 0x00EB, 0x00ED, 0x00EE, 0x00F0, 0x00F2, 0x00F3, 0x00F4,
+ 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FC,
+ 0x00FD, 0x00FE, 0x00FE, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
+};
+
+const uint16_t Cutscene::_sinTable[] = {
+ 0x0000, 0x0004, 0x0008, 0x000D, 0x0011, 0x0016, 0x001A, 0x001F,
+ 0x0023, 0x0028, 0x002C, 0x0030, 0x0035, 0x0039, 0x003D, 0x0042,
+ 0x0046, 0x004A, 0x004F, 0x0053, 0x0057, 0x005B, 0x005F, 0x0064,
+ 0x0068, 0x006C, 0x0070, 0x0074, 0x0078, 0x007C, 0x007F, 0x0083,
+ 0x0087, 0x008B, 0x008F, 0x0092, 0x0096, 0x009A, 0x009D, 0x00A1,
+ 0x00A4, 0x00A7, 0x00AB, 0x00AE, 0x00B1, 0x00B5, 0x00B8, 0x00BB,
+ 0x00BE, 0x00C1, 0x00C4, 0x00C6, 0x00C9, 0x00CC, 0x00CF, 0x00D1,
+ 0x00D4, 0x00D6, 0x00D9, 0x00DB, 0x00DD, 0x00DF, 0x00E2, 0x00E4,
+ 0x00E6, 0x00E8, 0x00E9, 0x00EB, 0x00ED, 0x00EE, 0x00F0, 0x00F2,
+ 0x00F3, 0x00F4, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB,
+ 0x00FC, 0x00FC, 0x00FD, 0x00FE, 0x00FE, 0x00FF, 0x00FF, 0x00FF,
+ 0x00FF, 0x00FF, 0x0100, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
+ 0x00FE, 0x00FE, 0x00FD, 0x00FC, 0x00FC, 0x00FB, 0x00FA, 0x00F9,
+ 0x00F8, 0x00F7, 0x00F6, 0x00F4, 0x00F3, 0x00F2, 0x00F0, 0x00EE,
+ 0x00ED, 0x00EB, 0x00E9, 0x00E8, 0x00E6, 0x00E4, 0x00E2, 0x00DF,
+ 0x00DD, 0x00DB, 0x00D9, 0x00D6, 0x00D4, 0x00D1, 0x00CF, 0x00CC,
+ 0x00C9, 0x00C6, 0x00C4, 0x00C1, 0x00BE, 0x00BB, 0x00B8, 0x00B5,
+ 0x00B1, 0x00AE, 0x00AB, 0x00A7, 0x00A4, 0x00A1, 0x009D, 0x009A,
+ 0x0096, 0x0092, 0x008F, 0x008B, 0x0087, 0x0083, 0x007F, 0x007C,
+ 0x0078, 0x0074, 0x0070, 0x006C, 0x0068, 0x0064, 0x005F, 0x005B,
+ 0x0057, 0x0053, 0x004F, 0x004A, 0x0046, 0x0042, 0x003D, 0x0039,
+ 0x0035, 0x0030, 0x002C, 0x0028, 0x0023, 0x001F, 0x001A, 0x0016,
+ 0x0011, 0x000D, 0x0008, 0x0004, 0x0000, 0xFFFC, 0xFFF8, 0xFFF3,
+ 0xFFEF, 0xFFEA, 0xFFE6, 0xFFE1, 0xFFDD, 0xFFD8, 0xFFD4, 0xFFD0,
+ 0xFFCB, 0xFFC7, 0xFFC3, 0xFFBE, 0xFFBA, 0xFFB6, 0xFFB1, 0xFFAD,
+ 0xFFA9, 0xFFA5, 0xFFA1, 0xFF9C, 0xFF98, 0xFF94, 0xFF90, 0xFF8C,
+ 0xFF88, 0xFF84, 0xFF80, 0xFF7D, 0xFF79, 0xFF75, 0xFF71, 0xFF6E,
+ 0xFF6A, 0xFF66, 0xFF63, 0xFF5F, 0xFF5C, 0xFF59, 0xFF55, 0xFF52,
+ 0xFF4F, 0xFF4B, 0xFF48, 0xFF45, 0xFF42, 0xFF3F, 0xFF3C, 0xFF3A,
+ 0xFF37, 0xFF34, 0xFF31, 0xFF2F, 0xFF2C, 0xFF2A, 0xFF27, 0xFF25,
+ 0xFF23, 0xFF21, 0xFF1E, 0xFF1C, 0xFF1A, 0xFF18, 0xFF17, 0xFF15,
+ 0xFF13, 0xFF12, 0xFF10, 0xFF0E, 0xFF0D, 0xFF0C, 0xFF0A, 0xFF09,
+ 0xFF08, 0xFF07, 0xFF06, 0xFF05, 0xFF04, 0xFF04, 0xFF03, 0xFF02,
+ 0xFF02, 0xFF01, 0xFF01, 0xFF01, 0xFF01, 0xFF01, 0xFF00, 0xFF01,
+ 0xFF01, 0xFF01, 0xFF01, 0xFF01, 0xFF02, 0xFF02, 0xFF03, 0xFF04,
+ 0xFF04, 0xFF05, 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFF0C,
+ 0xFF0D, 0xFF0E, 0xFF10, 0xFF12, 0xFF13, 0xFF15, 0xFF17, 0xFF18,
+ 0xFF1A, 0xFF1C, 0xFF1E, 0xFF21, 0xFF23, 0xFF25, 0xFF27, 0xFF2A,
+ 0xFF2C, 0xFF2F, 0xFF31, 0xFF34, 0xFF37, 0xFF3A, 0xFF3C, 0xFF3F,
+ 0xFF42, 0xFF45, 0xFF48, 0xFF4B, 0xFF4F, 0xFF52, 0xFF55, 0xFF59,
+ 0xFF5C, 0xFF5F, 0xFF63, 0xFF66, 0xFF6A, 0xFF6E, 0xFF71, 0xFF75,
+ 0xFF79, 0xFF7D, 0xFF81, 0xFF84, 0xFF88, 0xFF8C, 0xFF90, 0xFF94,
+ 0xFF98, 0xFF9C, 0xFFA1, 0xFFA5, 0xFFA9, 0xFFAD, 0xFFB1, 0xFFB6,
+ 0xFFBA, 0xFFBE, 0xFFC3, 0xFFC7, 0xFFCB, 0xFFD0, 0xFFD4, 0xFFD8,
+ 0xFFDD, 0xFFE1, 0xFFE6, 0xFFEA, 0xFFEF, 0xFFF3, 0xFFF8, 0xFFFC
+};
+
+const uint8_t Cutscene::_creditsData[] = {
+ 0xFE, 0x14, 0x00, 0x01, 0x00, 0x04, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x46, 0x6C, 0x61, 0x73,
+ 0x68, 0x42, 0x61, 0x63, 0x6B, 0x20, 0x54, 0x65, 0x61, 0x6D, 0x20, 0x69, 0x73, 0x2E, 0x2E, 0x2E,
+ 0xFE, 0x32, 0xFE, 0x14, 0x00, 0x01, 0x00, 0x07, 0x00, 0x01, 0x00, 0x05, 0x20, 0x20, 0x49, 0x6E,
+ 0x69, 0x74, 0x69, 0x61, 0x6C, 0x20, 0x50, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x50, 0x72,
+ 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x65, 0x72, 0x73, 0x3A, 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x65, 0x6E, 0x6F, 0x69,
+ 0x73, 0x74, 0x20, 0x41, 0x72, 0x6F, 0x6E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x68, 0x69, 0x6C,
+ 0x69, 0x70, 0x70, 0x65, 0x20, 0x43, 0x68, 0x61, 0x73, 0x74, 0x65, 0x6C, 0x20, 0x20, 0x20, 0x7C,
+ 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x50, 0x61, 0x75, 0x6C, 0x20, 0x43, 0x75, 0x69, 0x73, 0x73, 0x65, 0x74, 0x20, 0x20,
+ 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x46, 0x72, 0x65, 0x64, 0x65, 0x72, 0x69, 0x63, 0x20, 0x53, 0x61, 0x76, 0x6F, 0x69, 0x72, 0x20,
+ 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x05, 0x20, 0x20, 0x47, 0x72,
+ 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x72, 0x74, 0x69, 0x73, 0x74, 0x73, 0x3A, 0x7C, 0x7C,
+ 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50,
+ 0x61, 0x74, 0x72, 0x69, 0x63, 0x6B, 0x20, 0x44, 0x61, 0x68, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x54, 0x68, 0x69, 0x65, 0x72, 0x72, 0x79, 0x20, 0x4C, 0x65, 0x76, 0x61, 0x73, 0x74, 0x72,
+ 0x65, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x65, 0x6E, 0x69, 0x73, 0x20, 0x4D, 0x65, 0x72, 0x63, 0x69,
+ 0x65, 0x72, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x65, 0x72, 0x72, 0x79, 0x20, 0x50, 0x65, 0x72,
+ 0x72, 0x65, 0x61, 0x75, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x69, 0x61, 0x6E, 0x20, 0x52,
+ 0x6F, 0x62, 0x65, 0x72, 0x74, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x61, 0x62, 0x72, 0x69, 0x63, 0x65,
+ 0x20, 0x56, 0x69, 0x73, 0x73, 0x65, 0x72, 0x6F, 0x74, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E,
+ 0x00, 0x01, 0x00, 0x07, 0x20, 0x20, 0x50, 0x43, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E,
+ 0x20, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x65, 0x72, 0x73, 0x3A, 0x7C, 0x7C, 0xFE,
+ 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x68, 0x69,
+ 0x6C, 0x69, 0x70, 0x70, 0x65, 0x20, 0x43, 0x68, 0x61, 0x73, 0x74, 0x65, 0x6C, 0x20, 0x20, 0x20,
+ 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x50, 0x61, 0x75, 0x6C, 0x20, 0x43, 0x75, 0x69, 0x73, 0x73, 0x65, 0x74, 0x20,
+ 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x54, 0x68, 0x69, 0x65, 0x72, 0x72, 0x79, 0x20, 0x47, 0x61, 0x65, 0x72, 0x74, 0x68,
+ 0x6E, 0x65, 0x72, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6C, 0x61, 0x69, 0x6E, 0x20, 0x52, 0x61, 0x6D, 0x6F,
+ 0x6E, 0x64, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0xB4, 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x05, 0x20,
+ 0x20, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x50, 0x43, 0x20, 0x67,
+ 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x3A, 0x7C, 0x7C, 0xFE, 0x1E, 0x7C, 0x7C, 0xFE, 0x1E,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69,
+ 0x65, 0x72, 0x72, 0x79, 0x20, 0x4C, 0x65, 0x76, 0x61, 0x73, 0x74, 0x72, 0x65, 0x20, 0x20, 0x7C,
+ 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x44, 0x65, 0x6E, 0x69, 0x73, 0x20, 0x4D, 0x65, 0x72, 0x63, 0x69, 0x65, 0x72, 0x20, 0x20,
+ 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x54, 0x68, 0x69, 0x65, 0x72, 0x72, 0x79, 0x20, 0x50, 0x65, 0x72, 0x72, 0x65, 0x61, 0x75,
+ 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x05, 0x20, 0x20, 0x53, 0x74,
+ 0x6F, 0x72, 0x79, 0x3A, 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x75, 0x6C, 0x20, 0x43, 0x75, 0x69,
+ 0x73, 0x73, 0x65, 0x74, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x05,
+ 0x20, 0x20, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x20, 0x44, 0x65, 0x73, 0x69, 0x67, 0x6E, 0x3A, 0x7C,
+ 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x50, 0x61, 0x75, 0x6C, 0x20, 0x43, 0x75, 0x69, 0x73, 0x73, 0x65, 0x74, 0x20,
+ 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x50, 0x61, 0x74, 0x72, 0x69, 0x63, 0x6B, 0x20, 0x44, 0x61, 0x68, 0x65, 0x72, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x65, 0x6E, 0x69, 0x73, 0x20, 0x4D, 0x65, 0x72, 0x63,
+ 0x69, 0x65, 0x72, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x72, 0x65, 0x64, 0x65, 0x72, 0x69, 0x63, 0x20, 0x53, 0x61,
+ 0x76, 0x6F, 0x69, 0x72, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x61, 0x62, 0x72, 0x69, 0x63, 0x65, 0x20,
+ 0x56, 0x69, 0x73, 0x73, 0x65, 0x72, 0x6F, 0x74, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00,
+ 0x01, 0x00, 0x05, 0x20, 0x20, 0x4D, 0x75, 0x73, 0x69, 0x63, 0x3A, 0x7C, 0x7C, 0xFE, 0x1E, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4A,
+ 0x65, 0x61, 0x6E, 0x20, 0x42, 0x61, 0x75, 0x64, 0x6C, 0x6F, 0x74, 0x20, 0x20, 0x20, 0x7C, 0xFE,
+ 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x61,
+ 0x62, 0x72, 0x69, 0x63, 0x65, 0x20, 0x56, 0x69, 0x73, 0x73, 0x65, 0x72, 0x6F, 0x74, 0x20, 0x20,
+ 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x08, 0x20, 0x20, 0x53, 0x6F, 0x75, 0x6E, 0x64,
+ 0x20, 0x66, 0x78, 0x3A, 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x65, 0x6E, 0x6F, 0x69, 0x73, 0x74, 0x20, 0x41, 0x72, 0x6F,
+ 0x6E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x68, 0x69, 0x6C, 0x69, 0x70, 0x70, 0x65, 0x20, 0x43,
+ 0x68, 0x61, 0x73, 0x74, 0x65, 0x6C, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x75, 0x6C,
+ 0x20, 0x43, 0x75, 0x69, 0x73, 0x73, 0x65, 0x74, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x61, 0x62, 0x72, 0x69,
+ 0x63, 0x65, 0x20, 0x56, 0x69, 0x73, 0x73, 0x65, 0x72, 0x6F, 0x74, 0x20, 0x20, 0x7C, 0xFE, 0x50,
+ 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x06, 0x20, 0x20, 0x41, 0x63, 0x74, 0x6F, 0x72, 0x73, 0x3A, 0x7C,
+ 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x42, 0x65, 0x6E, 0x6F, 0x69, 0x73, 0x74, 0x20, 0x41, 0x72, 0x6F, 0x6E, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x50, 0x61, 0x74, 0x72, 0x69, 0x63, 0x6B, 0x20, 0x44, 0x61, 0x68, 0x65, 0x72, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x65, 0x72, 0x72, 0x79, 0x20, 0x4C, 0x65, 0x76, 0x61,
+ 0x73, 0x74, 0x72, 0x65, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x65, 0x6E, 0x69, 0x73, 0x20, 0x4D, 0x65,
+ 0x72, 0x63, 0x69, 0x65, 0x72, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x65, 0x72, 0x72, 0x79, 0x20,
+ 0x50, 0x65, 0x72, 0x72, 0x65, 0x61, 0x75, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x69, 0x61,
+ 0x6E, 0x20, 0x52, 0x6F, 0x62, 0x65, 0x72, 0x74, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x61, 0x62, 0x72,
+ 0x69, 0x63, 0x65, 0x20, 0x56, 0x69, 0x73, 0x73, 0x65, 0x72, 0x6F, 0x74, 0x20, 0x20, 0x7C, 0xFE,
+ 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x06, 0x20, 0x20, 0x53, 0x74, 0x75, 0x6E, 0x74, 0x6D, 0x61,
+ 0x6E, 0x3A, 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x65, 0x6E, 0x69, 0x73, 0x20, 0x4D, 0x65, 0x72, 0x63, 0x69,
+ 0x65, 0x72, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x06, 0x20, 0x20,
+ 0x56, 0x69, 0x64, 0x65, 0x6F, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x73, 0x3A,
+ 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x50, 0x61, 0x74, 0x72, 0x69, 0x63, 0x6B, 0x20, 0x44, 0x61, 0x68, 0x65, 0x72, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x65, 0x72, 0x72, 0x79, 0x20, 0x50, 0x65, 0x72, 0x72, 0x65,
+ 0x61, 0x75, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x61, 0x62, 0x72, 0x69, 0x63, 0x65, 0x20, 0x56, 0x69, 0x73,
+ 0x73, 0x65, 0x72, 0x6F, 0x74, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x06,
+ 0x20, 0x20, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x20, 0x43, 0x6F, 0x2D, 0x64, 0x69, 0x72, 0x65, 0x63,
+ 0x74, 0x6F, 0x72, 0x73, 0x3A, 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x65, 0x72, 0x72, 0x79, 0x20, 0x4C, 0x65,
+ 0x76, 0x61, 0x73, 0x74, 0x72, 0x65, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x65, 0x6E, 0x69, 0x73, 0x20,
+ 0x4D, 0x65, 0x72, 0x63, 0x69, 0x65, 0x72, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x69, 0x61,
+ 0x6E, 0x20, 0x52, 0x6F, 0x62, 0x65, 0x72, 0x74, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE,
+ 0x1E, 0x00, 0x01, 0x00, 0x06, 0x20, 0x20, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x20, 0x73, 0x66, 0x78,
+ 0x3A, 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x75, 0x6C, 0x20, 0x43, 0x75, 0x69, 0x73, 0x73, 0x65,
+ 0x74, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x65, 0x72, 0x72, 0x79, 0x20, 0x50, 0x65, 0x72, 0x72,
+ 0x65, 0x61, 0x75, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x61, 0x62, 0x72, 0x69, 0x63, 0x65, 0x20, 0x56, 0x69,
+ 0x73, 0x73, 0x65, 0x72, 0x6F, 0x74, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00,
+ 0x07, 0x20, 0x20, 0x54, 0x65, 0x73, 0x74, 0x65, 0x72, 0x73, 0x3A, 0x7C, 0x7C, 0xFE, 0x1E, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50,
+ 0x68, 0x69, 0x6C, 0x20, 0x42, 0x72, 0x61, 0x64, 0x6C, 0x65, 0x79, 0x20, 0x20, 0x20, 0x7C, 0xFE,
+ 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x74,
+ 0x72, 0x69, 0x63, 0x69, 0x61, 0x20, 0x43, 0x75, 0x69, 0x73, 0x73, 0x65, 0x74, 0x20, 0x20, 0x20,
+ 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x53, 0x69, 0x6D, 0x6F, 0x6E, 0x20, 0x48, 0x61, 0x64, 0x6C, 0x69, 0x6E, 0x67, 0x74,
+ 0x6F, 0x6E, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x44, 0x61, 0x6E, 0x69, 0x65, 0x6C, 0x20, 0x4C, 0x6C, 0x65, 0x77, 0x65, 0x6C,
+ 0x6C, 0x79, 0x6E, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x4A, 0x65, 0x61, 0x6E, 0x2D, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65, 0x20, 0x4C, 0x75, 0x63, 0x6B,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4D, 0x61, 0x72, 0x74, 0x69, 0x6E, 0x20, 0x53, 0x6D,
+ 0x69, 0x74, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00,
+ 0x08, 0x20, 0x20, 0x4D, 0x61, 0x6E, 0x79, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x6B, 0x73, 0x20, 0x74,
+ 0x6F, 0x2E, 0x2E, 0x2E, 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4C, 0x6F, 0x72, 0x69, 0x20, 0x43, 0x68, 0x72, 0x69,
+ 0x73, 0x74, 0x65, 0x6E, 0x73, 0x65, 0x6E, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x74, 0x72, 0x69, 0x63, 0x69, 0x61, 0x20, 0x43, 0x75,
+ 0x69, 0x73, 0x73, 0x65, 0x74, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6E, 0x6E, 0x65, 0x2D, 0x4D, 0x61, 0x72, 0x69, 0x65, 0x20,
+ 0x4A, 0x6F, 0x61, 0x73, 0x73, 0x69, 0x6D, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4A, 0x65, 0x61, 0x6E, 0x2D, 0x50, 0x69, 0x65, 0x72, 0x72,
+ 0x65, 0x20, 0x4C, 0x75, 0x63, 0x6B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4D,
+ 0x61, 0x72, 0x63, 0x20, 0x4D, 0x69, 0x6E, 0x69, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C,
+ 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00, 0x05, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x20, 0x62, 0x79, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x50, 0x61, 0x75, 0x6C, 0x20, 0x43, 0x75, 0x69, 0x73, 0x73, 0x65, 0x74, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0x1E, 0x00, 0x01, 0x00,
+ 0x03, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x72, 0x6F, 0x64, 0x75,
+ 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7C, 0x7C, 0xFE, 0x1E, 0x20, 0x7C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x65, 0x6C,
+ 0x70, 0x68, 0x69, 0x6E, 0x65, 0x20, 0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x53, 0x20, 0x47, 0x4F, 0x4C, 0x44, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x1E, 0x20, 0x7C, 0x20, 0x7C,
+ 0x20, 0x7C, 0x20, 0x7C, 0x20, 0x7C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x28, 0x63, 0x29, 0x4D, 0x43, 0x4D, 0x58, 0x43, 0x49, 0x49, 0x49, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7C, 0xFE, 0x50, 0xFE, 0xFF, 0x00, 0xFF
+};
+
+const uint16_t Cutscene::_creditsCutSeq[] = {
+ 0x00, 0x05, 0x2F, 0x32, 0x36, 0x3E, 0x30, 0x39, 0x3F, 0x14, 0x34, 0xFFFF
+};
+
+const uint8_t Cutscene::_musicTable[] = {
+ 0x10, 0x15, 0x15, 0xFF, 0x15, 0x19, 0x0F, 0xFF, 0x15, 0x04, 0x15, 0xFF, 0xFF, 0x00, 0x19, 0x15,
+ 0x15, 0x0D, 0x15, 0x0D, 0x18, 0x13, 0xFF, 0xFF, 0xFF, 0x14, 0x14, 0x14, 0x14, 0x14, 0xFF, 0xFF,
+ 0x13, 0x13, 0x13, 0x13, 0x15, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x13, 0x11, 0xFF, 0x03,
+ 0x0E, 0x13, 0x12, 0xFF, 0x06, 0x07, 0x0A, 0x0A, 0x15, 0x05, 0x13, 0x02, 0x15, 0x09, 0x17, 0x08,
+ 0x0B, 0x0C, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xFF, 0xFF, 0xFF
+};
+
+const uint8_t Cutscene::_protectionShapeData[] = {
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x06, 0xD4, 0x00, 0x00, 0x00, 0x92,
+ 0x00, 0x00, 0x08, 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x54, 0x00, 0x8C, 0x00, 0xB2,
+ 0x00, 0xDE, 0x01, 0x21, 0x01, 0x54, 0x01, 0x7B, 0x01, 0x9D, 0x01, 0xC2, 0x01, 0xF0, 0x02, 0x2C,
+ 0x02, 0x66, 0x02, 0x9F, 0x02, 0xBF, 0x02, 0xF7, 0x03, 0x35, 0x03, 0x75, 0x03, 0xA4, 0x03, 0xFE,
+ 0x04, 0x3B, 0x04, 0x7B, 0x04, 0xB6, 0x04, 0xF8, 0x05, 0x3B, 0x05, 0x66, 0x05, 0x9E, 0x05, 0xD2,
+ 0x06, 0x10, 0x00, 0x00, 0x0F, 0xFF, 0x02, 0x22, 0x03, 0x33, 0x04, 0x44, 0x05, 0x55, 0x06, 0x66,
+ 0x07, 0x77, 0x08, 0x88, 0x09, 0x99, 0x0A, 0xAA, 0x0B, 0xBB, 0x0C, 0xCC, 0x0D, 0xDD, 0x0E, 0xEE,
+ 0x0F, 0xFF, 0x00, 0x00, 0x04, 0x05, 0x05, 0x05, 0x00, 0x00, 0x04, 0x44, 0x05, 0x55, 0x06, 0x66,
+ 0x07, 0x77, 0x08, 0x88, 0x09, 0x99, 0x0A, 0xAA, 0x0B, 0xBB, 0x0C, 0xCC, 0x0D, 0xDD, 0x0E, 0xEE,
+ 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00,
+ 0x03, 0x01, 0x00, 0x04, 0x02, 0x00, 0x05, 0x01, 0x00, 0x06, 0x02, 0x00, 0x07, 0x02, 0x00, 0x08,
+ 0x02, 0x00, 0x09, 0x01, 0x00, 0x0A, 0x02, 0x00, 0x0B, 0x02, 0x00, 0x0A, 0x00, 0x0C, 0x02, 0x00,
+ 0x0D, 0x01, 0x00, 0x0E, 0x02, 0x00, 0x0F, 0x01, 0x80, 0x0A, 0x00, 0x61, 0x00, 0x00, 0x02, 0x00,
+ 0x10, 0x01, 0x80, 0x02, 0xFF, 0xC9, 0xFF, 0xFF, 0x02, 0x80, 0x04, 0xFF, 0xB1, 0xFF, 0xFF, 0x02,
+ 0x00, 0x11, 0x01, 0x00, 0x12, 0x02, 0x00, 0x0E, 0x00, 0x00, 0x02, 0x80, 0x0D, 0x00, 0x00, 0x00,
+ 0x0E, 0x01, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x02, 0x00, 0x13, 0x01, 0x00, 0x14, 0x02, 0x00,
+ 0x15, 0x01, 0x00, 0x16, 0x02, 0x80, 0x0B, 0xFF, 0xEE, 0x00, 0x4C, 0x02, 0x00, 0x17, 0x01, 0x00,
+ 0x18, 0x01, 0x00, 0x19, 0x02, 0x00, 0x1A, 0x02, 0x00, 0x1B, 0x02, 0x00, 0x1C, 0x02, 0x00, 0x08,
+ 0x00, 0x00, 0x02, 0x00, 0x18, 0x01, 0x00, 0x19, 0x02, 0x80, 0x0D, 0x00, 0x00, 0x00, 0x46, 0x01,
+ 0x80, 0x0E, 0x00, 0x00, 0x00, 0x46, 0x02, 0x00, 0x1D, 0x01, 0x00, 0x1E, 0x02, 0x80, 0x0B, 0x00,
+ 0x08, 0x00, 0x4D, 0x02, 0x00, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x1F, 0x01, 0x00, 0x20, 0x02, 0x00,
+ 0x21, 0x02, 0x00, 0x22, 0x02, 0x00, 0x23, 0x01, 0x00, 0x24, 0x02, 0x00, 0x25, 0x01, 0x00, 0x26,
+ 0x01, 0x00, 0x27, 0x02, 0x00, 0x28, 0x01, 0x00, 0x29, 0x02, 0x00, 0x2A, 0x01, 0x00, 0x2B, 0x01,
+ 0x00, 0x0F, 0x00, 0x00, 0x02, 0x00, 0x2C, 0x01, 0x00, 0x2D, 0x01, 0x00, 0x2E, 0x02, 0x00, 0x2F,
+ 0x01, 0x00, 0x30, 0x02, 0x80, 0x18, 0x00, 0x00, 0x00, 0x7F, 0x01, 0x80, 0x19, 0x00, 0x00, 0x00,
+ 0x7F, 0x02, 0x80, 0x0A, 0x00, 0x03, 0xFF, 0xB2, 0x01, 0x80, 0x0A, 0x00, 0x03, 0xFF, 0xDB, 0x01,
+ 0x00, 0x31, 0x01, 0x00, 0x32, 0x01, 0x00, 0x33, 0x01, 0x80, 0x31, 0x00, 0x10, 0x00, 0x22, 0x02,
+ 0x00, 0x34, 0x02, 0x00, 0x0F, 0x00, 0x00, 0x02, 0x00, 0x14, 0x02, 0x00, 0x15, 0x01, 0x00, 0x16,
+ 0x02, 0x80, 0x0B, 0xFF, 0xEE, 0x00, 0x4C, 0x02, 0x00, 0x18, 0x01, 0x00, 0x19, 0x02, 0x00, 0x25,
+ 0x01, 0x00, 0x26, 0x01, 0x00, 0x27, 0x02, 0x00, 0x28, 0x01, 0x00, 0x29, 0x02, 0x00, 0x2A, 0x01,
+ 0x00, 0x35, 0x01, 0x00, 0x36, 0x02, 0x00, 0x0B, 0x00, 0x00, 0x02, 0x00, 0x37, 0x01, 0x00, 0x38,
+ 0x02, 0x00, 0x39, 0x01, 0x00, 0x3A, 0x02, 0x00, 0x3B, 0x02, 0x80, 0x28, 0xFF, 0xC8, 0x00, 0x0B,
+ 0x01, 0x00, 0x3C, 0x02, 0x00, 0x3D, 0x01, 0x00, 0x3E, 0x01, 0x00, 0x3F, 0x02, 0x00, 0x08, 0x00,
+ 0x00, 0x02, 0x00, 0x40, 0x01, 0x00, 0x41, 0x02, 0x00, 0x42, 0x01, 0x80, 0x2D, 0x00, 0x00, 0x00,
+ 0x7E, 0x01, 0x80, 0x2E, 0x00, 0x00, 0x00, 0x36, 0x02, 0x00, 0x43, 0x01, 0x00, 0x44, 0x02, 0x00,
+ 0x09, 0x00, 0x00, 0x02, 0x00, 0x45, 0x01, 0x00, 0x46, 0x02, 0x00, 0x47, 0x01, 0x00, 0x48, 0x02,
+ 0x00, 0x49, 0x01, 0x80, 0x2D, 0xFF, 0xDA, 0x00, 0x7D, 0x01, 0x80, 0x2E, 0xFF, 0xE5, 0x00, 0x36,
+ 0x02, 0x00, 0x4A, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x25, 0x01, 0x00, 0x26, 0x01, 0x00,
+ 0x27, 0x02, 0x00, 0x28, 0x01, 0x00, 0x29, 0x02, 0x00, 0x2A, 0x01, 0x00, 0x10, 0x01, 0x80, 0x02,
+ 0xFF, 0xC9, 0xFF, 0xFF, 0x02, 0x80, 0x04, 0xFF, 0xB1, 0xFF, 0xFF, 0x02, 0x00, 0x11, 0x01, 0x00,
+ 0x12, 0x02, 0x00, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x4B, 0x01, 0x00, 0x4C, 0x02, 0x80, 0x14, 0x00,
+ 0x34, 0xFF, 0xDF, 0x02, 0x00, 0x4D, 0x01, 0x00, 0x4E, 0x02, 0x00, 0x4F, 0x01, 0x00, 0x50, 0x02,
+ 0x00, 0x51, 0x02, 0x00, 0x52, 0x02, 0x80, 0x18, 0x00, 0x7F, 0x00, 0x7F, 0x01, 0x80, 0x19, 0x00,
+ 0x7F, 0x00, 0x7F, 0x02, 0x00, 0x53, 0x03, 0x80, 0x2B, 0xFF, 0xF9, 0x00, 0x05, 0x01, 0x00, 0x0C,
+ 0x00, 0x00, 0x02, 0x00, 0x40, 0x01, 0x00, 0x41, 0x02, 0x00, 0x54, 0x01, 0x80, 0x38, 0xFF, 0xF3,
+ 0x00, 0x00, 0x02, 0x80, 0x2E, 0x00, 0x00, 0x00, 0x36, 0x02, 0x80, 0x47, 0x00, 0x00, 0x00, 0x2C,
+ 0x01, 0x00, 0x55, 0x02, 0x80, 0x47, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x80, 0x55, 0x00, 0x00, 0xFF,
+ 0xE1, 0x02, 0x00, 0x43, 0x01, 0x00, 0x44, 0x02, 0x00, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x39, 0x01,
+ 0x00, 0x3A, 0x02, 0x00, 0x3B, 0x02, 0x80, 0x28, 0xFF, 0xC8, 0x00, 0x0B, 0x01, 0x00, 0x3C, 0x02,
+ 0x80, 0x15, 0x00, 0x00, 0xFF, 0xF1, 0x01, 0x80, 0x16, 0x00, 0x00, 0xFF, 0xF1, 0x02, 0x80, 0x0B,
+ 0xFF, 0xEE, 0x00, 0x3D, 0x02, 0x00, 0x56, 0x01, 0x00, 0x57, 0x02, 0x00, 0x58, 0x01, 0x00, 0x59,
+ 0x02, 0x00, 0x0A, 0x00, 0x00, 0x02, 0x00, 0x5A, 0x01, 0x00, 0x5B, 0x02, 0x00, 0x5C, 0x01, 0x00,
+ 0x5D, 0x02, 0x00, 0x5E, 0x01, 0x00, 0x5F, 0x01, 0x00, 0x60, 0x02, 0x00, 0x61, 0x02, 0x00, 0x62,
+ 0x01, 0x00, 0x0A, 0x00, 0x00, 0x02, 0x00, 0x63, 0x01, 0x80, 0x41, 0x00, 0x3B, 0x00, 0x1F, 0x02,
+ 0x80, 0x56, 0x00, 0x00, 0xFF, 0xCB, 0x01, 0x80, 0x57, 0x00, 0x00, 0xFF, 0xCB, 0x02, 0x00, 0x64,
+ 0x01, 0x00, 0x65, 0x02, 0x80, 0x28, 0x00, 0x05, 0xFF, 0xF3, 0x01, 0x80, 0x18, 0x00, 0x00, 0x00,
+ 0x7F, 0x01, 0x80, 0x19, 0x00, 0x00, 0x00, 0x7F, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x39,
+ 0x01, 0x00, 0x3A, 0x02, 0x00, 0x3B, 0x02, 0x80, 0x28, 0xFF, 0xC8, 0x00, 0x0B, 0x01, 0x00, 0x3C,
+ 0x02, 0x80, 0x15, 0x00, 0x00, 0xFF, 0xDF, 0x01, 0x80, 0x16, 0x00, 0x00, 0xFF, 0xDF, 0x02, 0x80,
+ 0x0B, 0xFF, 0xEE, 0x00, 0x2B, 0x02, 0x00, 0x66, 0x01, 0x80, 0x5B, 0x00, 0x2F, 0x00, 0x00, 0x02,
+ 0x80, 0x62, 0x00, 0x2F, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x02, 0x80, 0x18, 0x00, 0x00,
+ 0x00, 0x7F, 0x01, 0x80, 0x19, 0x00, 0x00, 0x00, 0x7F, 0x02, 0x80, 0x5A, 0x00, 0x00, 0xFF, 0xA3,
+ 0x01, 0x80, 0x5B, 0x00, 0x00, 0xFF, 0xC5, 0x02, 0x80, 0x62, 0x00, 0x00, 0xFF, 0xC5, 0x01, 0x80,
+ 0x47, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x55, 0x02, 0x80, 0x47, 0x00, 0x00, 0x00, 0x0D, 0x01,
+ 0x80, 0x55, 0x00, 0x00, 0xFF, 0xE1, 0x02, 0x00, 0x0B, 0x00, 0x00, 0x02, 0x00, 0x67, 0x01, 0x00,
+ 0x68, 0x02, 0x00, 0x69, 0x01, 0x00, 0x6A, 0x01, 0x00, 0x6B, 0x02, 0x00, 0x6C, 0x02, 0x80, 0x58,
+ 0xFF, 0xD2, 0xFF, 0xE0, 0x01, 0x80, 0x59, 0xFF, 0xD2, 0xFF, 0xE0, 0x02, 0x00, 0x6D, 0x01, 0x80,
+ 0x14, 0xFF, 0xDB, 0x00, 0x16, 0x01, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x42, 0x01, 0x80, 0x2D,
+ 0x00, 0x00, 0x00, 0x7E, 0x01, 0x80, 0x2E, 0x00, 0x00, 0x00, 0x36, 0x02, 0x00, 0x10, 0x01, 0x80,
+ 0x02, 0xFF, 0xC9, 0xFF, 0xFF, 0x02, 0x80, 0x04, 0xFF, 0xB1, 0xFF, 0xFF, 0x02, 0x00, 0x11, 0x01,
+ 0x00, 0x12, 0x02, 0x80, 0x31, 0x00, 0x04, 0xFF, 0xED, 0x01, 0x00, 0x6E, 0x01, 0x80, 0x33, 0x00,
+ 0x04, 0xFF, 0x97, 0x01, 0x80, 0x31, 0x00, 0x14, 0xFF, 0xCB, 0x02, 0x80, 0x34, 0x00, 0x04, 0xFF,
+ 0xEC, 0x02, 0x80, 0x47, 0x00, 0x00, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x00, 0xFF, 0xD8, 0x02,
+ 0x00, 0x0D, 0x00, 0x00, 0x02, 0x80, 0x31, 0xFF, 0xBB, 0xFF, 0xFF, 0x01, 0x80, 0x32, 0xFF, 0xBB,
+ 0xFF, 0xFF, 0x01, 0x00, 0x6F, 0x01, 0x80, 0x31, 0xFF, 0xCB, 0x00, 0x21, 0x02, 0x80, 0x34, 0xFF,
+ 0xBB, 0xFF, 0xFF, 0x02, 0x00, 0x18, 0x01, 0x00, 0x19, 0x02, 0x00, 0x70, 0x01, 0x00, 0x71, 0x02,
+ 0x00, 0x72, 0x02, 0x00, 0x73, 0x02, 0x80, 0x28, 0xFF, 0xEE, 0x00, 0x2B, 0x01, 0x00, 0x0E, 0x00,
+ 0x00, 0x02, 0x00, 0x74, 0x01, 0x80, 0x2D, 0xFF, 0xF1, 0x00, 0x7D, 0x01, 0x80, 0x2E, 0x00, 0x00,
+ 0x00, 0x36, 0x02, 0x80, 0x31, 0xFF, 0xFB, 0xFF, 0xBF, 0x01, 0x00, 0x75, 0x01, 0x00, 0x76, 0x01,
+ 0x80, 0x31, 0x00, 0x1D, 0xFF, 0xCF, 0x02, 0x00, 0x77, 0x02, 0x00, 0x40, 0x01, 0x00, 0x41, 0x02,
+ 0x00, 0x78, 0x01, 0x00, 0x79, 0x01, 0x80, 0x28, 0xFF, 0xF8, 0x00, 0x05, 0x01, 0x00, 0x0F, 0x00,
+ 0x00, 0x02, 0x00, 0x4D, 0x01, 0x00, 0x4B, 0x01, 0x00, 0x7A, 0x02, 0x80, 0x14, 0x00, 0x33, 0xFF,
+ 0xDC, 0x02, 0x00, 0x4E, 0x02, 0x00, 0x7B, 0x01, 0x00, 0x7C, 0x02, 0x80, 0x15, 0x00, 0x66, 0xFF,
+ 0xD5, 0x01, 0x00, 0x7D, 0x02, 0x80, 0x0B, 0x00, 0x43, 0x00, 0x21, 0x02, 0x00, 0x7E, 0x01, 0x00,
+ 0x7F, 0x01, 0x00, 0x80, 0x01, 0x00, 0x81, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x80, 0x54, 0x00,
+ 0x00, 0xFF, 0xBA, 0x01, 0x80, 0x38, 0xFF, 0xF3, 0xFF, 0xF3, 0x02, 0x00, 0x56, 0x01, 0x00, 0x57,
+ 0x02, 0x00, 0x58, 0x01, 0x00, 0x59, 0x02, 0x80, 0x47, 0x00, 0x00, 0xFF, 0xEA, 0x01, 0x80, 0x55,
+ 0x00, 0x00, 0xFF, 0xBE, 0x02, 0x80, 0x47, 0x00, 0x00, 0xFF, 0xCB, 0x01, 0x80, 0x55, 0x00, 0x00,
+ 0xFF, 0x9F, 0x02, 0x80, 0x2B, 0x00, 0x0A, 0xFF, 0xC0, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x02, 0x00,
+ 0x82, 0x01, 0x00, 0x83, 0x01, 0x80, 0x18, 0x00, 0x7F, 0x00, 0x00, 0x01, 0x80, 0x19, 0x00, 0x7F,
+ 0x00, 0x00, 0x02, 0x00, 0x53, 0x03, 0x00, 0x84, 0x01, 0x00, 0x85, 0x02, 0x00, 0x86, 0x02, 0x80,
+ 0x31, 0x00, 0x1D, 0x00, 0x1D, 0x02, 0x00, 0x87, 0x01, 0x80, 0x0A, 0x00, 0x16, 0xFF, 0xF6, 0x02,
+ 0x00, 0x88, 0x02, 0x80, 0x31, 0xFF, 0xFB, 0x00, 0x2D, 0x01, 0x00, 0x89, 0x01, 0x00, 0x0B, 0x00,
+ 0x00, 0x02, 0x00, 0x8A, 0x01, 0x80, 0x46, 0x00, 0x01, 0xFF, 0xE9, 0x02, 0x00, 0x8B, 0x01, 0x80,
+ 0x78, 0xFF, 0xDF, 0x00, 0x0B, 0x02, 0x00, 0x8C, 0x01, 0x00, 0x8D, 0x01, 0x00, 0x8E, 0x02, 0x00,
+ 0x8F, 0x01, 0x00, 0x90, 0x02, 0x00, 0x91, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x92, 0x01,
+ 0x80, 0x02, 0xFF, 0xA7, 0x00, 0x58, 0x02, 0x00, 0x93, 0x01, 0x00, 0x94, 0x02, 0x00, 0x95, 0x02,
+ 0x00, 0x96, 0x01, 0x00, 0x97, 0x02, 0x00, 0x98, 0x01, 0x00, 0x99, 0x02, 0x00, 0x9A, 0x01, 0x00,
+ 0x9B, 0x02, 0x80, 0x9A, 0xFF, 0xE1, 0x00, 0x00, 0x01, 0x80, 0x9B, 0xFF, 0xE1, 0x00, 0x00, 0x02,
+ 0x00, 0x0A, 0x00, 0x00, 0x02, 0x80, 0x02, 0xFF, 0xA7, 0x00, 0x58, 0x02, 0x00, 0x9C, 0x01, 0x00,
+ 0x9D, 0x02, 0x00, 0x9E, 0x02, 0x80, 0x73, 0xFF, 0xBF, 0x00, 0x7F, 0x02, 0x80, 0x28, 0xFF, 0xAB,
+ 0x00, 0x2C, 0x01, 0x80, 0x18, 0x00, 0x7F, 0x00, 0x7F, 0x01, 0x80, 0x19, 0x00, 0x7F, 0x00, 0x7F,
+ 0x02, 0x00, 0x53, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x80, 0x17, 0x00, 0x01, 0x00, 0x00, 0x01,
+ 0x00, 0x9F, 0x01, 0x00, 0xA0, 0x02, 0x80, 0x14, 0x00, 0x02, 0x00, 0x03, 0x02, 0x80, 0x4E, 0x00,
+ 0x39, 0xFF, 0xF0, 0x02, 0x00, 0xA1, 0x01, 0x80, 0x7F, 0x00, 0x3B, 0x00, 0x26, 0x01, 0x00, 0xA2,
+ 0x01, 0x80, 0x78, 0x00, 0x01, 0xFF, 0xB4, 0x02, 0x00, 0xA3, 0x02, 0x80, 0x28, 0xFF, 0xF4, 0xFF,
+ 0xF6, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x02, 0x00, 0x25, 0x01, 0x00, 0x26, 0x01, 0x00, 0x27, 0x02,
+ 0x00, 0x28, 0x01, 0x00, 0x29, 0x02, 0x00, 0x2A, 0x01, 0x00, 0xA4, 0x01, 0x00, 0xA5, 0x02, 0x00,
+ 0xA6, 0x01, 0x00, 0xA7, 0x02, 0x80, 0xA6, 0xFF, 0xE1, 0x00, 0x00, 0x01, 0x80, 0xA7, 0xFF, 0xE1,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x26, 0x00, 0x2F, 0x00, 0x3A, 0x00, 0x43,
+ 0x00, 0x54, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x7F, 0x00, 0x8E, 0x00, 0x97, 0x00, 0xA0, 0x00, 0xAB,
+ 0x00, 0xC6, 0x00, 0xE1, 0x00, 0xF0, 0x01, 0x0B, 0x01, 0x1C, 0x01, 0x25, 0x01, 0x30, 0x01, 0x39,
+ 0x01, 0x44, 0x01, 0x55, 0x01, 0x5E, 0x01, 0x67, 0x01, 0x70, 0x01, 0x7B, 0x01, 0x86, 0x01, 0x8F,
+ 0x01, 0x9A, 0x01, 0xAB, 0x01, 0xB4, 0x01, 0xC1, 0x01, 0xCA, 0x01, 0xD3, 0x01, 0xF8, 0x02, 0x11,
+ 0x02, 0x1C, 0x02, 0x25, 0x02, 0x2E, 0x02, 0x37, 0x02, 0x40, 0x02, 0x4F, 0x02, 0x5A, 0x02, 0x65,
+ 0x02, 0x6E, 0x02, 0x77, 0x02, 0x90, 0x02, 0xA7, 0x02, 0xB0, 0x02, 0xBB, 0x02, 0xC6, 0x02, 0xD1,
+ 0x02, 0xF6, 0x03, 0x0F, 0x03, 0x1A, 0x03, 0x23, 0x03, 0x2E, 0x03, 0x37, 0x03, 0x48, 0x03, 0x51,
+ 0x03, 0x6A, 0x03, 0x75, 0x03, 0x8E, 0x03, 0x99, 0x03, 0xA2, 0x03, 0xAD, 0x03, 0xCE, 0x03, 0xE9,
+ 0x03, 0xF4, 0x03, 0xFD, 0x04, 0x16, 0x04, 0x2D, 0x04, 0x38, 0x04, 0x41, 0x04, 0x4C, 0x04, 0x57,
+ 0x04, 0x60, 0x04, 0x69, 0x04, 0x72, 0x04, 0x7F, 0x04, 0x88, 0x04, 0x99, 0x04, 0xA6, 0x04, 0xB1,
+ 0x04, 0xC2, 0x04, 0xCD, 0x04, 0xE2, 0x04, 0xFB, 0x05, 0x0C, 0x05, 0x17, 0x05, 0x20, 0x05, 0x2B,
+ 0x05, 0x34, 0x05, 0x4D, 0x05, 0x58, 0x05, 0x71, 0x05, 0x84, 0x05, 0x8D, 0x05, 0x98, 0x05, 0xB3,
+ 0x05, 0xC4, 0x05, 0xCF, 0x05, 0xDA, 0x05, 0xE3, 0x05, 0xEE, 0x05, 0xF7, 0x06, 0x02, 0x06, 0x0F,
+ 0x06, 0x1A, 0x06, 0x25, 0x06, 0x30, 0x06, 0x3B, 0x06, 0x4C, 0x06, 0x55, 0x06, 0x5E, 0x06, 0x69,
+ 0x06, 0x74, 0x06, 0x7F, 0x06, 0x8A, 0x06, 0x93, 0x06, 0x9C, 0x06, 0xAB, 0x06, 0xB6, 0x06, 0xBF,
+ 0x06, 0xD0, 0x06, 0xD9, 0x06, 0xE2, 0x06, 0xFB, 0x07, 0x0C, 0x07, 0x17, 0x07, 0x22, 0x07, 0x2D,
+ 0x07, 0x3E, 0x07, 0x4F, 0x07, 0x58, 0x07, 0x63, 0x07, 0x6C, 0x07, 0x77, 0x07, 0x86, 0x07, 0x91,
+ 0x07, 0x9A, 0x07, 0xA3, 0x07, 0xAC, 0x07, 0xB5, 0x07, 0xBE, 0x07, 0xD9, 0x07, 0xEA, 0x07, 0xF3,
+ 0x07, 0xFC, 0x08, 0x07, 0x08, 0x1C, 0x08, 0x35, 0x08, 0x46, 0x08, 0x5F, 0x08, 0x70, 0x08, 0x7B,
+ 0x08, 0x8C, 0x08, 0x95, 0x08, 0xA0, 0x08, 0xAF, 0x08, 0xB6, 0x08, 0xBF, 0x08, 0xCA, 0x08, 0xEF,
+ 0x09, 0x08, 0x09, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x81, 0x00, 0x0B,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0xFA, 0x00, 0xF8, 0xFE, 0xFA, 0xFD, 0xF7, 0xF7, 0xFC, 0xF9,
+ 0xFE, 0xF8, 0xFF, 0xFA, 0x00, 0xFC, 0x00, 0xA8, 0x1C, 0x00, 0xFF, 0x00, 0x5B, 0x00, 0x03, 0x00,
+ 0x1E, 0x00, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x19, 0xAD, 0x00, 0xFF, 0x00,
+ 0x67, 0x00, 0x4A, 0x00, 0x0F, 0x00, 0x16, 0x06, 0x00, 0x5B, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x03,
+ 0xFE, 0x06, 0xFC, 0x04, 0xFC, 0x01, 0xFD, 0x00, 0x06, 0x00, 0x53, 0x00, 0x01, 0x00, 0x18, 0xEB,
+ 0x00, 0x01, 0xF9, 0x03, 0xF9, 0x06, 0xFA, 0x06, 0xFD, 0x02, 0x00, 0x5B, 0x00, 0x23, 0x17, 0x17,
+ 0xE9, 0x06, 0x06, 0x00, 0x00, 0x00, 0x02, 0x06, 0x03, 0x06, 0x06, 0x03, 0x07, 0x02, 0x0A, 0xEB,
+ 0x00, 0x00, 0xE5, 0x05, 0x00, 0x00, 0x00, 0x1A, 0x65, 0x65, 0x9B, 0x00, 0x00, 0xDE, 0x1E, 0xFA,
+ 0x01, 0x00, 0xFF, 0x00, 0x0F, 0x00, 0x5D, 0x00, 0x0F, 0x00, 0x0F, 0xFF, 0x00, 0x27, 0x00, 0x19,
+ 0x00, 0x15, 0x00, 0x18, 0x03, 0x00, 0x7F, 0x00, 0x7F, 0x82, 0x00, 0x00, 0x81, 0x7E, 0x00, 0x0B,
+ 0x00, 0x7F, 0x00, 0x11, 0xE6, 0x0D, 0x00, 0xFB, 0x01, 0xFB, 0x03, 0xF9, 0x04, 0xFA, 0x03, 0xFD,
+ 0x06, 0xFD, 0x02, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x05, 0x00, 0x0B, 0x00, 0x7F, 0x00, 0x22, 0xE3,
+ 0x0D, 0x00, 0xFB, 0x01, 0xFB, 0x03, 0xF9, 0x04, 0xFA, 0x03, 0xFD, 0x06, 0xFD, 0x02, 0x00, 0x00,
+ 0x00, 0x02, 0xFF, 0x08, 0x00, 0x05, 0x00, 0x60, 0x00, 0x57, 0x01, 0x00, 0x1E, 0x06, 0x00, 0x22,
+ 0x9B, 0x00, 0x65, 0x9B, 0x0B, 0x00, 0x08, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x57, 0x00, 0x04, 0xFF,
+ 0x06, 0xFE, 0x08, 0xFC, 0x07, 0xF7, 0x09, 0xFA, 0x03, 0xF8, 0x03, 0xFA, 0x00, 0x00, 0x81, 0x06,
+ 0x00, 0x24, 0x00, 0x0D, 0xFD, 0x00, 0xFC, 0xFF, 0xFC, 0xFC, 0xFE, 0xFA, 0x00, 0xFE, 0x0D, 0x00,
+ 0x02, 0x00, 0x24, 0x00, 0x3F, 0xE9, 0xFA, 0x17, 0xE9, 0x03, 0x00, 0x7F, 0x00, 0x2D, 0x00, 0x52,
+ 0x81, 0x00, 0x00, 0xEE, 0xFF, 0x00, 0x25, 0x00, 0x50, 0x00, 0x19, 0x00, 0x19, 0x03, 0x00, 0x00,
+ 0x00, 0x69, 0x00, 0xD0, 0x19, 0x00, 0x00, 0x30, 0x06, 0x00, 0x01, 0x00, 0x39, 0x18, 0x00, 0x00,
+ 0x15, 0xF9, 0xFF, 0xF9, 0xFD, 0xFA, 0xFA, 0xFD, 0xFA, 0x02, 0x00, 0x01, 0x00, 0x7F, 0x32, 0xE7,
+ 0x00, 0x19, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x2A, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x00, 0x18, 0x03, 0x00, 0x7E, 0x00, 0x2D, 0xE9, 0x2D, 0xEE, 0xE5, 0x2A, 0xEB, 0x03,
+ 0x00, 0x31, 0x00, 0x66, 0xCF, 0x18, 0x00, 0xDF, 0x2A, 0xF5, 0xFF, 0x00, 0x56, 0x00, 0x4C, 0x00,
+ 0x16, 0x00, 0x16, 0x03, 0x00, 0x2F, 0x00, 0x66, 0x2C, 0x00, 0x00, 0x19, 0xD4, 0x00, 0x06, 0x00,
+ 0x56, 0x00, 0x7D, 0xFA, 0xFD, 0xFA, 0xFA, 0xFD, 0xF9, 0xFF, 0xF9, 0x15, 0x00, 0x00, 0x18, 0x02,
+ 0x00, 0x2C, 0x00, 0x7F, 0xD4, 0x00, 0x00, 0xAA, 0x04, 0x00, 0x11, 0x00, 0x70, 0xFE, 0xFC, 0x14,
+ 0x00, 0x0B, 0x13, 0xF2, 0x00, 0xFF, 0x00, 0x1C, 0x00, 0x69, 0x00, 0x0D, 0x00, 0x0B, 0xFF, 0x00,
+ 0x19, 0x00, 0x26, 0x00, 0x19, 0x00, 0x36, 0x10, 0x00, 0x2F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0A,
+ 0xFE, 0x0F, 0xFE, 0x09, 0xFD, 0x0A, 0xFB, 0x0A, 0xF8, 0x0A, 0xF9, 0x07, 0xF4, 0x08, 0xFC, 0x02,
+ 0xF9, 0x01, 0x00, 0xE9, 0x08, 0xF9, 0x06, 0xF5, 0x03, 0xF3, 0x02, 0xF3, 0x0A, 0x00, 0x17, 0x00,
+ 0x3C, 0x08, 0xFF, 0x0A, 0xFD, 0x05, 0xFC, 0x05, 0xFB, 0x06, 0xF7, 0xFE, 0x09, 0xFE, 0x06, 0xF7,
+ 0x0F, 0xF6, 0x0A, 0xF5, 0x09, 0x03, 0x00, 0x6F, 0x00, 0x1F, 0x10, 0x00, 0x00, 0x60, 0xF0, 0x00,
+ 0xFF, 0x00, 0x6B, 0x00, 0x2E, 0x00, 0x14, 0x00, 0x27, 0xFF, 0x00, 0x71, 0x00, 0x16, 0x00, 0x0E,
+ 0x00, 0x17, 0xFF, 0x00, 0x73, 0x00, 0x14, 0x00, 0x07, 0x00, 0x07, 0x02, 0x00, 0x6E, 0x00, 0x4D,
+ 0x00, 0x09, 0xF8, 0xFF, 0x05, 0x00, 0x6F, 0x00, 0x4D, 0x00, 0x32, 0xE1, 0x00, 0x0E, 0xF2, 0x08,
+ 0xF6, 0x06, 0xF5, 0x03, 0x00, 0x24, 0x00, 0x68, 0x2D, 0x00, 0x00, 0x07, 0xD3, 0x00, 0x03, 0x00,
+ 0x51, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x27, 0xD2, 0x00, 0xFF, 0x00, 0x51, 0x00, 0x00, 0x00, 0x2B,
+ 0x00, 0x26, 0xFF, 0x00, 0x67, 0x00, 0x24, 0x00, 0x17, 0x00, 0x17, 0x0A, 0x00, 0x7F, 0x00, 0x4B,
+ 0xFB, 0x00, 0xFB, 0xFE, 0x01, 0x00, 0xFA, 0xFD, 0xFD, 0xFD, 0xFD, 0xFC, 0xFC, 0xF7, 0xFF, 0xFB,
+ 0x00, 0xFB, 0x1A, 0x0D, 0x09, 0x00, 0x7F, 0x00, 0x39, 0xF8, 0x00, 0xFC, 0xFF, 0xFA, 0xFD, 0xFD,
+ 0xFD, 0xFC, 0xFA, 0xFD, 0xF9, 0xFF, 0xFB, 0x00, 0xFC, 0x1D, 0x0C, 0xFF, 0x00, 0x4E, 0x00, 0x49,
+ 0x00, 0x13, 0x00, 0x13, 0x03, 0x00, 0x45, 0x00, 0x36, 0x0C, 0x00, 0x04, 0x47, 0xF0, 0x00, 0x03,
+ 0x00, 0x45, 0x00, 0x69, 0x1B, 0x00, 0x00, 0x16, 0xE5, 0x00, 0x03, 0x00, 0x38, 0x00, 0x36, 0x0C,
+ 0x00, 0x00, 0x27, 0xF4, 0x00, 0x10, 0x00, 0x3F, 0x00, 0x7F, 0xE2, 0x00, 0x00, 0xF5, 0x01, 0xF1,
+ 0x02, 0xF7, 0x03, 0xF6, 0x05, 0xF6, 0x08, 0xF6, 0x07, 0xF9, 0x0C, 0xF8, 0x04, 0xFE, 0x07, 0xFF,
+ 0x00, 0x17, 0xF8, 0x07, 0xFA, 0x0B, 0xFD, 0x0D, 0xFE, 0x0D, 0x0A, 0x00, 0x54, 0x00, 0x43, 0xF8,
+ 0x00, 0xF9, 0x03, 0xFB, 0x04, 0xFB, 0x05, 0xFA, 0x09, 0x02, 0xF7, 0x02, 0xFA, 0x09, 0xF1, 0x09,
+ 0xF7, 0x08, 0xF9, 0x03, 0x00, 0x46, 0x00, 0x46, 0x39, 0x00, 0x00, 0x39, 0xC7, 0x00, 0xFF, 0x00,
+ 0x46, 0x00, 0x46, 0x00, 0x2F, 0x00, 0x2F, 0x03, 0x00, 0x20, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x2E,
+ 0xA1, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x21, 0x00, 0x49, 0x00, 0x24, 0x06, 0x00, 0x51, 0x00, 0x2E,
+ 0x09, 0xFE, 0x0F, 0xFE, 0x0A, 0x00, 0x0C, 0x02, 0x00, 0x04, 0xD0, 0x00, 0x02, 0x00, 0x43, 0x00,
+ 0x2A, 0x0C, 0x06, 0xF4, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x7F, 0x00, 0xC5, 0x19, 0x00, 0x0F, 0xFE,
+ 0x0D, 0xFC, 0x0E, 0x1A, 0xFB, 0x0C, 0xF8, 0x09, 0xF0, 0x0A, 0xF4, 0x04, 0xF1, 0x04, 0x03, 0x00,
+ 0x00, 0x00, 0x3D, 0x07, 0x04, 0x0C, 0x03, 0xED, 0x01, 0x0A, 0x00, 0x36, 0x00, 0x3D, 0x0D, 0x1A,
+ 0xF4, 0x07, 0xF3, 0x02, 0xF9, 0xFF, 0xFA, 0xFF, 0xFB, 0xFC, 0x06, 0xFF, 0x0A, 0xFB, 0x08, 0xF8,
+ 0x04, 0xF9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0xDF, 0x00, 0xFF, 0x00, 0x21,
+ 0x00, 0x30, 0x00, 0x23, 0x00, 0x23, 0x03, 0x00, 0x51, 0x00, 0x57, 0x2E, 0x00, 0x00, 0x28, 0xD2,
+ 0x00, 0x0E, 0x00, 0x60, 0x00, 0x0C, 0xFA, 0x0A, 0xFB, 0x0D, 0xFE, 0x0B, 0x01, 0x0A, 0xF0, 0x11,
+ 0xFC, 0xFA, 0xFE, 0xFC, 0xFD, 0xF2, 0x00, 0xF6, 0x01, 0xF3, 0x03, 0xF6, 0x05, 0xF7, 0x04, 0xF9,
+ 0x24, 0x00, 0x0B, 0x00, 0x43, 0x00, 0x4B, 0xFE, 0xF2, 0x01, 0xF7, 0x01, 0xF8, 0x03, 0xF7, 0x03,
+ 0xFA, 0x03, 0xFA, 0x00, 0x09, 0x00, 0x07, 0x01, 0x06, 0x03, 0x07, 0x05, 0x05, 0x03, 0x00, 0x00,
+ 0x00, 0x1B, 0x34, 0x00, 0x00, 0x2F, 0xCC, 0x00, 0xFF, 0x00, 0x34, 0x00, 0x4A, 0x00, 0x33, 0x00,
+ 0x21, 0x0A, 0x00, 0x7F, 0x00, 0x46, 0xE6, 0x0D, 0x00, 0xFB, 0x01, 0xFB, 0x04, 0xF7, 0x03, 0xFC,
+ 0x03, 0xFD, 0x06, 0xFD, 0xFF, 0x00, 0x05, 0xFF, 0x05, 0x00, 0x09, 0x00, 0x7F, 0x00, 0x57, 0xE3,
+ 0x0D, 0x00, 0xFB, 0x01, 0xFB, 0x03, 0xF9, 0x04, 0xFA, 0x03, 0xFD, 0x06, 0xFD, 0x04, 0xFF, 0x08,
+ 0x00, 0x03, 0x00, 0x30, 0x00, 0x57, 0x34, 0x00, 0x00, 0x28, 0xCC, 0x00, 0xFF, 0x00, 0x34, 0x00,
+ 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x52, 0x00, 0xAE, 0x7F, 0x00, 0x00, 0x12,
+ 0x03, 0x00, 0x4D, 0x00, 0x19, 0x32, 0xE8, 0x00, 0x21, 0xD5, 0x0B, 0x02, 0x00, 0x7D, 0x00, 0x00,
+ 0xCE, 0x19, 0x00, 0xE7, 0xFF, 0x00, 0x22, 0x00, 0x4F, 0x00, 0x24, 0x00, 0x32, 0x02, 0x00, 0x25,
+ 0x00, 0x7F, 0xDB, 0x00, 0x00, 0xB7, 0x04, 0x00, 0x0E, 0x00, 0x72, 0xFF, 0xFD, 0x10, 0x00, 0x0A,
+ 0x10, 0xF4, 0x00, 0xFF, 0x00, 0x18, 0x00, 0x6C, 0x00, 0x0B, 0x00, 0x09, 0x06, 0x00, 0x01, 0x00,
+ 0x3D, 0x01, 0xFB, 0x15, 0x29, 0xF5, 0xFC, 0xFC, 0xFB, 0xFB, 0xF7, 0xFE, 0xF4, 0x04, 0x00, 0x80,
+ 0x00, 0x00, 0x29, 0x00, 0x00, 0x7F, 0x00, 0x2A, 0xD7, 0x00, 0x03, 0x00, 0x39, 0x00, 0x7F, 0xC7,
+ 0x00, 0x00, 0xC7, 0x39, 0x00, 0x06, 0x00, 0x7F, 0x00, 0x7F, 0xE7, 0x00, 0x04, 0xFA, 0x03, 0xFD,
+ 0x06, 0xFD, 0x04, 0xFF, 0x08, 0x00, 0x03, 0x00, 0x44, 0x00, 0x4C, 0x3B, 0x00, 0x00, 0x33, 0xC5,
+ 0x00, 0x08, 0x00, 0x7F, 0x00, 0x5A, 0x00, 0x25, 0xD1, 0x00, 0x01, 0xF6, 0x07, 0xF5, 0x07, 0xF9,
+ 0x08, 0xFB, 0x06, 0xFE, 0x0A, 0xFE, 0x0A, 0x00, 0x48, 0x00, 0x5C, 0xFB, 0x00, 0xFB, 0xFF, 0x01,
+ 0x00, 0xFA, 0xFD, 0xFD, 0xFD, 0xFD, 0xFC, 0xFC, 0xF7, 0xFF, 0xFB, 0x00, 0xFB, 0x1A, 0x0D, 0x06,
+ 0x00, 0x48, 0x00, 0x4B, 0xF8, 0x00, 0xFC, 0xFF, 0xFA, 0xFD, 0xFD, 0xFD, 0xFC, 0xFA, 0x19, 0x00,
+ 0x03, 0x00, 0x2F, 0x00, 0x5D, 0x50, 0x00, 0x00, 0x22, 0xB0, 0x00, 0xFF, 0x00, 0x2F, 0x00, 0x5D,
+ 0x00, 0x21, 0x00, 0x21, 0x03, 0x00, 0x00, 0x00, 0x1A, 0x21, 0x00, 0x00, 0x65, 0xDF, 0x00, 0xFF,
+ 0x00, 0x21, 0x00, 0x1A, 0x00, 0x20, 0x00, 0x20, 0x0A, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x39, 0xDC,
+ 0x02, 0xF7, 0x02, 0xF7, 0x04, 0xF3, 0xE6, 0x04, 0xF4, 0x08, 0xF7, 0x10, 0xF6, 0x0C, 0xFC, 0x0F,
+ 0xFC, 0x03, 0x00, 0x7F, 0x00, 0x42, 0xF7, 0xFA, 0xF6, 0xFE, 0x13, 0x00, 0x0A, 0x00, 0x48, 0x00,
+ 0x42, 0xF4, 0xE6, 0x0B, 0xF9, 0x0D, 0xFE, 0x07, 0x01, 0x06, 0x01, 0x05, 0x04, 0xFA, 0x01, 0xF5,
+ 0x06, 0xF9, 0x07, 0xFC, 0x07, 0x07, 0x00, 0x21, 0x00, 0x7F, 0xE6, 0x00, 0x00, 0xF2, 0x02, 0xF2,
+ 0x04, 0xF3, 0x04, 0xF5, 0x07, 0xF7, 0x09, 0xF9, 0xFF, 0x00, 0x2F, 0x00, 0x5D, 0x00, 0x0D, 0x00,
+ 0x0D, 0x03, 0x00, 0x7F, 0x00, 0x7F, 0xDF, 0x00, 0x00, 0xD9, 0x21, 0x00, 0x0B, 0x00, 0x48, 0x00,
+ 0x27, 0xFB, 0x00, 0xFB, 0xFF, 0x01, 0x00, 0xFA, 0xFD, 0xFD, 0xFD, 0xFD, 0xFC, 0xFC, 0xF7, 0xFF,
+ 0xFB, 0xFF, 0xFB, 0x00, 0xF9, 0x1B, 0x14, 0x06, 0x00, 0x47, 0x00, 0x10, 0x03, 0x06, 0xF4, 0xFD,
+ 0xF7, 0xF9, 0xFD, 0xFD, 0xFC, 0xFA, 0x19, 0x00, 0x03, 0x00, 0x5E, 0x00, 0x7F, 0xA2, 0x00, 0x00,
+ 0xDE, 0x5E, 0x00, 0x03, 0x00, 0x3F, 0x00, 0x3F, 0x40, 0x00, 0x00, 0x40, 0xC0, 0x00, 0xFF, 0x00,
+ 0x3F, 0x00, 0x3F, 0x00, 0x37, 0x00, 0x37, 0x03, 0x00, 0x3F, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x4A,
+ 0xE3, 0x00, 0xFF, 0x00, 0x3F, 0x00, 0x4A, 0x00, 0x1D, 0x00, 0x1D, 0x03, 0x00, 0x22, 0x00, 0x2C,
+ 0x1C, 0x00, 0x00, 0x3E, 0xE4, 0x00, 0x04, 0x00, 0x5C, 0x00, 0x47, 0xF8, 0x00, 0x00, 0xED, 0x02,
+ 0xEA, 0x06, 0xE2, 0x03, 0x00, 0x00, 0x00, 0x66, 0x1A, 0x00, 0x00, 0x19, 0xE6, 0x00, 0x03, 0x00,
+ 0x49, 0x00, 0x02, 0x10, 0x00, 0xFC, 0x47, 0xF4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x68, 0x1B, 0x00,
+ 0x00, 0x17, 0xE5, 0x00, 0x03, 0x00, 0x7F, 0x00, 0x14, 0x00, 0x6B, 0xD2, 0x00, 0x00, 0x95, 0x06,
+ 0x00, 0x51, 0x00, 0x51, 0x02, 0x09, 0x02, 0x0F, 0x00, 0x0A, 0xFE, 0x0C, 0xFC, 0x00, 0x00, 0xD0,
+ 0x02, 0x00, 0x55, 0x00, 0x43, 0xFA, 0x0C, 0x00, 0xF4, 0xFF, 0x00, 0x60, 0x00, 0x00, 0x00, 0x1F,
+ 0x00, 0x4D, 0x03, 0x00, 0x43, 0x00, 0x57, 0x3C, 0x00, 0x00, 0x28, 0xC4, 0x00, 0x03, 0x00, 0x7D,
+ 0xFF, 0xFF, 0x00, 0x10, 0xB9, 0xFC, 0x00, 0xF4, 0x03, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x1B, 0xEA,
+ 0x00, 0x00, 0xE5, 0x03, 0x00, 0x5D, 0xFF, 0xF2, 0x00, 0x0C, 0xD9, 0x00, 0x00, 0xF4, 0xFF, 0x00,
+ 0x67, 0x00, 0x58, 0x00, 0x0C, 0x00, 0x0C, 0xFF, 0x00, 0x1A, 0x00, 0x2C, 0x00, 0x0A, 0x00, 0x0A,
+ 0x05, 0x00, 0x48, 0x00, 0x19, 0x0C, 0xF7, 0x12, 0xF7, 0x19, 0xFA, 0x00, 0x21, 0xD5, 0x0B, 0x03,
+ 0x00, 0x2E, 0x00, 0x53, 0x51, 0x00, 0x00, 0x2C, 0xAF, 0x00, 0xFF, 0x00, 0x1A, 0x00, 0x53, 0x00,
+ 0x64, 0x00, 0x20, 0x06, 0x00, 0x7D, 0x00, 0x13, 0xFD, 0x06, 0xFA, 0x06, 0xF9, 0x03, 0xF9, 0x01,
+ 0x00, 0xEB, 0x18, 0x00, 0x02, 0x00, 0x07, 0x00, 0x27, 0xF9, 0x15, 0x00, 0xF7, 0xFF, 0x00, 0x1F,
+ 0x00, 0x34, 0x00, 0x0B, 0x00, 0x0B, 0x0A, 0x00, 0x00, 0x00, 0x57, 0x1A, 0xF3, 0x00, 0x05, 0xFF,
+ 0x05, 0xFC, 0x09, 0xFD, 0x04, 0xFD, 0x03, 0xFA, 0x03, 0x01, 0x00, 0xFB, 0x01, 0xFB, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x4A, 0x19, 0x00, 0xFC, 0x06, 0xFD, 0x03, 0xFA, 0x03, 0xFC, 0x01, 0xF8, 0x00,
+ 0x03, 0x00, 0x69, 0x00, 0x7F, 0x00, 0xE5, 0x16, 0x00, 0x00, 0x1B, 0x03, 0x00, 0x36, 0x00, 0x7F,
+ 0x00, 0xF4, 0x47, 0xFC, 0x00, 0x10, 0x03, 0x00, 0x49, 0x00, 0x19, 0xD2, 0x00, 0x00, 0xE7, 0x2E,
+ 0x00, 0x06, 0x00, 0x21, 0x00, 0x02, 0x06, 0x03, 0x06, 0x06, 0x03, 0x07, 0x01, 0x07, 0xEA, 0x00,
+ 0x00, 0xE8, 0x06, 0x00, 0x49, 0x00, 0x01, 0x00, 0x18, 0xEA, 0x00, 0x01, 0xF9, 0x03, 0xF9, 0x06,
+ 0xFA, 0x06, 0xFD, 0x02, 0x00, 0x00, 0x00, 0x5E, 0x00, 0xA2, 0x5E, 0x5E, 0x03, 0x00, 0x2E, 0x00,
+ 0x47, 0x3D, 0x1E, 0xBE, 0x00, 0xFF, 0xE2, 0xFF, 0x00, 0x03, 0x00, 0x7D, 0x00, 0x11, 0x00, 0x11,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x36, 0xCC, 0x00, 0x05, 0x00, 0x39, 0x00, 0x5E,
+ 0x01, 0x00, 0x19, 0x05, 0x00, 0x1C, 0xAD, 0x00, 0x53, 0xAD, 0x03, 0x00, 0x71, 0x00, 0x2E, 0x0E,
+ 0x00, 0x00, 0x51, 0xF2, 0x00, 0xFF, 0x00, 0x6E, 0x00, 0x3B, 0x00, 0x11, 0x00, 0x21, 0xFF, 0x00,
+ 0x73, 0x00, 0x26, 0x00, 0x0C, 0x00, 0x13, 0xFF, 0x00, 0x74, 0x00, 0x25, 0x00, 0x06, 0x00, 0x06,
+ 0x02, 0x00, 0x70, 0x00, 0x55, 0x00, 0x07, 0xF9, 0x00, 0x02, 0x00, 0x71, 0x00, 0x55, 0x00, 0x2A,
+ 0xEB, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x77, 0x00, 0xE4, 0x57, 0x00, 0x04, 0x00, 0x06, 0x01, 0x08,
+ 0x02, 0x07, 0x04, 0x09, 0x09, 0x03, 0x06, 0x03, 0x08, 0x00, 0x06, 0x81, 0x00, 0x06, 0x00, 0x0D,
+ 0x00, 0x5B, 0x00, 0x03, 0xFF, 0x04, 0xFC, 0x04, 0xFA, 0x02, 0xFE, 0x00, 0x00, 0xF3, 0x02, 0x00,
+ 0x3F, 0x00, 0x5B, 0xFA, 0x17, 0xE9, 0xE9, 0xFF, 0x00, 0x48, 0x00, 0x68, 0x00, 0x14, 0x00, 0x0F,
+ 0x03, 0x00, 0x4C, 0x00, 0x3B, 0x00, 0xC5, 0x33, 0x00, 0x00, 0x3B, 0x08, 0x00, 0x5A, 0x00, 0x00,
+ 0x25, 0x00, 0x00, 0x2F, 0xF6, 0xFF, 0xF5, 0xF9, 0xF9, 0xF9, 0xFB, 0xF8, 0xFE, 0xFA, 0xFE, 0xF6,
+ 0x0A, 0x00, 0x5C, 0x00, 0x37, 0x00, 0x05, 0xFF, 0x05, 0x00, 0xFF, 0xFD, 0x06, 0xFD, 0x03, 0xFC,
+ 0x03, 0xF7, 0x04, 0xFB, 0x01, 0xFB, 0x00, 0x0D, 0xE6, 0x06, 0x00, 0x4B, 0x00, 0x37, 0x00, 0x08,
+ 0xFF, 0x04, 0xFD, 0x06, 0xFD, 0x03, 0xFA, 0x04, 0x00, 0xE7, 0x0A, 0x00, 0x30, 0x00, 0x00, 0x0D,
+ 0x1A, 0xFB, 0x00, 0xFB, 0xFF, 0xF7, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFA, 0x00, 0x01, 0xFF,
+ 0xFB, 0x00, 0xFB, 0x06, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x19, 0xFA, 0xFC, 0xFD, 0xFD, 0xFD, 0xFA,
+ 0xFF, 0xFC, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x94, 0x2E, 0x00, 0x00, 0x6C, 0x06,
+ 0x00, 0x2E, 0x00, 0x2E, 0xFE, 0xF7, 0xFE, 0xF1, 0x00, 0xF6, 0x02, 0xF4, 0x04, 0x00, 0x00, 0x30,
+ 0x02, 0x00, 0x2A, 0x00, 0x3C, 0x06, 0xF4, 0x00, 0x0C, 0x03, 0x00, 0x7F, 0x00, 0x3F, 0x00, 0x40,
+ 0x82, 0x00, 0x00, 0xEE, 0x05, 0x00, 0x37, 0x00, 0x66, 0xF4, 0x09, 0xEE, 0x09, 0xE8, 0x06, 0x00,
+ 0xDF, 0x2A, 0xF5, 0x01, 0x00, 0x7F, 0x00, 0x43, 0x00, 0x09, 0x02, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x4C, 0xB4, 0xB4, 0x03, 0x00, 0x33, 0x00, 0x00, 0x35, 0x00, 0x02, 0x17, 0xFA, 0x01, 0x10, 0x00,
+ 0x1E, 0x00, 0x0F, 0x02, 0x0D, 0x03, 0x0D, 0x06, 0x0B, 0x08, 0x07, 0x00, 0x17, 0xF9, 0xFF, 0xFC,
+ 0xFE, 0xF4, 0xF8, 0xF9, 0xF9, 0xF8, 0xF6, 0xFB, 0xF6, 0xFD, 0xF6, 0xFE, 0xF7, 0xFF, 0xF1, 0x00,
+ 0xF6, 0x1E, 0x00, 0x0A, 0x00, 0x37, 0x00, 0x57, 0xF4, 0xF7, 0xF6, 0xF6, 0xF7, 0xF1, 0xFE, 0xFA,
+ 0xFE, 0xF7, 0x06, 0x09, 0x05, 0x05, 0x05, 0x04, 0x0A, 0x03, 0x09, 0x01, 0x0A, 0x00, 0x2C, 0x00,
+ 0x7F, 0x00, 0xFB, 0x01, 0xFB, 0x00, 0x01, 0x03, 0xFA, 0x03, 0xFD, 0x04, 0xFD, 0x09, 0xFC, 0x05,
+ 0xFF, 0x05, 0x00, 0xF3, 0x1A, 0x06, 0x00, 0x3D, 0x00, 0x7F, 0x00, 0xF8, 0x01, 0xFC, 0x03, 0xFA,
+ 0x03, 0xFD, 0x06, 0xFC, 0x00, 0x19
+};
+
+const Level Game::_gameLevels[] = {
+ { "level1", "level1", "level1", 0x00, 1, 3 },
+ { "level2", "level2", "level2", 0x2F, 1, 4 },
+ { "level3", "level3", "dt", 0xFFFF, 3, 5 },
+ { "level4", "level4_1", "level3_1", 0x34, 3, 6 },
+ { "level4", "level4_2", "level3_2", 0x39, 3, 6 },
+ { "level5", "level5_1", "level4_1", 0x35, 4, 7 },
+ { "level5", "level5_2", "level4_2", 0xFFFF, 4, 7 }
+};
+
+const uint16_t Game::_scoreTable[] = {
+ 0, 200, 300, 400, 500, 800, 1000, 1200, 1500, 2000, 2200, 2500, 3000, 3200, 3500, 5000
+};
+
+const uint8_t Game::_monsterListLevel1[] = {
+ 0x22, 0, 0x23, 0, 0xFF
+};
+
+const uint8_t Game::_monsterListLevel2[] = {
+ 0x22, 0, 0x23, 0, 0x4B, 0, 0x49, 1, 0x4D, 1, 0x76, 2, 0xFF
+};
+
+const uint8_t Game::_monsterListLevel3[] = {
+ 0x76, 2, 0xFF
+};
+
+const uint8_t Game::_monsterListLevel4_1[] = {
+ 0x4D, 1, 0x76, 2, 0xFF
+};
+
+const uint8_t Game::_monsterListLevel4_2[] = {
+ 0x76, 2, 0xAC, 2, 0xD7, 3, 0xFF
+};
+
+const uint8_t Game::_monsterListLevel5_1[] = {
+ 0xB0, 3, 0xD7, 3, 0xFF
+};
+
+const uint8_t Game::_monsterListLevel5_2[] = {
+ 0xB0, 3, 0xD7, 3, 0xD8, 3, 0xFF
+};
+
+const uint8_t *Game::_monsterListLevels[] = {
+ _monsterListLevel1,
+ _monsterListLevel2,
+ _monsterListLevel3,
+ _monsterListLevel4_1,
+ _monsterListLevel4_2,
+ _monsterListLevel5_1,
+ _monsterListLevel5_2
+};
+
+const uint8_t Game::_monsterPals[4][32] = {
+ { // junkie
+ 0x00, 0x00, 0xAA, 0x0A, 0x65, 0x0A, 0x44, 0x08, 0x22, 0x06, 0x20, 0x03, 0x40, 0x05, 0x87, 0x0C,
+ 0x76, 0x0B, 0x34, 0x03, 0x55, 0x09, 0x30, 0x04, 0x60, 0x07, 0x55, 0x04, 0x77, 0x07, 0xFF, 0x0F
+ },
+ { // mercenaire
+ 0x00, 0x00, 0x86, 0x0C, 0x66, 0x09, 0x44, 0x08, 0xFC, 0x05, 0xA2, 0x02, 0x49, 0x05, 0x02, 0x00,
+ 0x14, 0x02, 0x37, 0x04, 0x25, 0x03, 0x38, 0x06, 0xAF, 0x0C, 0x6F, 0x09, 0x4C, 0x07, 0xFF, 0x0F
+ },
+ { // replicant
+ 0x00, 0x00, 0x79, 0x08, 0x44, 0x05, 0x55, 0x06, 0x66, 0x0B, 0x46, 0x05, 0x57, 0x06, 0x22, 0x03,
+ 0x44, 0x08, 0x33, 0x04, 0xAC, 0x08, 0x8A, 0x06, 0x68, 0x04, 0x56, 0x02, 0x35, 0x02, 0xCE, 0x0A
+ },
+ { // glue
+ 0x00, 0x00, 0x6C, 0x00, 0x39, 0x02, 0x4C, 0x02, 0x27, 0x02, 0x10, 0x07, 0x15, 0x01, 0x00, 0x04,
+ 0x10, 0x05, 0x20, 0x08, 0x00, 0x02, 0x30, 0x09, 0x55, 0x0B, 0xFF, 0x0F, 0x33, 0x0A, 0xFF, 0x0F
+ }
+};
+
+const char *Game::_monsterNames[2][4] = {
+ { // PC
+ "junky",
+ "mercenai",
+ "replican",
+ "glue"
+ },
+ { // Amiga
+ "junky",
+ "garde",
+ "replicant",
+ "glue"
+ }
+};
+
+const uint8_t LocaleData::_stringsTableFR[] = {
+ 0x5A, 0x00, 0x71, 0x00, 0x90, 0x00, 0x97, 0x01, 0x58, 0x02, 0x7B, 0x02, 0xC5, 0x02, 0xEA, 0x02,
+ 0x50, 0x03, 0x6C, 0x03, 0xA8, 0x03, 0xF7, 0x03, 0x46, 0x04, 0x98, 0x04, 0x1C, 0x05, 0x57, 0x05,
+ 0x69, 0x05, 0xE1, 0x05, 0xF4, 0x05, 0x19, 0x06, 0xB5, 0x06, 0x9C, 0x08, 0x11, 0x09, 0x2B, 0x09,
+ 0x8D, 0x09, 0xA6, 0x09, 0xB9, 0x09, 0xDC, 0x09, 0xEF, 0x09, 0x13, 0x0A, 0x15, 0x0A, 0x17, 0x0A,
+ 0x7F, 0x0A, 0x90, 0x0A, 0x21, 0x0B, 0x4A, 0x0B, 0x08, 0x0C, 0x20, 0x0C, 0x44, 0x0C, 0x77, 0x0C,
+ 0x0E, 0x0D, 0x55, 0x0D, 0x93, 0x0D, 0xBB, 0x0D, 0xF5, 0x0D, 0x4C, 0x45, 0x20, 0x46, 0x55, 0x53,
+ 0x49, 0x42, 0x4C, 0x45, 0x20, 0x45, 0x53, 0x54, 0x0A, 0x47, 0x52, 0x49, 0x4C, 0x4C, 0x45, 0x2E,
+ 0x00, 0x4D, 0x41, 0x49, 0x4E, 0x54, 0x45, 0x4E, 0x41, 0x4E, 0x54, 0x20, 0x43, 0x41, 0x0A, 0x44,
+ 0x4F, 0x49, 0x54, 0x20, 0x46, 0x4F, 0x4E, 0x43, 0x54, 0x49, 0x4F, 0x4E, 0x4E, 0x45, 0x52, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x4A, 0x27, 0x53, 0x55, 0x49, 0x53, 0x20, 0x4A, 0x41, 0x43, 0x4B, 0x2E, 0x0A,
+ 0x54, 0x55, 0x20, 0x56, 0x45, 0x55, 0x58, 0x20, 0x44, 0x45, 0x53, 0x20, 0x46, 0x41, 0x55, 0x58,
+ 0x0A, 0x50, 0x41, 0x50, 0x49, 0x45, 0x52, 0x53, 0x3F, 0x0B, 0xFF, 0xE9, 0xEA, 0x4F, 0x55, 0x49,
+ 0x2C, 0x45, 0x54, 0x20, 0x4C, 0x45, 0x20, 0x50, 0x4C, 0x55, 0x53, 0x0A, 0x56, 0x49, 0x54, 0x45,
+ 0x20, 0x50, 0x4F, 0x53, 0x53, 0x49, 0x42, 0x4C, 0x45, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x31, 0x35,
+ 0x30, 0x30, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x53, 0x21, 0x0B, 0xFF, 0xE9, 0xEA, 0x31,
+ 0x35, 0x30, 0x30, 0x3F, 0x3F, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x4F, 0x55, 0x41, 0x49, 0x53, 0x2C,
+ 0x4A, 0x27, 0x50, 0x52, 0x45, 0x4E, 0x44, 0x53, 0x0A, 0x55, 0x4E, 0x20, 0x47, 0x52, 0x4F, 0x53,
+ 0x20, 0x52, 0x49, 0x53, 0x51, 0x55, 0x45, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x4D, 0x41, 0x49, 0x53,
+ 0x20, 0x4A, 0x45, 0x20, 0x4E, 0x27, 0x41, 0x49, 0x20, 0x50, 0x41, 0x53, 0x0A, 0x41, 0x53, 0x53,
+ 0x45, 0x5A, 0x2E, 0x2E, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x56, 0x41, 0x20, 0x41, 0x20, 0x4C, 0x27,
+ 0x41, 0x47, 0x45, 0x4E, 0x43, 0x45, 0x0A, 0x50, 0x4F, 0x55, 0x52, 0x20, 0x4C, 0x27, 0x45, 0x4D,
+ 0x50, 0x4C, 0x4F, 0x49, 0x20, 0x45, 0x54, 0x0A, 0x54, 0x55, 0x20, 0x41, 0x55, 0x52, 0x41, 0x53,
+ 0x20, 0x55, 0x4E, 0x20, 0x4A, 0x4F, 0x42, 0x2E, 0x0B, 0x45, 0x54, 0x20, 0x52, 0x45, 0x56, 0x49,
+ 0x45, 0x4E, 0x53, 0x20, 0x4D, 0x45, 0x0A, 0x56, 0x4F, 0x49, 0x52, 0x20, 0x51, 0x55, 0x41, 0x4E,
+ 0x44, 0x20, 0x54, 0x55, 0x0A, 0x41, 0x55, 0x52, 0x41, 0x53, 0x20, 0x44, 0x45, 0x0A, 0x4C, 0x27,
+ 0x41, 0x52, 0x47, 0x45, 0x4E, 0x54, 0x00, 0xFF, 0xEB, 0xEC, 0x4A, 0x27, 0x43, 0x4F, 0x4E, 0x4E,
+ 0x41, 0x49, 0x53, 0x20, 0x43, 0x45, 0x0A, 0x47, 0x41, 0x52, 0x53, 0x20, 0x4C, 0x41, 0x2E, 0x20,
+ 0x49, 0x4C, 0x20, 0x41, 0x0A, 0x55, 0x4E, 0x20, 0x41, 0x4D, 0x49, 0x20, 0x51, 0x55, 0x49, 0x20,
+ 0x45, 0x53, 0x54, 0x0A, 0x55, 0x4E, 0x20, 0x52, 0x4F, 0x42, 0x4F, 0x54, 0x2D, 0x46, 0x4C, 0x49,
+ 0x43, 0x2E, 0x0B, 0x4F, 0x55, 0x20, 0x50, 0x55, 0x49, 0x53, 0x2D, 0x4A, 0x45, 0x0A, 0x54, 0x52,
+ 0x4F, 0x55, 0x56, 0x45, 0x52, 0x20, 0x43, 0x45, 0x54, 0x20, 0x41, 0x4D, 0x49, 0x3F, 0x0B, 0x56,
+ 0x41, 0x20, 0x56, 0x4F, 0x49, 0x52, 0x20, 0x41, 0x20, 0x4C, 0x41, 0x0A, 0x52, 0x45, 0x53, 0x54,
+ 0x52, 0x49, 0x43, 0x54, 0x45, 0x44, 0x20, 0x41, 0x52, 0x45, 0x41, 0x0A, 0x31, 0x2E, 0x4A, 0x45,
+ 0x20, 0x43, 0x52, 0x4F, 0x49, 0x53, 0x20, 0x51, 0x55, 0x27, 0x49, 0x4C, 0x0A, 0x45, 0x53, 0x54,
+ 0x20, 0x44, 0x45, 0x20, 0x47, 0x41, 0x52, 0x44, 0x45, 0x0B, 0x4D, 0x41, 0x49, 0x53, 0x20, 0x46,
+ 0x41, 0x49, 0x53, 0x20, 0x47, 0x41, 0x46, 0x46, 0x45, 0x0A, 0x43, 0x45, 0x53, 0x20, 0x54, 0x59,
+ 0x50, 0x45, 0x53, 0x2D, 0x4C, 0x41, 0x20, 0x0A, 0x53, 0x4F, 0x4E, 0x54, 0x20, 0x44, 0x41, 0x4E,
+ 0x47, 0x45, 0x55, 0x52, 0x45, 0x55, 0x58, 0x00, 0xFF, 0xEB, 0xEC, 0x4A, 0x45, 0x20, 0x4E, 0x45,
+ 0x20, 0x53, 0x41, 0x49, 0x53, 0x20, 0x52, 0x49, 0x45, 0x4E, 0x0A, 0x44, 0x45, 0x20, 0x50, 0x4C,
+ 0x55, 0x53, 0x2C, 0x20, 0x47, 0x41, 0x4D, 0x49, 0x4E, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x43, 0x59,
+ 0x2D, 0x42, 0x30, 0x32, 0x31, 0x20, 0x56, 0x45, 0x55, 0x54, 0x0A, 0x50, 0x41, 0x53, 0x53, 0x45,
+ 0x52, 0x20, 0x55, 0x4E, 0x20, 0x4D, 0x41, 0x52, 0x43, 0x48, 0x45, 0x0A, 0x41, 0x56, 0x45, 0x43,
+ 0x20, 0x54, 0x4F, 0x49, 0x2E, 0x0B, 0x49, 0x4C, 0x20, 0x54, 0x27, 0x41, 0x54, 0x54, 0x45, 0x4E,
+ 0x44, 0x52, 0x41, 0x0A, 0x44, 0x45, 0x52, 0x52, 0x49, 0x45, 0x52, 0x45, 0x20, 0x4C, 0x45, 0x20,
+ 0x42, 0x41, 0x52, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x56, 0x41, 0x20, 0x41, 0x55, 0x20, 0x42, 0x41,
+ 0x52, 0x2C, 0x20, 0x50, 0x45, 0x54, 0x49, 0x54, 0x0A, 0x43, 0x59, 0x2D, 0x42, 0x30, 0x32, 0x31,
+ 0x20, 0x54, 0x27, 0x41, 0x54, 0x54, 0x45, 0x4E, 0x44, 0x00, 0xFF, 0xEB, 0xEC, 0x4E, 0x45, 0x20,
+ 0x54, 0x49, 0x52, 0x45, 0x20, 0x50, 0x41, 0x53, 0x2E, 0x0A, 0x4A, 0x27, 0x53, 0x55, 0x49, 0x53,
+ 0x20, 0x50, 0x41, 0x53, 0x0A, 0x43, 0x59, 0x2D, 0x42, 0x30, 0x32, 0x31, 0x2E, 0x0B, 0x53, 0x41,
+ 0x20, 0x50, 0x4C, 0x41, 0x4E, 0x51, 0x55, 0x45, 0x20, 0x45, 0x53, 0x54, 0x0A, 0x45, 0x4E, 0x20,
+ 0x44, 0x45, 0x53, 0x53, 0x4F, 0x55, 0x53, 0x0B, 0x43, 0x27, 0x45, 0x53, 0x54, 0x20, 0x53, 0x4F,
+ 0x4E, 0x20, 0x43, 0x4F, 0x50, 0x41, 0x49, 0x4E, 0x0A, 0x4C, 0x45, 0x20, 0x46, 0x4C, 0x49, 0x43,
+ 0x2C, 0x20, 0x51, 0x55, 0x49, 0x20, 0x41, 0x0A, 0x4C, 0x41, 0x20, 0x43, 0x4C, 0x45, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x4A, 0x45, 0x20, 0x4E, 0x45, 0x20, 0x53, 0x41, 0x49, 0x53, 0x20, 0x52, 0x49,
+ 0x45, 0x4E, 0x0A, 0x44, 0x45, 0x20, 0x50, 0x4C, 0x55, 0x53, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x4D,
+ 0x4F, 0x4E, 0x53, 0x49, 0x45, 0x55, 0x52, 0x2E, 0x2E, 0x2E, 0x0A, 0x55, 0x4E, 0x20, 0x44, 0x45,
+ 0x4E, 0x4F, 0x4D, 0x4D, 0x45, 0x20, 0x4A, 0x41, 0x43, 0x4B, 0x0A, 0x56, 0x4F, 0x55, 0x53, 0x20,
+ 0x44, 0x4F, 0x4E, 0x4E, 0x45, 0x20, 0x52, 0x2E, 0x44, 0x2E, 0x56, 0x0A, 0x50, 0x52, 0x45, 0x53,
+ 0x20, 0x44, 0x55, 0x20, 0x42, 0x41, 0x52, 0x00, 0x4A, 0x45, 0x20, 0x56, 0x4F, 0x55, 0x44, 0x52,
+ 0x41, 0x49, 0x53, 0x20, 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53, 0x20, 0x44, 0x45,
+ 0x0A, 0x54, 0x52, 0x41, 0x56, 0x41, 0x49, 0x4C, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x41, 0x48, 0x20,
+ 0x4E, 0x4F, 0x4E, 0x2E, 0x43, 0x27, 0x45, 0x53, 0x54, 0x20, 0x50, 0x41, 0x53, 0x0A, 0x49, 0x43,
+ 0x49, 0x2E, 0x20, 0x56, 0x4F, 0x59, 0x45, 0x5A, 0x20, 0x4C, 0x45, 0x0A, 0x47, 0x55, 0x49, 0x43,
+ 0x48, 0x45, 0x54, 0x20, 0x43, 0x2E, 0x00, 0x4A, 0x45, 0x20, 0x56, 0x4F, 0x55, 0x44, 0x52, 0x41,
+ 0x49, 0x53, 0x20, 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53, 0x20, 0x64, 0x65, 0x0A,
+ 0x54, 0x52, 0x41, 0x56, 0x41, 0x49, 0x4C, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x42, 0x4F, 0x4E, 0x2E,
+ 0x2E, 0x2E, 0x20, 0x4F, 0x4B, 0x2C, 0x4C, 0x45, 0x0A, 0x47, 0x4F, 0x55, 0x56, 0x45, 0x52, 0x4E,
+ 0x45, 0x55, 0x52, 0x20, 0x56, 0x41, 0x0A, 0x56, 0x4F, 0x55, 0x53, 0x20, 0x52, 0x45, 0x43, 0x45,
+ 0x56, 0x4F, 0x49, 0x52, 0x2E, 0x00, 0x4A, 0x45, 0x20, 0x56, 0x4F, 0x55, 0x44, 0x52, 0x41, 0x49,
+ 0x53, 0x20, 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53, 0x20, 0x44, 0x45, 0x0A, 0x54,
+ 0x52, 0x41, 0x56, 0x41, 0x49, 0x4C, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x41, 0x48, 0x20, 0x4E, 0x4F,
+ 0x4E, 0x2E, 0x43, 0x45, 0x20, 0x4E, 0x27, 0x45, 0x53, 0x54, 0x0A, 0x50, 0x41, 0x53, 0x20, 0x49,
+ 0x43, 0x49, 0x2E, 0x20, 0x56, 0x4F, 0x59, 0x45, 0x5A, 0x0A, 0x4C, 0x45, 0x20, 0x47, 0x55, 0x49,
+ 0x43, 0x48, 0x45, 0x54, 0x20, 0x42, 0x2E, 0x00, 0x4A, 0x45, 0x20, 0x56, 0x4F, 0x55, 0x44, 0x52,
+ 0x41, 0x49, 0x53, 0x0A, 0x50, 0x41, 0x52, 0x4C, 0x45, 0x52, 0x20, 0x41, 0x20, 0x4A, 0x41, 0x43,
+ 0x4B, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x41, 0x48, 0x20, 0x4F, 0x55, 0x41, 0x49, 0x53, 0x3F, 0x20,
+ 0x4A, 0x41, 0x43, 0x4B, 0x0A, 0x4E, 0x27, 0x45, 0x53, 0x54, 0x20, 0x50, 0x41, 0x53, 0x20, 0x4C,
+ 0x41, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x48, 0x55, 0x4D, 0x2E, 0x2E, 0x2E, 0x4A, 0x45, 0x20, 0x56,
+ 0x49, 0x45, 0x4E, 0x53, 0x0A, 0x44, 0x45, 0x20, 0x4C, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x20,
+ 0x44, 0x45, 0x0A, 0x4D, 0x4F, 0x4E, 0x20, 0x41, 0x4D, 0x49, 0x20, 0x49, 0x41, 0x4E, 0x2E, 0x0B,
+ 0xFF, 0xEB, 0xEC, 0x4F, 0x4B, 0x2E, 0x4A, 0x41, 0x43, 0x4B, 0x20, 0x54, 0x27, 0x41, 0x54, 0x54,
+ 0x45, 0x4E, 0x44, 0x0A, 0x44, 0x45, 0x48, 0x4F, 0x52, 0x53, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x50,
+ 0x41, 0x53, 0x53, 0x45, 0x20, 0x54, 0x4F, 0x4E, 0x20, 0x43, 0x48, 0x45, 0x4D, 0x49, 0x4E, 0x0A,
+ 0x47, 0x41, 0x4D, 0x49, 0x4E, 0x2E, 0x20, 0x54, 0x27, 0x45, 0x53, 0x20, 0x54, 0x52, 0x4F, 0x50,
+ 0x0A, 0x4A, 0x45, 0x55, 0x4E, 0x45, 0x20, 0x50, 0x4F, 0x55, 0x52, 0x0A, 0x43, 0x4F, 0x4E, 0x53,
+ 0x4F, 0x4D, 0x4D, 0x45, 0x52, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x50, 0x41, 0x50, 0x49, 0x45, 0x52,
+ 0x53, 0x20, 0x53, 0x2E, 0x56, 0x2E, 0x50, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x4A, 0x45, 0x20, 0x53,
+ 0x55, 0x49, 0x53, 0x20, 0x4C, 0x45, 0x0A, 0x43, 0x4F, 0x55, 0x52, 0x53, 0x49, 0x45, 0x52, 0x2E,
+ 0x0B, 0xFF, 0xEB, 0xEC, 0x41, 0x48, 0x20, 0x4F, 0x55, 0x49, 0x21, 0x56, 0x4F, 0x49, 0x4C, 0x41,
+ 0x2C, 0x0A, 0x41, 0x4D, 0x45, 0x4E, 0x45, 0x5A, 0x20, 0x43, 0x45, 0x20, 0x50, 0x41, 0x51, 0x55,
+ 0x45, 0x54, 0x0A, 0x41, 0x20, 0x4C, 0x27, 0x41, 0x47, 0x45, 0x4E, 0x43, 0x45, 0x20, 0x44, 0x45,
+ 0x0A, 0x56, 0x4F, 0x59, 0x41, 0x47, 0x45, 0x2E, 0x0B, 0x45, 0x54, 0x20, 0x46, 0x41, 0x49, 0x54,
+ 0x45, 0x53, 0x0A, 0x41, 0x54, 0x54, 0x45, 0x4E, 0x54, 0x49, 0x4F, 0x4E, 0x2C, 0x20, 0x43, 0x41,
+ 0x0A, 0x41, 0x20, 0x44, 0x45, 0x20, 0x4C, 0x41, 0x20, 0x56, 0x41, 0x4C, 0x45, 0x55, 0x52, 0x2E,
+ 0x00, 0x4C, 0x45, 0x20, 0x54, 0x45, 0x4D, 0x50, 0x20, 0x45, 0x53, 0x54, 0x0A, 0x45, 0x43, 0x4F,
+ 0x55, 0x4C, 0x45, 0x00, 0x49, 0x4C, 0x20, 0x59, 0x20, 0x41, 0x20, 0x55, 0x4E, 0x0A, 0x45, 0x4D,
+ 0x50, 0x4C, 0x41, 0x43, 0x45, 0x4D, 0x45, 0x4E, 0x54, 0x20, 0x50, 0x4F, 0x55, 0x52, 0x0A, 0x4C,
+ 0x41, 0x20, 0x43, 0x41, 0x52, 0x54, 0x45, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x4D, 0x45, 0x52, 0x43,
+ 0x49, 0x20, 0x43, 0x4F, 0x4E, 0x52, 0x41, 0x44, 0x2E, 0x0A, 0x43, 0x45, 0x53, 0x20, 0x46, 0x4C,
+ 0x49, 0x43, 0x53, 0x0A, 0x4D, 0x27, 0x41, 0x55, 0x52, 0x41, 0x49, 0x45, 0x4E, 0x54, 0x20, 0x46,
+ 0x41, 0x49, 0x54, 0x0A, 0x4C, 0x41, 0x20, 0x50, 0x45, 0x41, 0x55, 0x0B, 0x42, 0x4F, 0x4E, 0x2C,
+ 0x4A, 0x45, 0x20, 0x53, 0x55, 0x50, 0x50, 0x4F, 0x53, 0x45, 0x0A, 0x51, 0x55, 0x45, 0x20, 0x54,
+ 0x55, 0x20, 0x4E, 0x45, 0x20, 0x54, 0x45, 0x0A, 0x52, 0x41, 0x50, 0x45, 0x4C, 0x4C, 0x45, 0x53,
+ 0x20, 0x50, 0x41, 0x53, 0x20, 0x44, 0x45, 0x0A, 0x54, 0x4F, 0x4E, 0x20, 0x41, 0x4D, 0x49, 0x20,
+ 0x49, 0x41, 0x4E, 0x2E, 0x0B, 0x41, 0x4C, 0x4C, 0x45, 0x5A, 0x2C, 0x41, 0x53, 0x53, 0x49, 0x45,
+ 0x44, 0x53, 0x0A, 0x54, 0x4F, 0x49, 0x20, 0x53, 0x55, 0x52, 0x20, 0x43, 0x45, 0x0A, 0x53, 0x49,
+ 0x45, 0x47, 0x45, 0x2C, 0x4F, 0x4E, 0x20, 0x56, 0x41, 0x20, 0x59, 0x0A, 0x52, 0x45, 0x4D, 0x45,
+ 0x44, 0x49, 0x45, 0x52, 0x00, 0x49, 0x41, 0x4E, 0x2C, 0x43, 0x4F, 0x4D, 0x4D, 0x45, 0x4E, 0x54,
+ 0x0A, 0x46, 0x41, 0x49, 0x52, 0x45, 0x20, 0x50, 0x4F, 0x55, 0x52, 0x0A, 0x41, 0x4C, 0x4C, 0x45,
+ 0x52, 0x20, 0x53, 0x55, 0x52, 0x20, 0x54, 0x45, 0x52, 0x52, 0x45, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x4C, 0x45, 0x20, 0x56, 0x4F, 0x59, 0x41, 0x47, 0x45, 0x20, 0x45, 0x53, 0x54, 0x0A, 0x48, 0x4F,
+ 0x52, 0x53, 0x20, 0x44, 0x45, 0x20, 0x50, 0x52, 0x49, 0x58, 0x2E, 0x0B, 0x4C, 0x45, 0x20, 0x53,
+ 0x45, 0x55, 0x4C, 0x20, 0x4D, 0x4F, 0x59, 0x45, 0x4E, 0x0A, 0x53, 0x45, 0x52, 0x41, 0x49, 0x54,
+ 0x20, 0x51, 0x55, 0x45, 0x20, 0x54, 0x55, 0x0A, 0x50, 0x41, 0x52, 0x54, 0x49, 0x43, 0x49, 0x50,
+ 0x45, 0x53, 0x20, 0x41, 0x55, 0x0A, 0x44, 0x45, 0x41, 0x54, 0x48, 0x20, 0x54, 0x4F, 0x57, 0x45,
+ 0x52, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x44, 0x45, 0x41, 0x54, 0x48, 0x20, 0x54, 0x4F, 0x57, 0x45,
+ 0x52, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x4F, 0x55, 0x49, 0x2C, 0x43, 0x27, 0x45, 0x53, 0x54, 0x20,
+ 0x55, 0x4E, 0x20, 0x4A, 0x45, 0x55, 0x0A, 0x54, 0x45, 0x4C, 0x45, 0x56, 0x49, 0x53, 0x45, 0x2E,
+ 0x4C, 0x45, 0x0A, 0x47, 0x41, 0x47, 0x4E, 0x41, 0x4E, 0x54, 0x20, 0x52, 0x45, 0x43, 0x4F, 0x49,
+ 0x54, 0x0A, 0x55, 0x4E, 0x20, 0x42, 0x49, 0x4C, 0x4C, 0x45, 0x54, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA,
+ 0x4F, 0x4B, 0x2E, 0x49, 0x4C, 0x20, 0x4D, 0x45, 0x20, 0x46, 0x41, 0x55, 0x54, 0x0A, 0x41, 0x55,
+ 0x53, 0x53, 0x49, 0x20, 0x44, 0x45, 0x53, 0x20, 0x46, 0x41, 0x55, 0x58, 0x0A, 0x50, 0x41, 0x50,
+ 0x49, 0x45, 0x52, 0x53, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x4F, 0x20, 0x50, 0x52, 0x4F, 0x42,
+ 0x4C, 0x45, 0x4D, 0x4F, 0x2C, 0x0A, 0x56, 0x41, 0x20, 0x41, 0x55, 0x20, 0x42, 0x41, 0x52, 0x2C,
+ 0x20, 0x45, 0x54, 0x0A, 0x44, 0x45, 0x4D, 0x41, 0x4E, 0x44, 0x45, 0x20, 0x4A, 0x41, 0x43, 0x4B,
+ 0x0A, 0x44, 0x45, 0x20, 0x4D, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x2E, 0x0B, 0x41, 0x48, 0x2C,
+ 0x41, 0x55, 0x20, 0x46, 0x41, 0x49, 0x54, 0x2C, 0x4A, 0x45, 0x0A, 0x54, 0x27, 0x41, 0x49, 0x20,
+ 0x4D, 0x49, 0x53, 0x20, 0x44, 0x41, 0x4E, 0x53, 0x20, 0x4C, 0x41, 0x0A, 0x50, 0x4F, 0x43, 0x48,
+ 0x45, 0x20, 0x4C, 0x45, 0x20, 0x43, 0x48, 0x41, 0x4D, 0x50, 0x0A, 0x44, 0x45, 0x20, 0x50, 0x52,
+ 0x4F, 0x54, 0x45, 0x43, 0x54, 0x49, 0x4F, 0x4E, 0x0B, 0x51, 0x55, 0x45, 0x20, 0x54, 0x55, 0x20,
+ 0x4D, 0x27, 0x41, 0x56, 0x41, 0x49, 0x53, 0x0A, 0x43, 0x4F, 0x4D, 0x4D, 0x41, 0x4E, 0x44, 0x45,
+ 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x50, 0x41, 0x52, 0x46, 0x41, 0x49, 0x54, 0x2E, 0x4A, 0x45, 0x20,
+ 0x54, 0x45, 0x0A, 0x52, 0x45, 0x4D, 0x45, 0x52, 0x43, 0x49, 0x45, 0x2E, 0x20, 0x41, 0x20, 0x4C,
+ 0x41, 0x0A, 0x50, 0x52, 0x4F, 0x43, 0x48, 0x41, 0x49, 0x4E, 0x45, 0x2C, 0x20, 0x49, 0x41, 0x4E,
+ 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x42, 0x4F, 0x4E, 0x4E, 0x45, 0x20, 0x43, 0x48, 0x41, 0x4E, 0x43,
+ 0x45, 0x2E, 0x4A, 0x45, 0x0A, 0x54, 0x45, 0x20, 0x43, 0x4F, 0x4E, 0x54, 0x41, 0x43, 0x54, 0x45,
+ 0x52, 0x41, 0x49, 0x0A, 0x41, 0x20, 0x54, 0x4F, 0x4E, 0x20, 0x41, 0x52, 0x52, 0x49, 0x56, 0x45,
+ 0x20, 0x53, 0x55, 0x52, 0x0A, 0x54, 0x45, 0x52, 0x52, 0x45, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x42,
+ 0x49, 0x45, 0x4E, 0x56, 0x45, 0x4E, 0x55, 0x45, 0x20, 0x41, 0x0A, 0x4E, 0x45, 0x57, 0x20, 0x57,
+ 0x41, 0x53, 0x48, 0x49, 0x4E, 0x47, 0x54, 0x4F, 0x4E, 0x2C, 0x0A, 0x4A, 0x45, 0x55, 0x4E, 0x45,
+ 0x20, 0x48, 0x4F, 0x4D, 0x4D, 0x45, 0x2E, 0x0B, 0x56, 0x4F, 0x49, 0x43, 0x49, 0x20, 0x55, 0x4E,
+ 0x20, 0x50, 0x4C, 0x41, 0x4E, 0x0A, 0x44, 0x45, 0x20, 0x4C, 0x41, 0x20, 0x56, 0x49, 0x4C, 0x4C,
+ 0x45, 0x2C, 0x20, 0x49, 0x4C, 0x0A, 0x50, 0x4F, 0x55, 0x52, 0x52, 0x41, 0x20, 0x56, 0x4F, 0x55,
+ 0x53, 0x20, 0x45, 0x54, 0x52, 0x45, 0x0A, 0x55, 0x54, 0x49, 0x4C, 0x45, 0x2E, 0x0B, 0xFF, 0xE9,
+ 0xEA, 0x4D, 0x45, 0x52, 0x43, 0x49, 0x2C, 0x4D, 0x4F, 0x4E, 0x53, 0x49, 0x45, 0x55, 0x52, 0x2E,
+ 0x00, 0xFF, 0xEB, 0xEC, 0x42, 0x4F, 0x4E, 0x20, 0x53, 0x45, 0x4A, 0x4F, 0x55, 0x52, 0x2C, 0x50,
+ 0x41, 0x52, 0x4D, 0x49, 0x0A, 0x4E, 0x4F, 0x55, 0x53, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x50, 0x4F,
+ 0x55, 0x52, 0x20, 0x54, 0x52, 0x41, 0x56, 0x41, 0x49, 0x4C, 0x4C, 0x45, 0x52, 0x0A, 0x49, 0x4C,
+ 0x20, 0x56, 0x4F, 0x55, 0x53, 0x20, 0x46, 0x41, 0x55, 0x54, 0x20, 0x55, 0x4E, 0x0A, 0x50, 0x45,
+ 0x52, 0x4D, 0x49, 0x53, 0x2E, 0x0B, 0x56, 0x4F, 0x55, 0x53, 0x20, 0x50, 0x4F, 0x55, 0x52, 0x52,
+ 0x45, 0x5A, 0x20, 0x45, 0x4E, 0x0A, 0x4F, 0x42, 0x54, 0x45, 0x4E, 0x49, 0x52, 0x20, 0x55, 0x4E,
+ 0x20, 0x41, 0x55, 0x0A, 0x43, 0x45, 0x4E, 0x54, 0x52, 0x45, 0x20, 0x41, 0x44, 0x4D, 0x49, 0x4E,
+ 0x49, 0x53, 0x2D, 0x0A, 0x2D, 0x54, 0x52, 0x41, 0x54, 0x49, 0x46, 0x2E, 0x00, 0xFF, 0xEB, 0xEC,
+ 0x4A, 0x45, 0x20, 0x4E, 0x27, 0x41, 0x49, 0x20, 0x50, 0x41, 0x53, 0x20, 0x4C, 0x45, 0x0A, 0x54,
+ 0x45, 0x4D, 0x50, 0x53, 0x2E, 0x00, 0x42, 0x4F, 0x4E, 0x4A, 0x4F, 0x55, 0x52, 0x20, 0x43, 0x48,
+ 0x45, 0x5A, 0x0A, 0x56, 0x4F, 0x55, 0x53, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x4A, 0x27, 0x41, 0x49,
+ 0x20, 0x44, 0x45, 0x4A, 0x41, 0x20, 0x56, 0x55, 0x0A, 0x43, 0x45, 0x20, 0x54, 0x59, 0x50, 0x45,
+ 0x20, 0x4C, 0x41, 0x20, 0x41, 0x55, 0x0A, 0x42, 0x41, 0x52, 0x2E, 0x00, 0x42, 0x4F, 0x4E, 0x4A,
+ 0x4F, 0x55, 0x52, 0x20, 0x43, 0x48, 0x45, 0x5A, 0x0A, 0x56, 0x4F, 0x55, 0x53, 0x2E, 0x00, 0x4F,
+ 0x55, 0x49, 0x2C, 0x4A, 0x45, 0x20, 0x4C, 0x45, 0x0A, 0x43, 0x4F, 0x4E, 0x4E, 0x41, 0x49, 0x53,
+ 0x2E, 0x43, 0x27, 0x45, 0x53, 0x54, 0x20, 0x55, 0x4E, 0x0A, 0x48, 0x41, 0x42, 0x49, 0x54, 0x55,
+ 0x45, 0x2E, 0x00, 0x20, 0x00, 0x20, 0x00, 0x4A, 0x45, 0x20, 0x56, 0x4F, 0x55, 0x44, 0x52, 0x41,
+ 0x49, 0x53, 0x20, 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53, 0x20, 0x44, 0x45, 0x0A,
+ 0x54, 0x52, 0x41, 0x56, 0x41, 0x49, 0x4C, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x50, 0x41, 0x53, 0x20,
+ 0x44, 0x45, 0x20, 0x50, 0x52, 0x4F, 0x42, 0x4C, 0x45, 0x4D, 0x45, 0x0A, 0x50, 0x4F, 0x55, 0x52,
+ 0x20, 0x41, 0x56, 0x4F, 0x49, 0x52, 0x20, 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53,
+ 0x2E, 0x2E, 0x2E, 0x0B, 0x49, 0x4C, 0x20, 0x4D, 0x45, 0x20, 0x46, 0x41, 0x55, 0x54, 0x0A, 0x56,
+ 0x4F, 0x54, 0x52, 0x45, 0x20, 0x43, 0x41, 0x52, 0x54, 0x45, 0x20, 0x49, 0x44, 0x2E, 0x00, 0xFF,
+ 0xEB, 0xEC, 0x41, 0x55, 0x20, 0x53, 0x45, 0x43, 0x4F, 0x55, 0x52, 0x53, 0x2E, 0x2E, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x41, 0x49, 0x44, 0x45, 0x5A, 0x20, 0x4D, 0x4F, 0x49, 0x2C, 0x4A, 0x45, 0x55,
+ 0x4E, 0x45, 0x0A, 0x48, 0x4F, 0x4D, 0x4D, 0x45, 0x2E, 0x4A, 0x27, 0x41, 0x49, 0x20, 0x45, 0x54,
+ 0x45, 0x0A, 0x41, 0x54, 0x54, 0x41, 0x51, 0x55, 0x45, 0x20, 0x50, 0x41, 0x52, 0x20, 0x44, 0x45,
+ 0x53, 0x0A, 0x4D, 0x55, 0x54, 0x41, 0x4E, 0x54, 0x53, 0x2E, 0x2E, 0x2E, 0x0B, 0x45, 0x54, 0x20,
+ 0x4A, 0x45, 0x20, 0x4E, 0x45, 0x20, 0x50, 0x45, 0x55, 0x58, 0x0A, 0x50, 0x4C, 0x55, 0x53, 0x20,
+ 0x4D, 0x41, 0x52, 0x43, 0x48, 0x45, 0x52, 0x0B, 0x52, 0x45, 0x54, 0x52, 0x4F, 0x55, 0x56, 0x45,
+ 0x5A, 0x20, 0x4D, 0x4F, 0x4E, 0x0A, 0x54, 0x45, 0x4C, 0x45, 0x50, 0x4F, 0x52, 0x54, 0x45, 0x55,
+ 0x52, 0x2C, 0x0A, 0x49, 0x4C, 0x20, 0x4D, 0x45, 0x20, 0x46, 0x41, 0x55, 0x54, 0x20, 0x44, 0x45,
+ 0x53, 0x0A, 0x53, 0x4F, 0x49, 0x4E, 0x53, 0x20, 0x55, 0x52, 0x47, 0x45, 0x4E, 0x54, 0x53, 0x2E,
+ 0x00, 0xFF, 0xEB, 0xEC, 0x4D, 0x45, 0x52, 0x43, 0x49, 0x2E, 0x56, 0x4F, 0x55, 0x53, 0x20, 0x56,
+ 0x45, 0x4E, 0x45, 0x5A, 0x0A, 0x44, 0x45, 0x20, 0x4D, 0x45, 0x20, 0x53, 0x41, 0x55, 0x56, 0x45,
+ 0x52, 0x20, 0x4C, 0x41, 0x0A, 0x56, 0x49, 0x45, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x50, 0x4F, 0x55,
+ 0x52, 0x20, 0x41, 0x4C, 0x4C, 0x45, 0x52, 0x20, 0x41, 0x20, 0x4E, 0x45, 0x57, 0x0A, 0x57, 0x41,
+ 0x53, 0x48, 0x49, 0x4E, 0x47, 0x54, 0x4F, 0x4E, 0x2C, 0x54, 0x55, 0x0A, 0x44, 0x4F, 0x49, 0x53,
+ 0x20, 0x53, 0x41, 0x55, 0x54, 0x45, 0x52, 0x20, 0x44, 0x41, 0x4E, 0x53, 0x0A, 0x43, 0x45, 0x20,
+ 0x47, 0x52, 0x41, 0x4E, 0x44, 0x20, 0x54, 0x52, 0x4F, 0x55, 0x0B, 0x4D, 0x41, 0x49, 0x53, 0x20,
+ 0x41, 0x20, 0x54, 0x41, 0x20, 0x50, 0x4C, 0x41, 0x43, 0x45, 0x0A, 0x4A, 0x27, 0x55, 0x54, 0x49,
+ 0x4C, 0x49, 0x53, 0x45, 0x52, 0x41, 0x49, 0x53, 0x0A, 0x55, 0x4E, 0x45, 0x20, 0x43, 0x45, 0x49,
+ 0x4E, 0x54, 0x55, 0x52, 0x45, 0x0A, 0x41, 0x4E, 0x54, 0x49, 0x2D, 0x47, 0x2E, 0x0B, 0xFF, 0xE9,
+ 0xEA, 0x4F, 0x55, 0x20, 0x50, 0x55, 0x49, 0x53, 0x2D, 0x4A, 0x45, 0x20, 0x45, 0x4E, 0x0A, 0x54,
+ 0x52, 0x4F, 0x55, 0x56, 0x45, 0x52, 0x20, 0x55, 0x4E, 0x45, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x48,
+ 0x45, 0x2E, 0x48, 0x45, 0x2E, 0x4A, 0x45, 0x20, 0x50, 0x45, 0x55, 0x58, 0x0A, 0x54, 0x45, 0x20,
+ 0x4C, 0x41, 0x20, 0x56, 0x45, 0x4E, 0x44, 0x52, 0x45, 0x3A, 0x0A, 0x35, 0x30, 0x30, 0x20, 0x43,
+ 0x52, 0x45, 0x44, 0x49, 0x54, 0x53, 0x2E, 0x00, 0x42, 0x4F, 0x4E, 0x20, 0x56, 0x4F, 0x59, 0x41,
+ 0x47, 0x45, 0x2C, 0x4A, 0x45, 0x55, 0x4E, 0x45, 0x0A, 0x48, 0x4F, 0x4D, 0x4D, 0x45, 0x2E, 0x00,
+ 0x49, 0x4C, 0x20, 0x46, 0x41, 0x55, 0x44, 0x52, 0x41, 0x49, 0x54, 0x0A, 0x55, 0x4E, 0x45, 0x20,
+ 0x50, 0x49, 0x4C, 0x45, 0x0A, 0x43, 0x48, 0x41, 0x52, 0x47, 0x45, 0x45, 0x20, 0x41, 0x20, 0x42,
+ 0x4C, 0x4F, 0x43, 0x00, 0x4A, 0x45, 0x20, 0x56, 0x4F, 0x55, 0x44, 0x52, 0x41, 0x49, 0x53, 0x20,
+ 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53, 0x20, 0x44, 0x45, 0x0A, 0x54, 0x52, 0x41,
+ 0x56, 0x41, 0x49, 0x4C, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x50, 0x52, 0x45, 0x4D, 0x49, 0x45, 0x52,
+ 0x20, 0x45, 0x54, 0x41, 0x47, 0x45, 0x00, 0x55, 0x4E, 0x45, 0x20, 0x56, 0x4F, 0x49, 0x58, 0x0A,
+ 0x49, 0x4E, 0x54, 0x45, 0x52, 0x49, 0x45, 0x55, 0x52, 0x45, 0x20, 0x73, 0x65, 0x0A, 0x46, 0x41,
+ 0x49, 0x54, 0x20, 0x45, 0x4E, 0x54, 0x45, 0x4E, 0x44, 0x52, 0x45, 0x3A, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x46, 0x41, 0x49, 0x53, 0x2D, 0x4D, 0x4F, 0x49, 0x0A, 0x43, 0x4F, 0x4E, 0x46, 0x49, 0x41, 0x4E,
+ 0x43, 0x45, 0x2E, 0x50, 0x4F, 0x53, 0x45, 0x0A, 0x4C, 0x41, 0x20, 0x43, 0x48, 0x41, 0x52, 0x47,
+ 0x45, 0x0A, 0x41, 0x54, 0x4F, 0x4D, 0x49, 0x51, 0x55, 0x45, 0x20, 0x49, 0x43, 0x49, 0x2E, 0x2E,
+ 0x2E, 0x0B, 0x45, 0x54, 0x20, 0x46, 0x55, 0x49, 0x53, 0x20, 0x41, 0x56, 0x41, 0x4E, 0x54, 0x0A,
+ 0x51, 0x55, 0x27, 0x45, 0x4C, 0x4C, 0x45, 0x20, 0x4E, 0x27, 0x41, 0x54, 0x2D, 0x0A, 0x2D, 0x54,
+ 0x45, 0x49, 0x47, 0x4E, 0x45, 0x20, 0x4C, 0x45, 0x20, 0x4E, 0x4F, 0x59, 0x41, 0x55, 0x0A, 0x44,
+ 0x45, 0x20, 0x4C, 0x41, 0x20, 0x50, 0x4C, 0x41, 0x4E, 0x45, 0x54, 0x45, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x4A, 0x45, 0x20, 0x56, 0x4F, 0x55, 0x53, 0x20, 0x53, 0x55, 0x49, 0x53, 0x2C, 0x0A, 0x4A,
+ 0x45, 0x55, 0x4E, 0x45, 0x20, 0x48, 0x4F, 0x4D, 0x4D, 0x45, 0x2E, 0x0B, 0x47, 0x55, 0x49, 0x44,
+ 0x45, 0x5A, 0x2D, 0x4D, 0x4F, 0x49, 0x0A, 0x4A, 0x55, 0x53, 0x51, 0x55, 0x27, 0x41, 0x55, 0x20,
+ 0x43, 0x45, 0x4E, 0x54, 0x52, 0x45, 0x0A, 0x44, 0x45, 0x20, 0x52, 0x45, 0x43, 0x48, 0x45, 0x52,
+ 0x43, 0x48, 0x45, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x4D, 0x45, 0x52, 0x43, 0x49, 0x20, 0x44, 0x45,
+ 0x20, 0x56, 0x4F, 0x54, 0x52, 0x45, 0x0A, 0x41, 0x49, 0x44, 0x45, 0x2E, 0x2E, 0x2E, 0x0B, 0x49,
+ 0x4C, 0x20, 0x4E, 0x27, 0x59, 0x20, 0x41, 0x20, 0x50, 0x4C, 0x55, 0x53, 0x0A, 0x44, 0x45, 0x20,
+ 0x44, 0x41, 0x4E, 0x47, 0x45, 0x52, 0x2C, 0x0A, 0x4D, 0x41, 0x49, 0x4E, 0x54, 0x45, 0x4E, 0x41,
+ 0x4E, 0x54, 0x00, 0xFF, 0xEB, 0xEC, 0x41, 0x4C, 0x4F, 0x52, 0x53, 0x2C, 0x4D, 0x27, 0x41, 0x56,
+ 0x45, 0x5A, 0x0A, 0x56, 0x4F, 0x55, 0x53, 0x20, 0x41, 0x50, 0x50, 0x4F, 0x52, 0x54, 0x45, 0x0A,
+ 0x4C, 0x45, 0x20, 0x50, 0x41, 0x51, 0x55, 0x45, 0x54, 0x3F, 0x00, 0x43, 0x4F, 0x4D, 0x42, 0x49,
+ 0x45, 0x4E, 0x20, 0x43, 0x4F, 0x55, 0x54, 0x45, 0x0A, 0x55, 0x4E, 0x20, 0x42, 0x49, 0x4C, 0x4C,
+ 0x45, 0x54, 0x20, 0x50, 0x4F, 0x55, 0x52, 0x0A, 0x4C, 0x41, 0x20, 0x54, 0x45, 0x52, 0x52, 0x45,
+ 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x35, 0x30, 0x20, 0x30, 0x30, 0x30, 0x20, 0x43, 0x52, 0x45, 0x44,
+ 0x49, 0x54, 0x53, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x44, 0x4F, 0x4E, 0x4E, 0x41, 0x4E, 0x54, 0x2C,
+ 0x44, 0x4F, 0x4E, 0x4E, 0x41, 0x4E, 0x54, 0x2E, 0x0A, 0x31, 0x35, 0x30, 0x30, 0x20, 0x43, 0x52,
+ 0x45, 0x44, 0x49, 0x54, 0x53, 0x20, 0x45, 0x54, 0x0A, 0x4C, 0x45, 0x53, 0x20, 0x50, 0x41, 0x50,
+ 0x49, 0x45, 0x52, 0x53, 0x20, 0x53, 0x4F, 0x4E, 0x54, 0x0A, 0x41, 0x20, 0x54, 0x4F, 0x49, 0x2E,
+ 0x00
+};
+
+const uint8_t LocaleData::_stringsTableEN[] = {
+ 0x5A, 0x00, 0x6D, 0x00, 0x83, 0x00, 0x97, 0x01, 0x48, 0x02, 0x6C, 0x02, 0xB7, 0x02, 0xE9, 0x02,
+ 0x40, 0x03, 0x5F, 0x03, 0x9F, 0x03, 0xDB, 0x03, 0x1D, 0x04, 0x59, 0x04, 0xDD, 0x04, 0x08, 0x05,
+ 0x1A, 0x05, 0x83, 0x05, 0x8E, 0x05, 0xAC, 0x05, 0x39, 0x06, 0x23, 0x08, 0x8E, 0x08, 0xA2, 0x08,
+ 0xF3, 0x08, 0x09, 0x09, 0x28, 0x09, 0x51, 0x09, 0x70, 0x09, 0x93, 0x09, 0x95, 0x09, 0x97, 0x09,
+ 0xEE, 0x09, 0x00, 0x0A, 0x80, 0x0A, 0xA2, 0x0A, 0x4B, 0x0B, 0x64, 0x0B, 0x8F, 0x0B, 0xB7, 0x0B,
+ 0x40, 0x0C, 0x76, 0x0C, 0xC7, 0x0C, 0xF4, 0x0C, 0x26, 0x0D, 0x54, 0x68, 0x65, 0x20, 0x66, 0x75,
+ 0x73, 0x65, 0x20, 0x69, 0x73, 0x0A, 0x62, 0x6C, 0x6F, 0x77, 0x6E, 0x2E, 0x00, 0x54, 0x68, 0x61,
+ 0x74, 0x20, 0x73, 0x68, 0x6F, 0x75, 0x6C, 0x64, 0x0A, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x6E, 0x6F,
+ 0x77, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x27, 0x6D, 0x20, 0x4A, 0x61, 0x63, 0x6B, 0x2E, 0x59,
+ 0x6F, 0x75, 0x27, 0x72, 0x65, 0x0A, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x73, 0x6F, 0x6D, 0x65,
+ 0x20, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x0A, 0x70, 0x61, 0x70, 0x65, 0x72, 0x73, 0x3F, 0x0B, 0xFF,
+ 0xE9, 0xEA, 0x59, 0x65, 0x73, 0x2C, 0x61, 0x6E, 0x64, 0x20, 0x61, 0x73, 0x0A, 0x71, 0x75, 0x69,
+ 0x63, 0x6B, 0x6C, 0x79, 0x20, 0x61, 0x73, 0x0A, 0x70, 0x6F, 0x73, 0x73, 0x69, 0x62, 0x6C, 0x65,
+ 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x31, 0x35, 0x30, 0x30, 0x20, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74,
+ 0x73, 0x21, 0x0B, 0xFF, 0xE9, 0xEA, 0x31, 0x35, 0x30, 0x30, 0x3F, 0x3F, 0x3F, 0x0B, 0xFF, 0xEB,
+ 0xEC, 0x59, 0x65, 0x61, 0x68, 0x2C, 0x49, 0x27, 0x6D, 0x20, 0x74, 0x61, 0x6B, 0x69, 0x6E, 0x67,
+ 0x0A, 0x61, 0x20, 0x62, 0x69, 0x67, 0x20, 0x72, 0x69, 0x73, 0x6B, 0x20, 0x68, 0x65, 0x72, 0x65,
+ 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x42, 0x75, 0x74, 0x20, 0x49, 0x20, 0x64, 0x6F, 0x6E, 0x27, 0x74,
+ 0x0A, 0x68, 0x61, 0x76, 0x65, 0x20, 0x65, 0x6E, 0x6F, 0x75, 0x67, 0x68, 0x2E, 0x2E, 0x2E, 0x0B,
+ 0xFF, 0xEB, 0xEC, 0x47, 0x6F, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65, 0x0A, 0x45, 0x6D, 0x70,
+ 0x6C, 0x6F, 0x79, 0x6D, 0x65, 0x6E, 0x74, 0x0A, 0x4F, 0x66, 0x66, 0x69, 0x63, 0x65, 0x2C, 0x20,
+ 0x79, 0x6F, 0x75, 0x27, 0x6C, 0x6C, 0x0A, 0x66, 0x69, 0x6E, 0x64, 0x20, 0x77, 0x6F, 0x72, 0x6B,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2E, 0x0B, 0x41, 0x6E, 0x64, 0x20, 0x63, 0x6F, 0x6D, 0x65,
+ 0x20, 0x62, 0x61, 0x63, 0x6B, 0x20, 0x74, 0x6F, 0x0A, 0x6D, 0x65, 0x20, 0x77, 0x68, 0x65, 0x6E,
+ 0x20, 0x79, 0x6F, 0x75, 0x27, 0x76, 0x65, 0x0A, 0x67, 0x6F, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6D, 0x6F, 0x6E, 0x65, 0x79, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x20, 0x6B, 0x6E, 0x6F, 0x77,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x75, 0x79, 0x2E, 0x0A, 0x48, 0x65, 0x20, 0x68, 0x61,
+ 0x73, 0x20, 0x61, 0x20, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x0A, 0x69, 0x6E, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x70, 0x6F, 0x6C, 0x69, 0x63, 0x65, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x57, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x63, 0x61, 0x6E, 0x20, 0x49, 0x20, 0x66, 0x69, 0x6E, 0x64, 0x0A, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x47, 0x6F,
+ 0x20, 0x74, 0x6F, 0x20, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x65, 0x64, 0x0A, 0x41,
+ 0x72, 0x65, 0x61, 0x20, 0x31, 0x2C, 0x20, 0x49, 0x20, 0x74, 0x68, 0x69, 0x6E, 0x6B, 0x0A, 0x68,
+ 0x65, 0x27, 0x73, 0x20, 0x6F, 0x6E, 0x20, 0x64, 0x75, 0x74, 0x79, 0x0A, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x2E, 0x0B, 0x42, 0x75, 0x74, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x72, 0x65, 0x66, 0x75,
+ 0x6C, 0x2C, 0x0A, 0x74, 0x68, 0x6F, 0x73, 0x65, 0x20, 0x67, 0x75, 0x79, 0x73, 0x20, 0x61, 0x72,
+ 0x65, 0x0A, 0x6D, 0x65, 0x61, 0x6E, 0x21, 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x20, 0x64, 0x6F, 0x6E,
+ 0x27, 0x74, 0x20, 0x6B, 0x6E, 0x6F, 0x77, 0x0A, 0x61, 0x6E, 0x79, 0x74, 0x68, 0x69, 0x6E, 0x67,
+ 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x2C, 0x0A, 0x73, 0x6F, 0x6E, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x43,
+ 0x59, 0x2D, 0x42, 0x30, 0x32, 0x31, 0x20, 0x77, 0x61, 0x6E, 0x74, 0x73, 0x0A, 0x74, 0x6F, 0x20,
+ 0x6D, 0x61, 0x6B, 0x65, 0x20, 0x61, 0x20, 0x64, 0x65, 0x61, 0x6C, 0x0A, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x79, 0x6F, 0x75, 0x2E, 0x0B, 0x48, 0x65, 0x27, 0x6C, 0x6C, 0x20, 0x62, 0x65, 0x20, 0x77,
+ 0x61, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x0A, 0x62, 0x65, 0x68, 0x69, 0x6E, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x62, 0x61, 0x72, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x47, 0x6F, 0x20, 0x74, 0x6F, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x2C, 0x0A, 0x73, 0x6F, 0x6E, 0x2C, 0x20, 0x43, 0x59,
+ 0x2D, 0x42, 0x30, 0x32, 0x31, 0x27, 0x73, 0x0A, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20,
+ 0x66, 0x6F, 0x72, 0x20, 0x79, 0x6F, 0x75, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x44, 0x6F, 0x6E, 0x27,
+ 0x74, 0x20, 0x73, 0x68, 0x6F, 0x6F, 0x74, 0x2C, 0x49, 0x27, 0x6D, 0x0A, 0x6E, 0x6F, 0x74, 0x20,
+ 0x43, 0x59, 0x2D, 0x42, 0x30, 0x32, 0x31, 0x21, 0x0B, 0x48, 0x69, 0x73, 0x20, 0x68, 0x69, 0x64,
+ 0x65, 0x6F, 0x75, 0x74, 0x27, 0x73, 0x0A, 0x64, 0x6F, 0x77, 0x6E, 0x20, 0x62, 0x65, 0x6C, 0x6F,
+ 0x77, 0x2E, 0x0B, 0x48, 0x69, 0x73, 0x20, 0x70, 0x61, 0x6C, 0x2C, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x6F, 0x70, 0x0A, 0x68, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6B, 0x65, 0x79, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x49, 0x20, 0x64, 0x6F, 0x6E, 0x27, 0x74, 0x20, 0x6B, 0x6E, 0x6F, 0x77, 0x0A,
+ 0x61, 0x6E, 0x79, 0x74, 0x68, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x73, 0x65, 0x2E, 0x00, 0xFF,
+ 0xEB, 0xEC, 0x53, 0x69, 0x72, 0x2E, 0x2E, 0x2E, 0x20, 0x73, 0x6F, 0x6D, 0x65, 0x20, 0x67, 0x75,
+ 0x79, 0x0B, 0x63, 0x61, 0x6C, 0x6C, 0x65, 0x64, 0x20, 0x4A, 0x61, 0x63, 0x6B, 0x0A, 0x61, 0x72,
+ 0x72, 0x61, 0x6E, 0x67, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x65, 0x65, 0x74, 0x0A, 0x79,
+ 0x6F, 0x75, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x2E, 0x00, 0x49,
+ 0x27, 0x64, 0x20, 0x6C, 0x69, 0x6B, 0x65, 0x20, 0x61, 0x0A, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x70,
+ 0x65, 0x72, 0x6D, 0x69, 0x74, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x6F, 0x2C, 0x20, 0x69, 0x74,
+ 0x27, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x0A, 0x68, 0x65, 0x72, 0x65, 0x2E, 0x20, 0x53, 0x65, 0x65,
+ 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x0A, 0x43, 0x2E, 0x00, 0x49, 0x27, 0x64, 0x20, 0x6C,
+ 0x69, 0x6B, 0x65, 0x20, 0x61, 0x0A, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x70, 0x65, 0x72, 0x6D, 0x69,
+ 0x74, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x47, 0x6F, 0x6F, 0x64, 0x2E, 0x2E, 0x2E, 0x4F, 0x2E, 0x6B,
+ 0x2E, 0x2C, 0x74, 0x68, 0x65, 0x0A, 0x62, 0x6F, 0x73, 0x73, 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20,
+ 0x73, 0x65, 0x65, 0x0A, 0x79, 0x6F, 0x75, 0x20, 0x6E, 0x6F, 0x77, 0x2E, 0x00, 0x49, 0x27, 0x64,
+ 0x20, 0x6C, 0x69, 0x6B, 0x65, 0x20, 0x61, 0x0A, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x70, 0x65, 0x72,
+ 0x6D, 0x69, 0x74, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x6F, 0x2C, 0x20, 0x69, 0x74, 0x27, 0x73,
+ 0x20, 0x6E, 0x6F, 0x74, 0x0A, 0x68, 0x65, 0x72, 0x65, 0x2E, 0x20, 0x53, 0x65, 0x65, 0x20, 0x57,
+ 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x0A, 0x42, 0x2E, 0x00, 0x49, 0x27, 0x64, 0x20, 0x6C, 0x69, 0x6B,
+ 0x65, 0x20, 0x74, 0x6F, 0x0A, 0x73, 0x70, 0x65, 0x61, 0x6B, 0x20, 0x74, 0x6F, 0x20, 0x4A, 0x61,
+ 0x63, 0x6B, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4F, 0x68, 0x20, 0x79, 0x65, 0x61, 0x68, 0x3F, 0x20,
+ 0x4A, 0x61, 0x63, 0x6B, 0x27, 0x73, 0x0A, 0x6E, 0x6F, 0x74, 0x20, 0x68, 0x65, 0x72, 0x65, 0x2E,
+ 0x0B, 0xFF, 0xE9, 0xEA, 0x49, 0x27, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E, 0x20, 0x73, 0x65,
+ 0x6E, 0x74, 0x0A, 0x62, 0x79, 0x20, 0x6D, 0x79, 0x20, 0x66, 0x72, 0x69, 0x65, 0x6E, 0x64, 0x0A,
+ 0x49, 0x61, 0x6E, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4F, 0x2E, 0x6B, 0x2E, 0x20, 0x4A, 0x61, 0x63,
+ 0x6B, 0x27, 0x73, 0x0A, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x66, 0x6F, 0x72, 0x20,
+ 0x79, 0x6F, 0x75, 0x0A, 0x6F, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x2E, 0x00, 0xFF, 0xEB, 0xEC,
+ 0x42, 0x65, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x73, 0x6F, 0x6E, 0x2E, 0x0A, 0x59, 0x6F, 0x75,
+ 0x27, 0x72, 0x65, 0x20, 0x74, 0x6F, 0x6F, 0x20, 0x79, 0x6F, 0x75, 0x6E, 0x67, 0x0A, 0x74, 0x6F,
+ 0x20, 0x64, 0x72, 0x69, 0x6E, 0x6B, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x50, 0x61, 0x70, 0x65, 0x72,
+ 0x73, 0x20, 0x70, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x2E, 0x00, 0x49, 0x27, 0x6D, 0x20, 0x74, 0x68,
+ 0x65, 0x0A, 0x6D, 0x65, 0x73, 0x73, 0x65, 0x6E, 0x67, 0x65, 0x72, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x4F, 0x68, 0x20, 0x79, 0x65, 0x73, 0x21, 0x20, 0x48, 0x65, 0x72, 0x65, 0x2C, 0x0A, 0x74, 0x61,
+ 0x6B, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x61, 0x72, 0x63, 0x65, 0x6C, 0x0A, 0x74,
+ 0x6F, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x76, 0x65, 0x6C, 0x0A, 0x61, 0x67, 0x65,
+ 0x6E, 0x63, 0x79, 0x2E, 0x0B, 0x41, 0x6E, 0x64, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x72, 0x65,
+ 0x66, 0x75, 0x6C, 0x0A, 0x69, 0x74, 0x27, 0x73, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x61, 0x62, 0x6C,
+ 0x65, 0x2E, 0x00, 0x54, 0x49, 0x4D, 0x45, 0x20, 0x49, 0x53, 0x20, 0x55, 0x50, 0x00, 0x54, 0x68,
+ 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x61, 0x20, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x0A, 0x66, 0x6F,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x72, 0x64, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x54,
+ 0x68, 0x61, 0x6E, 0x6B, 0x73, 0x2C, 0x20, 0x43, 0x6F, 0x6E, 0x72, 0x61, 0x64, 0x2E, 0x0A, 0x54,
+ 0x68, 0x6F, 0x73, 0x65, 0x20, 0x63, 0x6F, 0x70, 0x73, 0x0A, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x27,
+ 0x76, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6D, 0x79, 0x0A, 0x68, 0x69, 0x64, 0x65, 0x21, 0x0B,
+ 0x57, 0x65, 0x6C, 0x6C, 0x2C, 0x49, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x73, 0x65, 0x0A, 0x79,
+ 0x6F, 0x75, 0x20, 0x64, 0x6F, 0x6E, 0x27, 0x74, 0x0A, 0x72, 0x65, 0x6D, 0x65, 0x6D, 0x62, 0x65,
+ 0x72, 0x20, 0x79, 0x6F, 0x75, 0x72, 0x0A, 0x6F, 0x6C, 0x64, 0x20, 0x70, 0x61, 0x6C, 0x20, 0x49,
+ 0x61, 0x6E, 0x2E, 0x0B, 0x54, 0x61, 0x6B, 0x65, 0x20, 0x61, 0x20, 0x73, 0x65, 0x61, 0x74, 0x2C,
+ 0x0A, 0x77, 0x65, 0x27, 0x6C, 0x6C, 0x20, 0x66, 0x69, 0x78, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0A,
+ 0x73, 0x68, 0x6F, 0x72, 0x74, 0x6C, 0x79, 0x2E, 0x00, 0x49, 0x61, 0x6E, 0x2C, 0x77, 0x68, 0x61,
+ 0x74, 0x20, 0x64, 0x6F, 0x20, 0x79, 0x6F, 0x75, 0x0A, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x6F,
+ 0x20, 0x64, 0x6F, 0x20, 0x74, 0x6F, 0x0A, 0x67, 0x65, 0x74, 0x20, 0x74, 0x6F, 0x20, 0x45, 0x41,
+ 0x52, 0x54, 0x48, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6F, 0x73, 0x74,
+ 0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0A, 0x74, 0x69, 0x63, 0x6B, 0x65, 0x74, 0x20, 0x69,
+ 0x73, 0x0A, 0x61, 0x73, 0x74, 0x72, 0x6F, 0x6E, 0x6F, 0x6D, 0x69, 0x63, 0x61, 0x6C, 0x2E, 0x0B,
+ 0x54, 0x68, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x20, 0x77, 0x61, 0x79, 0x0A, 0x77, 0x6F, 0x75,
+ 0x6C, 0x64, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x79, 0x6F, 0x75, 0x0A, 0x74, 0x6F,
+ 0x20, 0x74, 0x61, 0x6B, 0x65, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x69, 0x6E, 0x0A, 0x44, 0x65,
+ 0x61, 0x74, 0x68, 0x20, 0x54, 0x6F, 0x77, 0x65, 0x72, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x44, 0x65,
+ 0x61, 0x74, 0x68, 0x20, 0x54, 0x6F, 0x77, 0x65, 0x72, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x59, 0x65,
+ 0x73, 0x2C, 0x69, 0x74, 0x27, 0x73, 0x20, 0x61, 0x0A, 0x74, 0x65, 0x6C, 0x65, 0x76, 0x69, 0x73,
+ 0x69, 0x6F, 0x6E, 0x20, 0x67, 0x61, 0x6D, 0x65, 0x2E, 0x0A, 0x54, 0x68, 0x65, 0x20, 0x77, 0x69,
+ 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x67, 0x65, 0x74, 0x73, 0x0A, 0x61, 0x20, 0x74, 0x69, 0x63, 0x6B,
+ 0x65, 0x74, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x4F, 0x2E, 0x6B, 0x2E, 0x43, 0x61, 0x6E, 0x20, 0x79,
+ 0x6F, 0x75, 0x0A, 0x73, 0x75, 0x70, 0x70, 0x6C, 0x79, 0x20, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x0A,
+ 0x70, 0x61, 0x70, 0x65, 0x72, 0x73, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x6F, 0x20, 0x70, 0x72,
+ 0x6F, 0x62, 0x6C, 0x65, 0x6D, 0x2E, 0x0A, 0x47, 0x6F, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x61, 0x72, 0x0A, 0x61, 0x6E, 0x64, 0x20, 0x61, 0x73, 0x6B, 0x20, 0x66, 0x6F, 0x72,
+ 0x0A, 0x4A, 0x61, 0x63, 0x6B, 0x2E, 0x0B, 0x53, 0x61, 0x79, 0x20, 0x49, 0x20, 0x73, 0x65, 0x6E,
+ 0x74, 0x20, 0x79, 0x6F, 0x75, 0x2E, 0x0A, 0x4F, 0x68, 0x2C, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x79, 0x2E, 0x2E, 0x2E, 0x0B, 0x49, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x6F, 0x72, 0x63, 0x65, 0x0A, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x79, 0x6F,
+ 0x75, 0x20, 0x61, 0x73, 0x6B, 0x65, 0x64, 0x0A, 0x6D, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x69,
+ 0x6E, 0x20, 0x79, 0x6F, 0x75, 0x72, 0x0A, 0x70, 0x6F, 0x63, 0x6B, 0x65, 0x74, 0x2E, 0x0B, 0xFF,
+ 0xE9, 0xEA, 0x47, 0x72, 0x65, 0x61, 0x74, 0x2E, 0x54, 0x68, 0x61, 0x6E, 0x6B, 0x0A, 0x79, 0x6F,
+ 0x75, 0x2C, 0x20, 0x49, 0x61, 0x6E, 0x2E, 0x27, 0x54, 0x69, 0x6C, 0x6C, 0x0A, 0x74, 0x68, 0x65,
+ 0x20, 0x6E, 0x65, 0x78, 0x74, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x2E, 0x2E, 0x2E, 0x0B, 0xFF, 0xEB,
+ 0xEC, 0x47, 0x6F, 0x6F, 0x64, 0x20, 0x6C, 0x75, 0x63, 0x6B, 0x2E, 0x49, 0x27, 0x6C, 0x6C, 0x0A,
+ 0x62, 0x65, 0x20, 0x69, 0x6E, 0x20, 0x74, 0x6F, 0x75, 0x63, 0x68, 0x20, 0x77, 0x68, 0x65, 0x6E,
+ 0x0A, 0x79, 0x6F, 0x75, 0x20, 0x67, 0x65, 0x74, 0x20, 0x74, 0x6F, 0x0A, 0x45, 0x61, 0x72, 0x74,
+ 0x68, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x57, 0x65, 0x6C, 0x63, 0x6F, 0x6D, 0x65, 0x20, 0x74, 0x6F,
+ 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x2C,
+ 0x0A, 0x79, 0x6F, 0x75, 0x6E, 0x67, 0x20, 0x6D, 0x61, 0x6E, 0x2E, 0x0B, 0x48, 0x65, 0x72, 0x65,
+ 0x27, 0x73, 0x20, 0x61, 0x20, 0x6D, 0x61, 0x70, 0x20, 0x6F, 0x66, 0x0A, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x2C, 0x77, 0x68, 0x69, 0x63, 0x68, 0x0A, 0x79, 0x6F, 0x75, 0x20, 0x6D,
+ 0x61, 0x79, 0x20, 0x66, 0x69, 0x6E, 0x64, 0x0A, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6C, 0x2E, 0x0B,
+ 0xFF, 0xE9, 0xEA, 0x54, 0x68, 0x61, 0x6E, 0x6B, 0x20, 0x79, 0x6F, 0x75, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x48, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x6E, 0x69, 0x63, 0x65, 0x0A, 0x64, 0x61, 0x79,
+ 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x59, 0x6F, 0x75, 0x20, 0x6D, 0x75, 0x73, 0x74, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x61, 0x0A, 0x70, 0x65, 0x72, 0x6D, 0x69, 0x74, 0x20, 0x69, 0x6E, 0x20, 0x6F,
+ 0x72, 0x64, 0x65, 0x72, 0x0A, 0x74, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6B, 0x2E, 0x0B, 0x59, 0x6F,
+ 0x75, 0x20, 0x63, 0x61, 0x6E, 0x20, 0x67, 0x65, 0x74, 0x20, 0x6F, 0x6E, 0x65, 0x0A, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x64, 0x6D, 0x69, 0x6E, 0x0A, 0x43, 0x65, 0x6E, 0x74, 0x65,
+ 0x72, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x20, 0x64, 0x6F, 0x6E, 0x27, 0x74, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x0A, 0x74, 0x69, 0x6D, 0x65, 0x2E, 0x00, 0x47, 0x6F, 0x6F, 0x64, 0x20, 0x6D, 0x6F,
+ 0x72, 0x6E, 0x69, 0x6E, 0x67, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x47, 0x6F, 0x6F, 0x64, 0x20, 0x6D,
+ 0x6F, 0x72, 0x6E, 0x69, 0x6E, 0x67, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x27, 0x76, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x6E, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0A, 0x67, 0x75, 0x79, 0x20, 0x62, 0x65,
+ 0x66, 0x6F, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x0A, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x2E,
+ 0x00, 0x47, 0x6F, 0x6F, 0x64, 0x20, 0x6D, 0x6F, 0x72, 0x6E, 0x69, 0x6E, 0x67, 0x2E, 0x0B, 0xFF,
+ 0xEB, 0xEC, 0x47, 0x6F, 0x6F, 0x64, 0x20, 0x6D, 0x6F, 0x72, 0x6E, 0x69, 0x6E, 0x67, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x59, 0x65, 0x73, 0x2C, 0x49, 0x20, 0x6B, 0x6E, 0x6F, 0x77, 0x20, 0x68, 0x69,
+ 0x6D, 0x2E, 0x0A, 0x48, 0x65, 0x27, 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x67, 0x75, 0x6C, 0x61,
+ 0x72, 0x2E, 0x00, 0x20, 0x00, 0x20, 0x00, 0x49, 0x27, 0x64, 0x20, 0x6C, 0x69, 0x6B, 0x65, 0x20,
+ 0x61, 0x0A, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x70, 0x65, 0x72, 0x6D, 0x69, 0x74, 0x2E, 0x0B, 0xFF,
+ 0xEB, 0xEC, 0x54, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x6E, 0x6F, 0x0A, 0x70, 0x72, 0x6F,
+ 0x62, 0x6C, 0x65, 0x6D, 0x20, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x0A, 0x61, 0x20, 0x70,
+ 0x65, 0x72, 0x6D, 0x69, 0x74, 0x2E, 0x2E, 0x2E, 0x0B, 0x49, 0x20, 0x6E, 0x65, 0x65, 0x64, 0x20,
+ 0x79, 0x6F, 0x75, 0x72, 0x20, 0x49, 0x44, 0x0A, 0x63, 0x61, 0x72, 0x64, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x48, 0x45, 0x4C, 0x50, 0x2E, 0x2E, 0x2E, 0x48, 0x45, 0x4C, 0x50, 0x2E, 0x2E, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x48, 0x65, 0x6C, 0x70, 0x20, 0x6D, 0x65, 0x20, 0x79, 0x6F, 0x75, 0x6E, 0x67,
+ 0x0A, 0x6D, 0x61, 0x6E, 0x2E, 0x20, 0x49, 0x27, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E, 0x0A,
+ 0x61, 0x74, 0x74, 0x61, 0x63, 0x6B, 0x65, 0x64, 0x20, 0x62, 0x79, 0x0A, 0x6D, 0x75, 0x74, 0x61,
+ 0x6E, 0x74, 0x73, 0x2E, 0x2E, 0x2E, 0x0B, 0x61, 0x6E, 0x64, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6E,
+ 0x27, 0x74, 0x0A, 0x77, 0x61, 0x6C, 0x6B, 0x2E, 0x0B, 0x46, 0x69, 0x6E, 0x64, 0x20, 0x6D, 0x79,
+ 0x0A, 0x74, 0x65, 0x6C, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x72, 0x2C, 0x49, 0x0A, 0x6E, 0x65,
+ 0x65, 0x64, 0x20, 0x75, 0x72, 0x67, 0x65, 0x6E, 0x74, 0x20, 0x6D, 0x65, 0x64, 0x2D, 0x0A, 0x69,
+ 0x63, 0x61, 0x6C, 0x20, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x54, 0x68, 0x61, 0x6E, 0x6B, 0x73, 0x2E, 0x59, 0x6F, 0x75, 0x20, 0x6A, 0x75,
+ 0x73, 0x74, 0x0A, 0x73, 0x61, 0x76, 0x65, 0x64, 0x20, 0x6D, 0x79, 0x20, 0x6C, 0x69, 0x66, 0x65,
+ 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x54, 0x6F, 0x20, 0x67, 0x65, 0x74, 0x20, 0x74, 0x6F, 0x20, 0x4E,
+ 0x65, 0x77, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x2C, 0x79, 0x6F,
+ 0x75, 0x0A, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x6A, 0x75, 0x6D, 0x70, 0x0A, 0x69,
+ 0x6E, 0x74, 0x6F, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6F, 0x6C, 0x65, 0x2C, 0x0B, 0x62,
+ 0x75, 0x74, 0x20, 0x69, 0x66, 0x20, 0x49, 0x20, 0x77, 0x65, 0x72, 0x65, 0x0A, 0x79, 0x6F, 0x75,
+ 0x20, 0x49, 0x27, 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x6E, 0x0A, 0x41, 0x6E, 0x74, 0x69,
+ 0x2D, 0x47, 0x20, 0x62, 0x65, 0x6C, 0x74, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x57, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x63, 0x61, 0x6E, 0x20, 0x49, 0x20, 0x66, 0x69, 0x6E, 0x64, 0x0A, 0x6F, 0x6E, 0x65,
+ 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x6F, 0x77, 0x2C, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6E, 0x0A,
+ 0x73, 0x65, 0x6C, 0x6C, 0x20, 0x79, 0x6F, 0x75, 0x20, 0x6F, 0x6E, 0x65, 0x3A, 0x0A, 0x35, 0x30,
+ 0x30, 0x20, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x42, 0x6F,
+ 0x6E, 0x20, 0x76, 0x6F, 0x79, 0x61, 0x67, 0x65, 0x2C, 0x79, 0x6F, 0x75, 0x6E, 0x67, 0x0A, 0x6D,
+ 0x61, 0x6E, 0x2E, 0x00, 0x49, 0x20, 0x6E, 0x65, 0x65, 0x64, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6C,
+ 0x6C, 0x79, 0x0A, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x64, 0x20, 0x6D, 0x61, 0x67, 0x6E, 0x65,
+ 0x74, 0x69, 0x63, 0x0A, 0x63, 0x61, 0x72, 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0x2E, 0x00, 0x49,
+ 0x27, 0x64, 0x20, 0x6C, 0x69, 0x6B, 0x65, 0x20, 0x61, 0x0A, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x70,
+ 0x65, 0x72, 0x6D, 0x69, 0x74, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20,
+ 0x66, 0x6C, 0x6F, 0x6F, 0x72, 0x2E, 0x00, 0x41, 0x6E, 0x20, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x20,
+ 0x76, 0x6F, 0x69, 0x63, 0x65, 0x0A, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x73,
+ 0x20, 0x79, 0x6F, 0x75, 0x72, 0x0A, 0x74, 0x68, 0x6F, 0x75, 0x67, 0x68, 0x74, 0x73, 0x2E, 0x0B,
+ 0xFF, 0xEB, 0xEC, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x6D, 0x65, 0x2C, 0x73, 0x6F, 0x6E, 0x2C,
+ 0x70, 0x75, 0x74, 0x0A, 0x74, 0x68, 0x65, 0x20, 0x61, 0x74, 0x6F, 0x6D, 0x69, 0x63, 0x0A, 0x63,
+ 0x68, 0x61, 0x72, 0x67, 0x65, 0x20, 0x68, 0x65, 0x72, 0x65, 0x2E, 0x2E, 0x2E, 0x0B, 0x61, 0x6E,
+ 0x64, 0x20, 0x66, 0x6C, 0x65, 0x65, 0x20, 0x61, 0x73, 0x0A, 0x73, 0x6F, 0x6F, 0x6E, 0x20, 0x61,
+ 0x73, 0x20, 0x69, 0x74, 0x0A, 0x72, 0x65, 0x61, 0x63, 0x68, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x0A, 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x74, 0x27, 0x73, 0x20, 0x63, 0x6F, 0x72, 0x65, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x4C, 0x65, 0x61, 0x64, 0x20, 0x6F, 0x6E, 0x2C, 0x79, 0x6F, 0x75, 0x6E, 0x67,
+ 0x0A, 0x6D, 0x61, 0x6E, 0x2E, 0x0B, 0x54, 0x61, 0x6B, 0x65, 0x20, 0x6D, 0x65, 0x20, 0x74, 0x6F,
+ 0x20, 0x74, 0x68, 0x65, 0x0A, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x43, 0x65,
+ 0x6E, 0x74, 0x65, 0x72, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x54, 0x68, 0x61, 0x6E, 0x6B, 0x20, 0x79,
+ 0x6F, 0x75, 0x20, 0x66, 0x6F, 0x72, 0x0A, 0x79, 0x6F, 0x75, 0x72, 0x20, 0x68, 0x65, 0x6C, 0x70,
+ 0x2E, 0x2E, 0x2E, 0x0B, 0x49, 0x20, 0x61, 0x72, 0x72, 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x61,
+ 0x66, 0x65, 0x6C, 0x79, 0x0A, 0x61, 0x6E, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73,
+ 0x20, 0x6E, 0x6F, 0x0A, 0x6C, 0x6F, 0x6E, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x79, 0x0A, 0x64,
+ 0x61, 0x6E, 0x67, 0x65, 0x72, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x57, 0x65, 0x6C, 0x6C, 0x20, 0x74,
+ 0x68, 0x65, 0x6E, 0x2C, 0x68, 0x61, 0x76, 0x65, 0x0A, 0x79, 0x6F, 0x75, 0x20, 0x62, 0x72, 0x6F,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x6D, 0x65, 0x0A, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x72, 0x63,
+ 0x65, 0x6C, 0x3F, 0x00, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x75, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20,
+ 0x61, 0x0A, 0x74, 0x69, 0x63, 0x6B, 0x65, 0x74, 0x20, 0x74, 0x6F, 0x20, 0x45, 0x61, 0x72, 0x74,
+ 0x68, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x35, 0x30, 0x2C, 0x30, 0x30, 0x30, 0x20, 0x63, 0x72, 0x65,
+ 0x64, 0x69, 0x74, 0x73, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74,
+ 0x63, 0x68, 0x20, 0x79, 0x6F, 0x75, 0x72, 0x0A, 0x62, 0x61, 0x63, 0x6B, 0x2C, 0x79, 0x6F, 0x75,
+ 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x0A, 0x6D, 0x69, 0x6E, 0x65, 0x3A, 0x0B, 0x31,
+ 0x35, 0x30, 0x30, 0x20, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x0A,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x70, 0x65, 0x72, 0x73, 0x20, 0x61, 0x72, 0x65, 0x0A, 0x79,
+ 0x6F, 0x75, 0x72, 0x73, 0x2E, 0x00
+};
+
+const uint8_t LocaleData::_stringsTableDE[] = {
+ 0x5A, 0x00, 0x7B, 0x00, 0x9B, 0x00, 0xB0, 0x01, 0x63, 0x02, 0x87, 0x02, 0xD3, 0x02, 0x04, 0x03,
+ 0x6D, 0x03, 0x86, 0x03, 0xBF, 0x03, 0x0E, 0x04, 0x5E, 0x04, 0xAD, 0x04, 0x30, 0x05, 0x60, 0x05,
+ 0x73, 0x05, 0xDD, 0x05, 0xEE, 0x05, 0x09, 0x06, 0xC0, 0x06, 0xBB, 0x08, 0x24, 0x09, 0x39, 0x09,
+ 0x87, 0x09, 0x9F, 0x09, 0xBE, 0x09, 0xEF, 0x09, 0x0E, 0x0A, 0x30, 0x0A, 0x32, 0x0A, 0x34, 0x0A,
+ 0x9D, 0x0A, 0xB2, 0x0A, 0x42, 0x0B, 0x66, 0x0B, 0x1F, 0x0C, 0x3B, 0x0C, 0x6C, 0x0C, 0x9D, 0x0C,
+ 0x39, 0x0D, 0x74, 0x0D, 0xC5, 0x0D, 0xED, 0x0D, 0x20, 0x0E, 0x44, 0x49, 0x45, 0x20, 0x53, 0x49,
+ 0x43, 0x48, 0x45, 0x52, 0x55, 0x4E, 0x47, 0x0A, 0x49, 0x53, 0x54, 0x0A, 0x44, 0x55, 0x52, 0x43,
+ 0x48, 0x47, 0x45, 0x42, 0x52, 0x41, 0x4E, 0x4E, 0x54, 0x2E, 0x00, 0x44, 0x41, 0x53, 0x20, 0x4D,
+ 0x5B, 0x53, 0x53, 0x54, 0x45, 0x20, 0x4A, 0x45, 0x54, 0x5A, 0x54, 0x0A, 0x46, 0x55, 0x4E, 0x4B,
+ 0x54, 0x49, 0x4F, 0x4E, 0x49, 0x45, 0x52, 0x45, 0x4E, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x43,
+ 0x48, 0x20, 0x42, 0x49, 0x4E, 0x20, 0x4A, 0x41, 0x43, 0x4B, 0x2E, 0x0A, 0x53, 0x49, 0x45, 0x20,
+ 0x57, 0x4F, 0x4C, 0x4C, 0x45, 0x4E, 0x0A, 0x47, 0x45, 0x46, 0x5C, 0x4C, 0x53, 0x43, 0x48, 0x54,
+ 0x45, 0x0A, 0x50, 0x41, 0x50, 0x49, 0x45, 0x52, 0x45, 0x3F, 0x0B, 0xFF, 0xE9, 0xEA, 0x4A, 0x41,
+ 0x2C, 0x20, 0x55, 0x4E, 0x44, 0x20, 0x53, 0x4F, 0x0A, 0x53, 0x43, 0x48, 0x4E, 0x45, 0x4C, 0x4C,
+ 0x20, 0x57, 0x49, 0x45, 0x0A, 0x4D, 0x5D, 0x47, 0x4C, 0x49, 0x43, 0x48, 0x2E, 0x0B, 0xFF, 0xEB,
+ 0xEC, 0x31, 0x35, 0x30, 0x30, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x53, 0x21, 0x0B, 0xFF,
+ 0xE9, 0xEA, 0x31, 0x35, 0x30, 0x30, 0x3F, 0x3F, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x4A, 0x41, 0x2C,
+ 0x20, 0x45, 0x53, 0x20, 0x49, 0x53, 0x54, 0x20, 0x45, 0x49, 0x4E, 0x0A, 0x47, 0x52, 0x4F, 0x53,
+ 0x53, 0x45, 0x53, 0x20, 0x52, 0x49, 0x53, 0x49, 0x4B, 0x4F, 0x0B, 0xFF, 0xE9, 0xEA, 0x41, 0x42,
+ 0x45, 0x52, 0x20, 0x49, 0x43, 0x48, 0x20, 0x48, 0x41, 0x42, 0x45, 0x0A, 0x4E, 0x49, 0x43, 0x48,
+ 0x54, 0x20, 0x47, 0x45, 0x4E, 0x55, 0x47, 0x2E, 0x2E, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x47, 0x45,
+ 0x48, 0x45, 0x4E, 0x20, 0x53, 0x49, 0x45, 0x20, 0x5A, 0x55, 0x4D, 0x0A, 0x41, 0x52, 0x42, 0x45,
+ 0x49, 0x54, 0x53, 0x41, 0x4D, 0x54, 0x2C, 0x20, 0x44, 0x4F, 0x52, 0x54, 0x0A, 0x46, 0x49, 0x4E,
+ 0x44, 0x45, 0x4E, 0x20, 0x53, 0x49, 0x45, 0x0A, 0x41, 0x52, 0x42, 0x45, 0x49, 0x54, 0x2E, 0x0B,
+ 0x55, 0x4E, 0x44, 0x20, 0x4B, 0x4F, 0x4D, 0x4D, 0x45, 0x4E, 0x20, 0x53, 0x49, 0x45, 0x0A, 0x5A,
+ 0x55, 0x52, 0x5B, 0x43, 0x4B, 0x2C, 0x20, 0x57, 0x45, 0x4E, 0x4E, 0x20, 0x53, 0x49, 0x45, 0x0A,
+ 0x44, 0x41, 0x53, 0x20, 0x47, 0x45, 0x4C, 0x44, 0x20, 0x48, 0x41, 0x42, 0x45, 0x4E, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x49, 0x43, 0x48, 0x20, 0x4B, 0x45, 0x4E, 0x4E, 0x45, 0x0A, 0x43, 0x59, 0x2D,
+ 0x42, 0x30, 0x32, 0x31, 0x2E, 0x0A, 0x53, 0x45, 0x49, 0x4E, 0x20, 0x46, 0x52, 0x45, 0x55, 0x4E,
+ 0x44, 0x20, 0x49, 0x53, 0x54, 0x0A, 0x42, 0x45, 0x49, 0x20, 0x44, 0x45, 0x52, 0x20, 0x50, 0x4F,
+ 0x4C, 0x49, 0x5A, 0x45, 0x49, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x57, 0x4F, 0x20, 0x4B, 0x41, 0x4E,
+ 0x4E, 0x20, 0x49, 0x43, 0x48, 0x0A, 0x44, 0x45, 0x4E, 0x20, 0x46, 0x49, 0x4E, 0x44, 0x45, 0x4E,
+ 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x49, 0x4E, 0x20, 0x44, 0x45, 0x52, 0x20, 0x56, 0x45, 0x52, 0x42,
+ 0x4F, 0x2D, 0x0A, 0x54, 0x45, 0x4E, 0x45, 0x4E, 0x20, 0x5A, 0x4F, 0x4E, 0x45, 0x2E, 0x20, 0x45,
+ 0x52, 0x0A, 0x49, 0x53, 0x54, 0x20, 0x44, 0x4F, 0x52, 0x54, 0x0A, 0x41, 0x4E, 0x47, 0x45, 0x53,
+ 0x54, 0x45, 0x4C, 0x4C, 0x54, 0x2E, 0x0B, 0x41, 0x42, 0x45, 0x52, 0x2C, 0x20, 0x50, 0x41, 0x53,
+ 0x53, 0x20, 0x41, 0x55, 0x46, 0x21, 0x0A, 0x44, 0x49, 0x45, 0x53, 0x45, 0x20, 0x4C, 0x45, 0x55,
+ 0x54, 0x45, 0x20, 0x53, 0x49, 0x4E, 0x44, 0x0A, 0x47, 0x45, 0x46, 0x5C, 0x48, 0x52, 0x4C, 0x49,
+ 0x43, 0x48, 0x00, 0xFF, 0xEB, 0xEC, 0x4D, 0x45, 0x48, 0x52, 0x20, 0x57, 0x45, 0x49, 0x53, 0x53,
+ 0x20, 0x49, 0x43, 0x48, 0x0A, 0x4E, 0x49, 0x43, 0x48, 0x54, 0x2C, 0x20, 0x4D, 0x45, 0x49, 0x4E,
+ 0x0A, 0x53, 0x4F, 0x48, 0x4E, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x43, 0x59, 0x2D, 0x42, 0x4F, 0x32,
+ 0x31, 0x20, 0x4D, 0x5D, 0x43, 0x48, 0x54, 0x45, 0x0A, 0x45, 0x49, 0x4E, 0x20, 0x47, 0x45, 0x53,
+ 0x43, 0x48, 0x5C, 0x46, 0x54, 0x0A, 0x4D, 0x49, 0x54, 0x20, 0x44, 0x49, 0x52, 0x20, 0x4D, 0x41,
+ 0x43, 0x48, 0x45, 0x4E, 0x2E, 0x0B, 0x45, 0x52, 0x20, 0x57, 0x41, 0x52, 0x54, 0x45, 0x54, 0x20,
+ 0x48, 0x49, 0x4E, 0x54, 0x45, 0x52, 0x0A, 0x44, 0x45, 0x52, 0x20, 0x4B, 0x4E, 0x45, 0x49, 0x50,
+ 0x45, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x47, 0x45, 0x48, 0x20, 0x5A, 0x55, 0x52, 0x20, 0x4B, 0x4E,
+ 0x45, 0x49, 0x50, 0x45, 0x2C, 0x0A, 0x43, 0x59, 0x2D, 0x42, 0x4F, 0x32, 0x31, 0x20, 0x57, 0x41,
+ 0x52, 0x54, 0x45, 0x54, 0x0A, 0x44, 0x4F, 0x52, 0x54, 0x20, 0x41, 0x55, 0x46, 0x20, 0x44, 0x49,
+ 0x43, 0x48, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x4E, 0x49, 0x43, 0x48, 0x54, 0x20, 0x53, 0x43, 0x48,
+ 0x49, 0x45, 0x53, 0x53, 0x45, 0x4E, 0x2C, 0x0A, 0x49, 0x43, 0x48, 0x20, 0x42, 0x49, 0x4E, 0x20,
+ 0x4E, 0x49, 0x43, 0x48, 0x54, 0x0A, 0x43, 0x59, 0x2D, 0x42, 0x4F, 0x32, 0x31, 0x21, 0x0B, 0x53,
+ 0x45, 0x49, 0x4E, 0x20, 0x56, 0x45, 0x52, 0x53, 0x54, 0x45, 0x43, 0x4B, 0x0A, 0x49, 0x53, 0x54,
+ 0x20, 0x47, 0x41, 0x4E, 0x5A, 0x20, 0x55, 0x4E, 0x54, 0x45, 0x4E, 0x2E, 0x0B, 0x44, 0x45, 0x52,
+ 0x20, 0x50, 0x4F, 0x4C, 0x49, 0x5A, 0x49, 0x53, 0x54, 0x20, 0x48, 0x41, 0x54, 0x0A, 0x44, 0x45,
+ 0x4E, 0x20, 0x53, 0x43, 0x48, 0x4C, 0x5B, 0x53, 0x53, 0x45, 0x4C, 0x2E, 0x00, 0xFF, 0xEB, 0xEC,
+ 0x4D, 0x45, 0x48, 0x52, 0x20, 0x57, 0x45, 0x49, 0x53, 0x53, 0x0A, 0x49, 0x43, 0x48, 0x20, 0x4E,
+ 0x49, 0x43, 0x48, 0x54, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x53, 0x49, 0x52, 0x2E, 0x2E, 0x2E, 0x20,
+ 0x4A, 0x41, 0x43, 0x4B, 0x20, 0x48, 0x41, 0x54, 0x0A, 0x45, 0x49, 0x4E, 0x20, 0x54, 0x52, 0x45,
+ 0x46, 0x46, 0x45, 0x4E, 0x0A, 0x42, 0x45, 0x49, 0x20, 0x44, 0x45, 0x52, 0x20, 0x4B, 0x4E, 0x45,
+ 0x49, 0x50, 0x45, 0x0A, 0x41, 0x52, 0x52, 0x41, 0x4E, 0x47, 0x49, 0x45, 0x52, 0x54, 0x00, 0x49,
+ 0x43, 0x48, 0x20, 0x4D, 0x5D, 0x43, 0x48, 0x54, 0x45, 0x20, 0x45, 0x49, 0x4E, 0x45, 0x0A, 0x41,
+ 0x52, 0x42, 0x45, 0x49, 0x54, 0x53, 0x45, 0x52, 0x4C, 0x41, 0x55, 0x42, 0x4E, 0x49, 0x53, 0x0B,
+ 0xFF, 0xEB, 0xEC, 0x4E, 0x45, 0x49, 0x4E, 0x2C, 0x20, 0x4E, 0x49, 0x43, 0x48, 0x54, 0x0A, 0x48,
+ 0x49, 0x45, 0x52, 0x2E, 0x20, 0x47, 0x45, 0x48, 0x45, 0x4E, 0x20, 0x53, 0x49, 0x45, 0x0A, 0x5A,
+ 0x55, 0x20, 0x53, 0x43, 0x48, 0x41, 0x4C, 0x54, 0x45, 0x52, 0x20, 0x43, 0x2E, 0x00, 0x49, 0x43,
+ 0x48, 0x20, 0x4D, 0x5D, 0x43, 0x48, 0x54, 0x45, 0x20, 0x45, 0x49, 0x4E, 0x45, 0x0A, 0x41, 0x52,
+ 0x42, 0x45, 0x49, 0x54, 0x53, 0x45, 0x52, 0x4C, 0x41, 0x55, 0x42, 0x4E, 0x49, 0x53, 0x0B, 0xFF,
+ 0xEB, 0xEC, 0x47, 0x55, 0x54, 0x2E, 0x2E, 0x2E, 0x20, 0x4F, 0x2E, 0x4B, 0x2E, 0x2C, 0x20, 0x44,
+ 0x45, 0x52, 0x0A, 0x43, 0x48, 0x45, 0x46, 0x20, 0x57, 0x49, 0x4C, 0x4C, 0x20, 0x53, 0x49, 0x45,
+ 0x0A, 0x4A, 0x45, 0x54, 0x5A, 0x54, 0x20, 0x53, 0x45, 0x48, 0x45, 0x4E, 0x2E, 0x00, 0x49, 0x43,
+ 0x48, 0x20, 0x4D, 0x5D, 0x43, 0x48, 0x54, 0x45, 0x20, 0x45, 0x49, 0x4E, 0x45, 0x0A, 0x41, 0x52,
+ 0x42, 0x45, 0x49, 0x54, 0x53, 0x45, 0x52, 0x4C, 0x41, 0x55, 0x42, 0x4E, 0x49, 0x53, 0x0B, 0xFF,
+ 0xEB, 0xEC, 0x4E, 0x45, 0x49, 0x4E, 0x2C, 0x20, 0x4E, 0x49, 0x43, 0x48, 0x54, 0x0A, 0x48, 0x49,
+ 0x45, 0x52, 0x2E, 0x20, 0x47, 0x45, 0x48, 0x45, 0x4E, 0x20, 0x53, 0x49, 0x45, 0x0A, 0x5A, 0x55,
+ 0x20, 0x53, 0x43, 0x48, 0x41, 0x4C, 0x54, 0x45, 0x52, 0x20, 0x42, 0x2E, 0x00, 0x49, 0x43, 0x48,
+ 0x20, 0x4D, 0x5D, 0x43, 0x48, 0x54, 0x45, 0x0A, 0x4A, 0x41, 0x43, 0x4B, 0x20, 0x53, 0x50, 0x52,
+ 0x45, 0x43, 0x48, 0x45, 0x4E, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x41, 0x43, 0x48, 0x20, 0x4A, 0x41,
+ 0x3F, 0x20, 0x4A, 0x41, 0x43, 0x4B, 0x0A, 0x49, 0x53, 0x54, 0x20, 0x4E, 0x49, 0x43, 0x48, 0x54,
+ 0x20, 0x44, 0x41, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x49, 0x43, 0x48, 0x20, 0x4B, 0x4F, 0x4D, 0x4D,
+ 0x45, 0x20, 0x56, 0x4F, 0x4E, 0x0A, 0x4D, 0x45, 0x49, 0x4E, 0x45, 0x4D, 0x20, 0x46, 0x52, 0x45,
+ 0x55, 0x4E, 0x44, 0x0A, 0x49, 0x41, 0x4E, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4F, 0x2E, 0x4B, 0x2E,
+ 0x20, 0x4A, 0x41, 0x43, 0x4B, 0x20, 0x57, 0x41, 0x52, 0x54, 0x45, 0x54, 0x0A, 0x44, 0x52, 0x41,
+ 0x55, 0x53, 0x53, 0x45, 0x4E, 0x20, 0x41, 0x55, 0x46, 0x0A, 0x44, 0x49, 0x43, 0x48, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x4E, 0x45, 0x45, 0x2C, 0x20, 0x4D, 0x45, 0x49, 0x4E, 0x20, 0x53, 0x4F, 0x48,
+ 0x4E, 0x2E, 0x0A, 0x44, 0x55, 0x20, 0x42, 0x49, 0x53, 0x54, 0x20, 0x5A, 0x55, 0x20, 0x4A, 0x55,
+ 0x4E, 0x47, 0x0A, 0x5A, 0x55, 0x4D, 0x20, 0x54, 0x52, 0x49, 0x4E, 0x4B, 0x45, 0x4E, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x50, 0x41, 0x50, 0x49, 0x45, 0x52, 0x45, 0x2C, 0x20, 0x42, 0x49, 0x54, 0x54,
+ 0x45, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x43, 0x48, 0x20, 0x42, 0x49, 0x4E, 0x20, 0x44, 0x45,
+ 0x52, 0x0A, 0x42, 0x4F, 0x54, 0x45, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4F, 0x48, 0x20, 0x4A, 0x41,
+ 0x21, 0x0A, 0x44, 0x49, 0x45, 0x53, 0x45, 0x53, 0x20, 0x50, 0x41, 0x4B, 0x45, 0x54, 0x0A, 0x4D,
+ 0x55, 0x53, 0x53, 0x20, 0x5A, 0x55, 0x4D, 0x0A, 0x52, 0x45, 0x49, 0x53, 0x45, 0x42, 0x5B, 0x52,
+ 0x4F, 0x0B, 0x53, 0x45, 0x49, 0x45, 0x4E, 0x20, 0x53, 0x49, 0x45, 0x0A, 0x56, 0x4F, 0x52, 0x53,
+ 0x49, 0x43, 0x48, 0x54, 0x49, 0x47, 0x2C, 0x0A, 0x45, 0x53, 0x20, 0x49, 0x53, 0x54, 0x20, 0x53,
+ 0x45, 0x48, 0x52, 0x0A, 0x57, 0x45, 0x52, 0x54, 0x56, 0x4F, 0x4C, 0x4C, 0x00, 0x5A, 0x45, 0x49,
+ 0x54, 0x20, 0x41, 0x42, 0x47, 0x45, 0x4C, 0x41, 0x55, 0x46, 0x45, 0x4E, 0x2E, 0x00, 0x44, 0x49,
+ 0x45, 0x20, 0x4B, 0x41, 0x52, 0x54, 0x45, 0x20, 0x48, 0x41, 0x54, 0x0A, 0x45, 0x49, 0x4E, 0x45,
+ 0x4E, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x5A, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x44, 0x41, 0x4E, 0x4B,
+ 0x45, 0x2C, 0x20, 0x43, 0x4F, 0x4E, 0x52, 0x41, 0x44, 0x2E, 0x0A, 0x44, 0x49, 0x45, 0x20, 0x50,
+ 0x4F, 0x4C, 0x49, 0x5A, 0x49, 0x53, 0x54, 0x45, 0x4E, 0x0A, 0x48, 0x5C, 0x54, 0x54, 0x45, 0x4E,
+ 0x20, 0x4D, 0x45, 0x49, 0x4E, 0x20, 0x56, 0x45, 0x52, 0x2D, 0x0A, 0x53, 0x54, 0x45, 0x43, 0x4B,
+ 0x20, 0x47, 0x45, 0x46, 0x55, 0x4E, 0x44, 0x45, 0x4E, 0x2E, 0x0B, 0x44, 0x55, 0x20, 0x45, 0x52,
+ 0x49, 0x4E, 0x4E, 0x45, 0x52, 0x53, 0x54, 0x0A, 0x44, 0x49, 0x43, 0x48, 0x20, 0x57, 0x4F, 0x48,
+ 0x4C, 0x20, 0x4E, 0x49, 0x43, 0x48, 0x54, 0x0A, 0x41, 0x4E, 0x20, 0x44, 0x45, 0x49, 0x4E, 0x45,
+ 0x4E, 0x20, 0x41, 0x4C, 0x54, 0x45, 0x4E, 0x0A, 0x4B, 0x55, 0x4D, 0x50, 0x45, 0x4C, 0x20, 0x49,
+ 0x41, 0x4E, 0x2E, 0x0B, 0x53, 0x45, 0x54, 0x5A, 0x20, 0x44, 0x49, 0x43, 0x48, 0x2C, 0x20, 0x57,
+ 0x49, 0x52, 0x0A, 0x42, 0x52, 0x49, 0x4E, 0x47, 0x45, 0x4E, 0x20, 0x44, 0x45, 0x49, 0x4E, 0x20,
+ 0x47, 0x45, 0x2D, 0x0A, 0x44, 0x5C, 0x43, 0x48, 0x54, 0x4E, 0x49, 0x53, 0x20, 0x57, 0x49, 0x45,
+ 0x44, 0x45, 0x52, 0x0A, 0x49, 0x4E, 0x20, 0x4F, 0x52, 0x44, 0x4E, 0x55, 0x4E, 0x47, 0x2E, 0x00,
+ 0x49, 0x41, 0x4E, 0x2C, 0x20, 0x57, 0x41, 0x53, 0x20, 0x4D, 0x55, 0x53, 0x53, 0x0A, 0x49, 0x43,
+ 0x48, 0x20, 0x4D, 0x41, 0x43, 0x48, 0x45, 0x4E, 0x2C, 0x20, 0x55, 0x4D, 0x0A, 0x5A, 0x55, 0x52,
+ 0x20, 0x45, 0x52, 0x44, 0x45, 0x20, 0x5A, 0x55, 0x0A, 0x4B, 0x4F, 0x4D, 0x4D, 0x45, 0x4E, 0x3F,
+ 0x0B, 0x44, 0x45, 0x52, 0x20, 0x50, 0x52, 0x45, 0x49, 0x53, 0x20, 0x46, 0x5B, 0x52, 0x0A, 0x44,
+ 0x41, 0x53, 0x20, 0x54, 0x49, 0x43, 0x4B, 0x45, 0x54, 0x20, 0x49, 0x53, 0x54, 0x0A, 0x41, 0x53,
+ 0x54, 0x52, 0x4F, 0x4E, 0x4F, 0x4D, 0x49, 0x53, 0x43, 0x48, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x44,
+ 0x45, 0x52, 0x20, 0x45, 0x49, 0x4E, 0x5A, 0x49, 0x47, 0x45, 0x20, 0x57, 0x45, 0x47, 0x0A, 0x57,
+ 0x5C, 0x52, 0x45, 0x20, 0x44, 0x49, 0x45, 0x0A, 0x54, 0x45, 0x49, 0x4C, 0x4E, 0x41, 0x48, 0x4D,
+ 0x45, 0x0A, 0x41, 0x4D, 0x20, 0x54, 0x4F, 0x44, 0x45, 0x53, 0x54, 0x55, 0x52, 0x4D, 0x2E, 0x0B,
+ 0xFF, 0xE9, 0xEA, 0x54, 0x4F, 0x44, 0x45, 0x53, 0x54, 0x55, 0x52, 0x4D, 0x3F, 0x0B, 0xFF, 0xEB,
+ 0xEC, 0x44, 0x41, 0x53, 0x20, 0x49, 0x53, 0x54, 0x20, 0x45, 0x49, 0x4E, 0x45, 0x0A, 0x46, 0x45,
+ 0x52, 0x4E, 0x53, 0x45, 0x48, 0x53, 0x48, 0x4F, 0x57, 0x2E, 0x0A, 0x44, 0x45, 0x52, 0x20, 0x47,
+ 0x45, 0x57, 0x49, 0x4E, 0x4E, 0x45, 0x52, 0x20, 0x42, 0x45, 0x2D, 0x0A, 0x4B, 0x4F, 0x4D, 0x4D,
+ 0x54, 0x20, 0x45, 0x49, 0x4E, 0x20, 0x54, 0x49, 0x43, 0x4B, 0x45, 0x54, 0x0B, 0xFF, 0xE9, 0xEA,
+ 0x4B, 0x41, 0x4E, 0x4E, 0x53, 0x54, 0x20, 0x44, 0x55, 0x20, 0x4D, 0x49, 0x52, 0x0A, 0x46, 0x41,
+ 0x4C, 0x53, 0x43, 0x48, 0x45, 0x20, 0x50, 0x41, 0x50, 0x49, 0x45, 0x52, 0x45, 0x0A, 0x42, 0x45,
+ 0x53, 0x4F, 0x52, 0x47, 0x45, 0x4E, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x4B, 0x45, 0x49, 0x4E, 0x20,
+ 0x50, 0x52, 0x4F, 0x42, 0x4C, 0x45, 0x4D, 0x2E, 0x0A, 0x47, 0x45, 0x48, 0x20, 0x5A, 0x55, 0x52,
+ 0x20, 0x4B, 0x4E, 0x45, 0x49, 0x50, 0x45, 0x2C, 0x0A, 0x55, 0x4E, 0x44, 0x20, 0x46, 0x52, 0x41,
+ 0x47, 0x0A, 0x4E, 0x41, 0x43, 0x48, 0x20, 0x4A, 0x41, 0x43, 0x4B, 0x2E, 0x0B, 0x53, 0x41, 0x47,
+ 0x2C, 0x20, 0x44, 0x41, 0x53, 0x53, 0x20, 0x44, 0x55, 0x20, 0x56, 0x4F, 0x4E, 0x0A, 0x4D, 0x49,
+ 0x52, 0x20, 0x4B, 0x4F, 0x4D, 0x4D, 0x53, 0x54, 0x2E, 0x0A, 0x41, 0x43, 0x48, 0x2E, 0x2E, 0x2E,
+ 0x0B, 0x2E, 0x2E, 0x49, 0x43, 0x48, 0x20, 0x48, 0x41, 0x42, 0x45, 0x20, 0x5B, 0x42, 0x52, 0x49,
+ 0x2D, 0x0A, 0x47, 0x45, 0x4E, 0x53, 0x20, 0x45, 0x49, 0x4E, 0x20, 0x53, 0x43, 0x48, 0x55, 0x54,
+ 0x5A, 0x2D, 0x0A, 0x46, 0x45, 0x4C, 0x44, 0x2C, 0x20, 0x49, 0x4E, 0x20, 0x44, 0x45, 0x49, 0x4E,
+ 0x45, 0x0A, 0x54, 0x41, 0x53, 0x43, 0x48, 0x45, 0x20, 0x47, 0x45, 0x53, 0x54, 0x45, 0x43, 0x4B,
+ 0x54, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x47, 0x52, 0x4F, 0x53, 0x53, 0x41, 0x52, 0x54, 0x49, 0x47,
+ 0x2E, 0x0A, 0x44, 0x41, 0x4E, 0x4B, 0x45, 0x2C, 0x20, 0x49, 0x41, 0x4E, 0x2E, 0x20, 0x42, 0x49,
+ 0x53, 0x0A, 0x44, 0x45, 0x4D, 0x4E, 0x5C, 0x43, 0x48, 0x53, 0x54, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x49, 0x43, 0x48, 0x20, 0x4D, 0x45, 0x4C, 0x44, 0x45, 0x20, 0x4D, 0x49, 0x43, 0x48, 0x2C, 0x0A,
+ 0x57, 0x45, 0x4E, 0x4E, 0x20, 0x44, 0x55, 0x20, 0x41, 0x55, 0x46, 0x0A, 0x44, 0x45, 0x52, 0x20,
+ 0x45, 0x52, 0x44, 0x45, 0x20, 0x42, 0x49, 0x53, 0x54, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x57, 0x49,
+ 0x4C, 0x4C, 0x4B, 0x4F, 0x4D, 0x4D, 0x45, 0x4E, 0x20, 0x49, 0x4E, 0x0A, 0x4E, 0x45, 0x57, 0x20,
+ 0x57, 0x41, 0x53, 0x48, 0x49, 0x4E, 0x47, 0x54, 0x4F, 0x4E, 0x2C, 0x0A, 0x4A, 0x55, 0x4E, 0x47,
+ 0x45, 0x52, 0x20, 0x4D, 0x41, 0x4E, 0x4E, 0x2E, 0x0B, 0x48, 0x49, 0x45, 0x52, 0x20, 0x49, 0x53,
+ 0x54, 0x20, 0x45, 0x49, 0x4E, 0x0A, 0x53, 0x54, 0x41, 0x44, 0x54, 0x50, 0x4C, 0x41, 0x4E, 0x2C,
+ 0x0A, 0x53, 0x49, 0x45, 0x20, 0x57, 0x45, 0x52, 0x44, 0x45, 0x4E, 0x20, 0x49, 0x48, 0x4E, 0x0A,
+ 0x42, 0x52, 0x41, 0x55, 0x43, 0x48, 0x45, 0x4E, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x44, 0x41, 0x4E,
+ 0x4B, 0x45, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x53, 0x43, 0x48, 0x5D, 0x4E, 0x45, 0x4E, 0x20, 0x54,
+ 0x41, 0x47, 0x0A, 0x4E, 0x4F, 0x43, 0x48, 0x21, 0x00, 0xFF, 0xEB, 0xEC, 0x53, 0x49, 0x45, 0x20,
+ 0x42, 0x52, 0x41, 0x55, 0x43, 0x48, 0x45, 0x4E, 0x0A, 0x45, 0x49, 0x4E, 0x45, 0x20, 0x41, 0x52,
+ 0x42, 0x45, 0x49, 0x54, 0x53, 0x2D, 0x0A, 0x45, 0x52, 0x4C, 0x41, 0x55, 0x42, 0x4E, 0x49, 0x53,
+ 0x2E, 0x0B, 0x53, 0x49, 0x45, 0x20, 0x42, 0x45, 0x4B, 0x4F, 0x4D, 0x4D, 0x45, 0x4E, 0x0A, 0x45,
+ 0x49, 0x4E, 0x45, 0x20, 0x49, 0x4E, 0x20, 0x44, 0x45, 0x52, 0x0A, 0x56, 0x45, 0x52, 0x57, 0x41,
+ 0x4C, 0x54, 0x55, 0x4E, 0x47, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x43, 0x48, 0x20, 0x48, 0x41,
+ 0x42, 0x45, 0x20, 0x4B, 0x45, 0x49, 0x4E, 0x45, 0x0A, 0x5A, 0x45, 0x49, 0x54, 0x2E, 0x00, 0x47,
+ 0x55, 0x54, 0x45, 0x4E, 0x20, 0x4D, 0x4F, 0x52, 0x47, 0x45, 0x4E, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x47, 0x55, 0x54, 0x45, 0x4E, 0x20, 0x4D, 0x4F, 0x52, 0x47, 0x45, 0x4E, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x49, 0x43, 0x48, 0x20, 0x53, 0x41, 0x48, 0x20, 0x44, 0x49, 0x45, 0x53, 0x45, 0x4E, 0x0A,
+ 0x54, 0x59, 0x50, 0x45, 0x4E, 0x20, 0x53, 0x43, 0x48, 0x4F, 0x4E, 0x20, 0x4D, 0x41, 0x4C, 0x0A,
+ 0x49, 0x4E, 0x20, 0x44, 0x45, 0x52, 0x20, 0x4B, 0x4E, 0x45, 0x49, 0x50, 0x45, 0x2E, 0x00, 0x47,
+ 0x55, 0x54, 0x45, 0x4E, 0x20, 0x4D, 0x4F, 0x52, 0x47, 0x45, 0x4E, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x47, 0x55, 0x54, 0x45, 0x4E, 0x20, 0x4D, 0x4F, 0x52, 0x47, 0x45, 0x4E, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x49, 0x43, 0x48, 0x20, 0x4B, 0x45, 0x4E, 0x4E, 0x45, 0x20, 0x49, 0x48, 0x4E, 0x2E, 0x0A,
+ 0x49, 0x53, 0x54, 0x20, 0x53, 0x54, 0x41, 0x4D, 0x4D, 0x4B, 0x55, 0x4E, 0x44, 0x45, 0x2E, 0x00,
+ 0x20, 0x00, 0x20, 0x00, 0x49, 0x43, 0x48, 0x20, 0x4D, 0x5D, 0x43, 0x48, 0x54, 0x45, 0x20, 0x45,
+ 0x49, 0x4E, 0x45, 0x0A, 0x41, 0x52, 0x42, 0x45, 0x49, 0x54, 0x53, 0x45, 0x52, 0x4C, 0x41, 0x55,
+ 0x42, 0x4E, 0x49, 0x53, 0x0B, 0xFF, 0xEB, 0xEC, 0x4B, 0x45, 0x49, 0x4E, 0x20, 0x50, 0x52, 0x4F,
+ 0x42, 0x4C, 0x45, 0x4D, 0x2C, 0x0A, 0x45, 0x49, 0x4E, 0x45, 0x20, 0x45, 0x52, 0x4C, 0x41, 0x55,
+ 0x42, 0x4E, 0x49, 0x53, 0x0A, 0x5A, 0x55, 0x20, 0x42, 0x45, 0x4B, 0x4F, 0x4D, 0x4D, 0x45, 0x4E,
+ 0x2E, 0x2E, 0x2E, 0x0B, 0x49, 0x43, 0x48, 0x20, 0x42, 0x45, 0x4E, 0x5D, 0x54, 0x49, 0x47, 0x45,
+ 0x0A, 0x49, 0x48, 0x52, 0x45, 0x20, 0x4B, 0x41, 0x52, 0x54, 0x45, 0x2E, 0x00, 0xFF, 0xEB, 0xEC,
+ 0x48, 0x49, 0x4C, 0x46, 0x45, 0x2E, 0x2E, 0x2E, 0x0A, 0x48, 0x49, 0x4C, 0x46, 0x45, 0x2E, 0x2E,
+ 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x48, 0x45, 0x4C, 0x46, 0x45, 0x4E, 0x20, 0x53, 0x49, 0x45, 0x20,
+ 0x4D, 0x49, 0x52, 0x2E, 0x0A, 0x49, 0x43, 0x48, 0x20, 0x57, 0x55, 0x52, 0x44, 0x45, 0x20, 0x56,
+ 0x4F, 0x4E, 0x0A, 0x4D, 0x55, 0x54, 0x41, 0x4E, 0x54, 0x45, 0x4E, 0x0A, 0x41, 0x4E, 0x47, 0x45,
+ 0x47, 0x52, 0x49, 0x46, 0x46, 0x45, 0x4E, 0x2E, 0x2E, 0x2E, 0x0B, 0x55, 0x4E, 0x44, 0x20, 0x49,
+ 0x43, 0x48, 0x20, 0x4B, 0x41, 0x4E, 0x4E, 0x0A, 0x4E, 0x49, 0x43, 0x48, 0x54, 0x20, 0x4C, 0x41,
+ 0x55, 0x46, 0x45, 0x4E, 0x2E, 0x0B, 0x48, 0x4F, 0x4C, 0x45, 0x4E, 0x20, 0x53, 0x49, 0x45, 0x20,
+ 0x4D, 0x45, 0x49, 0x4E, 0x45, 0x4E, 0x0A, 0x54, 0x45, 0x4C, 0x45, 0x50, 0x4F, 0x52, 0x54, 0x45,
+ 0x52, 0x2C, 0x20, 0x49, 0x43, 0x48, 0x0A, 0x42, 0x52, 0x41, 0x55, 0x43, 0x48, 0x45, 0x20, 0x5C,
+ 0x52, 0x5A, 0x54, 0x2D, 0x0A, 0x4C, 0x49, 0x43, 0x48, 0x45, 0x20, 0x48, 0x49, 0x4C, 0x46, 0x45,
+ 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x44, 0x41, 0x4E, 0x4B, 0x45, 0x2E, 0x20, 0x53, 0x49, 0x45, 0x20,
+ 0x52, 0x45, 0x54, 0x2D, 0x0A, 0x54, 0x45, 0x54, 0x45, 0x4E, 0x20, 0x4D, 0x45, 0x49, 0x4E, 0x20,
+ 0x4C, 0x45, 0x42, 0x45, 0x4E, 0x00, 0xFF, 0xEB, 0xEC, 0x53, 0x50, 0x52, 0x49, 0x4E, 0x47, 0x45,
+ 0x4E, 0x20, 0x53, 0x49, 0x45, 0x20, 0x49, 0x4E, 0x0A, 0x44, 0x49, 0x45, 0x53, 0x45, 0x53, 0x20,
+ 0x4C, 0x4F, 0x43, 0x48, 0x2C, 0x0B, 0x55, 0x4D, 0x20, 0x4E, 0x41, 0x43, 0x48, 0x20, 0x4E, 0x45,
+ 0x57, 0x0A, 0x57, 0x41, 0x53, 0x48, 0x49, 0x4E, 0x47, 0x54, 0x4F, 0x4E, 0x0A, 0x5A, 0x55, 0x20,
+ 0x4B, 0x4F, 0x4D, 0x4D, 0x45, 0x4E, 0x2E, 0x0B, 0x41, 0x42, 0x45, 0x52, 0x2C, 0x20, 0x49, 0x43,
+ 0x48, 0x20, 0x57, 0x5B, 0x52, 0x44, 0x45, 0x0A, 0x45, 0x49, 0x4E, 0x45, 0x4E, 0x20, 0x41, 0x4E,
+ 0x54, 0x49, 0x2D, 0x47, 0x2D, 0x0A, 0x47, 0x5B, 0x52, 0x54, 0x45, 0x4C, 0x20, 0x42, 0x45, 0x4E,
+ 0x55, 0x54, 0x5A, 0x45, 0x4E, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x57, 0x4F, 0x20, 0x4B, 0x41, 0x4E,
+ 0x4E, 0x20, 0x49, 0x43, 0x48, 0x0A, 0x45, 0x49, 0x4E, 0x45, 0x4E, 0x20, 0x42, 0x45, 0x4B, 0x4F,
+ 0x4D, 0x4D, 0x45, 0x4E, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x55, 0x4E, 0x2C, 0x20, 0x49, 0x43,
+ 0x48, 0x0A, 0x56, 0x45, 0x52, 0x4B, 0x41, 0x55, 0x46, 0x45, 0x20, 0x45, 0x49, 0x4E, 0x45, 0x4E,
+ 0x3A, 0x0A, 0x35, 0x30, 0x30, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x53, 0x2E, 0x00, 0xFF,
+ 0xEB, 0xEC, 0x47, 0x55, 0x54, 0x45, 0x20, 0x52, 0x45, 0x49, 0x53, 0x45, 0x2C, 0x0A, 0x4A, 0x55,
+ 0x4E, 0x47, 0x45, 0x52, 0x20, 0x4D, 0x41, 0x4E, 0x4E, 0x2E, 0x00, 0x49, 0x43, 0x48, 0x20, 0x42,
+ 0x52, 0x41, 0x55, 0x43, 0x48, 0x45, 0x20, 0x45, 0x49, 0x4E, 0x0A, 0x41, 0x55, 0x46, 0x47, 0x45,
+ 0x4C, 0x41, 0x44, 0x45, 0x4E, 0x45, 0x53, 0x20, 0x4D, 0x41, 0x2D, 0x0A, 0x47, 0x4E, 0x45, 0x54,
+ 0x2D, 0x43, 0x41, 0x52, 0x54, 0x52, 0x49, 0x44, 0x47, 0x45, 0x2E, 0x00, 0x49, 0x43, 0x48, 0x20,
+ 0x4D, 0x5D, 0x43, 0x48, 0x54, 0x45, 0x20, 0x45, 0x49, 0x4E, 0x45, 0x0A, 0x41, 0x52, 0x42, 0x45,
+ 0x49, 0x54, 0x53, 0x45, 0x52, 0x4C, 0x41, 0x55, 0x42, 0x4E, 0x49, 0x53, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x45, 0x52, 0x53, 0x54, 0x45, 0x20, 0x45, 0x54, 0x41, 0x47, 0x45, 0x2E, 0x00, 0x45, 0x49, 0x4E,
+ 0x45, 0x20, 0x49, 0x4E, 0x4E, 0x45, 0x52, 0x45, 0x0A, 0x53, 0x54, 0x49, 0x4D, 0x4D, 0x45, 0x0A,
+ 0x55, 0x4E, 0x54, 0x45, 0x52, 0x42, 0x52, 0x49, 0x43, 0x48, 0x54, 0x0A, 0x44, 0x45, 0x49, 0x4E,
+ 0x45, 0x20, 0x47, 0x45, 0x44, 0x41, 0x4E, 0x4B, 0x45, 0x4E, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x56,
+ 0x45, 0x52, 0x54, 0x52, 0x41, 0x55, 0x20, 0x4D, 0x49, 0x52, 0x2C, 0x0A, 0x42, 0x52, 0x49, 0x4E,
+ 0x47, 0x20, 0x44, 0x49, 0x45, 0x20, 0x41, 0x54, 0x4F, 0x4D, 0x2D, 0x0A, 0x4C, 0x41, 0x44, 0x55,
+ 0x4E, 0x47, 0x20, 0x48, 0x49, 0x45, 0x52, 0x20, 0x41, 0x4E, 0x2E, 0x2E, 0x0B, 0x55, 0x4E, 0x44,
+ 0x20, 0x46, 0x4C, 0x49, 0x45, 0x48, 0x45, 0x2C, 0x20, 0x42, 0x45, 0x2D, 0x0A, 0x56, 0x4F, 0x52,
+ 0x20, 0x53, 0x49, 0x45, 0x20, 0x44, 0x41, 0x53, 0x20, 0x48, 0x45, 0x52, 0x5A, 0x0A, 0x44, 0x45,
+ 0x53, 0x20, 0x50, 0x4C, 0x41, 0x4E, 0x45, 0x54, 0x45, 0x4E, 0x0A, 0x45, 0x52, 0x52, 0x45, 0x49,
+ 0x43, 0x48, 0x54, 0x20, 0x48, 0x41, 0x54, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x5A, 0x55, 0x4D, 0x20,
+ 0x46, 0x4F, 0x52, 0x53, 0x43, 0x48, 0x55, 0x4E, 0x47, 0x53, 0x2D, 0x0A, 0x5A, 0x45, 0x4E, 0x54,
+ 0x52, 0x55, 0x4D, 0x2C, 0x20, 0x42, 0x49, 0x54, 0x54, 0x45, 0x2E, 0x0B, 0x4E, 0x41, 0x43, 0x48,
+ 0x20, 0x49, 0x48, 0x4E, 0x45, 0x4E, 0x2C, 0x0A, 0x4A, 0x55, 0x4E, 0x47, 0x45, 0x52, 0x20, 0x4D,
+ 0x41, 0x4E, 0x4E, 0x00, 0xFF, 0xEB, 0xEC, 0x44, 0x41, 0x4E, 0x4B, 0x45, 0x20, 0x46, 0x5B, 0x52,
+ 0x0A, 0x49, 0x48, 0x52, 0x45, 0x20, 0x48, 0x49, 0x4C, 0x46, 0x45, 0x0B, 0x49, 0x43, 0x48, 0x20,
+ 0x42, 0x49, 0x4E, 0x20, 0x53, 0x49, 0x43, 0x48, 0x45, 0x52, 0x0A, 0x41, 0x4E, 0x47, 0x45, 0x4B,
+ 0x4F, 0x4D, 0x4D, 0x45, 0x4E, 0x2E, 0x20, 0x45, 0x53, 0x0A, 0x42, 0x45, 0x53, 0x54, 0x45, 0x48,
+ 0x54, 0x20, 0x4B, 0x45, 0x49, 0x4E, 0x45, 0x0A, 0x47, 0x45, 0x46, 0x41, 0x48, 0x52, 0x20, 0x4D,
+ 0x45, 0x48, 0x52, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x48, 0x41, 0x42, 0x45, 0x4E, 0x20, 0x53, 0x49,
+ 0x45, 0x20, 0x4D, 0x49, 0x52, 0x0A, 0x44, 0x41, 0x53, 0x20, 0x50, 0x41, 0x4B, 0x45, 0x54, 0x0A,
+ 0x4D, 0x49, 0x54, 0x47, 0x45, 0x42, 0x52, 0x41, 0x43, 0x48, 0x54, 0x3F, 0x00, 0x57, 0x41, 0x53,
+ 0x20, 0x4B, 0x4F, 0x53, 0x54, 0x45, 0x54, 0x20, 0x45, 0x49, 0x4E, 0x0A, 0x54, 0x49, 0x43, 0x4B,
+ 0x45, 0x54, 0x20, 0x5A, 0x55, 0x52, 0x0A, 0x45, 0x52, 0x44, 0x45, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x35, 0x30, 0x2E, 0x30, 0x30, 0x30, 0x20, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x45, 0x49, 0x4E, 0x45, 0x20, 0x48, 0x41, 0x4E, 0x44, 0x0A, 0x57, 0x5C, 0x53,
+ 0x43, 0x48, 0x54, 0x0A, 0x44, 0x49, 0x45, 0x20, 0x41, 0x4E, 0x44, 0x45, 0x52, 0x45, 0x2E, 0x0B,
+ 0x31, 0x2E, 0x35, 0x30, 0x30, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x53, 0x0A, 0x55, 0x4E,
+ 0x44, 0x20, 0x44, 0x49, 0x45, 0x20, 0x50, 0x41, 0x50, 0x49, 0x45, 0x52, 0x45, 0x0A, 0x47, 0x45,
+ 0x48, 0x5D, 0x52, 0x45, 0x4E, 0x20, 0x44, 0x49, 0x52, 0x2E, 0x00
+};
+
+const uint8_t LocaleData::_stringsTableSP[] = {
+ 0x5A, 0x00, 0x71, 0x00, 0x8F, 0x00, 0xA7, 0x01, 0x71, 0x02, 0x8D, 0x02, 0xD8, 0x02, 0x09, 0x03,
+ 0x6E, 0x03, 0x84, 0x03, 0xBE, 0x03, 0x08, 0x04, 0x51, 0x04, 0x9B, 0x04, 0x18, 0x05, 0x49, 0x05,
+ 0x60, 0x05, 0xC3, 0x05, 0xD4, 0x05, 0xF2, 0x05, 0x8D, 0x06, 0x9B, 0x08, 0x10, 0x09, 0x2A, 0x09,
+ 0x89, 0x09, 0x9D, 0x09, 0xBA, 0x09, 0xE1, 0x09, 0xFE, 0x09, 0x21, 0x0A, 0x23, 0x0A, 0x25, 0x0A,
+ 0x8D, 0x0A, 0xA1, 0x0A, 0x2A, 0x0B, 0x51, 0x0B, 0x05, 0x0C, 0x1F, 0x0C, 0x48, 0x0C, 0x7A, 0x0C,
+ 0x06, 0x0D, 0x40, 0x0D, 0x89, 0x0D, 0xAD, 0x0D, 0xE8, 0x0D, 0x48, 0x41, 0x20, 0x53, 0x41, 0x4C,
+ 0x54, 0x41, 0x44, 0x4F, 0x0A, 0x45, 0x4C, 0x20, 0x46, 0x55, 0x53, 0x49, 0x42, 0x4C, 0x45, 0x2E,
+ 0x00, 0x45, 0x53, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x45, 0x52, 0x49, 0x41, 0x0A, 0x46, 0x55,
+ 0x4E, 0x43, 0x49, 0x4F, 0x4E, 0x41, 0x52, 0x20, 0x41, 0x48, 0x4F, 0x52, 0x41, 0x2E, 0x00, 0xFF,
+ 0xEB, 0xEC, 0x53, 0x4F, 0x59, 0x20, 0x4A, 0x41, 0x43, 0x4B, 0x2E, 0x40, 0x45, 0x53, 0x54, 0x41,
+ 0x53, 0x0A, 0x42, 0x55, 0x53, 0x43, 0x41, 0x4E, 0x44, 0x4F, 0x0A, 0x44, 0x4F, 0x43, 0x55, 0x4D,
+ 0x45, 0x4E, 0x54, 0x41, 0x43, 0x49, 0x4F, 0x4E, 0x0A, 0x46, 0x41, 0x4C, 0x53, 0x41, 0x3F, 0x0B,
+ 0xFF, 0xE9, 0xEA, 0x53, 0x49, 0x2C, 0x20, 0x59, 0x20, 0x4C, 0x4F, 0x0A, 0x4D, 0x41, 0x53, 0x20,
+ 0x52, 0x41, 0x50, 0x49, 0x44, 0x4F, 0x0A, 0x50, 0x4F, 0x53, 0x49, 0x42, 0x4C, 0x45, 0x2E, 0x0B,
+ 0xFF, 0xEB, 0xEC, 0x7B, 0x31, 0x35, 0x30, 0x30, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54, 0x4F,
+ 0x53, 0x21, 0x0B, 0xFF, 0xE9, 0xEA, 0x40, 0x40, 0x40, 0x31, 0x35, 0x30, 0x30, 0x3F, 0x3F, 0x3F,
+ 0x0B, 0xFF, 0xEB, 0xEC, 0x53, 0x49, 0x49, 0x49, 0x2C, 0x20, 0x43, 0x4F, 0x52, 0x52, 0x4F, 0x20,
+ 0x55, 0x4E, 0x0A, 0x47, 0x52, 0x41, 0x4E, 0x20, 0x50, 0x45, 0x4C, 0x49, 0x47, 0x52, 0x4F, 0x0A,
+ 0x41, 0x51, 0x55, 0x49, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x50, 0x45, 0x52, 0x4F, 0x2C, 0x20, 0x59,
+ 0x4F, 0x20, 0x4E, 0x4F, 0x0A, 0x54, 0x45, 0x4E, 0x47, 0x4F, 0x20, 0x53, 0x55, 0x46, 0x49, 0x43,
+ 0x49, 0x45, 0x4E, 0x54, 0x45, 0x0B, 0xFF, 0xEB, 0xEC, 0x56, 0x45, 0x20, 0x41, 0x20, 0x4C, 0x41,
+ 0x20, 0x4F, 0x46, 0x49, 0x43, 0x49, 0x4E, 0x41, 0x0A, 0x44, 0x45, 0x20, 0x45, 0x4D, 0x50, 0x4C,
+ 0x45, 0x4F, 0x2C, 0x0A, 0x41, 0x4C, 0x4C, 0x49, 0x20, 0x45, 0x4E, 0x43, 0x4F, 0x4E, 0x54, 0x52,
+ 0x41, 0x52, 0x41, 0x53, 0x0A, 0x54, 0x52, 0x41, 0x42, 0x41, 0x4A, 0x4F, 0x2E, 0x0B, 0x59, 0x20,
+ 0x56, 0x55, 0x45, 0x4C, 0x56, 0x45, 0x20, 0x41, 0x20, 0x56, 0x45, 0x52, 0x4D, 0x45, 0x0A, 0x43,
+ 0x55, 0x41, 0x4E, 0x44, 0x4F, 0x20, 0x54, 0x45, 0x4E, 0x47, 0x41, 0x53, 0x0A, 0x4C, 0x41, 0x20,
+ 0x50, 0x41, 0x53, 0x54, 0x41, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x43, 0x4F, 0x4E, 0x4F, 0x5A, 0x43,
+ 0x4F, 0x20, 0x41, 0x20, 0x45, 0x53, 0x45, 0x0A, 0x54, 0x49, 0x4F, 0x2E, 0x20, 0x54, 0x49, 0x45,
+ 0x4E, 0x45, 0x20, 0x55, 0x4E, 0x0A, 0x41, 0x4D, 0x49, 0x47, 0x4F, 0x20, 0x45, 0x4E, 0x20, 0x4C,
+ 0x41, 0x0A, 0x50, 0x4F, 0x4C, 0x49, 0x43, 0x49, 0x41, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x40, 0x44,
+ 0x4F, 0x4E, 0x44, 0x45, 0x20, 0x50, 0x55, 0x45, 0x44, 0x4F, 0x0A, 0x45, 0x4E, 0x43, 0x4F, 0x4E,
+ 0x54, 0x52, 0x41, 0x52, 0x20, 0x41, 0x0A, 0x45, 0x53, 0x45, 0x20, 0x41, 0x4D, 0x49, 0x47, 0x4F,
+ 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x56, 0x45, 0x20, 0x41, 0x4C, 0x20, 0x41, 0x52, 0x45, 0x41, 0x0A,
+ 0x52, 0x45, 0x53, 0x54, 0x52, 0x49, 0x4E, 0x47, 0x49, 0x44, 0x41, 0x20, 0x31, 0x2C, 0x0A, 0x43,
+ 0x52, 0x45, 0x4F, 0x20, 0x51, 0x55, 0x45, 0x20, 0x45, 0x53, 0x54, 0x41, 0x20, 0x44, 0x45, 0x0A,
+ 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x49, 0x4F, 0x20, 0x41, 0x4C, 0x4C, 0x49, 0x2E, 0x0B, 0x50,
+ 0x45, 0x52, 0x4F, 0x20, 0x54, 0x45, 0x4E, 0x20, 0x43, 0x55, 0x49, 0x44, 0x41, 0x44, 0x4F, 0x2C,
+ 0x0A, 0x7B, 0x45, 0x53, 0x4F, 0x53, 0x20, 0x54, 0x49, 0x4F, 0x53, 0x20, 0x53, 0x4F, 0x4E, 0x0A,
+ 0x55, 0x4E, 0x4F, 0x53, 0x20, 0x4D, 0x49, 0x53, 0x45, 0x52, 0x41, 0x42, 0x4C, 0x45, 0x53, 0x21,
+ 0x00, 0xFF, 0xEB, 0xEC, 0x59, 0x4F, 0x20, 0x4E, 0x4F, 0x20, 0x53, 0x45, 0x0A, 0x4E, 0x41, 0x44,
+ 0x41, 0x20, 0x4D, 0x41, 0x53, 0x2C, 0x0A, 0x48, 0x49, 0x4A, 0x4F, 0x2E, 0x00, 0xFF, 0xEB, 0xEC,
+ 0x43, 0x59, 0x2D, 0x42, 0x30, 0x32, 0x31, 0x20, 0x51, 0x55, 0x49, 0x45, 0x52, 0x45, 0x0A, 0x48,
+ 0x41, 0x43, 0x45, 0x52, 0x20, 0x55, 0x4E, 0x20, 0x54, 0x52, 0x41, 0x54, 0x4F, 0x0A, 0x43, 0x4F,
+ 0x4E, 0x54, 0x49, 0x47, 0x4F, 0x2E, 0x0B, 0x45, 0x53, 0x54, 0x41, 0x52, 0x41, 0x20, 0x45, 0x53,
+ 0x50, 0x45, 0x52, 0x41, 0x4E, 0x44, 0x4F, 0x0A, 0x44, 0x45, 0x54, 0x52, 0x41, 0x53, 0x20, 0x44,
+ 0x45, 0x4C, 0x20, 0x42, 0x41, 0x52, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x56, 0x45, 0x54, 0x45, 0x20,
+ 0x41, 0x4C, 0x20, 0x42, 0x41, 0x52, 0x2C, 0x0A, 0x48, 0x49, 0x4A, 0x4F, 0x2C, 0x20, 0x43, 0x59,
+ 0x2D, 0x42, 0x30, 0x32, 0x31, 0x20, 0x54, 0x45, 0x0A, 0x45, 0x53, 0x54, 0x41, 0x20, 0x45, 0x53,
+ 0x50, 0x45, 0x52, 0x41, 0x4E, 0x44, 0x4F, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x7B, 0x4E, 0x4F, 0x20,
+ 0x44, 0x49, 0x53, 0x50, 0x41, 0x52, 0x45, 0x53, 0x2C, 0x20, 0x59, 0x4F, 0x0A, 0x4E, 0x4F, 0x20,
+ 0x53, 0x4F, 0x59, 0x20, 0x43, 0x59, 0x2D, 0x42, 0x30, 0x32, 0x31, 0x21, 0x0B, 0x53, 0x55, 0x20,
+ 0x45, 0x53, 0x43, 0x4F, 0x4E, 0x44, 0x52, 0x49, 0x4A, 0x4F, 0x0A, 0x45, 0x53, 0x54, 0x41, 0x20,
+ 0x41, 0x48, 0x49, 0x20, 0x41, 0x42, 0x41, 0x4A, 0x4F, 0x2E, 0x0B, 0x53, 0x55, 0x20, 0x43, 0x4F,
+ 0x4C, 0x45, 0x47, 0x41, 0x2C, 0x0A, 0x45, 0x4C, 0x20, 0x50, 0x4F, 0x4C, 0x49, 0x0A, 0x54, 0x49,
+ 0x45, 0x4E, 0x45, 0x20, 0x4C, 0x41, 0x20, 0x4C, 0x4C, 0x41, 0x56, 0x45, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x59, 0x4F, 0x20, 0x4E, 0x4F, 0x20, 0x53, 0x45, 0x0A, 0x4E, 0x41, 0x44, 0x41, 0x20, 0x4D,
+ 0x41, 0x53, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x55, 0x4E, 0x20, 0x54, 0x49, 0x4F, 0x20, 0x4C, 0x4C,
+ 0x41, 0x4D, 0x41, 0x44, 0x4F, 0x0B, 0x4A, 0x41, 0x43, 0x4B, 0x20, 0x41, 0x43, 0x4F, 0x52, 0x44,
+ 0x4F, 0x0A, 0x52, 0x45, 0x55, 0x4E, 0x49, 0x52, 0x53, 0x45, 0x20, 0x43, 0x4F, 0x4E, 0x20, 0x55,
+ 0x44, 0x2E, 0x0A, 0x45, 0x4E, 0x20, 0x45, 0x4C, 0x20, 0x42, 0x41, 0x52, 0x2E, 0x00, 0x51, 0x55,
+ 0x45, 0x52, 0x52, 0x49, 0x41, 0x20, 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53, 0x4F,
+ 0x20, 0x44, 0x45, 0x0A, 0x54, 0x52, 0x41, 0x42, 0x41, 0x4A, 0x4F, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x4E, 0x4F, 0x2C, 0x20, 0x4E, 0x4F, 0x20, 0x45, 0x53, 0x20, 0x41, 0x51, 0x55, 0x49, 0x2E, 0x0A,
+ 0x56, 0x41, 0x59, 0x41, 0x20, 0x41, 0x20, 0x4C, 0x41, 0x0A, 0x56, 0x45, 0x4E, 0x54, 0x41, 0x4E,
+ 0x49, 0x4C, 0x4C, 0x41, 0x20, 0x43, 0x2E, 0x00, 0x51, 0x55, 0x45, 0x52, 0x52, 0x49, 0x41, 0x20,
+ 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53, 0x4F, 0x20, 0x44, 0x45, 0x0A, 0x54, 0x52,
+ 0x41, 0x42, 0x41, 0x4A, 0x4F, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x42, 0x49, 0x45, 0x4E, 0x20, 0x2E,
+ 0x2E, 0x4F, 0x2E, 0x4B, 0x2E, 0x2C, 0x0A, 0x45, 0x4C, 0x20, 0x4A, 0x45, 0x46, 0x45, 0x20, 0x4C,
+ 0x45, 0x0A, 0x52, 0x45, 0x43, 0x49, 0x42, 0x49, 0x52, 0x41, 0x20, 0x41, 0x48, 0x4F, 0x52, 0x41,
+ 0x00, 0x51, 0x55, 0x45, 0x52, 0x52, 0x49, 0x41, 0x20, 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D,
+ 0x49, 0x53, 0x4F, 0x20, 0x44, 0x45, 0x0A, 0x54, 0x52, 0x41, 0x42, 0x41, 0x4A, 0x4F, 0x2E, 0x0B,
+ 0xFF, 0xEB, 0xEC, 0x4E, 0x4F, 0x2C, 0x20, 0x4E, 0x4F, 0x20, 0x45, 0x53, 0x20, 0x41, 0x51, 0x55,
+ 0x49, 0x2E, 0x0A, 0x56, 0x41, 0x59, 0x41, 0x20, 0x41, 0x20, 0x4C, 0x41, 0x0A, 0x56, 0x45, 0x4E,
+ 0x54, 0x41, 0x4E, 0x49, 0x4C, 0x4C, 0x41, 0x20, 0x42, 0x2E, 0x00, 0x51, 0x55, 0x49, 0x45, 0x52,
+ 0x4F, 0x20, 0x48, 0x41, 0x42, 0x4C, 0x41, 0x52, 0x0A, 0x43, 0x4F, 0x4E, 0x20, 0x4A, 0x41, 0x43,
+ 0x4B, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x40, 0x41, 0x48, 0x20, 0x53, 0x49, 0x3F, 0x20, 0x4A, 0x41,
+ 0x43, 0x4B, 0x20, 0x4E, 0x4F, 0x0A, 0x45, 0x53, 0x54, 0x41, 0x20, 0x41, 0x51, 0x55, 0x49, 0x20,
+ 0x41, 0x48, 0x4F, 0x52, 0x41, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x4D, 0x45, 0x20, 0x45, 0x4E, 0x56,
+ 0x49, 0x41, 0x0A, 0x4D, 0x49, 0x20, 0x41, 0x4D, 0x49, 0x47, 0x4F, 0x20, 0x49, 0x41, 0x4E, 0x2E,
+ 0x0B, 0xFF, 0xEB, 0xEC, 0x4F, 0x2E, 0x4B, 0x2E, 0x20, 0x4A, 0x41, 0x43, 0x4B, 0x20, 0x54, 0x45,
+ 0x0A, 0x45, 0x53, 0x54, 0x41, 0x20, 0x45, 0x53, 0x50, 0x45, 0x52, 0x41, 0x4E, 0x44, 0x4F, 0x0A,
+ 0x41, 0x46, 0x55, 0x45, 0x52, 0x41, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x54, 0x49, 0x52, 0x41, 0x4C,
+ 0x4F, 0x2C, 0x20, 0x48, 0x49, 0x4A, 0x4F, 0x2E, 0x0A, 0x45, 0x52, 0x45, 0x53, 0x20, 0x44, 0x45,
+ 0x4D, 0x41, 0x53, 0x49, 0x41, 0x44, 0x4F, 0x0A, 0x4A, 0x4F, 0x56, 0x45, 0x4E, 0x20, 0x50, 0x41,
+ 0x52, 0x41, 0x20, 0x42, 0x45, 0x42, 0x45, 0x52, 0x00, 0xFF, 0xEB, 0xEC, 0x50, 0x41, 0x50, 0x45,
+ 0x4C, 0x45, 0x53, 0x2C, 0x0A, 0x50, 0x4F, 0x52, 0x20, 0x46, 0x41, 0x56, 0x4F, 0x52, 0x2E, 0x00,
+ 0x53, 0x4F, 0x59, 0x20, 0x45, 0x4C, 0x0A, 0x4D, 0x45, 0x4E, 0x53, 0x41, 0x4A, 0x45, 0x52, 0x4F,
+ 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x7B, 0x41, 0x48, 0x20, 0x53, 0x49, 0x21, 0x20, 0x4C, 0x4C, 0x45,
+ 0x56, 0x41, 0x0A, 0x45, 0x53, 0x54, 0x45, 0x20, 0x50, 0x41, 0x51, 0x55, 0x45, 0x54, 0x45, 0x20,
+ 0x41, 0x0A, 0x4C, 0x41, 0x20, 0x41, 0x47, 0x45, 0x4E, 0x43, 0x49, 0x41, 0x20, 0x44, 0x45, 0x0A,
+ 0x56, 0x49, 0x41, 0x4A, 0x45, 0x53, 0x2E, 0x0B, 0x59, 0x20, 0x54, 0x45, 0x4E, 0x20, 0x43, 0x55,
+ 0x49, 0x44, 0x41, 0x44, 0x4F, 0x2C, 0x0A, 0x45, 0x53, 0x20, 0x56, 0x41, 0x4C, 0x49, 0x4F, 0x53,
+ 0x4F, 0x2E, 0x00, 0x54, 0x49, 0x45, 0x4D, 0x50, 0x4F, 0x20, 0x43, 0x4F, 0x4E, 0x43, 0x4C, 0x55,
+ 0x49, 0x44, 0x4F, 0x00, 0x48, 0x41, 0x59, 0x20, 0x55, 0x4E, 0x20, 0x4C, 0x55, 0x47, 0x41, 0x52,
+ 0x0A, 0x50, 0x41, 0x52, 0x41, 0x20, 0x4C, 0x41, 0x20, 0x54, 0x41, 0x52, 0x4A, 0x45, 0x54, 0x41,
+ 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x47, 0x52, 0x41, 0x43, 0x49, 0x41, 0x53, 0x2C, 0x20, 0x43, 0x4F,
+ 0x4E, 0x52, 0x41, 0x44, 0x2E, 0x0A, 0x7B, 0x45, 0x53, 0x54, 0x4F, 0x53, 0x20, 0x50, 0x4F, 0x4C,
+ 0x49, 0x53, 0x0A, 0x48, 0x41, 0x42, 0x52, 0x49, 0x41, 0x4E, 0x20, 0x43, 0x4F, 0x4E, 0x53, 0x45,
+ 0x47, 0x55, 0x49, 0x44, 0x4F, 0x0A, 0x4D, 0x49, 0x20, 0x50, 0x45, 0x4C, 0x4C, 0x45, 0x4A, 0x4F,
+ 0x21, 0x0B, 0x42, 0x49, 0x45, 0x4E, 0x2C, 0x53, 0x55, 0x50, 0x4F, 0x4E, 0x47, 0x4F, 0x20, 0x51,
+ 0x55, 0x45, 0x0A, 0x4E, 0x4F, 0x20, 0x52, 0x45, 0x43, 0x55, 0x45, 0x52, 0x44, 0x41, 0x53, 0x20,
+ 0x41, 0x0A, 0x54, 0x55, 0x20, 0x56, 0x49, 0x45, 0x4A, 0x4F, 0x0A, 0x41, 0x4D, 0x49, 0x47, 0x4F,
+ 0x20, 0x49, 0x41, 0x4E, 0x2E, 0x0B, 0x53, 0x49, 0x45, 0x4E, 0x54, 0x41, 0x54, 0x45, 0x2C, 0x0A,
+ 0x41, 0x52, 0x52, 0x45, 0x47, 0x4C, 0x41, 0x52, 0x45, 0x4D, 0x4F, 0x53, 0x0A, 0x45, 0x53, 0x54,
+ 0x4F, 0x20, 0x45, 0x4E, 0x53, 0x45, 0x47, 0x55, 0x49, 0x44, 0x41, 0x2E, 0x00, 0x49, 0x41, 0x4E,
+ 0x2C, 0x20, 0x40, 0x51, 0x55, 0x45, 0x20, 0x54, 0x49, 0x45, 0x4E, 0x45, 0x0A, 0x55, 0x4E, 0x4F,
+ 0x20, 0x51, 0x55, 0x45, 0x20, 0x48, 0x41, 0x43, 0x45, 0x52, 0x20, 0x0A, 0x50, 0x41, 0x52, 0x41,
+ 0x20, 0x49, 0x52, 0x20, 0x41, 0x0A, 0x4C, 0x41, 0x20, 0x54, 0x49, 0x45, 0x52, 0x52, 0x41, 0x3F,
+ 0x0B, 0xFF, 0xEB, 0xEC, 0x45, 0x4C, 0x20, 0x50, 0x52, 0x45, 0x43, 0x49, 0x4F, 0x20, 0x44, 0x45,
+ 0x4C, 0x0A, 0x42, 0x49, 0x4C, 0x4C, 0x45, 0x54, 0x45, 0x20, 0x45, 0x53, 0x0A, 0x41, 0x53, 0x54,
+ 0x52, 0x4F, 0x4E, 0x4F, 0x4D, 0x49, 0x43, 0x4F, 0x2E, 0x0B, 0x53, 0x4F, 0x4C, 0x4F, 0x20, 0x54,
+ 0x45, 0x20, 0x51, 0x55, 0x45, 0x44, 0x41, 0x0A, 0x50, 0x41, 0x52, 0x54, 0x49, 0x43, 0x49, 0x50,
+ 0x41, 0x52, 0x20, 0x45, 0x4E, 0x20, 0x4C, 0x41, 0x0A, 0x54, 0x4F, 0x52, 0x52, 0x45, 0x20, 0x44,
+ 0x45, 0x20, 0x4C, 0x41, 0x0A, 0x4D, 0x55, 0x45, 0x52, 0x54, 0x45, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA,
+ 0x40, 0x4C, 0x41, 0x20, 0x54, 0x4F, 0x52, 0x52, 0x45, 0x0A, 0x44, 0x45, 0x20, 0x4C, 0x41, 0x20,
+ 0x4D, 0x55, 0x45, 0x52, 0x54, 0x45, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x45, 0x53, 0x20, 0x55, 0x4E,
+ 0x20, 0x43, 0x4F, 0x4E, 0x43, 0x55, 0x52, 0x53, 0x4F, 0x0A, 0x44, 0x45, 0x20, 0x4C, 0x41, 0x20,
+ 0x54, 0x45, 0x4C, 0x45, 0x2E, 0x20, 0x45, 0x4C, 0x0A, 0x47, 0x41, 0x4E, 0x41, 0x44, 0x4F, 0x52,
+ 0x20, 0x4F, 0x42, 0x54, 0x49, 0x45, 0x4E, 0x45, 0x0A, 0x55, 0x4E, 0x20, 0x42, 0x49, 0x4C, 0x4C,
+ 0x45, 0x54, 0x45, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x4F, 0x2E, 0x4B, 0x2E, 0x20, 0x40, 0x50, 0x55,
+ 0x45, 0x44, 0x45, 0x53, 0x0A, 0x43, 0x4F, 0x4E, 0x53, 0x45, 0x47, 0x55, 0x49, 0x52, 0x4D, 0x45,
+ 0x0A, 0x44, 0x4F, 0x43, 0x55, 0x4D, 0x45, 0x4E, 0x54, 0x41, 0x43, 0x49, 0x4F, 0x4E, 0x0A, 0x46,
+ 0x41, 0x4C, 0x53, 0x41, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x53, 0x49, 0x4E, 0x20, 0x50, 0x52, 0x4F,
+ 0x42, 0x4C, 0x45, 0x4D, 0x41, 0x53, 0x2E, 0x0A, 0x56, 0x45, 0x20, 0x41, 0x4C, 0x20, 0x42, 0x41,
+ 0x52, 0x20, 0x59, 0x0A, 0x50, 0x52, 0x45, 0x47, 0x55, 0x4E, 0x54, 0x41, 0x20, 0x50, 0x4F, 0x52,
+ 0x0A, 0x4A, 0x41, 0x43, 0x4B, 0x2E, 0x0B, 0x44, 0x49, 0x4C, 0x45, 0x20, 0x51, 0x55, 0x45, 0x20,
+ 0x54, 0x45, 0x0A, 0x45, 0x4E, 0x56, 0x49, 0x4F, 0x20, 0x59, 0x4F, 0x2E, 0x20, 0x41, 0x48, 0x2C,
+ 0x0A, 0x50, 0x4F, 0x52, 0x20, 0x43, 0x49, 0x45, 0x52, 0x54, 0x4F, 0x2E, 0x2E, 0x2E, 0x0B, 0x50,
+ 0x55, 0x53, 0x45, 0x20, 0x45, 0x4C, 0x20, 0x43, 0x41, 0x4D, 0x50, 0x4F, 0x20, 0x44, 0x45, 0x0A,
+ 0x46, 0x55, 0x45, 0x52, 0x5A, 0x41, 0x20, 0x51, 0x55, 0x45, 0x20, 0x4D, 0x45, 0x0A, 0x50, 0x45,
+ 0x44, 0x49, 0x53, 0x54, 0x45, 0x20, 0x45, 0x4E, 0x20, 0x54, 0x55, 0x0A, 0x42, 0x4F, 0x4C, 0x53,
+ 0x49, 0x4C, 0x4C, 0x4F, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x43, 0x48, 0x41, 0x43, 0x48, 0x49, 0x2E,
+ 0x20, 0x47, 0x52, 0x41, 0x43, 0x49, 0x41, 0x53, 0x0A, 0x49, 0x41, 0x4E, 0x2E, 0x20, 0x48, 0x41,
+ 0x53, 0x54, 0x41, 0x20, 0x4C, 0x41, 0x0A, 0x50, 0x52, 0x4F, 0x58, 0x49, 0x4D, 0x41, 0x2E, 0x2E,
+ 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x42, 0x55, 0x45, 0x4E, 0x41, 0x20, 0x53, 0x55, 0x45, 0x52, 0x54,
+ 0x45, 0x2E, 0x0A, 0x43, 0x4F, 0x4E, 0x54, 0x41, 0x43, 0x54, 0x41, 0x52, 0x45, 0x4D, 0x4F, 0x53,
+ 0x0A, 0x41, 0x20, 0x54, 0x55, 0x20, 0x4C, 0x4C, 0x45, 0x47, 0x41, 0x44, 0x41, 0x20, 0x41, 0x0A,
+ 0x4C, 0x41, 0x20, 0x54, 0x49, 0x45, 0x52, 0x52, 0x41, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x42, 0x49,
+ 0x45, 0x4E, 0x56, 0x45, 0x4E, 0x49, 0x44, 0x4F, 0x20, 0x41, 0x0A, 0x4E, 0x45, 0x57, 0x20, 0x57,
+ 0x41, 0x53, 0x48, 0x49, 0x4E, 0x47, 0x54, 0x4F, 0x4E, 0x2C, 0x0A, 0x4A, 0x4F, 0x56, 0x45, 0x4E,
+ 0x43, 0x49, 0x54, 0x4F, 0x2E, 0x0B, 0x41, 0x51, 0x55, 0x49, 0x20, 0x54, 0x49, 0x45, 0x4E, 0x45,
+ 0x53, 0x20, 0x55, 0x4E, 0x0A, 0x4D, 0x41, 0x50, 0x41, 0x20, 0x44, 0x45, 0x20, 0x4C, 0x41, 0x0A,
+ 0x43, 0x49, 0x55, 0x44, 0x41, 0x44, 0x20, 0x51, 0x55, 0x45, 0x20, 0x54, 0x45, 0x0A, 0x53, 0x45,
+ 0x52, 0x41, 0x20, 0x4D, 0x55, 0x59, 0x20, 0x55, 0x54, 0x49, 0x4C, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA,
+ 0x4D, 0x55, 0x43, 0x48, 0x41, 0x53, 0x20, 0x47, 0x52, 0x41, 0x43, 0x49, 0x41, 0x53, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x51, 0x55, 0x45, 0x20, 0x54, 0x45, 0x4E, 0x47, 0x41, 0x20, 0x55, 0x4E, 0x0A,
+ 0x42, 0x55, 0x45, 0x4E, 0x20, 0x44, 0x49, 0x41, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x44, 0x45, 0x42,
+ 0x45, 0x20, 0x54, 0x45, 0x4E, 0x45, 0x52, 0x20, 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49,
+ 0x53, 0x4F, 0x20, 0x50, 0x41, 0x52, 0x41, 0x0A, 0x50, 0x4F, 0x44, 0x45, 0x52, 0x20, 0x54, 0x52,
+ 0x41, 0x42, 0x41, 0x4A, 0x41, 0x52, 0x2E, 0x0B, 0x50, 0x55, 0x45, 0x44, 0x45, 0x20, 0x43, 0x4F,
+ 0x4E, 0x53, 0x45, 0x47, 0x55, 0x49, 0x52, 0x0A, 0x55, 0x4E, 0x4F, 0x20, 0x45, 0x4E, 0x20, 0x45,
+ 0x4C, 0x20, 0x43, 0x45, 0x4E, 0x54, 0x52, 0x4F, 0x0A, 0x41, 0x44, 0x4D, 0x49, 0x4E, 0x49, 0x53,
+ 0x54, 0x52, 0x41, 0x54, 0x49, 0x56, 0x4F, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x4E, 0x4F, 0x20, 0x54,
+ 0x45, 0x4E, 0x47, 0x4F, 0x0A, 0x54, 0x49, 0x45, 0x4D, 0x50, 0x4F, 0x2E, 0x00, 0x42, 0x55, 0x45,
+ 0x4E, 0x4F, 0x53, 0x20, 0x44, 0x49, 0x41, 0x53, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x42, 0x55, 0x45,
+ 0x4E, 0x4F, 0x53, 0x20, 0x44, 0x49, 0x41, 0x53, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x48, 0x45, 0x20,
+ 0x56, 0x49, 0x53, 0x54, 0x4F, 0x20, 0x41, 0x20, 0x45, 0x53, 0x45, 0x0A, 0x54, 0x49, 0x4F, 0x20,
+ 0x41, 0x4E, 0x54, 0x45, 0x53, 0x20, 0x45, 0x4E, 0x0A, 0x45, 0x4C, 0x20, 0x42, 0x41, 0x52, 0x2E,
+ 0x00, 0x42, 0x55, 0x45, 0x4E, 0x4F, 0x53, 0x20, 0x44, 0x49, 0x41, 0x53, 0x2E, 0x0B, 0xFF, 0xEB,
+ 0xEC, 0x42, 0x55, 0x45, 0x4E, 0x4F, 0x53, 0x20, 0x44, 0x49, 0x41, 0x53, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x53, 0x49, 0x2C, 0x20, 0x4C, 0x45, 0x20, 0x43, 0x4F, 0x4E, 0x4F, 0x5A, 0x43, 0x4F, 0x2E,
+ 0x0A, 0x45, 0x53, 0x20, 0x55, 0x4E, 0x20, 0x48, 0x41, 0x42, 0x49, 0x54, 0x55, 0x41, 0x4C, 0x2E,
+ 0x00, 0x20, 0x00, 0x20, 0x00, 0x51, 0x55, 0x45, 0x52, 0x52, 0x49, 0x41, 0x20, 0x55, 0x4E, 0x0A,
+ 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53, 0x4F, 0x20, 0x44, 0x45, 0x0A, 0x54, 0x52, 0x41, 0x42, 0x41,
+ 0x4A, 0x4F, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x4F, 0x20, 0x48, 0x41, 0x59, 0x20, 0x50, 0x52,
+ 0x4F, 0x42, 0x4C, 0x45, 0x4D, 0x41, 0x2E, 0x0A, 0x50, 0x41, 0x52, 0x41, 0x20, 0x43, 0x4F, 0x4E,
+ 0x53, 0x45, 0x47, 0x55, 0x49, 0x52, 0x0A, 0x55, 0x4E, 0x20, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53,
+ 0x4F, 0x2E, 0x2E, 0x2E, 0x0B, 0x4E, 0x45, 0x43, 0x45, 0x53, 0x49, 0x54, 0x4F, 0x20, 0x53, 0x55,
+ 0x0A, 0x54, 0x41, 0x52, 0x4A, 0x45, 0x54, 0x41, 0x20, 0x49, 0x44, 0x2E, 0x00, 0xFF, 0xEB, 0xEC,
+ 0x41, 0x59, 0x55, 0x44, 0x41, 0x2E, 0x2E, 0x2E, 0x41, 0x59, 0x55, 0x44, 0x41, 0x2E, 0x2E, 0x2E,
+ 0x00, 0xFF, 0xEB, 0xEC, 0x41, 0x59, 0x55, 0x44, 0x45, 0x4D, 0x45, 0x2C, 0x20, 0x4A, 0x4F, 0x56,
+ 0x45, 0x4E, 0x2E, 0x0A, 0x48, 0x45, 0x20, 0x53, 0x49, 0x44, 0x4F, 0x20, 0x41, 0x54, 0x41, 0x43,
+ 0x41, 0x44, 0x4F, 0x0A, 0x50, 0x4F, 0x52, 0x20, 0x55, 0x4E, 0x4F, 0x53, 0x20, 0x0A, 0x4D, 0x55,
+ 0x54, 0x41, 0x4E, 0x54, 0x45, 0x53, 0x2E, 0x2E, 0x2E, 0x0B, 0x59, 0x20, 0x4E, 0x4F, 0x20, 0x50,
+ 0x55, 0x45, 0x44, 0x4F, 0x0A, 0x43, 0x41, 0x4D, 0x49, 0x4E, 0x41, 0x52, 0x2E, 0x0B, 0x42, 0x55,
+ 0x53, 0x51, 0x55, 0x45, 0x20, 0x4D, 0x49, 0x0A, 0x54, 0x45, 0x4C, 0x45, 0x50, 0x4F, 0x52, 0x54,
+ 0x41, 0x44, 0x4F, 0x52, 0x2E, 0x0B, 0x4E, 0x45, 0x43, 0x45, 0x53, 0x49, 0x54, 0x4F, 0x0A, 0x41,
+ 0x53, 0x49, 0x53, 0x54, 0x45, 0x4E, 0x43, 0x49, 0x41, 0x0A, 0x4D, 0x45, 0x44, 0x49, 0x43, 0x41,
+ 0x20, 0x55, 0x52, 0x47, 0x45, 0x4E, 0x54, 0x45, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x47, 0x52, 0x41,
+ 0x43, 0x49, 0x41, 0x53, 0x2E, 0x41, 0x43, 0x41, 0x42, 0x41, 0x53, 0x0A, 0x44, 0x45, 0x20, 0x53,
+ 0x41, 0x4C, 0x56, 0x41, 0x52, 0x4D, 0x45, 0x0A, 0x4C, 0x41, 0x20, 0x56, 0x49, 0x44, 0x41, 0x2E,
+ 0x00, 0xFF, 0xEB, 0xEC, 0x50, 0x41, 0x52, 0x41, 0x20, 0x49, 0x52, 0x20, 0x41, 0x20, 0x4E, 0x45,
+ 0x57, 0x0A, 0x57, 0x41, 0x53, 0x48, 0x49, 0x4E, 0x47, 0x54, 0x4F, 0x4E, 0x2C, 0x0A, 0x54, 0x49,
+ 0x45, 0x4E, 0x45, 0x20, 0x51, 0x55, 0x45, 0x20, 0x53, 0x41, 0x4C, 0x54, 0x41, 0x52, 0x0A, 0x50,
+ 0x4F, 0x52, 0x20, 0x45, 0x53, 0x54, 0x45, 0x20, 0x41, 0x47, 0x55, 0x4A, 0x45, 0x52, 0x4F, 0x0B,
+ 0x50, 0x45, 0x52, 0x4F, 0x20, 0x59, 0x4F, 0x20, 0x51, 0x55, 0x45, 0x20, 0x54, 0x55, 0x0A, 0x55,
+ 0x53, 0x41, 0x52, 0x49, 0x41, 0x20, 0x55, 0x4E, 0x0A, 0x43, 0x49, 0x4E, 0x54, 0x55, 0x52, 0x4F,
+ 0x4E, 0x20, 0x41, 0x4E, 0x54, 0x49, 0x2D, 0x47, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x40, 0x44, 0x4F,
+ 0x4E, 0x44, 0x45, 0x20, 0x50, 0x55, 0x45, 0x44, 0x4F, 0x0A, 0x45, 0x4E, 0x43, 0x4F, 0x4E, 0x54,
+ 0x52, 0x41, 0x52, 0x20, 0x55, 0x4E, 0x4F, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x41, 0x48, 0x4F, 0x52,
+ 0x41, 0x2C, 0x20, 0x50, 0x55, 0x45, 0x44, 0x4F, 0x0A, 0x56, 0x45, 0x4E, 0x44, 0x45, 0x52, 0x54,
+ 0x45, 0x20, 0x55, 0x4E, 0x4F, 0x3A, 0x0A, 0x35, 0x30, 0x30, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49,
+ 0x54, 0x4F, 0x53, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x42, 0x4F, 0x4E, 0x20, 0x56, 0x4F, 0x59, 0x41,
+ 0x47, 0x45, 0x2C, 0x0A, 0x4A, 0x4F, 0x56, 0x45, 0x4E, 0x43, 0x49, 0x54, 0x4F, 0x2E, 0x00, 0x4E,
+ 0x45, 0x43, 0x45, 0x53, 0x49, 0x54, 0x4F, 0x20, 0x55, 0x4E, 0x0A, 0x43, 0x41, 0x52, 0x54, 0x55,
+ 0x43, 0x48, 0x4F, 0x0A, 0x4D, 0x41, 0x47, 0x4E, 0x45, 0x54, 0x49, 0x43, 0x4F, 0x0A, 0x52, 0x45,
+ 0x43, 0x41, 0x52, 0x47, 0x41, 0x44, 0x4F, 0x00, 0x51, 0x55, 0x45, 0x52, 0x52, 0x49, 0x41, 0x20,
+ 0x55, 0x4E, 0x0A, 0x50, 0x45, 0x52, 0x4D, 0x49, 0x53, 0x4F, 0x20, 0x44, 0x45, 0x0A, 0x54, 0x52,
+ 0x41, 0x42, 0x41, 0x4A, 0x4F, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x50, 0x52, 0x49, 0x4D, 0x45, 0x52,
+ 0x41, 0x20, 0x50, 0x4C, 0x41, 0x4E, 0x54, 0x41, 0x2E, 0x00, 0x55, 0x4E, 0x41, 0x20, 0x56, 0x4F,
+ 0x5A, 0x20, 0x49, 0x4E, 0x54, 0x45, 0x52, 0x49, 0x4F, 0x52, 0x0A, 0x49, 0x4E, 0x54, 0x45, 0x52,
+ 0x52, 0x55, 0x4D, 0x50, 0x45, 0x20, 0x54, 0x55, 0x53, 0x0A, 0x50, 0x45, 0x4E, 0x53, 0x41, 0x4D,
+ 0x49, 0x45, 0x4E, 0x54, 0x4F, 0x53, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x43, 0x52, 0x45, 0x45, 0x4D,
+ 0x45, 0x2C, 0x20, 0x48, 0x49, 0x4A, 0x4F, 0x2C, 0x0A, 0x50, 0x4F, 0x4E, 0x20, 0x4C, 0x41, 0x20,
+ 0x43, 0x41, 0x52, 0x47, 0x41, 0x0A, 0x41, 0x54, 0x4F, 0x4D, 0x49, 0x43, 0x41, 0x20, 0x41, 0x51,
+ 0x55, 0x49, 0x2E, 0x2E, 0x2E, 0x0B, 0x59, 0x20, 0x48, 0x55, 0x59, 0x45, 0x20, 0x45, 0x4E, 0x20,
+ 0x43, 0x55, 0x41, 0x4E, 0x54, 0x4F, 0x0A, 0x41, 0x4C, 0x43, 0x41, 0x4E, 0x43, 0x45, 0x20, 0x45,
+ 0x4C, 0x0A, 0x4E, 0x55, 0x43, 0x4C, 0x45, 0x4F, 0x20, 0x44, 0x45, 0x4C, 0x0A, 0x50, 0x4C, 0x41,
+ 0x4E, 0x45, 0x54, 0x41, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x47, 0x55, 0x49, 0x41, 0x4D, 0x45, 0x2C,
+ 0x0A, 0x4A, 0x4F, 0x56, 0x45, 0x4E, 0x43, 0x49, 0x54, 0x4F, 0x2E, 0x0B, 0x4C, 0x4C, 0x45, 0x56,
+ 0x41, 0x4D, 0x45, 0x20, 0x41, 0x4C, 0x20, 0x0A, 0x43, 0x45, 0x4E, 0x54, 0x52, 0x4F, 0x20, 0x44,
+ 0x45, 0x0A, 0x49, 0x4E, 0x56, 0x45, 0x53, 0x54, 0x49, 0x47, 0x41, 0x43, 0x49, 0x4F, 0x4E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x47, 0x52, 0x41, 0x43, 0x49, 0x41, 0x53, 0x20, 0x50, 0x4F, 0x52, 0x0A, 0x54,
+ 0x55, 0x20, 0x41, 0x59, 0x55, 0x44, 0x41, 0x2E, 0x2E, 0x2E, 0x0B, 0x48, 0x45, 0x20, 0x4C, 0x4C,
+ 0x45, 0x47, 0x41, 0x44, 0x4F, 0x0A, 0x53, 0x49, 0x4E, 0x20, 0x50, 0x52, 0x4F, 0x42, 0x4C, 0x45,
+ 0x4D, 0x41, 0x53, 0x0A, 0x59, 0x20, 0x59, 0x41, 0x20, 0x4E, 0x4F, 0x20, 0x48, 0x41, 0x59, 0x0A,
+ 0x50, 0x45, 0x4C, 0x49, 0x47, 0x52, 0x4F, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x42, 0x49, 0x45, 0x4E,
+ 0x2C, 0x20, 0x40, 0x4D, 0x45, 0x20, 0x48, 0x41, 0x53, 0x0A, 0x54, 0x52, 0x41, 0x49, 0x44, 0x4F,
+ 0x20, 0x45, 0x4C, 0x0A, 0x50, 0x41, 0x51, 0x55, 0x45, 0x54, 0x45, 0x3F, 0x00, 0x40, 0x43, 0x55,
+ 0x41, 0x4E, 0x54, 0x4F, 0x20, 0x43, 0x55, 0x45, 0x53, 0x54, 0x41, 0x0A, 0x55, 0x4E, 0x20, 0x42,
+ 0x49, 0x4C, 0x4C, 0x45, 0x54, 0x45, 0x20, 0x41, 0x0A, 0x4C, 0x41, 0x20, 0x54, 0x49, 0x45, 0x52,
+ 0x52, 0x41, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x35, 0x30, 0x2E, 0x30, 0x30, 0x30, 0x20, 0x43, 0x52,
+ 0x45, 0x44, 0x49, 0x54, 0x4F, 0x53, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x46, 0x41, 0x56, 0x4F, 0x52,
+ 0x2C, 0x20, 0x43, 0x4F, 0x4E, 0x0A, 0x46, 0x41, 0x56, 0x4F, 0x52, 0x20, 0x53, 0x45, 0x0A, 0x50,
+ 0x41, 0x47, 0x41, 0x3A, 0x0B, 0x31, 0x35, 0x30, 0x30, 0x20, 0x43, 0x52, 0x45, 0x44, 0x49, 0x54,
+ 0x4F, 0x53, 0x20, 0x59, 0x0A, 0x4C, 0x4F, 0x53, 0x20, 0x50, 0x41, 0x50, 0x45, 0x4C, 0x45, 0x53,
+ 0x0A, 0x53, 0x4F, 0x4E, 0x20, 0x54, 0x55, 0x59, 0x4F, 0x53, 0x2E, 0x00
+};
+
+const uint8_t LocaleData::_stringsTableIT[] = {
+ 0x5A, 0x00, 0x71, 0x00, 0x8A, 0x00, 0xA2, 0x01, 0x56, 0x02, 0x75, 0x02, 0xBB, 0x02, 0xEE, 0x02,
+ 0x59, 0x03, 0x72, 0x03, 0xA8, 0x03, 0xF3, 0x03, 0x3F, 0x04, 0x8A, 0x04, 0x0C, 0x05, 0x3E, 0x05,
+ 0x52, 0x05, 0xB6, 0x05, 0xC4, 0x05, 0xE3, 0x05, 0x7D, 0x06, 0x8D, 0x08, 0xF7, 0x08, 0x0A, 0x09,
+ 0x5E, 0x09, 0x6F, 0x09, 0x8A, 0x09, 0xAE, 0x09, 0xC9, 0x09, 0xED, 0x09, 0xEF, 0x09, 0xF1, 0x09,
+ 0x5E, 0x0A, 0x72, 0x0A, 0xF8, 0x0A, 0x1B, 0x0B, 0xCB, 0x0B, 0xEA, 0x0B, 0x17, 0x0C, 0x47, 0x0C,
+ 0xD7, 0x0C, 0x10, 0x0D, 0x61, 0x0D, 0x86, 0x0D, 0xC1, 0x0D, 0x49, 0x6C, 0x20, 0x66, 0x75, 0x73,
+ 0x69, 0x62, 0x69, 0x6C, 0x65, 0x20, 0x5C, 0x0A, 0x73, 0x61, 0x6C, 0x74, 0x61, 0x74, 0x6F, 0x2E,
+ 0x00, 0x4F, 0x72, 0x61, 0x20, 0x64, 0x6F, 0x76, 0x72, 0x65, 0x62, 0x62, 0x65, 0x0A, 0x66, 0x75,
+ 0x6E, 0x7A, 0x69, 0x6F, 0x6E, 0x61, 0x72, 0x65, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x53, 0x6F, 0x6E,
+ 0x6F, 0x20, 0x4A, 0x61, 0x63, 0x6B, 0x2E, 0x20, 0x53, 0x74, 0x61, 0x69, 0x0A, 0x63, 0x65, 0x72,
+ 0x63, 0x61, 0x6E, 0x64, 0x6F, 0x20, 0x64, 0x65, 0x69, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x69, 0x0A, 0x66, 0x61, 0x6C, 0x73, 0x69, 0x3F, 0x0B, 0xFF, 0xE9, 0xEA, 0x53, 0x69,
+ 0x2C, 0x20, 0x65, 0x20, 0x69, 0x6C, 0x20, 0x70, 0x69, 0x5F, 0x0A, 0x70, 0x72, 0x65, 0x73, 0x74,
+ 0x6F, 0x0A, 0x70, 0x6F, 0x73, 0x73, 0x69, 0x62, 0x69, 0x6C, 0x65, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC,
+ 0x31, 0x35, 0x30, 0x30, 0x20, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x69, 0x21, 0x0B, 0xFF, 0xE9,
+ 0xEA, 0x31, 0x35, 0x30, 0x30, 0x3F, 0x3F, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x43, 0x65, 0x72, 0x74,
+ 0x6F, 0x2C, 0x20, 0x73, 0x74, 0x6F, 0x0A, 0x70, 0x72, 0x65, 0x6E, 0x64, 0x65, 0x6E, 0x64, 0x6F,
+ 0x20, 0x75, 0x6E, 0x0A, 0x67, 0x72, 0x6F, 0x73, 0x73, 0x6F, 0x20, 0x72, 0x69, 0x73, 0x63, 0x68,
+ 0x69, 0x6F, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x4D, 0x61, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x6E, 0x65,
+ 0x20, 0x68, 0x6F, 0x0A, 0x61, 0x62, 0x62, 0x61, 0x73, 0x74, 0x61, 0x6E, 0x7A, 0x61, 0x2E, 0x2E,
+ 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x56, 0x61, 0x69, 0x20, 0x61, 0x6C, 0x6C, 0x27, 0x55, 0x66, 0x66,
+ 0x69, 0x63, 0x69, 0x6F, 0x0A, 0x64, 0x69, 0x20, 0x43, 0x6F, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x6D,
+ 0x65, 0x6E, 0x74, 0x6F, 0x2E, 0x0A, 0x4C, 0x5B, 0x20, 0x74, 0x72, 0x6F, 0x76, 0x65, 0x72, 0x61,
+ 0x69, 0x0A, 0x64, 0x65, 0x6C, 0x20, 0x6C, 0x61, 0x76, 0x6F, 0x72, 0x6F, 0x2E, 0x0B, 0x45, 0x20,
+ 0x74, 0x6F, 0x72, 0x6E, 0x61, 0x20, 0x64, 0x61, 0x20, 0x6D, 0x65, 0x0A, 0x71, 0x75, 0x61, 0x6E,
+ 0x64, 0x6F, 0x20, 0x61, 0x76, 0x72, 0x61, 0x69, 0x0A, 0x69, 0x20, 0x73, 0x6F, 0x6C, 0x64, 0x69,
+ 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x43, 0x6F, 0x6E, 0x6F, 0x73, 0x63, 0x6F, 0x20, 0x71, 0x75, 0x65,
+ 0x6C, 0x20, 0x74, 0x69, 0x70, 0x6F, 0x2E, 0x0A, 0x48, 0x61, 0x20, 0x75, 0x6E, 0x20, 0x61, 0x6D,
+ 0x69, 0x63, 0x6F, 0x0A, 0x6E, 0x65, 0x6C, 0x6C, 0x61, 0x20, 0x70, 0x6F, 0x6C, 0x69, 0x7A, 0x69,
+ 0x61, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x44, 0x6F, 0x76, 0x65, 0x20, 0x70, 0x6F, 0x73, 0x73, 0x6F,
+ 0x0A, 0x74, 0x72, 0x6F, 0x76, 0x61, 0x72, 0x65, 0x20, 0x6C, 0x27, 0x61, 0x6D, 0x69, 0x63, 0x6F,
+ 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x56, 0x61, 0x69, 0x20, 0x61, 0x20, 0x52, 0x65, 0x73, 0x74, 0x72,
+ 0x69, 0x63, 0x74, 0x65, 0x64, 0x0A, 0x41, 0x72, 0x65, 0x61, 0x20, 0x31, 0x2C, 0x20, 0x70, 0x65,
+ 0x6E, 0x73, 0x6F, 0x0A, 0x63, 0x68, 0x65, 0x20, 0x73, 0x69, 0x61, 0x20, 0x64, 0x69, 0x0A, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x7A, 0x69, 0x6F, 0x20, 0x6C, 0x5B, 0x2E, 0x0B, 0x4D, 0x61, 0x20, 0x73,
+ 0x74, 0x61, 0x69, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6E, 0x74, 0x6F, 0x2C, 0x0A, 0x71, 0x75, 0x65,
+ 0x69, 0x20, 0x74, 0x69, 0x70, 0x69, 0x20, 0x73, 0x6F, 0x6E, 0x6F, 0x0A, 0x64, 0x65, 0x69, 0x20,
+ 0x64, 0x75, 0x72, 0x69, 0x21, 0x00, 0xFF, 0xEB, 0xEC, 0x4E, 0x6F, 0x6E, 0x20, 0x73, 0x6F, 0x0A,
+ 0x6E, 0x69, 0x65, 0x6E, 0x74, 0x61, 0x6C, 0x74, 0x72, 0x6F, 0x2C, 0x0A, 0x72, 0x61, 0x67, 0x61,
+ 0x7A, 0x7A, 0x6F, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x43, 0x59, 0x2D, 0x42, 0x30, 0x32, 0x31, 0x20,
+ 0x76, 0x75, 0x6F, 0x6C, 0x65, 0x0A, 0x66, 0x61, 0x72, 0x74, 0x69, 0x20, 0x75, 0x6E, 0x61, 0x0A,
+ 0x70, 0x72, 0x6F, 0x70, 0x6F, 0x73, 0x74, 0x61, 0x2E, 0x0B, 0x54, 0x69, 0x20, 0x73, 0x74, 0x61,
+ 0x0A, 0x61, 0x73, 0x70, 0x65, 0x74, 0x74, 0x61, 0x6E, 0x64, 0x6F, 0x0A, 0x64, 0x69, 0x65, 0x74,
+ 0x72, 0x6F, 0x20, 0x61, 0x6C, 0x20, 0x62, 0x61, 0x72, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x56, 0x61,
+ 0x69, 0x20, 0x61, 0x6C, 0x20, 0x62, 0x61, 0x72, 0x2C, 0x0A, 0x72, 0x61, 0x67, 0x61, 0x7A, 0x7A,
+ 0x6F, 0x2C, 0x20, 0x43, 0x59, 0x2D, 0x42, 0x30, 0x32, 0x31, 0x0A, 0x74, 0x69, 0x20, 0x73, 0x74,
+ 0x61, 0x0A, 0x61, 0x73, 0x70, 0x65, 0x74, 0x74, 0x61, 0x6E, 0x64, 0x6F, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x4E, 0x6F, 0x6E, 0x20, 0x73, 0x70, 0x61, 0x72, 0x61, 0x72, 0x65, 0x2C, 0x20, 0x6E, 0x6F,
+ 0x6E, 0x0A, 0x73, 0x6F, 0x6E, 0x6F, 0x20, 0x43, 0x59, 0x2D, 0x42, 0x30, 0x32, 0x31, 0x21, 0x0B,
+ 0x49, 0x6C, 0x20, 0x73, 0x75, 0x6F, 0x20, 0x72, 0x69, 0x66, 0x75, 0x67, 0x69, 0x6F, 0x0A, 0x5C,
+ 0x20, 0x64, 0x69, 0x20, 0x73, 0x6F, 0x74, 0x74, 0x6F, 0x2E, 0x0B, 0x49, 0x6C, 0x20, 0x73, 0x75,
+ 0x6F, 0x20, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x67, 0x6E, 0x6F, 0x2C, 0x0A, 0x69, 0x6C, 0x20, 0x70,
+ 0x6F, 0x6C, 0x69, 0x7A, 0x69, 0x6F, 0x74, 0x74, 0x6F, 0x2C, 0x0A, 0x68, 0x61, 0x20, 0x6C, 0x61,
+ 0x20, 0x63, 0x68, 0x69, 0x61, 0x76, 0x65, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x4E, 0x6F, 0x6E, 0x20,
+ 0x73, 0x6F, 0x20, 0x6E, 0x69, 0x65, 0x6E, 0x74, 0x65, 0x0A, 0x64, 0x69, 0x20, 0x70, 0x69, 0x5F,
+ 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x53, 0x69, 0x67, 0x6E, 0x6F, 0x72, 0x65, 0x2E, 0x2E, 0x2E, 0x20,
+ 0x75, 0x6E, 0x0A, 0x63, 0x65, 0x72, 0x74, 0x6F, 0x20, 0x4A, 0x61, 0x63, 0x6B, 0x0A, 0x76, 0x69,
+ 0x20, 0x61, 0x73, 0x70, 0x65, 0x74, 0x74, 0x61, 0x0A, 0x76, 0x69, 0x63, 0x69, 0x6E, 0x6F, 0x20,
+ 0x61, 0x6C, 0x20, 0x62, 0x61, 0x72, 0x2E, 0x00, 0x56, 0x6F, 0x72, 0x72, 0x65, 0x69, 0x20, 0x75,
+ 0x6E, 0x20, 0x70, 0x65, 0x72, 0x2D, 0x0A, 0x6D, 0x65, 0x73, 0x73, 0x6F, 0x20, 0x64, 0x69, 0x20,
+ 0x6C, 0x61, 0x76, 0x6F, 0x72, 0x6F, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x6F, 0x2C, 0x20, 0x6E,
+ 0x6F, 0x6E, 0x20, 0x71, 0x75, 0x69, 0x2E, 0x0A, 0x43, 0x68, 0x69, 0x65, 0x64, 0x65, 0x74, 0x65,
+ 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x0A, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x6C, 0x6C, 0x6F, 0x20,
+ 0x43, 0x2E, 0x00, 0x56, 0x6F, 0x72, 0x72, 0x65, 0x69, 0x20, 0x75, 0x6E, 0x20, 0x70, 0x65, 0x72,
+ 0x2D, 0x0A, 0x6D, 0x65, 0x73, 0x73, 0x6F, 0x20, 0x64, 0x69, 0x20, 0x6C, 0x61, 0x76, 0x6F, 0x72,
+ 0x6F, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x42, 0x65, 0x6E, 0x65, 0x2E, 0x2E, 0x2E, 0x4F, 0x2E, 0x6B,
+ 0x2E, 0x2C, 0x20, 0x69, 0x6C, 0x0A, 0x63, 0x61, 0x70, 0x6F, 0x20, 0x76, 0x69, 0x20, 0x72, 0x69,
+ 0x63, 0x65, 0x76, 0x65, 0x72, 0x5B, 0x0A, 0x61, 0x64, 0x65, 0x73, 0x73, 0x6F, 0x2E, 0x00, 0x56,
+ 0x6F, 0x72, 0x72, 0x65, 0x69, 0x20, 0x75, 0x6E, 0x20, 0x70, 0x65, 0x72, 0x2D, 0x0A, 0x6D, 0x65,
+ 0x73, 0x73, 0x6F, 0x20, 0x64, 0x69, 0x20, 0x6C, 0x61, 0x76, 0x6F, 0x72, 0x6F, 0x2E, 0x0B, 0xFF,
+ 0xEB, 0xEC, 0x4E, 0x6F, 0x2C, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x71, 0x75, 0x69, 0x2E, 0x0A, 0x43,
+ 0x68, 0x69, 0x65, 0x64, 0x65, 0x74, 0x65, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x0A, 0x73, 0x70, 0x6F,
+ 0x72, 0x74, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x42, 0x2E, 0x00, 0x56, 0x6F, 0x72, 0x72, 0x65, 0x69,
+ 0x20, 0x70, 0x61, 0x72, 0x6C, 0x61, 0x72, 0x65, 0x0A, 0x63, 0x6F, 0x6E, 0x20, 0x4A, 0x61, 0x63,
+ 0x6B, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x41, 0x68, 0x20, 0x73, 0x69, 0x3F, 0x20, 0x4A, 0x61, 0x63,
+ 0x6B, 0x0A, 0x6E, 0x6F, 0x6E, 0x20, 0x63, 0x27, 0x5C, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x53, 0x6F,
+ 0x6E, 0x6F, 0x20, 0x73, 0x74, 0x61, 0x74, 0x6F, 0x0A, 0x6D, 0x61, 0x6E, 0x64, 0x61, 0x74, 0x6F,
+ 0x20, 0x64, 0x61, 0x6C, 0x20, 0x6D, 0x69, 0x6F, 0x0A, 0x61, 0x6D, 0x69, 0x63, 0x6F, 0x20, 0x49,
+ 0x61, 0x6E, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4F, 0x2E, 0x6B, 0x2E, 0x20, 0x4A, 0x61, 0x63, 0x6B,
+ 0x0A, 0x74, 0x69, 0x20, 0x73, 0x74, 0x61, 0x20, 0x61, 0x73, 0x70, 0x65, 0x74, 0x2D, 0x0A, 0x74,
+ 0x61, 0x6E, 0x64, 0x6F, 0x20, 0x66, 0x75, 0x6F, 0x72, 0x69, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x4E,
+ 0x69, 0x65, 0x6E, 0x74, 0x65, 0x20, 0x64, 0x61, 0x20, 0x66, 0x61, 0x72, 0x65, 0x2E, 0x0A, 0x53,
+ 0x65, 0x69, 0x20, 0x74, 0x72, 0x6F, 0x70, 0x70, 0x6F, 0x20, 0x67, 0x69, 0x6F, 0x2D, 0x0A, 0x76,
+ 0x61, 0x6E, 0x65, 0x20, 0x70, 0x65, 0x72, 0x20, 0x62, 0x65, 0x72, 0x65, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x44, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x69, 0x20, 0x70, 0x72, 0x65, 0x67, 0x6F,
+ 0x2E, 0x00, 0x53, 0x6F, 0x6E, 0x6F, 0x20, 0x69, 0x6C, 0x0A, 0x63, 0x6F, 0x72, 0x72, 0x69, 0x65,
+ 0x72, 0x65, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x4F, 0x68, 0x20, 0x62, 0x65, 0x6E, 0x65, 0x21, 0x20,
+ 0x45, 0x63, 0x63, 0x6F, 0x2C, 0x0A, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x20, 0x69, 0x6C, 0x20, 0x70,
+ 0x61, 0x63, 0x63, 0x6F, 0x0A, 0x61, 0x6C, 0x6C, 0x27, 0x61, 0x67, 0x65, 0x6E, 0x7A, 0x69, 0x61,
+ 0x0A, 0x76, 0x69, 0x61, 0x67, 0x67, 0x69, 0x2E, 0x0B, 0x45, 0x20, 0x66, 0x61, 0x69, 0x20, 0x61,
+ 0x74, 0x74, 0x65, 0x6E, 0x7A, 0x69, 0x6F, 0x6E, 0x65, 0x0A, 0x5C, 0x20, 0x70, 0x72, 0x65, 0x7A,
+ 0x69, 0x6F, 0x73, 0x6F, 0x2E, 0x00, 0x54, 0x45, 0x4D, 0x50, 0x4F, 0x20, 0x53, 0x43, 0x41, 0x44,
+ 0x55, 0x54, 0x4F, 0x00, 0x43, 0x27, 0x5C, 0x20, 0x75, 0x6E, 0x61, 0x20, 0x66, 0x65, 0x73, 0x73,
+ 0x75, 0x72, 0x61, 0x0A, 0x70, 0x65, 0x72, 0x20, 0x6C, 0x61, 0x20, 0x73, 0x63, 0x68, 0x65, 0x64,
+ 0x61, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x47, 0x72, 0x61, 0x7A, 0x69, 0x65, 0x2C, 0x20, 0x43, 0x6F,
+ 0x6E, 0x72, 0x61, 0x64, 0x2E, 0x0A, 0x51, 0x75, 0x65, 0x69, 0x20, 0x70, 0x6F, 0x6C, 0x69, 0x7A,
+ 0x69, 0x6F, 0x74, 0x74, 0x69, 0x0A, 0x6D, 0x69, 0x20, 0x73, 0x74, 0x61, 0x76, 0x61, 0x6E, 0x6F,
+ 0x20, 0x70, 0x65, 0x72, 0x0A, 0x73, 0x63, 0x6F, 0x70, 0x72, 0x69, 0x72, 0x65, 0x21, 0x0B, 0x42,
+ 0x65, 0x68, 0x2C, 0x20, 0x69, 0x6D, 0x6D, 0x61, 0x67, 0x69, 0x6E, 0x6F, 0x0A, 0x63, 0x68, 0x65,
+ 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x74, 0x69, 0x0A, 0x72, 0x69, 0x63, 0x6F, 0x72, 0x64, 0x69, 0x20,
+ 0x64, 0x65, 0x6C, 0x20, 0x74, 0x75, 0x6F, 0x0A, 0x63, 0x61, 0x72, 0x6F, 0x20, 0x61, 0x6D, 0x69,
+ 0x63, 0x6F, 0x20, 0x49, 0x61, 0x6E, 0x2E, 0x0B, 0x53, 0x69, 0x65, 0x64, 0x69, 0x74, 0x69, 0x2C,
+ 0x0A, 0x72, 0x69, 0x73, 0x6F, 0x6C, 0x76, 0x65, 0x72, 0x65, 0x6D, 0x6F, 0x0A, 0x74, 0x75, 0x74,
+ 0x74, 0x6F, 0x20, 0x66, 0x72, 0x61, 0x20, 0x70, 0x6F, 0x63, 0x6F, 0x2E, 0x00, 0x49, 0x61, 0x6E,
+ 0x2C, 0x20, 0x63, 0x6F, 0x73, 0x61, 0x20, 0x64, 0x65, 0x76, 0x6F, 0x0A, 0x66, 0x61, 0x72, 0x65,
+ 0x20, 0x70, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x65, 0x0A, 0x73, 0x75, 0x6C, 0x6C,
+ 0x61, 0x20, 0x54, 0x45, 0x52, 0x52, 0x41, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x49, 0x6C, 0x20, 0x63,
+ 0x6F, 0x73, 0x74, 0x6F, 0x20, 0x64, 0x69, 0x20, 0x75, 0x6E, 0x0A, 0x62, 0x69, 0x67, 0x6C, 0x69,
+ 0x65, 0x74, 0x74, 0x6F, 0x20, 0x5C, 0x0A, 0x61, 0x73, 0x74, 0x72, 0x6F, 0x6E, 0x6F, 0x6D, 0x69,
+ 0x63, 0x6F, 0x2E, 0x0B, 0x4C, 0x27, 0x75, 0x6E, 0x69, 0x63, 0x6F, 0x20, 0x6D, 0x6F, 0x64, 0x6F,
+ 0x0A, 0x73, 0x61, 0x72, 0x65, 0x62, 0x62, 0x65, 0x20, 0x71, 0x75, 0x65, 0x6C, 0x6C, 0x6F, 0x0A,
+ 0x64, 0x69, 0x20, 0x70, 0x61, 0x72, 0x74, 0x65, 0x63, 0x69, 0x70, 0x61, 0x72, 0x65, 0x20, 0x61,
+ 0x6C, 0x0A, 0x44, 0x65, 0x61, 0x74, 0x68, 0x20, 0x54, 0x6F, 0x77, 0x65, 0x72, 0x2E, 0x0B, 0xFF,
+ 0xE9, 0xEA, 0x44, 0x65, 0x61, 0x74, 0x68, 0x20, 0x54, 0x6F, 0x77, 0x65, 0x72, 0x3F, 0x0B, 0xFF,
+ 0xEB, 0xEC, 0x53, 0x69, 0x2C, 0x5C, 0x20, 0x75, 0x6E, 0x20, 0x67, 0x69, 0x6F, 0x63, 0x6F, 0x0A,
+ 0x74, 0x65, 0x6C, 0x65, 0x76, 0x69, 0x73, 0x69, 0x76, 0x6F, 0x2E, 0x20, 0x49, 0x6C, 0x0A, 0x76,
+ 0x69, 0x6E, 0x63, 0x69, 0x74, 0x6F, 0x72, 0x65, 0x20, 0x72, 0x69, 0x63, 0x65, 0x76, 0x65, 0x0A,
+ 0x75, 0x6E, 0x20, 0x62, 0x69, 0x67, 0x6C, 0x69, 0x65, 0x74, 0x74, 0x6F, 0x2E, 0x0B, 0xFF, 0xE9,
+ 0xEA, 0x4F, 0x2E, 0x6B, 0x2E, 0x20, 0x4D, 0x69, 0x20, 0x70, 0x75, 0x6F, 0x69, 0x0A, 0x66, 0x6F,
+ 0x72, 0x6E, 0x69, 0x72, 0x65, 0x20, 0x64, 0x65, 0x69, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65,
+ 0x6E, 0x74, 0x69, 0x20, 0x66, 0x61, 0x6C, 0x73, 0x69, 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x6F,
+ 0x20, 0x70, 0x72, 0x6F, 0x62, 0x6C, 0x65, 0x6D, 0x6F, 0x2E, 0x0A, 0x56, 0x61, 0x69, 0x20, 0x61,
+ 0x6C, 0x20, 0x62, 0x61, 0x72, 0x0A, 0x65, 0x20, 0x63, 0x68, 0x69, 0x65, 0x64, 0x69, 0x20, 0x64,
+ 0x69, 0x0A, 0x4A, 0x61, 0x63, 0x6B, 0x2E, 0x0B, 0x44, 0x69, 0x67, 0x6C, 0x69, 0x20, 0x63, 0x68,
+ 0x65, 0x20, 0x74, 0x69, 0x20, 0x68, 0x6F, 0x0A, 0x6D, 0x61, 0x6E, 0x64, 0x61, 0x74, 0x6F, 0x20,
+ 0x69, 0x6F, 0x2E, 0x0A, 0x4F, 0x68, 0x2C, 0x61, 0x20, 0x70, 0x72, 0x6F, 0x70, 0x6F, 0x73, 0x69,
+ 0x74, 0x6F, 0x2E, 0x2E, 0x0B, 0x54, 0x69, 0x20, 0x68, 0x6F, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x6F,
+ 0x0A, 0x6E, 0x65, 0x6C, 0x6C, 0x65, 0x20, 0x74, 0x61, 0x73, 0x63, 0x68, 0x65, 0x20, 0x69, 0x6C,
+ 0x0A, 0x63, 0x61, 0x6D, 0x70, 0x6F, 0x20, 0x64, 0x69, 0x20, 0x66, 0x6F, 0x72, 0x7A, 0x61, 0x0A,
+ 0x63, 0x68, 0x65, 0x20, 0x76, 0x6F, 0x6C, 0x65, 0x76, 0x69, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x4F,
+ 0x74, 0x74, 0x69, 0x6D, 0x6F, 0x2E, 0x20, 0x47, 0x72, 0x61, 0x7A, 0x69, 0x65, 0x0A, 0x49, 0x61,
+ 0x6E, 0x2E, 0x20, 0x43, 0x69, 0x20, 0x76, 0x65, 0x64, 0x69, 0x61, 0x6D, 0x6F, 0x0A, 0x61, 0x6C,
+ 0x6C, 0x61, 0x20, 0x70, 0x72, 0x6F, 0x73, 0x73, 0x69, 0x6D, 0x61, 0x2E, 0x2E, 0x2E, 0x00, 0xFF,
+ 0xEB, 0xEC, 0x42, 0x75, 0x6F, 0x6E, 0x61, 0x20, 0x66, 0x6F, 0x72, 0x74, 0x75, 0x6E, 0x61, 0x2E,
+ 0x0A, 0x74, 0x69, 0x20, 0x63, 0x6F, 0x6E, 0x74, 0x61, 0x74, 0x74, 0x65, 0x72, 0x5E, 0x0A, 0x71,
+ 0x75, 0x61, 0x6E, 0x64, 0x6F, 0x20, 0x61, 0x72, 0x72, 0x69, 0x76, 0x65, 0x72, 0x61, 0x69, 0x0A,
+ 0x73, 0x75, 0x6C, 0x6C, 0x61, 0x20, 0x74, 0x65, 0x72, 0x72, 0x61, 0x2E, 0x00, 0xFF, 0xEB, 0xEC,
+ 0x42, 0x65, 0x6E, 0x76, 0x65, 0x6E, 0x75, 0x74, 0x6F, 0x20, 0x61, 0x0A, 0x4E, 0x65, 0x77, 0x20,
+ 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x2C, 0x0A, 0x67, 0x69, 0x6F, 0x76,
+ 0x61, 0x6E, 0x6F, 0x74, 0x74, 0x6F, 0x2E, 0x0B, 0x45, 0x63, 0x63, 0x6F, 0x20, 0x75, 0x6E, 0x61,
+ 0x20, 0x6D, 0x61, 0x70, 0x70, 0x61, 0x0A, 0x64, 0x65, 0x6C, 0x6C, 0x61, 0x20, 0x63, 0x69, 0x74,
+ 0x74, 0x5B, 0x20, 0x63, 0x68, 0x65, 0x0A, 0x70, 0x6F, 0x74, 0x72, 0x5B, 0x20, 0x65, 0x73, 0x73,
+ 0x65, 0x72, 0x74, 0x69, 0x0A, 0x75, 0x74, 0x69, 0x6C, 0x65, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x47,
+ 0x72, 0x61, 0x7A, 0x69, 0x65, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x42, 0x75, 0x6F, 0x6E, 0x61, 0x0A,
+ 0x67, 0x69, 0x6F, 0x72, 0x6E, 0x61, 0x74, 0x61, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x44, 0x65, 0x76,
+ 0x69, 0x20, 0x61, 0x76, 0x65, 0x72, 0x65, 0x20, 0x75, 0x6E, 0x0A, 0x70, 0x65, 0x72, 0x6D, 0x65,
+ 0x73, 0x73, 0x6F, 0x20, 0x70, 0x65, 0x72, 0x0A, 0x6C, 0x61, 0x76, 0x6F, 0x72, 0x61, 0x72, 0x65,
+ 0x0B, 0x50, 0x75, 0x6F, 0x69, 0x20, 0x6F, 0x74, 0x74, 0x65, 0x6E, 0x65, 0x72, 0x6E, 0x65, 0x0A,
+ 0x75, 0x6E, 0x6F, 0x20, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x72, 0x6F, 0x0A, 0x41, 0x6D,
+ 0x6D, 0x69, 0x6E, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x6F, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x4E, 0x6F, 0x6E, 0x20, 0x68, 0x6F, 0x0A, 0x74, 0x65, 0x6D, 0x70, 0x6F, 0x2E, 0x00, 0x42,
+ 0x75, 0x6F, 0x6E, 0x67, 0x69, 0x6F, 0x72, 0x6E, 0x6F, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x42, 0x75,
+ 0x6F, 0x6E, 0x67, 0x69, 0x6F, 0x72, 0x6E, 0x6F, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x48, 0x6F, 0x20,
+ 0x76, 0x69, 0x73, 0x74, 0x6F, 0x20, 0x71, 0x75, 0x65, 0x6C, 0x0A, 0x74, 0x69, 0x70, 0x6F, 0x20,
+ 0x70, 0x72, 0x69, 0x6D, 0x61, 0x0A, 0x61, 0x6C, 0x20, 0x62, 0x61, 0x72, 0x2E, 0x00, 0x42, 0x75,
+ 0x6F, 0x6E, 0x67, 0x69, 0x6F, 0x72, 0x6E, 0x6F, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x42, 0x75, 0x6F,
+ 0x6E, 0x67, 0x69, 0x6F, 0x72, 0x6E, 0x6F, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x53, 0x69, 0x2C, 0x20,
+ 0x6C, 0x6F, 0x20, 0x63, 0x6F, 0x6E, 0x6F, 0x73, 0x63, 0x6F, 0x2E, 0x0A, 0x45, 0x27, 0x20, 0x63,
+ 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x65, 0x20, 0x66, 0x69, 0x73, 0x73, 0x6F, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x56, 0x6F, 0x72, 0x72, 0x65, 0x69, 0x20, 0x75, 0x6E, 0x20, 0x70, 0x65, 0x72, 0x2D, 0x0A,
+ 0x6D, 0x65, 0x73, 0x73, 0x6F, 0x20, 0x64, 0x69, 0x20, 0x6C, 0x61, 0x76, 0x6F, 0x72, 0x6F, 0x2E,
+ 0x0B, 0xFF, 0xEB, 0xEC, 0x4E, 0x6F, 0x6E, 0x20, 0x63, 0x27, 0x5C, 0x20, 0x70, 0x72, 0x6F, 0x62,
+ 0x6C, 0x65, 0x6D, 0x61, 0x0A, 0x61, 0x64, 0x20, 0x61, 0x76, 0x65, 0x72, 0x65, 0x20, 0x75, 0x6E,
+ 0x0A, 0x70, 0x65, 0x72, 0x6D, 0x65, 0x73, 0x73, 0x6F, 0x2E, 0x2E, 0x2E, 0x0B, 0x4C, 0x61, 0x20,
+ 0x73, 0x75, 0x61, 0x20, 0x63, 0x61, 0x72, 0x74, 0x61, 0x20, 0x64, 0x69, 0x0A, 0x69, 0x64, 0x65,
+ 0x6E, 0x74, 0x69, 0x74, 0x5B, 0x2C, 0x20, 0x70, 0x72, 0x65, 0x67, 0x6F, 0x2E, 0x00, 0xFF, 0xEB,
+ 0xEC, 0x41, 0x49, 0x55, 0x54, 0x4F, 0x2E, 0x2E, 0x2E, 0x41, 0x49, 0x55, 0x54, 0x4F, 0x2E, 0x2E,
+ 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x41, 0x69, 0x75, 0x74, 0x61, 0x6D, 0x69, 0x20, 0x67, 0x69, 0x6F,
+ 0x76, 0x61, 0x6E, 0x65, 0x2E, 0x0A, 0x53, 0x6F, 0x6E, 0x6F, 0x20, 0x73, 0x74, 0x61, 0x74, 0x6F,
+ 0x0A, 0x61, 0x74, 0x74, 0x61, 0x63, 0x63, 0x61, 0x74, 0x6F, 0x20, 0x64, 0x61, 0x69, 0x0A, 0x6D,
+ 0x75, 0x74, 0x61, 0x6E, 0x74, 0x69, 0x2E, 0x2E, 0x2E, 0x0B, 0x65, 0x20, 0x6E, 0x6F, 0x6E, 0x20,
+ 0x70, 0x6F, 0x73, 0x73, 0x6F, 0x0A, 0x63, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x61, 0x72, 0x65, 0x2E,
+ 0x0B, 0x54, 0x72, 0x6F, 0x76, 0x61, 0x20, 0x69, 0x6C, 0x20, 0x6D, 0x69, 0x6F, 0x0A, 0x74, 0x65,
+ 0x6C, 0x65, 0x74, 0x72, 0x61, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x6F, 0x2C, 0x68, 0x6F, 0x0A, 0x62,
+ 0x69, 0x73, 0x6F, 0x67, 0x6E, 0x6F, 0x20, 0x64, 0x69, 0x0A, 0x63, 0x75, 0x72, 0x65, 0x20, 0x75,
+ 0x72, 0x67, 0x65, 0x6E, 0x74, 0x69, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x47, 0x72, 0x61, 0x7A, 0x69,
+ 0x65, 0x2E, 0x20, 0x4D, 0x69, 0x20, 0x68, 0x61, 0x69, 0x0A, 0x73, 0x61, 0x6C, 0x76, 0x61, 0x74,
+ 0x6F, 0x20, 0x6C, 0x61, 0x20, 0x76, 0x69, 0x74, 0x61, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x50, 0x65,
+ 0x72, 0x20, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x4E, 0x65, 0x77, 0x0A, 0x57,
+ 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x2C, 0x20, 0x64, 0x65, 0x76, 0x69, 0x0A,
+ 0x73, 0x61, 0x6C, 0x74, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x0A, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x6F, 0x20, 0x62, 0x75, 0x63, 0x6F, 0x2C, 0x0B, 0x6D, 0x61, 0x20, 0x73, 0x65, 0x20, 0x66, 0x6F,
+ 0x73, 0x73, 0x69, 0x20, 0x69, 0x6E, 0x0A, 0x74, 0x65, 0x2C, 0x20, 0x75, 0x73, 0x65, 0x72, 0x65,
+ 0x69, 0x20, 0x75, 0x6E, 0x61, 0x0A, 0x63, 0x69, 0x6E, 0x74, 0x75, 0x72, 0x61, 0x20, 0x41, 0x6E,
+ 0x74, 0x69, 0x2D, 0x47, 0x2E, 0x0B, 0xFF, 0xE9, 0xEA, 0x44, 0x6F, 0x76, 0x65, 0x20, 0x70, 0x6F,
+ 0x73, 0x73, 0x6F, 0x0A, 0x74, 0x72, 0x6F, 0x76, 0x61, 0x72, 0x6E, 0x65, 0x20, 0x75, 0x6E, 0x61,
+ 0x3F, 0x0B, 0xFF, 0xEB, 0xEC, 0x53, 0x75, 0x62, 0x69, 0x74, 0x6F, 0x2C, 0x20, 0x74, 0x65, 0x20,
+ 0x6E, 0x65, 0x0A, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x20, 0x75, 0x6E, 0x61, 0x3A, 0x0A, 0x35, 0x30,
+ 0x30, 0x20, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x69, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x42, 0x75,
+ 0x6F, 0x6E, 0x20, 0x76, 0x69, 0x61, 0x67, 0x67, 0x69, 0x6F, 0x2C, 0x0A, 0x67, 0x69, 0x6F, 0x76,
+ 0x61, 0x6E, 0x65, 0x20, 0x75, 0x6F, 0x6D, 0x6F, 0x2E, 0x00, 0x48, 0x6F, 0x20, 0x62, 0x69, 0x73,
+ 0x6F, 0x67, 0x6E, 0x6F, 0x20, 0x64, 0x69, 0x0A, 0x75, 0x6E, 0x61, 0x20, 0x63, 0x61, 0x72, 0x74,
+ 0x75, 0x63, 0x63, 0x69, 0x61, 0x0A, 0x6D, 0x61, 0x67, 0x6E, 0x65, 0x74, 0x69, 0x63, 0x61, 0x20,
+ 0x63, 0x61, 0x72, 0x69, 0x63, 0x61, 0x00, 0x56, 0x6F, 0x72, 0x72, 0x65, 0x69, 0x20, 0x75, 0x6E,
+ 0x20, 0x70, 0x65, 0x72, 0x2D, 0x0A, 0x6D, 0x65, 0x73, 0x73, 0x6F, 0x20, 0x64, 0x69, 0x20, 0x6C,
+ 0x61, 0x76, 0x6F, 0x72, 0x6F, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x50, 0x72, 0x69, 0x6D, 0x6F, 0x20,
+ 0x70, 0x69, 0x61, 0x6E, 0x6F, 0x2E, 0x00, 0x55, 0x6E, 0x61, 0x20, 0x76, 0x6F, 0x63, 0x65, 0x20,
+ 0x69, 0x6E, 0x74, 0x65, 0x2D, 0x0A, 0x72, 0x69, 0x6F, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x74, 0x65,
+ 0x72, 0x72, 0x6F, 0x6D, 0x70, 0x65, 0x0A, 0x69, 0x20, 0x74, 0x75, 0x6F, 0x69, 0x20, 0x70, 0x65,
+ 0x6E, 0x73, 0x69, 0x65, 0x72, 0x69, 0x2E, 0x0B, 0xFF, 0xEB, 0xEC, 0x46, 0x69, 0x64, 0x61, 0x74,
+ 0x69, 0x2C, 0x20, 0x6D, 0x65, 0x74, 0x74, 0x69, 0x0A, 0x6C, 0x61, 0x20, 0x63, 0x61, 0x72, 0x69,
+ 0x63, 0x61, 0x0A, 0x61, 0x74, 0x6F, 0x6D, 0x69, 0x63, 0x61, 0x20, 0x71, 0x75, 0x69, 0x2E, 0x2E,
+ 0x2E, 0x0B, 0x65, 0x20, 0x73, 0x63, 0x61, 0x70, 0x70, 0x61, 0x20, 0x6E, 0x6F, 0x6E, 0x0A, 0x61,
+ 0x70, 0x70, 0x65, 0x6E, 0x61, 0x20, 0x72, 0x61, 0x67, 0x67, 0x69, 0x75, 0x6E, 0x67, 0x65, 0x0A,
+ 0x69, 0x6C, 0x20, 0x6E, 0x75, 0x63, 0x6C, 0x65, 0x6F, 0x0A, 0x64, 0x65, 0x6C, 0x20, 0x70, 0x69,
+ 0x61, 0x6E, 0x65, 0x74, 0x61, 0x2E, 0x00, 0xFF, 0xEB, 0xEC, 0x46, 0x61, 0x69, 0x20, 0x73, 0x74,
+ 0x72, 0x61, 0x64, 0x61, 0x2C, 0x0A, 0x67, 0x69, 0x6F, 0x76, 0x61, 0x6E, 0x65, 0x20, 0x75, 0x6F,
+ 0x6D, 0x6F, 0x2E, 0x0B, 0x50, 0x6F, 0x72, 0x74, 0x61, 0x6D, 0x69, 0x20, 0x61, 0x6C, 0x0A, 0x43,
+ 0x65, 0x6E, 0x74, 0x72, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x65, 0x72, 0x63, 0x68, 0x65, 0x2E, 0x00,
+ 0xFF, 0xEB, 0xEC, 0x47, 0x72, 0x61, 0x7A, 0x69, 0x65, 0x20, 0x70, 0x65, 0x72, 0x20, 0x69, 0x6C,
+ 0x0A, 0x74, 0x75, 0x6F, 0x20, 0x61, 0x69, 0x75, 0x74, 0x6F, 0x2E, 0x2E, 0x2E, 0x0B, 0x53, 0x6F,
+ 0x6E, 0x6F, 0x20, 0x61, 0x72, 0x72, 0x69, 0x76, 0x61, 0x74, 0x6F, 0x0A, 0x73, 0x61, 0x6E, 0x6F,
+ 0x20, 0x65, 0x20, 0x73, 0x61, 0x6C, 0x76, 0x6F, 0x0A, 0x65, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x63,
+ 0x27, 0x5C, 0x20, 0x70, 0x69, 0x5F, 0x0A, 0x70, 0x65, 0x72, 0x69, 0x63, 0x6F, 0x6C, 0x6F, 0x2E,
+ 0x00, 0xFF, 0xEB, 0xEC, 0x41, 0x6C, 0x6C, 0x6F, 0x72, 0x61, 0x2C, 0x20, 0x68, 0x61, 0x69, 0x0A,
+ 0x70, 0x6F, 0x72, 0x74, 0x61, 0x74, 0x6F, 0x20, 0x69, 0x6C, 0x0A, 0x70, 0x61, 0x63, 0x63, 0x68,
+ 0x65, 0x74, 0x74, 0x6F, 0x3F, 0x00, 0x51, 0x75, 0x61, 0x6E, 0x74, 0x6F, 0x20, 0x63, 0x6F, 0x73,
+ 0x74, 0x61, 0x20, 0x75, 0x6E, 0x0A, 0x62, 0x69, 0x67, 0x6C, 0x69, 0x65, 0x74, 0x74, 0x6F, 0x20,
+ 0x70, 0x65, 0x72, 0x0A, 0x6C, 0x61, 0x20, 0x74, 0x65, 0x72, 0x72, 0x61, 0x3F, 0x0B, 0xFF, 0xEB,
+ 0xEC, 0x35, 0x30, 0x2E, 0x30, 0x30, 0x30, 0x20, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x69, 0x2E,
+ 0x00, 0xFF, 0xEB, 0xEC, 0x49, 0x6F, 0x20, 0x64, 0x5E, 0x20, 0x75, 0x6E, 0x61, 0x20, 0x6D, 0x61,
+ 0x6E, 0x6F, 0x20, 0x61, 0x0A, 0x74, 0x65, 0x20, 0x65, 0x20, 0x74, 0x75, 0x20, 0x6E, 0x65, 0x20,
+ 0x64, 0x61, 0x69, 0x0A, 0x75, 0x6E, 0x61, 0x20, 0x61, 0x20, 0x6D, 0x65, 0x3A, 0x0B, 0x31, 0x35,
+ 0x30, 0x30, 0x20, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x69, 0x20, 0x65, 0x0A, 0x69, 0x20, 0x64,
+ 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x69, 0x0A, 0x73, 0x6F, 0x6E, 0x6F, 0x20, 0x74, 0x75,
+ 0x6F, 0x69, 0x2E, 0x00
+};
+
+const char *LocaleData::_textsTableFR[] = {
+ "CONTINUER OU ABANDONNER ?",
+ "TEMPS",
+ "CONTINUER",
+ "ABANDONNER",
+ "TERMINEE",
+ "NIVEAU",
+ "START",
+ "DIFFICULTE",
+ "MOT DE PASSE",
+ "INFO",
+ "QUITTER",
+ "NIVEAU DE DIFFICULTE :",
+ "FACILE",
+ "NORMAL",
+ "EXPERT",
+ "ENTREZ LE MOT DE PASSE POUR",
+ "ACCEDER AU NIVEAU SOUHAITE:",
+ "REPRENDRE",
+ "ABANDONNER",
+ "CHARGER",
+ "SAUVEGARDER",
+ "PARTIE"
+};
+
+const char *LocaleData::_textsTableEN[] = {
+ "CONTINUE OR ABORT THIS GAME ?",
+ "TIME",
+ "CONTINUE",
+ "ABORT",
+ "COMPLETED",
+ "LEVEL",
+ "START",
+ "SKILL",
+ "PASSWORD",
+ "INFO",
+ "QUIT",
+ "SKILL LEVEL :",
+ "EASY",
+ "NORMAL",
+ "EXPERT",
+ "Enter password for desired",
+ "level :",
+ "RESUME GAME",
+ "ABORT GAME",
+ "LOAD GAME",
+ "SAVE GAME",
+ "SLOT"
+};
+
+const char *LocaleData::_textsTableDE[] = {
+ "WEITERSPIELEN ODER ABBRECHEN ?",
+ "ZEIT : ",
+ "WEITERSPIELEN",
+ "ABBRECHEN",
+ "FERTIG",
+ "LEVEL",
+ "START",
+ "SKILL",
+ "PASSWORD",
+ "INFO",
+ "END",
+ "SKILL LEVEL :",
+ "LEICHT",
+ "NORMAL",
+ "PROFI",
+ "GEBEN SIE DAS PASSWORT F[R",
+ "DAS GEW[NSCHTE LEVEL EIN :",
+ "WEITERSPIELEN",
+ "SPIEL ABBRECHEN",
+ "LADEN",
+ "SPEICHERN",
+ "SPIEL"
+};
+
+const char *LocaleData::_textsTableSP[] = {
+ "CONTINUAR O TERMINAR JUEGO ?",
+ "TIEMPO",
+ "SEGUIR",
+ "PARAR",
+ "PUNTOS",
+ "NIVEL",
+ "EMPEZAR",
+ "DIFICULTAD",
+ "CONTRASE}A",
+ "INFO",
+ "SALIR",
+ "NIVEL DE DIFICULTAD :",
+ "SENCILLO",
+ "NORMAL",
+ "EXPERTO",
+ "ESCRIBA LA CONTRASE}A",
+ "PARA EL NIVEL DESEADO :",
+ "REANUDAR JUEGO",
+ "PARAR JUEGO",
+ "CARGAR DATOS",
+ "GUARDAR DATOS",
+ "JUEGO"
+};
+
+const char *LocaleData::_textsTableIT[] = {
+ "CONTINUA O ABBANDONA GIOCO",
+ "TEMPO",
+ "CONTINUA",
+ "ESCI",
+ "ABBANDONA",
+ "LIVELLO",
+ "INIZIO",
+ "ABILITA",
+ "PASSWORD",
+ "INFORMAZIONI",
+ "ESCI",
+ "LIVELLO ABILITA :",
+ "FACILE",
+ "NORMAL",
+ "EXPERTO",
+ "INSERISCI LA PASSWORD PER",
+ "IL LIVELLO DESIDERATO :",
+ "RIPRENDI GIOCO",
+ "ESCI DAL GIOCO",
+ "CARICA IL GIOCO",
+ "SALVA IL GIOCO",
+ "SLOT"
+};
+
+const uint16_t Resource::_voicesOffsetsTable[] = {
+ 0x0064, 0x006A, 0x0070, 0x0084, 0x0090, 0x0096, 0x009E, 0x00A4, 0x00AE, 0x00B4,
+ 0x00BC, 0x00C4, 0x00CC, 0x00D4, 0x00E0, 0x00E6, 0x00EC, 0x00F6, 0x00FC, 0x0102,
+ 0x010C, 0x0126, 0x0130, 0x0136, 0x013E, 0x0144, 0x014C, 0x0152, 0x015A, 0x0160,
+ 0x0166, 0x016C, 0x0176, 0x017C, 0x0186, 0x018C, 0x0198, 0x019E, 0x01A4, 0x01AC,
+ 0x01B6, 0x01BE, 0x01C6, 0x01CC, 0x01D4, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0x0000, 0x0001, 0x0073, 0x0073, 0x0001, 0x0050, 0x00C3, 0x0008, 0x00D7, 0x007D,
+ 0x0078, 0x007D, 0x0087, 0x005A, 0x00E1, 0x0087, 0x0555, 0x0004, 0x00D7, 0x0069,
+ 0x00EB, 0x00A5, 0x0825, 0x0001, 0x008C, 0x08B1, 0x0002, 0x00CD, 0x0073, 0x09F1,
+ 0x0001, 0x0113, 0x0B04, 0x0003, 0x0113, 0x008C, 0x00B9, 0x0D5C, 0x0001, 0x0096,
+ 0x0DF2, 0x0002, 0x00AF, 0x0082, 0x0F23, 0x0002, 0x0069, 0x009B, 0x1027, 0x0002,
+ 0x0069, 0x00EB, 0x117B, 0x0002, 0x0069, 0x00C3, 0x12A7, 0x0004, 0x0064, 0x00AA,
+ 0x0078, 0x00DC, 0x1509, 0x0001, 0x00B4, 0x15BD, 0x0001, 0x0046, 0x1603, 0x0003,
+ 0x0050, 0x0118, 0x00A5, 0x1810, 0x0001, 0x0041, 0x1851, 0x0001, 0x0082, 0x18D3,
+ 0x0003, 0x0104, 0x00D7, 0x00AF, 0x1B5D, 0x000B, 0x00AA, 0x00BE, 0x0127, 0x005A,
+ 0x00F5, 0x00AA, 0x0104, 0x00BE, 0x00DC, 0x00B9, 0x00D7, 0x2413, 0x0003, 0x00C3,
+ 0x00E6, 0x003C, 0x25F8, 0x0001, 0x0069, 0x2661, 0x0002, 0x00BE, 0x00AF, 0x27CE,
+ 0x0001, 0x0050, 0x281E, 0x0002, 0x0041, 0x0037, 0x2896, 0x0001, 0x011D, 0x29B3,
+ 0x0002, 0x0041, 0x003C, 0x2A30, 0x0001, 0x00A5, 0x2AD5, 0x0001, 0x0000, 0x2AD5,
+ 0x0001, 0x0000, 0x2AD5, 0x0003, 0x005A, 0x00B9, 0x0073, 0x2C5B, 0x0001, 0x005F,
+ 0x2CBA, 0x0003, 0x00DC, 0x0064, 0x00F0, 0x2EEA, 0x0001, 0x00B9, 0x2FA3, 0x0004,
+ 0x0181, 0x013B, 0x005F, 0x0154, 0x3412, 0x0001, 0x00AF, 0x34C1, 0x0001, 0x00A0,
+ 0x3561, 0x0002, 0x0069, 0x003C, 0x3606, 0x0003, 0x0000, 0x00FA, 0x00F0, 0x37F0,
+ 0x0002, 0x006E, 0x00A0, 0x38FE, 0x0002, 0x0064, 0x00E6, 0x3A48, 0x0001, 0x00A5,
+ 0x3AED, 0x0002, 0x0078, 0x0087, 0x3BEC, 0x0002, 0x00AA, 0x00F0
+};
+
+const uint32_t Resource::_spmOffsetsTable[1287] = {
+ 0x00000, 0x000C5, 0x001AC, 0x00299, 0x00383, 0x00454, 0x0053B, 0x00627,
+ 0x00713, 0x007EA, 0x008C8, 0x009AE, 0x00A9B, 0x00B80, 0x00D39, 0x00EF5,
+ 0x00FE1, 0x010C2, 0x011AD, 0x01362, 0x01513, 0x016BA, 0x017A1, 0x0188A,
+ 0x0198C, 0x01A62, 0x01B2C, 0x01BD4, 0x01C78, 0x01D04, 0x01D9F, 0x01E40,
+ 0x01EFF, 0x01FD2, 0x0209C, 0x02167, 0x02232, 0x022EB, 0x02397, 0x02433,
+ 0x024CC, 0x02558, 0x025D3, 0x02662, 0x02739, 0x027C1, 0x0285E, 0x0290D,
+ 0x029E6, 0x02AC4, 0x02BA7, 0x02C8A, 0x02E09, 0x02ECF, 0x02FA2, 0x0313E,
+ 0x032F3, 0x03499, 0x0363A, 0x037BA, 0x0393F, 0x03AD4, 0x03C63, 0x03D24,
+ 0x03DF5, 0x03F99, 0x0413F, 0x042DA, 0x04472, 0x045FA, 0x0477D, 0x048F0,
+ 0x049DA, 0x04AC2, 0x04BA6, 0x04C88, 0x04E2B, 0x04FC0, 0x0514D, 0x052D6,
+ 0x0544D, 0x055D7, 0x0569F, 0x05854, 0x059CC, 0x05B57, 0x05CE4, 0x05E49,
+ 0x05F9E, 0x060F8, 0x061BA, 0x0628A, 0x0636B, 0x0643E, 0x06505, 0x065D6,
+ 0x0674A, 0x068D1, 0x06A5E, 0x06BC3, 0x06D10, 0x06E5B, 0x06FA3, 0x070DD,
+ 0x07219, 0x0734C, 0x0749A, 0x075F9, 0x0776A, 0x078FB, 0x07A8B, 0x07B60,
+ 0x07C25, 0x07CEB, 0x07DC8, 0x07E9F, 0x0803F, 0x081DD, 0x08371, 0x08444,
+ 0x0852C, 0x085EF, 0x086BA, 0x08839, 0x08992, 0x08AE7, 0x08C58, 0x08D27,
+ 0x08DED, 0x08EAF, 0x08F71, 0x0901F, 0x090D1, 0x09189, 0x09239, 0x092E5,
+ 0x0938F, 0x094D7, 0x09608, 0x0969B, 0x09724, 0x0979B, 0x09816, 0x0989F,
+ 0x0995B, 0x09AC8, 0x09C4A, 0x09DD5, 0x09F61, 0x0A020, 0x0A0DF, 0x0A184,
+ 0x0A218, 0x0A2BD, 0x0A3EE, 0x0A509, 0x0A633, 0x0A755, 0x0A86D, 0x0A8FF,
+ 0x0A99B, 0x0AA38, 0x0AB65, 0x0AC9E, 0x0ADFF, 0x0AF7A, 0x0B051, 0x0B121,
+ 0x0B1F6, 0x0B2CF, 0x0B3B6, 0x0B49D, 0x0B596, 0x0B681, 0x0B744, 0x0B801,
+ 0x0B8B2, 0x0B954, 0x0B9F5, 0x0BAA1, 0x0BBFF, 0x0BD69, 0x0BED3, 0x0C03A,
+ 0x0C188, 0x0C2DD, 0x0C422, 0x0C4C8, 0x0C55C, 0x0C5EF, 0x0C683, 0x0C734,
+ 0x0C7FC, 0x0C8D1, 0x0CA54, 0x0CBC0, 0x0CD36, 0x0CEA7, 0x0CF5A, 0x0D0C2,
+ 0x0D188, 0x0D272, 0x0D3C2, 0x0D503, 0x0D631, 0x0D75C, 0x0D87E, 0x0D933,
+ 0x0D9E2, 0x0DA9D, 0x0DB5C, 0x0DC96, 0x0DD51, 0x0DE39, 0x0DF3E, 0x0E041,
+ 0x0E129, 0x0E211, 0x0E383, 0x0E4E5, 0x0E619, 0x0E732, 0x0E848, 0x0E944,
+ 0x0EA47, 0x0EB52, 0x0EC5F, 0x0ED6F, 0x0EE6F, 0x0EF59, 0x0EFD4, 0x0F04A,
+ 0x0F119, 0x0F1DF, 0x0F2B1, 0x0F38F, 0x0F462, 0x0F57A, 0x0F6B1, 0x0F807,
+ 0x0F8D2, 0x0F9B5, 0x0FA9E, 0x0FBA3, 0x0FC4B, 0x0FD2C, 0x0FD92, 0x0FE5B,
+ 0x0FEC6, 0x0FF2B, 0x0FF8B, 0x0FFFB, 0x10078, 0x10101, 0x1019D, 0x1024D,
+ 0x10320, 0x103FA, 0x1057D, 0x106FC, 0x1087B, 0x10945, 0x10A14, 0x10AE7,
+ 0x10BC3, 0x10C92, 0x10D63, 0x10E3A, 0x10F12, 0x10FF6, 0x111AA, 0x1133F,
+ 0x114DA, 0x11672, 0x11814, 0x119BA, 0x11B60, 0x11CF3, 0x11E7D, 0x12015,
+ 0x121C3, 0x12368, 0x1250D, 0x126AB, 0x1284D, 0x129E7, 0x12B85, 0x12D39,
+ 0x12EC8, 0x1303F, 0x1319E, 0x132E5, 0x13410, 0x1352C, 0x135C5, 0x13669,
+ 0x13711, 0x13841, 0x1395D, 0x13A69, 0x13C00, 0x13CDB, 0x13DAF, 0x13E81,
+ 0x13F53, 0x14076, 0x14196, 0x1422F, 0x142C7, 0x14360, 0x143F7, 0x144CF,
+ 0x145A8, 0x14680, 0x14757, 0x1482F, 0x14907, 0x149E1, 0x14AB3, 0x14B89,
+ 0x14C5D, 0x14D3D, 0x14E1E, 0x14F05, 0x14FF1, 0x150D7, 0x1527C, 0x153BD,
+ 0x15478, 0x15561, 0x1566D, 0x15772, 0x15862, 0x1596B, 0x15A7C, 0x15B83,
+ 0x15C81, 0x15D80, 0x15E7F, 0x15F7F, 0x16072, 0x1613D, 0x16211, 0x162EA,
+ 0x163A0, 0x16438, 0x164B9, 0x1652A, 0x16604, 0x166E4, 0x167BE, 0x16948,
+ 0x16AE2, 0x16C57, 0x16D17, 0x16DF1, 0x16F96, 0x17083, 0x17168, 0x17249,
+ 0x1732F, 0x17411, 0x174F1, 0x175BC, 0x176A9, 0x17791, 0x17870, 0x17952,
+ 0x17AF2, 0x17C96, 0x17E2F, 0x17F04, 0x17FD9, 0x180AE, 0x18183, 0x18253,
+ 0x1831D, 0x183F2, 0x18583, 0x18703, 0x18884, 0x18A01, 0x18B7C, 0x18CFD,
+ 0x18E8A, 0x1900D, 0x1919F, 0x19348, 0x194EA, 0x1967D, 0x197FA, 0x19989,
+ 0x19B14, 0x19BE9, 0x19CC0, 0x19DA9, 0x19E77, 0x19F49, 0x1A01B, 0x1A0FA,
+ 0x1A1C0, 0x1A298, 0x1A37E, 0x1A3F7, 0x1A574, 0x1A6CD, 0x1A812, 0x1A94A,
+ 0x1AA80, 0x1AB98, 0x1ACA3, 0x1ADD8, 0x1AEC3, 0x1AF9C, 0x1B071, 0x1B125,
+ 0x1B1E1, 0x1B2A7, 0x1B339, 0x1B39F, 0x1B411, 0x1B54D, 0x1B6A1, 0x1B814,
+ 0x1B9A9, 0x1BA87, 0x1BB73, 0x1BCE7, 0x1BE2C, 0x1BF22, 0x1BFD9, 0x1C04E,
+ 0x1C0B2, 0x1C10C, 0x1C166, 0x1C1C0, 0x1C363, 0x1C454, 0x1C534, 0x1C616,
+ 0x1C706, 0x1C7EC, 0x1C8D3, 0x1C9B7, 0x1CAA4, 0x1CC5C, 0x1CDB4, 0x1CF00,
+ 0x1D044, 0x1D1A2, 0x1D2ED, 0x1D3F7, 0x1D49F, 0x1D540, 0x1D5FD, 0x1D703,
+ 0x1D80A, 0x1D91E, 0x1DA48, 0x1DB58, 0x1DC63, 0x1DD2D, 0x1DDB2, 0x1DE1D,
+ 0x1DE74, 0x1DEBB, 0x1DFD0, 0x1E0C0, 0x1E177, 0x1E2CF, 0x1E402, 0x1E505,
+ 0x1E5C1, 0x1E627, 0x1E705, 0x1E7A8, 0x1E81A, 0x1E874, 0x1E8CE, 0x1E928,
+ 0x1E982, 0x1E9E5, 0x1EA64, 0x1EB07, 0x1EBB6, 0x1EC81, 0x1ED58, 0x1EE30,
+ 0x1EF08, 0x1F01D, 0x1F0C0, 0x1F170, 0x1F233, 0x1F3D3, 0x1F5BD, 0x1F6C3,
+ 0x1F7B7, 0x1F89C, 0x1FA67, 0x1FC0B, 0x1FD7D, 0x1FEAB, 0x1FFBD, 0x2019E,
+ 0x20354, 0x20511, 0x206C1, 0x2089E, 0x20A66, 0x20B44, 0x20C87, 0x20D0D,
+ 0x20D8B, 0x20E0D, 0x20E7F, 0x20ED9, 0x20F4B, 0x20FD3, 0x21059, 0x210DF,
+ 0x21179, 0x21223, 0x212E4, 0x2139E, 0x21458, 0x2151F, 0x215D2, 0x216A0,
+ 0x21770, 0x2182D, 0x218EB, 0x219AD, 0x21A1B, 0x21A9D, 0x21B37, 0x21BE4,
+ 0x21C9E, 0x21D5E, 0x21E1C, 0x21EE3, 0x21FAF, 0x22067, 0x2211E, 0x22210,
+ 0x22321, 0x2244D, 0x22516, 0x225D5, 0x2269C, 0x2280B, 0x229A3, 0x22B6B,
+ 0x22C45, 0x22DE5, 0x22F76, 0x2310E, 0x232A7, 0x2345B, 0x23623, 0x2B9D7,
+ 0x2BB9B, 0x2BD57, 0x2BF22, 0x2C0ED, 0x2C2AD, 0x2C46C, 0x2C631, 0x2C7F8,
+ 0x2C9B4, 0x2CB6F, 0x2CD2A, 0x2CEE7, 0x2D0B0, 0x2D284, 0x2D458, 0x2D622,
+ 0x2D7E8, 0x2D9AF, 0x2DB6F, 0x2DD41, 0x2DF14, 0x2E104, 0x2E309, 0x2E517,
+ 0x2E71C, 0x2E92F, 0x2EB47, 0x2ED4C, 0x2EF2E, 0x2F0FF, 0x2F2D5, 0x2F4A7,
+ 0x2F670, 0x2F827, 0x2F9D3, 0x2FB73, 0x2FD28, 0x2FEDD, 0x300AD, 0x3029A,
+ 0x30487, 0x3065D, 0x30833, 0x30A08, 0x30BDF, 0x30DB5, 0x30F8E, 0x30F93,
+ 0x31168, 0x3133D, 0x31512, 0x316E7, 0x318BC, 0x31A91, 0x31C5E, 0x31E22,
+ 0x31FE1, 0x32194, 0x3232E, 0x3249F, 0x325E5, 0x3270A, 0x32835, 0x3297C,
+ 0x32B67, 0x32D5D, 0x32F34, 0x330EC, 0x33299, 0x33428, 0x335B5, 0x33714,
+ 0x3382E, 0x3393B, 0x339FF, 0x33A95, 0x33B50, 0x33C13, 0x33CA2, 0x33D21,
+ 0x33D8F, 0x33DE7, 0x33E35, 0x3402E, 0x341EF, 0x34343, 0x344AE, 0x345D6,
+ 0x346DF, 0x347E7, 0x348D1, 0x34967, 0x349FD, 0x34A7B, 0x23726, 0x237A3,
+ 0x23826, 0x238AD, 0x23936, 0x23A3A, 0x23B3E, 0x23BC8, 0x23CD9, 0x23DEF,
+ 0x23F0B, 0x240C2, 0x241AD, 0x24295, 0x2443F, 0x245E5, 0x2478B, 0x24933,
+ 0x24ACD, 0x24C66, 0x24E09, 0x24FD1, 0x251A7, 0x2537F, 0x25483, 0x255E7,
+ 0x256DA, 0x257C6, 0x25837, 0x258B9, 0x25953, 0x25A00, 0x25AC1, 0x25B9C,
+ 0x25C7D, 0x25D5C, 0x25E3C, 0x25F14, 0x26029, 0x260D7, 0x261FA, 0x262A0,
+ 0x26348, 0x263F8, 0x264AD, 0x26557, 0x265FF, 0x266A7, 0x26752, 0x2687D,
+ 0x26922, 0x269C2, 0x26A74, 0x26BE6, 0x26D86, 0x26E49, 0x26F08, 0x26FEA,
+ 0x270CC, 0x271AC, 0x2728E, 0x27370, 0x27451, 0x2751C, 0x275EB, 0x276B5,
+ 0x27792, 0x2792E, 0x27ABD, 0x27C55, 0x27D33, 0x27E06, 0x27F00, 0x2800C,
+ 0x280A3, 0x281CD, 0x282E7, 0x283FE, 0x284A6, 0x28572, 0x2863D, 0x286FD,
+ 0x287A8, 0x28849, 0x288E2, 0x2896D, 0x289F4, 0x28A75, 0x28AF7, 0x28B80,
+ 0x28C1B, 0x28CD2, 0x2B9D7, 0x2BBB2, 0x2BD81, 0x2BF42, 0x2C105, 0x2C2CA,
+ 0x2C47D, 0x2C645, 0x2C817, 0x2C9F2, 0x2CBB2, 0x2CD68, 0x2CF20, 0x2D0CA,
+ 0x2D265, 0x2D420, 0x2D5F4, 0x2D6D6, 0x2D7C2, 0x2D97B, 0x2DA59, 0x2DB2E,
+ 0x2DC07, 0x2DCF3, 0x2DDDB, 0x2DEC6, 0x2E091, 0x2E256, 0x2E41A, 0x2E5DE,
+ 0x2E7B7, 0x2E956, 0x2EAFE, 0x2ECA7, 0x2EE55, 0x2F035, 0x2F215, 0x2F3E5,
+ 0x2F4D2, 0x2F5C1, 0x2F786, 0x2F953, 0x2FB21, 0x2FD03, 0x2FEEA, 0x300CE,
+ 0x302CB, 0x304D5, 0x306DF, 0x308C9, 0x30AB3, 0x30C87, 0x30E5B, 0x3102F,
+ 0x31203, 0x313D7, 0x315BB, 0x31787, 0x3195B, 0x31B2F, 0x31D03, 0x31EE9,
+ 0x320CC, 0x322AC, 0x3247B, 0x3265B, 0x3283B, 0x32A2D, 0x32C1F, 0x32E11,
+ 0x33003, 0x331D3, 0x33379, 0x3351E, 0x336BF, 0x33883, 0x33A44, 0x33C05,
+ 0x33DD8, 0x33F9C, 0x3415C, 0x34341, 0x34514, 0x34608, 0x346EF, 0x347D6,
+ 0x348CE, 0x34AA5, 0x34C78, 0x34E6A, 0x3505C, 0x3524E, 0x35440, 0x35632,
+ 0x35824, 0x3590C, 0x35AB2, 0x35C7D, 0x35E3A, 0x35FF0, 0x36184, 0x36313,
+ 0x36470, 0x36597, 0x36662, 0x3672A, 0x367C4, 0x3682B, 0x36878, 0x368B1,
+ 0x368D5, 0x368E7, 0x36AAE, 0x36C67, 0x36E0A, 0x36F74, 0x3708E, 0x37163,
+ 0x3723A, 0x37332, 0x37456, 0x375A7, 0x3771B, 0x37893, 0x379EE, 0x37B39,
+ 0x37C54, 0x37CD8, 0x37D08, 0x37D0F, 0x37EBC, 0x3804C, 0x3823E, 0x38404,
+ 0x385BF, 0x387B2, 0x38997, 0x38B7E, 0x38D55, 0x38F2C, 0x39103, 0x392DB,
+ 0x394B0, 0x3967B, 0x3983C, 0x39A03, 0x39B8C, 0x39CF6, 0x39E55, 0x39F90,
+ 0x3A0CB, 0x3A209, 0x3A353, 0x3A49B, 0x3A5D6, 0x3A711, 0x28D70, 0x2B9D7,
+ 0x2BBAD, 0x2BD84, 0x2BF5A, 0x2C127, 0x2C2F5, 0x2C4C2, 0x2C683, 0x2C856,
+ 0x2CA2D, 0x2CBFF, 0x2CDD9, 0x2CFA6, 0x2D173, 0x2D341, 0x2D50F, 0x2D6E9,
+ 0x2D8C4, 0x2DA9E, 0x2DC74, 0x2DE4E, 0x2DF33, 0x2E006, 0x2E180, 0x2E2D6,
+ 0x2E408, 0x2E524, 0x2E63F, 0x2E75A, 0x2E875, 0x2E99C, 0x2EABE, 0x2EB90,
+ 0x2ECE8, 0x2EEA1, 0x2F029, 0x2F16D, 0x2F298, 0x2F3B0, 0x2F58A, 0x2F67B,
+ 0x2F76C, 0x2F85C, 0x2F94B, 0x2FA3A, 0x2FB2B, 0x2FC1B, 0x2FD0C, 0x2FEE6,
+ 0x300B9, 0x30288, 0x30447, 0x305F6, 0x306FC, 0x308CB, 0x30AA5, 0x30C5A,
+ 0x30DE0, 0x30F36, 0x31074, 0x3119A, 0x3123D, 0x313AB, 0x31555, 0x3176D,
+ 0x319A0, 0x31AC3, 0x31BD2, 0x31CE3, 0x31ECA, 0x320A8, 0x3226E, 0x323FE,
+ 0x32580, 0x326F4, 0x32860, 0x329BE, 0x32B37, 0x32CAB, 0x32E3A, 0x32FFC,
+ 0x331D6, 0x333B0, 0x3358A, 0x33764, 0x3393E, 0x33B18, 0x33CF3, 0x33ECD,
+ 0x340A7, 0x34281, 0x3445B, 0x34635, 0x34810, 0x349EB, 0x34AD6, 0x34C9B,
+ 0x34E56, 0x35010, 0x351C3, 0x35375, 0x354C5, 0x355C5, 0x35653, 0x35726,
+ 0x35840, 0x35990, 0x35B2B, 0x35CF4, 0x35DE4, 0x35ED5, 0x360AB, 0x36279,
+ 0x36427, 0x365A6, 0x366D2, 0x36780, 0x36819, 0x3687D, 0x368D6, 0x36948,
+ 0x369F6, 0x36AC8, 0x36BA6, 0x36C90, 0x36D92, 0x36EB8, 0x3701A, 0x371AC,
+ 0x37363, 0x3752D, 0x37704, 0x3789D, 0x379FF, 0x37B42, 0x37C69, 0x37D38,
+ 0x37DDB, 0x37E63, 0x37EED, 0x37F8E, 0x38054, 0x3813E, 0x3824C, 0x3837E,
+ 0x383D7, 0x38431, 0x3848B, 0x384E5, 0x3853E, 0x38598, 0x385F2, 0x3864C,
+ 0x386D4, 0x3875E, 0x387E6, 0x38870, 0x388F7, 0x38969, 0x389CF, 0x38A32,
+ 0x38A95, 0x38AF8, 0x38B49, 0x38B6F, 0x38D4A, 0x38E4C, 0x38F6D, 0x3915D,
+ 0x2B9D7, 0x2BACB, 0x2BBC0, 0x2BD7C, 0x2BF38, 0x2C106, 0x2C1F8, 0x2C2E9,
+ 0x2C3DC, 0x2C4D0, 0x2C5C2, 0x2C788, 0x2C942, 0x2CAFF, 0x2CCCA, 0x2CE9B,
+ 0x2CF91, 0x2D083, 0x2D24D, 0x2D40E, 0x2D5CF, 0x2D795, 0x2D966, 0x2DA59,
+ 0x2DB4E, 0x2DC39, 0x2DD18, 0x2DDDB, 0x2DE7D, 0x2DF0A, 0x2DFD9, 0x2E094,
+ 0x2E0D6, 0x2E130, 0x2E170, 0x2E1B9, 0x2E214, 0x2E293, 0x2E308, 0x2E36E,
+ 0x2E3B9, 0x2E401, 0x2E443, 0x2E48E, 0x2E4E9, 0x2E569, 0x2E5DF, 0x2E645,
+ 0x2E692, 0x2E6DC, 0x2E763, 0x2E7E1, 0x2E867, 0x2E8C6, 0x2E972, 0x2EA3A,
+ 0x2EAAF, 0x2EB2F, 0x2EBDB, 0x2EC43, 0x2EC8B, 0x2ECD3, 0x2ED1A, 0x2ED60,
+ 0x2EDA8, 0x2EE32, 0x2EF19, 0x2EFD5, 0x2F069, 0x2F0B2, 0x2F11D, 0x2F1B9,
+ 0x2F285, 0x2F30A, 0x2F39E, 0x2F431, 0x2F4D1, 0x2F54E, 0x2F5B9, 0x2F61C,
+ 0x2F68C, 0x2F705, 0x2F796, 0x2F839, 0x2F8CA, 0x2F962, 0x2F9EC, 0x2FA7C,
+ 0x2FB0D, 0x2FC08, 0x2FCE8, 0x2FD61, 0x2FDD4, 0x2FE48, 0x2FEBA, 0x2FF26,
+ 0x2FFAF, 0x30040, 0x300BA, 0x3012E, 0x301AF, 0x3027A, 0x30321, 0x30372,
+ 0x303B9, 0x303F8, 0x3043A, 0x304C2, 0x30541, 0x30578, 0x30601, 0x30690,
+ 0x30707, 0x30750, 0x30794, 0x30811, 0x308FA, 0x309F0, 0x30A74, 0x30AE9,
+ 0x30B5C, 0x30BCC, 0x30C38, 0x30CC0, 0x30D4F, 0x30DC8, 0x30E3B, 0x31015,
+ 0x311CE, 0x3137B, 0x31512, 0x3169F, 0x31807, 0x31921, 0x319C2, 0x31A27,
+ 0x31A82, 0x31ABE, 0x31C9B, 0x31E7F, 0x32040, 0x321D6, 0x322F6, 0x3238A,
+ 0x323D4, 0x32420, 0x32474, 0x324D9, 0x3254B, 0x325CF, 0x32659, 0x326C1,
+ 0x326CF, 0x32897, 0x32A64, 0x32B5B, 0x32C53, 0x32D4C, 0x32E3F, 0x32F2C,
+ 0x33013, 0x330F9, 0x331D9, 0x332BC, 0x333AD, 0x3359C, 0x3376B, 0x33854,
+ 0x33932, 0x339FF, 0x33AC0, 0x33B72, 0x33C1F, 0x33CBE, 0x33DFD, 0x33F3B,
+ 0x34070, 0x341A4, 0x342D2, 0x343FC, 0x34522, 0x34654, 0x34700, 0x34855,
+ 0x34991, 0x28D75, 0x2903C, 0x292F0, 0x29562, 0x297CB, 0x298EF, 0x299F6,
+ 0x29AE4, 0x29B54, 0x29CEA, 0x29E90, 0x2A03A, 0x2A1E4, 0x2A39E, 0x2A578,
+ 0x2A67C, 0x2A84B, 0x2A9D1, 0x2AB7E, 0x2AD36, 0x2AEF3, 0x2B08C, 0x2B223,
+ 0x2B3DE, 0x2B595, 0x2B74A, 0x2B7C6, 0x2B847, 0x2B8CE, 0x2B952
+};
+
+const char *Resource::_splNames[] = {
+ "pneuma05.spl",
+ "bip00105.spl",
+ "bip00205.spl",
+ "laser205.spl",
+ "tir2",
+ "explo.spl",
+ "mort0105.spl",
+ "mort0310.spl",
+ "bouclier.spl",
+ "asc_debut",
+ "asc_milieu",
+ "asc_fin",
+ "verre_casse",
+ "chalu110.spl",
+ "saut.spl",
+ "trappe.spl",
+ "impact_shield.spl",
+ "stby0105.spl",
+ "teletower.spl",
+ "desint.spl",
+ "recharge.spl",
+ "mitrail.spl",
+ "touche.spl",
+ "coup",
+ "chenille.spl",
+ "robot.spl",
+ "tombe.spl",
+ "porte_ferme.spl",
+ "canon_down",
+ "elec.spl",
+ "mater210.spl",
+ "mater07.spl",
+ "mur_bouge.spl",
+ "taxi.spl",
+ "souris.spl",
+ "et.spl",
+ "et_touche.spl",
+ "et_transform.spl",
+ "alien_move.spl",
+ "jungle2",
+ "jungle1",
+ "piaf2",
+ "goute_eau",
+ "piaf1",
+ "pas1",
+ "pas2",
+ "croa",
+ "alien1",
+ "alien2",
+ "alien3",
+ "ventilo",
+ "poussiere",
+ "bip",
+ "electri",
+ "machine",
+ "alarme2",
+ "cerveau",
+ "reflet",
+ "roule_boule",
+ "hehe3",
+ "recept",
+ "bestiole",
+ "lampe",
+ "mine",
+ "effort",
+ "frappe",
+ 0
+};
+
+const Game::pge_OpcodeProc Game::_pge_opcodeTable[] = {
+ /* 0x00 */
+ 0,
+ &Game::pge_op_isInpUp,
+ &Game::pge_op_isInpBackward,
+ &Game::pge_op_isInpDown,
+ /* 0x04 */
+ &Game::pge_op_isInpForward,
+ &Game::pge_op_isInpUpMod,
+ &Game::pge_op_isInpBackwardMod,
+ &Game::pge_op_isInpDownMod,
+ /* 0x08 */
+ &Game::pge_op_isInpForwardMod,
+ &Game::pge_op_isInpIdle,
+ &Game::pge_op_isInpNoMod,
+ &Game::pge_op_getCollision0u,
+ /* 0x0C */
+ &Game::pge_op_getCollision00,
+ &Game::pge_op_getCollision0d,
+ &Game::pge_op_getCollision1u,
+ &Game::pge_op_getCollision10,
+ /* 0x10 */
+ &Game::pge_op_getCollision1d,
+ &Game::pge_op_getCollision2u,
+ &Game::pge_op_getCollision20,
+ &Game::pge_op_getCollision2d,
+ /* 0x14 */
+ &Game::pge_op_doesNotCollide0u,
+ &Game::pge_op_doesNotCollide00,
+ &Game::pge_op_doesNotCollide0d,
+ &Game::pge_op_doesNotCollide1u,
+ /* 0x18 */
+ &Game::pge_op_doesNotCollide10,
+ &Game::pge_op_doesNotCollide1d,
+ &Game::pge_op_doesNotCollide2u,
+ &Game::pge_op_doesNotCollide20,
+ /* 0x1C */
+ &Game::pge_op_doesNotCollide2d,
+ &Game::pge_op_collides0o0d,
+ &Game::pge_op_collides2o2d,
+ &Game::pge_op_collides0o0u,
+ /* 0x20 */
+ &Game::pge_op_collides2o2u,
+ &Game::pge_op_collides2u2o,
+ &Game::pge_op_isInGroup,
+ &Game::pge_op_updateGroup0,
+ /* 0x24 */
+ &Game::pge_op_updateGroup1,
+ &Game::pge_op_updateGroup2,
+ &Game::pge_op_updateGroup3,
+ &Game::pge_op_isPiegeDead,
+ /* 0x28 */
+ &Game::pge_op_collides1u2o,
+ &Game::pge_op_collides1u1o,
+ &Game::pge_op_collides1o1u,
+ &Game::pge_o_unk0x2B,
+ /* 0x2C */
+ &Game::pge_o_unk0x2C,
+ &Game::pge_o_unk0x2D,
+ &Game::pge_op_nop,
+ &Game::pge_op_pickupObject,
+ /* 0x30 */
+ &Game::pge_op_addItemToInventory,
+ &Game::pge_op_copyPiege,
+ &Game::pge_op_canUseCurrentInventoryItem,
+ &Game::pge_op_removeItemFromInventory,
+ /* 0x34 */
+ &Game::pge_o_unk0x34,
+ &Game::pge_op_isInpMod,
+ &Game::pge_op_setCollisionState1,
+ &Game::pge_op_setCollisionState0,
+ /* 0x38 */
+ &Game::pge_op_isInGroup1,
+ &Game::pge_op_isInGroup2,
+ &Game::pge_op_isInGroup3,
+ &Game::pge_op_isInGroup4,
+ /* 0x3C */
+ &Game::pge_o_unk0x3C,
+ &Game::pge_o_unk0x3D,
+ &Game::pge_op_setPiegeCounter,
+ &Game::pge_op_decPiegeCounter,
+ /* 0x40 */
+ &Game::pge_o_unk0x40,
+ &Game::pge_op_wakeUpPiege,
+ &Game::pge_op_removePiege,
+ &Game::pge_op_removePiegeIfNotNear,
+ /* 0x44 */
+ &Game::pge_op_loadPiegeCounter,
+ &Game::pge_o_unk0x45,
+ &Game::pge_o_unk0x46,
+ &Game::pge_o_unk0x47,
+ /* 0x48 */
+ &Game::pge_o_unk0x48,
+ &Game::pge_o_unk0x49,
+ &Game::pge_o_unk0x4A,
+ &Game::pge_op_killPiege,
+ /* 0x4C */
+ &Game::pge_op_isInCurrentRoom,
+ &Game::pge_op_isNotInCurrentRoom,
+ &Game::pge_op_scrollPosY,
+ &Game::pge_op_playDefaultDeathCutscene,
+ /* 0x50 */
+ &Game::pge_o_unk0x50,
+ 0,
+ &Game::pge_o_unk0x52,
+ &Game::pge_o_unk0x53,
+ /* 0x54 */
+ &Game::pge_op_isPiegeNear,
+ &Game::pge_op_setLife,
+ &Game::pge_op_incLife,
+ &Game::pge_op_setPiegeDefaultAnim,
+ /* 0x58 */
+ &Game::pge_op_setLifeCounter,
+ &Game::pge_op_decLifeCounter,
+ &Game::pge_op_playCutscene,
+ &Game::pge_op_isTempVar2Set,
+ /* 0x5C */
+ &Game::pge_op_playDeathCutscene,
+ &Game::pge_o_unk0x5D,
+ &Game::pge_o_unk0x5E,
+ &Game::pge_o_unk0x5F,
+ /* 0x60 */
+ &Game::pge_op_findAndCopyPiege,
+ &Game::pge_op_isInRandomRange,
+ &Game::pge_o_unk0x62,
+ &Game::pge_o_unk0x63,
+ /* 0x64 */
+ &Game::pge_o_unk0x64,
+ &Game::pge_op_addToCredits,
+ &Game::pge_op_subFromCredits,
+ &Game::pge_o_unk0x67,
+ /* 0x68 */
+ &Game::pge_op_setCollisionState2,
+ &Game::pge_op_saveState,
+ &Game::pge_o_unk0x6A,
+ &Game::pge_op_isInGroupSlice,
+ /* 0x6C */
+ &Game::pge_o_unk0x6C,
+ &Game::pge_op_isCollidingObject,
+ &Game::pge_o_unk0x6E,
+ &Game::pge_o_unk0x6F,
+ /* 0x70 */
+ &Game::pge_o_unk0x70,
+ &Game::pge_o_unk0x71,
+ &Game::pge_o_unk0x72,
+ &Game::pge_o_unk0x73,
+ /* 0x74 */
+ &Game::pge_op_collides4u,
+ &Game::pge_op_doesNotCollide4u,
+ &Game::pge_op_isBelowConrad,
+ &Game::pge_op_isAboveConrad,
+ /* 0x78 */
+ &Game::pge_op_isNotFacingConrad,
+ &Game::pge_op_isFacingConrad,
+ &Game::pge_op_collides2u1u,
+ &Game::pge_op_displayText,
+ /* 0x7C */
+ &Game::pge_o_unk0x7C,
+ &Game::pge_op_playSound,
+ &Game::pge_o_unk0x7E,
+ &Game::pge_o_unk0x7F,
+ /* 0x80 */
+ &Game::pge_op_setPiegePosX,
+ &Game::pge_op_setPiegePosModX,
+ &Game::pge_op_changeRoom,
+ &Game::pge_op_hasInventoryItem,
+ /* 0x84 */
+ &Game::pge_op_changeLevel,
+ &Game::pge_op_shakeScreen,
+ &Game::pge_o_unk0x86,
+ &Game::pge_op_playSoundGroup,
+ /* 0x88 */
+ &Game::pge_op_adjustPos,
+ 0,
+ &Game::pge_op_setTempVar1,
+ &Game::pge_op_isTempVar1Set
+};
+
+const uint8_t Game::_pge_modKeysTable[] = {
+ 0x40, 0x10, 0x20
+};
+
+const uint8_t Game::_protectionCodeData[] = {
+ 0xF9, 0x77, 0x79, 0xF9, 0xF7, 0x39, 0x79, 0x97, 0x39, 0xF9, 0x19, 0x59, 0xB9, 0x59, 0x39, 0xC9,
+ 0xB9, 0x19, 0xB9, 0x47, 0xB7, 0x49, 0xC9, 0xF9, 0xB9, 0x77, 0xD9, 0x07, 0x77, 0x47, 0xC9, 0x79,
+ 0x47, 0xF9, 0xD9, 0x19, 0x39, 0xD9, 0xB9, 0x79, 0x39, 0xD9, 0x39, 0xB9, 0x39, 0xF9, 0x19, 0x59,
+ 0xF9, 0xB7, 0xB9, 0x39, 0x27, 0x79, 0xB9, 0x49, 0x39, 0xD9, 0xB7, 0x07, 0xF9, 0x37, 0x99, 0x07,
+ 0x37, 0xD9, 0x39, 0xF9, 0xB9, 0x99, 0xB9, 0x79, 0x19, 0x59, 0xB9, 0xF9, 0x39, 0xF7, 0x39, 0x07,
+ 0xF9, 0x39, 0xD9, 0xD9, 0x99, 0x17, 0xD9, 0xB9, 0x77, 0xD7, 0x47, 0x77, 0x87, 0x39, 0xF9, 0x77,
+ 0x19, 0x59, 0xB9, 0x79, 0xB9, 0x19, 0x49, 0xD7, 0xB9, 0x99, 0x19, 0x59, 0x47, 0xF9, 0x37, 0x59,
+ 0x87, 0x37, 0x49, 0xC9, 0xD7, 0x77, 0xB9, 0x17, 0xD9, 0xD9, 0x17, 0x19, 0x79, 0xB7, 0xB9, 0x39,
+ 0x39, 0xC9, 0x39, 0x97, 0x39, 0xD9, 0x39, 0xC9, 0x39, 0xF7, 0xF9, 0x17, 0xD9, 0xC9, 0xF9, 0x99,
+ 0xF9, 0xB7, 0x39, 0x17, 0x37, 0x99, 0xF9, 0x97, 0x27, 0x39, 0x19, 0x99, 0x19, 0x59, 0x39, 0x79,
+ 0x49, 0x19, 0x39, 0x39, 0x39, 0xD9, 0xB9, 0xF9, 0x0F, 0x1F, 0xDF, 0x17, 0x19, 0xD9, 0x49, 0x49,
+ 0x79, 0x17, 0x39, 0xD9, 0x79, 0x19, 0x97, 0x27, 0x87, 0x67, 0xB9, 0x79, 0x19, 0x59, 0x19, 0xD9,
+ 0x59, 0x59, 0x79, 0x99, 0xB9, 0x19, 0x19, 0x39, 0x97, 0x99, 0x3F, 0x17, 0x17, 0x97, 0x3F, 0x39,
+ 0xF9, 0x99, 0xF9, 0xB7, 0x17, 0x79, 0x39, 0xC9, 0x39, 0xD9, 0x39, 0x99, 0x39, 0x17, 0x39, 0xF9,
+ 0xB9, 0x19, 0x19, 0x59, 0xD9, 0x19, 0xB7, 0x99, 0xC9, 0xC9, 0xD9, 0xB7, 0x19, 0x79, 0x1F, 0x7F,
+ 0x79, 0xD9, 0x37, 0x99, 0xF7, 0xF9, 0xB9, 0xF9, 0x39, 0xF7, 0x19, 0x59, 0xB9, 0x99, 0x39, 0x37,
+ 0x39, 0x39, 0xC9, 0x19, 0xC9, 0x37, 0xF9, 0xD9, 0xE7, 0x4F, 0xD9, 0xF9, 0x9F, 0x19, 0xD9, 0xD9,
+ 0x19, 0x79, 0x99, 0x19, 0xB9, 0x79, 0x19, 0x59, 0x39, 0xF7, 0x19, 0xB9, 0x39, 0xD9, 0x19, 0x59,
+ 0x99, 0x37, 0x79, 0xF9, 0x39, 0xF7, 0x39, 0x49, 0x59, 0x99, 0x59, 0xF7, 0xD9, 0x87, 0xB7, 0x39,
+ 0xF9, 0xB9, 0xB9, 0x19, 0x39, 0xC9, 0x39, 0xF9, 0x39, 0xF7, 0x19, 0x59, 0x39, 0x79, 0x97, 0x1F,
+ 0xF9, 0x77, 0x39, 0x19, 0x39, 0x99, 0x1F, 0xC9, 0x49, 0xB9, 0xD9, 0xD9, 0xF9, 0xB7, 0x49, 0xF9,
+ 0x39, 0xF9, 0x19, 0x59, 0x39, 0xB9, 0x39, 0x97, 0x39, 0x37, 0xB9, 0x19, 0xD9, 0x47, 0x67, 0xE7,
+ 0x37, 0xC9, 0x19, 0x99, 0x27, 0x39, 0x47, 0xF9, 0x87, 0x87, 0x17, 0x37, 0xD9, 0x19, 0x39, 0xC9,
+ 0x39, 0xF9, 0xB9, 0xF9, 0xB9, 0x49, 0x19, 0x97, 0x19, 0x59, 0x67, 0xE7, 0x47, 0xC9, 0xF9, 0x37,
+ 0xD9, 0x17, 0x19, 0x99, 0xC9, 0xF9, 0x79, 0x79, 0x39, 0x9F, 0xB7, 0x19, 0x39, 0x99, 0x19, 0xB9,
+ 0x39, 0xF9, 0xB9, 0x99, 0xB9, 0x79, 0x19, 0x59, 0xC9, 0x47, 0x79, 0x39, 0x7F, 0xFF, 0xF9, 0xB7,
+ 0x37, 0x79, 0x39, 0xD9, 0xB9, 0x99, 0x47, 0xD9, 0x99, 0x19, 0x39, 0x99, 0x39, 0x37, 0x39, 0x77,
+ 0x39, 0x77, 0x39, 0xF9, 0x19, 0x59, 0xC9, 0x79, 0xF9, 0xB7, 0x99, 0xD9, 0xC9, 0x17, 0xF9, 0x39,
+ 0x37, 0xE7, 0xD9, 0xF9, 0x0F, 0x77, 0xC9, 0x39, 0xB9, 0x99, 0x39, 0xF9, 0x19, 0x59, 0xB9, 0x39,
+ 0x39, 0xD9, 0x39, 0xF7, 0x39, 0xB7, 0x1F, 0x99, 0x19, 0xD9, 0x79, 0x77, 0x99, 0x99, 0xC9, 0x39,
+ 0x19, 0x99, 0x9F, 0x17, 0xD9, 0x19, 0xB9, 0x79, 0x39, 0xF9, 0xB9, 0x19, 0x19, 0x59, 0x39, 0x79,
+ 0x39, 0xF9, 0xD9, 0xF9, 0xC9, 0x4F, 0xBF, 0x9F, 0xB9, 0xB9, 0x17, 0x1F, 0xC9, 0x99, 0x19, 0x79,
+ 0x37, 0x77, 0x77, 0xD9, 0x19, 0x59, 0xB9, 0x99, 0x39, 0xD9, 0xB9, 0x39, 0x39, 0x37, 0x39, 0xC9,
+ 0x39, 0x3F, 0x37, 0xF9, 0x39, 0x99, 0xC9, 0xC9, 0x17, 0xB7, 0x79, 0x19, 0xC9, 0xB9, 0x7F, 0x37,
+ 0x39, 0x79, 0xB9, 0x19, 0x19, 0x59, 0x39, 0x39, 0x39, 0xD9, 0x39, 0xC9, 0xB9, 0x19, 0xD9, 0xD9,
+ 0x19, 0x39, 0x49, 0x19, 0x17, 0x37, 0x77, 0x79, 0x39, 0xD9, 0x39, 0x37, 0xF9, 0xC9, 0xF9, 0x79,
+ 0x39, 0xF9, 0x19, 0x59, 0x39, 0x79, 0xB9, 0xF9, 0x19, 0x59, 0xB9, 0x39, 0xC9, 0xB9, 0x79, 0x77,
+ 0xB7, 0x9F, 0xF7, 0x0F, 0x49, 0xF9, 0x39, 0xD9, 0xF9, 0x79, 0xB7, 0x7F, 0xC7, 0xD7, 0x49, 0x19,
+ 0x39, 0x97, 0x39, 0x37, 0x19, 0xF7, 0x59, 0x59, 0x79, 0xF9, 0xF7, 0x39, 0x7F, 0x49, 0x9F, 0xF9,
+ 0x39, 0x9F, 0x47, 0x19, 0x59, 0xF9, 0xC9, 0xC9, 0x39, 0x37, 0xF9, 0x39, 0xB9, 0x79, 0x19, 0x59,
+ 0x39, 0x99, 0x19, 0xB9, 0x39, 0xF9, 0xB9, 0x99, 0x79, 0x9F, 0xE7, 0xD9, 0x19, 0x79, 0x87, 0x87,
+ 0xC9, 0xF9, 0x39, 0x99, 0xC9, 0x39, 0x39, 0x37, 0xF7, 0x99, 0xB9, 0x79, 0x19, 0x59, 0x39, 0xD9,
+ 0xB9, 0x39, 0x39, 0xD9, 0x39, 0xF7, 0xC9, 0x37, 0x77, 0x79, 0x39, 0x19, 0xD9, 0x37, 0xF9, 0x77,
+ 0x39, 0x19, 0x1F, 0x7F, 0xC9, 0x39, 0xF9, 0x37, 0xB9, 0x79, 0x19, 0x59, 0xB9, 0x79, 0x39, 0x37,
+ 0xB9, 0xF9, 0xB9, 0x79, 0xF9, 0x37, 0x37, 0xD7, 0x9F, 0xF9, 0x5F, 0xE7, 0x9F, 0xC9, 0x39, 0x99,
+ 0x39, 0x9F, 0x9F, 0x79, 0xF9, 0x19, 0x19, 0x59, 0xB9, 0x59, 0x39, 0xD9, 0xB9, 0x19, 0x39, 0x39,
+ 0x39, 0xD9, 0xC9, 0x77, 0x9F, 0x07, 0x99, 0x99, 0xC9, 0x37, 0x77, 0x79, 0x39, 0x19, 0xF7, 0x39,
+ 0x7F, 0x49, 0x9F, 0xF9, 0x39, 0xC9, 0xB9, 0x79, 0x39, 0xF9, 0x39, 0x77, 0x39, 0xF9, 0x39, 0xF7,
+ 0xD7, 0x79, 0xF9, 0x39, 0x9F, 0xF7, 0x79, 0xF9, 0x0F, 0x39, 0x49, 0xB9, 0xD9, 0x77, 0x39, 0xDF,
+ 0x07, 0x19, 0xB9, 0x79, 0x19, 0x59, 0x39, 0xC9, 0xB9, 0x19, 0xB9, 0x19, 0x39, 0xF9, 0xD9, 0xB7,
+ 0x37, 0x39, 0x37, 0x19, 0x39, 0x47, 0xF9, 0x39, 0x39, 0xB7, 0x19, 0xD9, 0xE7, 0x87, 0x07, 0xB7,
+ 0xB9, 0x99, 0xB9, 0x59, 0x39, 0x37, 0x39, 0xF7, 0xB9, 0x99, 0x39, 0xD9, 0xD9, 0x99, 0x99, 0x79,
+ 0xF9, 0x39, 0x79, 0xD9, 0x19, 0x79, 0xB9, 0x87, 0xD7, 0x1F, 0x77, 0xF9, 0x79, 0xB9, 0x39, 0x19,
+ 0x39, 0x97, 0x39, 0xF9, 0x99, 0x79, 0xE7, 0x07, 0xA7, 0x5F, 0xD9, 0x79, 0xF9, 0x39, 0x17, 0x3F,
+ 0x39, 0x79, 0x5F, 0xFF, 0x27, 0xF9, 0x99, 0x99, 0x47, 0xB7, 0x37, 0x27, 0xF9, 0x79, 0x87, 0x3F,
+ 0x97, 0x99, 0x47, 0xB7, 0x59, 0x99, 0xB9, 0xD9, 0xC9, 0x49, 0xB7, 0x39, 0x37, 0xD9, 0xF9, 0xB7,
+ 0x37, 0x37, 0x39, 0xF9
+};
+
+const uint8_t Game::_protectionPal[] = {
+ 0x00, 0x00, 0x00, 0x42, 0x00, 0x63, 0x00, 0x00, 0x0F, 0xFF, 0x0F, 0xF0, 0x07, 0x77, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+const char *Menu::_passwords[8][3] = {
+ { "JAGUAR", "BANTHA", "TOHOLD" },
+ { "COMBEL", "SHIVA", "PICOLO" },
+ { "ANTIC", "KASYYK", "FUGU" },
+ { "NOLAN", "SARLAC", "CAPSUL" },
+ { "ARTHUR", "MAENOC", "ZZZAP" },
+ { "SHIRYU", "SULUST", "MANIAC" },
+ { "RENDER", "NEPTUN", "NO WAY" },
+ { "BELUGA", "BELUGA", "BELUGA" }
+};
+
+const uint8_t Video::_conradPal1[] = {
+ 0x00, 0x00, 0xCC, 0x0C, 0x8F, 0x08, 0x7E, 0x07, 0x6C, 0x06, 0x5B, 0x05, 0x4A, 0x04, 0x63, 0x09,
+ 0x52, 0x07, 0x41, 0x06, 0x30, 0x06, 0x76, 0x0C, 0x14, 0x09, 0x25, 0x0B, 0x88, 0x08, 0xFF, 0x0F
+};
+
+const uint8_t Video::_conradPal2[] = {
+ 0x00, 0x00, 0x7C, 0x0B, 0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x26, 0x0A,
+ 0x14, 0x08, 0x03, 0x06, 0x02, 0x04, 0x43, 0x09, 0x02, 0x06, 0x02, 0x07, 0x6A, 0x0A, 0xFF, 0x0F
+};
+
+const uint8_t Video::_textPal[] = {
+ 0x00, 0x00, 0x11, 0x01, 0x22, 0x02, 0xEF, 0x0E, 0x00, 0x0F, 0xF0, 0x0F, 0xA0, 0x0E, 0xB0, 0x0F,
+ 0xA0, 0x0E, 0xA0, 0x0E, 0xAA, 0x0A, 0xF0, 0x00, 0xCC, 0x0C, 0xDF, 0x0D, 0xEE, 0x0E, 0xEE, 0x0E
+};
+
+const uint8_t Video::_palSlot0xF[] = {
+ 0x00, 0x00, 0x00, 0x1F, 0x17, 0x2B, 0x2B, 0x1F, 0x37, 0x37, 0x2B, 0x47, 0x43, 0x37, 0x53, 0x4F,
+ 0x43, 0x63, 0x5F, 0x53, 0x6F, 0x6F, 0x63, 0x7F, 0x7F, 0x73, 0x8B, 0x8F, 0x87, 0x9B, 0x9F, 0x97,
+ 0xA7, 0xAF, 0xA7, 0xB3, 0xBF, 0xBB, 0xBF, 0xCF, 0xCF, 0xCF, 0x00, 0x33, 0x00, 0x17, 0x0F, 0x1F
+};
+
+const int8_t ModPlayer::_sineWaveTable[] = {
+ 0, 24, 49, 74, 97, 120, -115, -95, -76, -59, -44, -32, -21, -12, -6, -3,
+ -1, -3, -6, -12, -21, -32, -44, -59, -76, -95, -115, 120, 97, 74, 49, 24,
+ 0, -24, -49, -74, -97, -120, 115, 95, 76, 59, 44, 32, 21, 12, 6, 3,
+ 1, 3, 6, 12, 21, 32, 44, 59, 76, 95, 115, -120, -97, -74, -49, -24
+};
+
+const uint16_t ModPlayer::_periodTable[] = {
+ 856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453, // C-1 to B-1 Finetune 0
+ 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, // C-2 to B-2 Finetune 0
+ 214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113, // C-3 to B-3 Finetune 0
+ 850, 802, 757, 715, 674, 637, 601, 567, 535, 505, 477, 450, // C-1 to B-1 Finetune +1
+ 425, 401, 379, 357, 337, 318, 300, 284, 268, 253, 239, 225, // C-2 to B-2 Finetune +1
+ 213, 201, 189, 179, 169, 159, 150, 142, 134, 126, 119, 113, // C-3 to B-3 Finetune +1
+ 844, 796, 752, 709, 670, 632, 597, 563, 532, 502, 474, 447, // C-1 to B-1 Finetune +2
+ 422, 398, 376, 355, 335, 316, 298, 282, 266, 251, 237, 224, // C-2 to B-2 Finetune +2
+ 211, 199, 188, 177, 167, 158, 149, 141, 133, 125, 118, 112, // C-3 to B-3 Finetune +2
+ 838, 791, 746, 704, 665, 628, 592, 559, 528, 498, 470, 444, // C-1 to B-1 Finetune +3
+ 419, 395, 373, 352, 332, 314, 296, 280, 264, 249, 235, 222, // C-2 to B-2 Finetune +3
+ 209, 198, 187, 176, 166, 157, 148, 140, 132, 125, 118, 111, // C-3 to B-3 Finetune +3
+ 832, 785, 741, 699, 660, 623, 588, 555, 524, 495, 467, 441, // C-1 to B-1 Finetune +4
+ 416, 392, 370, 350, 330, 312, 294, 278, 262, 247, 233, 220, // C-2 to B-2 Finetune +4
+ 208, 196, 185, 175, 165, 156, 147, 139, 131, 124, 117, 110, // C-3 to B-3 Finetune +4
+ 826, 779, 736, 694, 655, 619, 584, 551, 520, 491, 463, 437, // C-1 to B-1 Finetune +5
+ 413, 390, 368, 347, 328, 309, 292, 276, 260, 245, 232, 219, // C-2 to B-2 Finetune +5
+ 206, 195, 184, 174, 164, 155, 146, 138, 130, 123, 116, 109, // C-3 to B-3 Finetune +5
+ 820, 774, 730, 689, 651, 614, 580, 547, 516, 487, 460, 434, // C-1 to B-1 Finetune +6
+ 410, 387, 365, 345, 325, 307, 290, 274, 258, 244, 230, 217, // C-2 to B-2 Finetune +6
+ 205, 193, 183, 172, 163, 154, 145, 137, 129, 122, 115, 109, // C-3 to B-3 Finetune +6
+ 814, 768, 725, 684, 646, 610, 575, 543, 513, 484, 457, 431, // C-1 to B-1 Finetune +7
+ 407, 384, 363, 342, 323, 305, 288, 272, 256, 242, 228, 216, // C-2 to B-2 Finetune +7
+ 204, 192, 181, 171, 161, 152, 144, 136, 128, 121, 114, 108, // C-3 to B-3 Finetune +7
+ 907, 856, 808, 762, 720, 678, 640, 604, 570, 538, 504, 480, // C-1 to B-1 Finetune -8
+ 453, 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, // C-2 to B-2 Finetune -8
+ 226, 214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, // C-3 to B-3 Finetune -8
+ 900, 850, 802, 757, 715, 675, 636, 601, 567, 535, 505, 477, // C-1 to B-1 Finetune -7
+ 450, 425, 401, 379, 357, 337, 318, 300, 284, 268, 253, 238, // C-2 to B-2 Finetune -7
+ 225, 212, 200, 189, 179, 169, 159, 150, 142, 134, 126, 119, // C-3 to B-3 Finetune -7
+ 894, 844, 796, 752, 709, 670, 632, 597, 563, 532, 502, 474, // C-1 to B-1 Finetune -6
+ 447, 422, 398, 376, 355, 335, 316, 298, 282, 266, 251, 237, // C-2 to B-2 Finetune -6
+ 223, 211, 199, 188, 177, 167, 158, 149, 141, 133, 125, 118, // C-3 to B-3 Finetune -6
+ 887, 838, 791, 746, 704, 665, 628, 592, 559, 528, 498, 470, // C-1 to B-1 Finetune -5
+ 444, 419, 395, 373, 352, 332, 314, 296, 280, 264, 249, 235, // C-2 to B-2 Finetune -5
+ 222, 209, 198, 187, 176, 166, 157, 148, 140, 132, 125, 118, // C-3 to B-3 Finetune -5
+ 881, 832, 785, 741, 699, 660, 623, 588, 555, 524, 494, 467, // C-1 to B-1 Finetune -4
+ 441, 416, 392, 370, 350, 330, 312, 294, 278, 262, 247, 233, // C-2 to B-2 Finetune -4
+ 220, 208, 196, 185, 175, 165, 156, 147, 139, 131, 123, 117, // C-3 to B-3 Finetune -4
+ 875, 826, 779, 736, 694, 655, 619, 584, 551, 520, 491, 463, // C-1 to B-1 Finetune -3
+ 437, 413, 390, 368, 347, 338, 309, 292, 276, 260, 245, 232, // C-2 to B-2 Finetune -3
+ 219, 206, 195, 184, 174, 164, 155, 146, 138, 130, 123, 116, // C-3 to B-3 Finetune -3
+ 868, 820, 774, 730, 689, 651, 614, 580, 547, 516, 487, 460, // C-1 to B-1 Finetune -2
+ 434, 410, 387, 365, 345, 325, 307, 290, 274, 258, 244, 230, // C-2 to B-2 Finetune -2
+ 217, 205, 193, 183, 172, 163, 154, 145, 137, 129, 122, 115, // C-3 to B-3 Finetune -2
+ 862, 814, 768, 725, 684, 646, 610, 575, 543, 513, 484, 457, // C-1 to B-1 Finetune -1
+ 431, 407, 384, 363, 342, 323, 305, 288, 272, 256, 242, 228, // C-2 to B-2 Finetune -1
+ 216, 203, 192, 181, 171, 161, 152, 144, 136, 128, 121, 114 // C-3 to B-3 Finetune -1
+};
+
+const char *ModPlayer::_modulesFiles[][2] = {
+ { "intro", "mod.flashback-introb" }, // introl3
+ { "options", "mod.flashback-options2" }, // option3
+ { "journal", "mod.flashback-options1" }, // journal3
+ { "ceinture", "mod.flashback-ceinturea" }, // chute3
+ { "desinteg", "mod.flashback-desintegr" }, // desinte3
+ { "reunion", "mod.flashback-reunion" }, // capture3
+ { "voyage", "mod.flashback-voyage" }, // voyage3
+ { "level4", "mod.flashback-teleporta" }, // telepor3
+ { "planetexplo", "mod.flashback-teleport2" }, // planexp3
+ { "fin", "mod.flashback-fin" }, // end31
+ { "ascenseur", "mod.flashback-ascenseur" }, // lift3
+ { "logo", "mod.flashback-logo" }, // present3
+ { "game_over", "mod.flashback-game_over" }, // gameove3
+ { "holocube", "mod.flashback-holocube" }, // holo3
+ { "memoire", "mod.flashback-memoire" }, // memory3
+ { "chute", "mod.flashback-chute" }, // chutevi3
+ { "debut", "mod.flashback-jungle" }, // reveil3
+ { "missions", "mod.flashback-missionca" }, // misvali3
+ { "taxi", "mod.flashback-taxi" }, // taxi3
+ { "donneobj", "mod.flashback-donneobjt" }, // donner3
+ { "missions2", "mod.flashback-fin2" } // mission3
+// { 0, 0, }, // objet3
+// { 0, 0, }, // recharg3
+// { 0, 0, }, // generat3
+// { 0, 0, }, // pont3
+// { 0, 0, } // rechage3
+};
+
+const int ModPlayer::_modulesFilesCount = ARRAYSIZE(_modulesFiles);
+
+const char *SeqPlayer::_namesTable[] = {
+ /* 0x00 */
+ "WAKEUP", // 'DEBUT' (0x0000) num 0
+ "TKHOLOCB", // 'OBJET' (0x0001) num 3
+ "TAKEKEY0", // 'OBJET' (0x0001) num 4
+ 0,
+ /* 0x04 */
+ "TKGUN", // 'OBJET' (0x0001) num 2
+ "RECHARG0", // 'GEN' (0x0003) num 0
+ "FALLJUNG", // 'CHUTE' (0x0004) num 0
+ 0,
+ /* 0x08 */
+ 0,
+ "DISINTEG", // 'DESINTEG' (0x0006) num 0
+ "TKCRED0", // 'OBJET' (0x0001) num 1
+ 0,
+ /* 0x0C */
+ 0,
+ "INTRO", // 'INTRO1' (0x8007) num 0
+ "RCHGBATT", // 'GEN' (0x0003) num 1
+ "TAKEBATT", // 'OBJET' (0x0001) num 11
+ /* 0x10 */
+ "TKTELER0", // 'OBJET' (0x0001) num 5
+ "HOLOCUBE", // 'HOLOSEQ' (0x0009) num 0
+ "TKCARD", // 'OBJET' (0x0001) num 6
+ 0,
+ /* 0x14 */
+ "BRIDGE", // 'PONT' (0x000B) num 0
+ "GVTELER", // 'OBJET' (0x0001) num 10
+ 0,
+ 0,
+ /* 0x18 */
+ 0,
+ "HOLOMAP", // 'MAP' (0x000D) num 4
+ "MAP1", // 'MAP' (0x000D) num 0
+ "MAP2", // 'MAP' (0x000D) num 1
+ /* 0x1C */
+ "MAP3", // 'MAP' (0x000D) num 2
+ "MAP4", // 'MAP' (0x000D) num 3
+ 0,
+ 0,
+ /* 0x20 */
+ "GIVEPACK", // 'OBJET' (0x0001) num 12
+ "GIVEPACK", // 'OBJET' (0x0001) num 13
+ "GETWORKP", // 'OBJET' (0x0001) num 14
+ "GETID", // 'OBJET' (0x0001) num 15
+ /* 0x24 */
+ "TKFUSE", // 'OBJET' (0x0001) num 16
+ "MISSION1", // 'MISSIONS' (0x000F) num 0
+ "MISSION2", // 'MISSIONS' (0x000F) num 1
+ "MISSION2", // 'MISSIONS' (0x000F) num 1
+ /* 0x28 */
+ "MISSION3", // 'MISSIONS' (0x000F) num 3
+ "MISSION4", // 'MISSIONS' (0x000F) num 2
+ "MISSION5", // 'MISSIONS' (0x000F) num 4
+ "GIVEID1", // 'OBJET' (0x0001) num 8
+ /* 0x2C */
+ "GVCREDS1", // 'OBJET' (0x0001) num 7
+ "MISSVALD", // 'MISSIONS' (0x000F) num 5
+ 0,
+ "ANTIG", // 'CHUTE' (0x0004) num 1
+ /* 0x30 */
+ "MEMORY", // 'MEMO' (0x0011) num 0
+ "GETANTIG", // 'OBJET' (0x0001) num 9
+ "TAXI", // 'TAXI' (0x0012) num 0
+ 0,
+ /* 0x34 */
+ "VOYAGE", // 'VOYAGE' (0x0014) num 0
+ "TELEPORT", // 'TELEPORT' (0x0015) num 0
+ "LIFTUP", // 'LIFT' (0x0016) num 0
+ "LIFTDOWN", // 'LIFT' (0x0016) num 1
+ /* 0x38 */
+ 0,
+ "SPY", // 'ESPIONS' (0x0017) num 0
+ "GETDYNAM", // 'OBJET' (0x0001) num 17
+ "JOURNAL", // 'LOG' (0x0018) num 0
+ /* 0x3C */
+ "TKTELEX0", // 'OBJET' (0x0001) num 19
+ "END", // 'FIN' (0x0019) num 0
+ "GENEXPL", // 'GENEXP' (0x001A) num 0
+ "BADEND", // 'FIN' (0x0019) num 1
+ /* 0x40 */
+ 0, // 'LOGOS' (0x001B) num 0
+ "GAMEOVER", // 'OVER' (0x001C) num 0
+ "MISSEND1", // 'MISSIONS' (0x000F) num 6
+ "MISSEND1", // 'MISSIONS' (0x000F) num 6
+ /* 0x44 */
+ "MISSEND2", // 'MISSIONS' (0x000F) num 7
+ "MISSEND3", // 'MISSIONS' (0x000F) num 8
+ "MISSEND4", // 'MISSIONS' (0x000F) num 9
+ "MISSEND5", // 'MISSIONS' (0x000F) num 10
+ /* 0x48 */
+ 0, // 'SCORE' (0x001D) num 0
+ 0, // 'LOGOS' (0x001B) num 1
+ 0, // 'INTRO2' (0x001E) num 0
+};
+
+const uint8_t SfxPlayer::_musicData68[] = {
+ 0x00, 0x1B, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x18, 0xFF, 0xF4, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A,
+ 0x02, 0x01, 0x04, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x0A, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x0D, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x14, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x16, 0x04, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x0F
+};
+
+const uint8_t SfxPlayer::_musicData70[] = {
+ 0x00, 0x12, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x02, 0x01, 0x00, 0x00, 0x01, 0x0D,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x16, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00
+};
+
+const uint8_t SfxPlayer::_musicData72[] = {
+ 0x00, 0x4F, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x24, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x05, 0x02, 0x01, 0x04, 0x1B, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x05,
+ 0x02, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1B,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x1B, 0x01, 0x0D, 0x00, 0x00,
+ 0x04, 0x1D, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x1B, 0x01, 0x0F, 0x02, 0x01, 0x04, 0x1D, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x11, 0x02, 0x01, 0x04, 0x1B,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x10, 0x02, 0x01, 0x04, 0x1B, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1D, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1B,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1B, 0x01, 0x10, 0x03, 0x01,
+ 0x04, 0x1D, 0x01, 0x0F, 0x03, 0x01, 0x04, 0x1B, 0x01, 0x0D, 0x02, 0x01, 0x04, 0x1D, 0x01, 0x0F,
+ 0x03, 0x01, 0x04, 0x1B, 0x01, 0x0D, 0x02, 0x01, 0x04, 0x1D, 0x01, 0x0A, 0x03, 0x01, 0x04, 0x1B,
+ 0x01, 0x08, 0x03, 0x01, 0x04, 0x1D, 0x01, 0x08, 0x02, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00,
+ 0x04, 0x1D, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x00, 0x00,
+ 0x03, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1B,
+ 0x01, 0x0A, 0x02, 0x01, 0x04, 0x1D, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x01, 0x0A, 0x02, 0x01,
+ 0x04, 0x1D, 0x00, 0x00, 0x02, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x08,
+ 0x03, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x0D, 0x00, 0x00, 0x04, 0x1B,
+ 0x01, 0x0F, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x08, 0x02, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00,
+ 0x04, 0x1D, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x00, 0x00,
+ 0x03, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1B,
+ 0x01, 0x0A, 0x02, 0x01, 0x04, 0x1D, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x01, 0x0A, 0x02, 0x01,
+ 0x04, 0x1D, 0x00, 0x00, 0x02, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x08,
+ 0x03, 0x01, 0x04, 0x1B, 0x01, 0x03, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x05, 0x00, 0x00, 0x04, 0x1B,
+ 0x01, 0x08, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x08, 0x02, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00,
+ 0x04, 0x1D, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x00, 0x00,
+ 0x03, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1B,
+ 0x01, 0x0A, 0x02, 0x01, 0x04, 0x1D, 0x01, 0x08, 0x00, 0x00, 0x04, 0x1B, 0x01, 0x0A, 0x02, 0x01,
+ 0x04, 0x1D, 0x00, 0x00, 0x02, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x1D, 0x01, 0x08,
+ 0x03, 0x01, 0x04, 0x1B, 0x01, 0x0A, 0x03, 0x01, 0x04, 0x1D, 0x01, 0x0D, 0x03, 0x01, 0x04, 0x1B,
+ 0x01, 0x0F, 0x03, 0x01, 0x04, 0x1D, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x1B
+};
+
+const uint8_t SfxPlayer::_musicData73[] = {
+ 0x00, 0x41, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x0C, 0xFF, 0xF4, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x11, 0x01, 0x08,
+ 0x03, 0x01, 0x04, 0x12, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x04, 0x11,
+ 0x01, 0x0A, 0x02, 0x01, 0x04, 0x12, 0x00, 0x00, 0x03, 0x01, 0x04, 0x0A, 0x01, 0x05, 0x00, 0x00,
+ 0x04, 0x11, 0x01, 0x08, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x11, 0x01, 0x08,
+ 0x03, 0x01, 0x04, 0x12, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x04, 0x11,
+ 0x01, 0x0A, 0x02, 0x01, 0x04, 0x12, 0x00, 0x00, 0x03, 0x01, 0x04, 0x0A, 0x01, 0x05, 0x00, 0x00,
+ 0x04, 0x11, 0x01, 0x08, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x11, 0x01, 0x08,
+ 0x03, 0x01, 0x04, 0x12, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x04, 0x11,
+ 0x01, 0x0A, 0x02, 0x01, 0x04, 0x12, 0x00, 0x00, 0x03, 0x01, 0x04, 0x0A, 0x01, 0x0D, 0x00, 0x00,
+ 0x04, 0x11, 0x00, 0x00, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0F, 0x02, 0x01, 0x04, 0x11, 0x01, 0x0C,
+ 0x03, 0x01, 0x04, 0x12, 0x01, 0x0D, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x11,
+ 0x01, 0x05, 0x02, 0x01, 0x04, 0x12, 0x01, 0x08, 0x03, 0x01, 0x04, 0x0A, 0x01, 0x0D, 0x00, 0x00,
+ 0x04, 0x11, 0x01, 0x08, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x11, 0x01, 0x08,
+ 0x03, 0x01, 0x04, 0x12, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x04, 0x11,
+ 0x01, 0x0A, 0x02, 0x01, 0x04, 0x12, 0x00, 0x00, 0x03, 0x01, 0x04, 0x0A, 0x01, 0x05, 0x00, 0x00,
+ 0x04, 0x11, 0x01, 0x08, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x11, 0x01, 0x08,
+ 0x03, 0x01, 0x04, 0x12, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x04, 0x11,
+ 0x01, 0x0A, 0x02, 0x01, 0x04, 0x12, 0x00, 0x00, 0x03, 0x01, 0x04, 0x0A, 0x01, 0x05, 0x00, 0x00,
+ 0x04, 0x11, 0x01, 0x08, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x11, 0x01, 0x08,
+ 0x03, 0x01, 0x04, 0x12, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x04, 0x11,
+ 0x01, 0x0A, 0x02, 0x01, 0x04, 0x12, 0x00, 0x00, 0x03, 0x01, 0x04, 0x0A, 0x01, 0x0D, 0x00, 0x00,
+ 0x04, 0x11, 0x00, 0x00, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0F, 0x02, 0x01, 0x04, 0x11, 0x01, 0x0C,
+ 0x03, 0x01, 0x04, 0x12, 0x01, 0x0D, 0x02, 0x01, 0x04, 0x0A, 0x01, 0x0A, 0x00, 0x00, 0x04, 0x11,
+ 0x01, 0x05, 0x02, 0x01, 0x04, 0x12, 0x01, 0x08, 0x03, 0x01, 0x04, 0x0A, 0x01, 0x0D, 0x03, 0x01,
+ 0x04, 0x11, 0x01, 0x0A, 0x02, 0x01, 0x04, 0x0A
+};
+
+const uint8_t SfxPlayer::_musicData74[] = {
+ 0x00, 0x41, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x24, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00,
+ 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x01, 0x00, 0x00,
+ 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x04, 0x08, 0x01, 0x08,
+ 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x04, 0x08,
+ 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27,
+ 0x04, 0x08, 0x01, 0x06, 0x02, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08,
+ 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x01, 0x00, 0x00,
+ 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x00, 0x00, 0x01, 0x0B, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x04, 0x08, 0x01, 0x08,
+ 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x04, 0x08,
+ 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27,
+ 0x04, 0x08, 0x01, 0x06, 0x02, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08,
+ 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x0B, 0x02, 0x01, 0x00, 0x00,
+ 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x00, 0x00, 0x01, 0x0B, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x04, 0x08, 0x01, 0x08,
+ 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x04, 0x08,
+ 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27,
+ 0x04, 0x08, 0x01, 0x06, 0x02, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08,
+ 0x03, 0x01, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00,
+ 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x0B, 0x03, 0x01, 0x00, 0x00, 0x01, 0x0D, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00
+};
+
+const uint8_t SfxPlayer::_musicData75[] = {
+ 0x00, 0x41, 0x00, 0x05, 0x00, 0x0C, 0x00, 0x24, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x04, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ 0x05, 0x27, 0x04, 0x14, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x04, 0x12,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x04, 0x14, 0x01, 0x08, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x04, 0x12, 0x01, 0x08, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x04, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ 0x05, 0x27, 0x04, 0x14, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x04, 0x12,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x04, 0x14, 0x01, 0x08, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ 0x05, 0x27, 0x04, 0x12, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x06, 0x03, 0x01, 0x04, 0x11,
+ 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x05, 0x27, 0x04, 0x12, 0x01, 0x06, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x04, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ 0x05, 0x27, 0x04, 0x14, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x04, 0x12,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x04, 0x14, 0x01, 0x08, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x04, 0x12, 0x01, 0x08, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x04, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ 0x05, 0x27, 0x04, 0x14, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x03, 0x01, 0x04, 0x12,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x04, 0x14, 0x01, 0x08, 0x05, 0x27,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ 0x05, 0x27, 0x00, 0x00, 0x01, 0x08, 0x05, 0x27, 0x00, 0x00, 0x01, 0x06, 0x03, 0x01, 0x00, 0x00,
+ 0x01, 0x06, 0x03, 0x01, 0x00, 0x00, 0x01, 0x05, 0x03, 0x01, 0x00, 0x00, 0x01, 0x06, 0x03, 0x01,
+ 0x00, 0x00, 0x01, 0x08, 0x02, 0x01, 0x00, 0x00
+};
+
+const uint8_t SfxPlayer::_musicDataSample1[] = {
+ 0x08, 0x2C, 0x00, 0x40, 0x07, 0x2A, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x04,
+ 0x03, 0x05, 0x07, 0x08, 0x08, 0x0B, 0x0E, 0x0F, 0x11, 0x14, 0x14, 0x16, 0x18, 0x1C, 0x20, 0x1E,
+ 0x1A, 0x1A, 0x1F, 0x22, 0x1F, 0x19, 0x16, 0x27, 0x1C, 0xC8, 0x0F, 0x7F, 0x30, 0xA0, 0x97, 0x0F,
+ 0x73, 0x50, 0xC4, 0x96, 0xE7, 0x15, 0xFC, 0xFD, 0x12, 0x0C, 0xE6, 0xEF, 0x0F, 0xF8, 0xE3, 0xFF,
+ 0x47, 0x4E, 0x08, 0xD2, 0xEA, 0x27, 0x3B, 0x22, 0x09, 0x03, 0xFF, 0xF2, 0xF3, 0x03, 0x00, 0xEA,
+ 0xDE, 0xD4, 0xC7, 0xC2, 0xBC, 0xB4, 0xB6, 0xB8, 0xA8, 0x96, 0x95, 0x99, 0x9C, 0x9F, 0xA0, 0xA0,
+ 0xA3, 0xA4, 0xA4, 0xB3, 0xCB, 0xD7, 0xDB, 0xDF, 0xEA, 0xFD, 0x0F, 0x1C, 0x26, 0x37, 0x4B, 0x57,
+ 0x5F, 0x6A, 0x73, 0x78, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x78, 0x6C, 0x64, 0x5E, 0x58, 0x4B, 0x40, 0x3A, 0x2E, 0x1E, 0x16, 0x11, 0x0B, 0x06, 0xFE,
+ 0xF3, 0xE9, 0xE2, 0xDD, 0xDE, 0xE3, 0xE0, 0xD7, 0xCE, 0xCC, 0xCE, 0xD3, 0xD4, 0xCF, 0xCB, 0xCF,
+ 0xD2, 0xCF, 0xCD, 0xCF, 0xD1, 0xD6, 0xD9, 0xD3, 0xCD, 0xD3, 0xDE, 0xDF, 0xDA, 0xD8, 0xD9, 0xDF,
+ 0xE5, 0xE4, 0xDE, 0xDF, 0xE4, 0xEA, 0xED, 0xEE, 0xF2, 0xF4, 0xF7, 0xF5, 0xF5, 0xFE, 0x0B, 0x0C,
+ 0x0B, 0x0F, 0x13, 0x13, 0x11, 0x13, 0x1B, 0x26, 0x23, 0x1B, 0x1D, 0x1C, 0x1E, 0x20, 0x1E, 0x1F,
+ 0x1E, 0x15, 0x17, 0x20, 0x10, 0x07, 0x15, 0x14, 0x0B, 0x0B, 0x08, 0x04, 0x07, 0x04, 0xFA, 0xFB,
+ 0xFE, 0xFB, 0xFB, 0xFB, 0xF6, 0xF1, 0xF4, 0xF9, 0xFC, 0x00, 0x01, 0xFE, 0xF8, 0xF7, 0xFB, 0x03,
+ 0x0C, 0x11, 0x0F, 0x08, 0xFE, 0xFE, 0x0B, 0x1B, 0x1E, 0x11, 0x04, 0x04, 0x09, 0x0C, 0x0D, 0x08,
+ 0x08, 0x0C, 0x09, 0x00, 0xF4, 0xF2, 0xFB, 0x03, 0x02, 0xFA, 0xF6, 0xF5, 0xF4, 0xF6, 0xF9, 0xFA,
+ 0xF9, 0xFD, 0x01, 0x02, 0x01, 0xFE, 0x01, 0x0C, 0x10, 0x0D, 0x0A, 0x08, 0x0B, 0x14, 0x19, 0x1A,
+ 0x1B, 0x19, 0x15, 0x17, 0x18, 0x15, 0x17, 0x1E, 0x1C, 0x16, 0x11, 0x11, 0x14, 0x19, 0x19, 0x17,
+ 0x15, 0x13, 0x15, 0x1A, 0x1C, 0x1E, 0x23, 0x28, 0x28, 0x24, 0x23, 0x28, 0x2D, 0x2F, 0x2E, 0x2E,
+ 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x16, 0x0B, 0x02, 0xFF, 0xF9, 0xEB, 0xE0, 0xD6, 0xCC, 0xC3, 0xBA,
+ 0xB0, 0xA6, 0xA0, 0x99, 0x92, 0x8C, 0x88, 0x88, 0x88, 0x85, 0x83, 0x85, 0x89, 0x8C, 0x91, 0x9A,
+ 0xA2, 0xAB, 0xB2, 0xBB, 0xC7, 0xD6, 0xE3, 0xF1, 0xFF, 0x0C, 0x17, 0x23, 0x2D, 0x39, 0x45, 0x50,
+ 0x5A, 0x63, 0x67, 0x6A, 0x6E, 0x72, 0x76, 0x7A, 0x7A, 0x76, 0x73, 0x72, 0x6E, 0x6B, 0x6A, 0x66,
+ 0x61, 0x5D, 0x53, 0x4B, 0x48, 0x45, 0x40, 0x3C, 0x3A, 0x33, 0x2D, 0x2A, 0x24, 0x20, 0x20, 0x20,
+ 0x1C, 0x1B, 0x1A, 0x16, 0x13, 0x12, 0x11, 0x12, 0x12, 0x10, 0x0D, 0x0B, 0x0B, 0x09, 0x07, 0x07,
+ 0x06, 0x05, 0x04, 0x02, 0x01, 0xFE, 0xFC, 0xFC, 0xFF, 0x00, 0xFE, 0xFB, 0xFA, 0xFA, 0xFC, 0xFD,
+ 0xFC, 0xFD, 0x01, 0x02, 0x00, 0x00, 0x04, 0x08, 0x0C, 0x0E, 0x0D, 0x10, 0x13, 0x16, 0x19, 0x1B,
+ 0x1D, 0x1E, 0x21, 0x23, 0x23, 0x23, 0x24, 0x26, 0x28, 0x26, 0x23, 0x21, 0x21, 0x23, 0x23, 0x1F,
+ 0x1C, 0x1C, 0x1B, 0x1A, 0x18, 0x16, 0x15, 0x14, 0x13, 0x11, 0x0F, 0x0E, 0x0C, 0x0A, 0x08, 0x03,
+ 0xFD, 0xFA, 0xFA, 0xF9, 0xF6, 0xF3, 0xF1, 0xEF, 0xEF, 0xEF, 0xF0, 0xF3, 0xF4, 0xF2, 0xF4, 0xF9,
+ 0xFD, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x08, 0x05, 0x01, 0xFD, 0xF9, 0xF5, 0xF1,
+ 0xED, 0xE6, 0xDE, 0xD9, 0xD7, 0xD5, 0xD3, 0xD0, 0xCD, 0xCB, 0xCA, 0xC8, 0xC8, 0xCB, 0xCC, 0xCE,
+ 0xD1, 0xD4, 0xD4, 0xD6, 0xDD, 0xE4, 0xE9, 0xEB, 0xEC, 0xEF, 0xF6, 0xFC, 0xFD, 0xFB, 0xFB, 0xFC,
+ 0xFC, 0xFC, 0xF9, 0xF6, 0xF5, 0xF3, 0xEE, 0xEB, 0xE9, 0xE7, 0xE7, 0xE7, 0xE6, 0xE5, 0xE5, 0xE6,
+ 0xEA, 0xEE, 0xF2, 0xF6, 0xFA, 0xFE, 0x03, 0x0A, 0x10, 0x15, 0x1A, 0x1D, 0x20, 0x23, 0x25, 0x25,
+ 0x26, 0x26, 0x24, 0x20, 0x1A, 0x15, 0x0F, 0x09, 0x02, 0xF8, 0xEE, 0xE4, 0xD9, 0xCF, 0xC8, 0xC1,
+ 0xB8, 0xAF, 0xA7, 0xA0, 0x9A, 0x97, 0x94, 0x92, 0x92, 0x92, 0x94, 0x97, 0x99, 0x9D, 0xA5, 0xAD,
+ 0xB6, 0xBF, 0xC7, 0xD1, 0xDC, 0xE7, 0xF3, 0xFF, 0x0B, 0x16, 0x1F, 0x29, 0x33, 0x3B, 0x44, 0x4D,
+ 0x55, 0x5A, 0x5E, 0x62, 0x64, 0x66, 0x67, 0x68, 0x68, 0x68, 0x66, 0x63, 0x60, 0x5D, 0x5B, 0x59,
+ 0x56, 0x52, 0x4F, 0x4B, 0x48, 0x46, 0x44, 0x42, 0x40, 0x3F, 0x3E, 0x3D, 0x3A, 0x39, 0x39, 0x3A,
+ 0x39, 0x37, 0x36, 0x35, 0x35, 0x35, 0x35, 0x34, 0x32, 0x31, 0x30, 0x2E, 0x2D, 0x2B, 0x2A, 0x29,
+ 0x27, 0x26, 0x25, 0x24, 0x22, 0x21, 0x20, 0x20, 0x1F, 0x1D, 0x1D, 0x1F, 0x20, 0x1F, 0x1F, 0x1F,
+ 0x20, 0x23, 0x25, 0x26, 0x26, 0x29, 0x2B, 0x2C, 0x2D, 0x2E, 0x30, 0x32, 0x33, 0x34, 0x34, 0x35,
+ 0x35, 0x35, 0x36, 0x36, 0x35, 0x34, 0x33, 0x33, 0x32, 0x31, 0x30, 0x2F, 0x2E, 0x2B, 0x29, 0x29,
+ 0x29, 0x28, 0x27, 0x27, 0x27, 0x26, 0x26, 0x26, 0x28, 0x28, 0x28, 0x27, 0x27, 0x26, 0x24, 0x22,
+ 0x20, 0x1D, 0x1A, 0x15, 0x0F, 0x0A, 0x05, 0x01, 0xFE, 0xFA, 0xF5, 0xF2, 0xF0, 0xED, 0xEC, 0xEB,
+ 0xEA, 0xE9, 0xE9, 0xE9, 0xEA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEA, 0xE9, 0xE6, 0xE3, 0xE1, 0xDC, 0xD8,
+ 0xD4, 0xCE, 0xC8, 0xC3, 0xBF, 0xBA, 0xB6, 0xB1, 0xAE, 0xAB, 0xAA, 0xA8, 0xA7, 0xA6, 0xA6, 0xA7,
+ 0xA9, 0xAB, 0xAE, 0xAF, 0xB1, 0xB3, 0xB8, 0xBC, 0xC0, 0xC3, 0xC5, 0xC7, 0xCA, 0xCD, 0xCE, 0xCF,
+ 0xD0, 0xD2, 0xD3, 0xD2, 0xD1, 0xCF, 0xD0, 0xD0, 0xD0, 0xCF, 0xCF, 0xCF, 0xCF, 0xD1, 0xD3, 0xD5,
+ 0xD8, 0xDB, 0xDF, 0xE3, 0xE7, 0xEB, 0xF0, 0xF6, 0xFB, 0xFF, 0x03, 0x08, 0x0C, 0x0E, 0x11, 0x12,
+ 0x13, 0x14, 0x13, 0x11, 0x0E, 0x0A, 0x05, 0x00, 0xFA, 0xF4, 0xED, 0xE5, 0xDE, 0xD6, 0xCE, 0xC6,
+ 0xC0, 0xBA, 0xB4, 0xAF, 0xAA, 0xA7, 0xA5, 0xA4, 0xA4, 0xA4, 0xA6, 0xA9, 0xAE, 0xB3, 0xB8, 0xBF,
+ 0xC7, 0xCF, 0xD7, 0xDF, 0xE9, 0xF4, 0xFE, 0x08, 0x11, 0x1B, 0x24, 0x2D, 0x35, 0x3D, 0x45, 0x4B,
+ 0x50, 0x55, 0x58, 0x5B, 0x5E, 0x60, 0x60, 0x60, 0x5F, 0x5E, 0x5D, 0x5B, 0x59, 0x58, 0x57, 0x54,
+ 0x52, 0x4F, 0x4E, 0x4D, 0x4C, 0x4A, 0x48, 0x47, 0x46, 0x46, 0x46, 0x46, 0x46, 0x45, 0x44, 0x44,
+ 0x44, 0x45, 0x44, 0x44, 0x43, 0x43, 0x43, 0x43, 0x42, 0x41, 0x41, 0x40, 0x3F, 0x3D, 0x3C, 0x3C,
+ 0x3B, 0x3A, 0x39, 0x38, 0x36, 0x36, 0x35, 0x34, 0x34, 0x34, 0x33, 0x32, 0x32, 0x33, 0x34, 0x35,
+ 0x34, 0x34, 0x34, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x36, 0x34,
+ 0x35, 0x34, 0x33, 0x32, 0x32, 0x32, 0x32, 0x31, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x30, 0x30, 0x30,
+ 0x31, 0x31, 0x32, 0x32, 0x33, 0x34, 0x35, 0x36, 0x36, 0x36, 0x37, 0x38, 0x38, 0x38, 0x37, 0x35,
+ 0x32, 0x2F, 0x2D, 0x29, 0x24, 0x20, 0x1A, 0x14, 0x0E, 0x08, 0x03, 0xFE, 0xF8, 0xF3, 0xEE, 0xEA,
+ 0xE6, 0xE2, 0xE0, 0xDE, 0xDB, 0xD9, 0xD8, 0xD6, 0xD5, 0xD3, 0xD1, 0xD0, 0xCD, 0xCA, 0xC7, 0xC4,
+ 0xC1, 0xBD, 0xBA, 0xB6, 0xB3, 0xB0, 0xAC, 0xA9, 0xA7, 0xA5, 0xA3, 0xA1, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA1, 0xA1, 0xA2, 0xA2, 0xA4, 0xA6, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAC, 0xAD, 0xAE,
+ 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB5, 0xB7, 0xB9, 0xBB, 0xBE, 0xC0, 0xC4, 0xC8, 0xCC, 0xD1, 0xD5,
+ 0xDA, 0xDF, 0xE5, 0xEA, 0xEF, 0xF5, 0xFA, 0xFF, 0x04, 0x08, 0x0B, 0x0D, 0x10, 0x12, 0x12, 0x11,
+ 0x10, 0x0E, 0x0B, 0x08, 0x03, 0xFE, 0xF8, 0xF1, 0xEB, 0xE4, 0xDD, 0xD6, 0xD0, 0xC9, 0xC3, 0xBD,
+ 0xB8, 0xB4, 0xB1, 0xAE, 0xAC, 0xAB, 0xAA, 0xAB, 0xAD, 0xB0, 0xB3, 0xB8, 0xBD, 0xC3, 0xCA, 0xD2,
+ 0xD9, 0xE1, 0xE9, 0xF2, 0xFA, 0x02, 0x0B, 0x13, 0x1C, 0x23, 0x2A, 0x31, 0x36, 0x3B, 0x40, 0x45,
+ 0x48, 0x4B, 0x4D, 0x4F, 0x50, 0x50, 0x50, 0x50, 0x50, 0x4F, 0x4E, 0x4C, 0x4C, 0x4B, 0x4B, 0x4A,
+ 0x49, 0x49, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4B, 0x4B, 0x4B,
+ 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4A, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x44, 0x44, 0x43, 0x41,
+ 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3B, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x39, 0x3A, 0x3B, 0x3C,
+ 0x3C, 0x3C, 0x3C, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3E, 0x3E, 0x3E, 0x3E, 0x3D, 0x3D, 0x3C,
+ 0x3B, 0x39, 0x38, 0x38, 0x37, 0x36, 0x34, 0x33, 0x32, 0x32, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x31, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3A, 0x3B,
+ 0x3A, 0x3A, 0x38, 0x37, 0x34, 0x31, 0x2E, 0x2B, 0x27, 0x22, 0x1D, 0x18, 0x13, 0x0D, 0x08, 0x01,
+ 0xFC, 0xF7, 0xF2, 0xED, 0xE9, 0xE4, 0xE0, 0xDC, 0xD8, 0xD4, 0xD0, 0xCB, 0xC7, 0xC3, 0xBF, 0xBA,
+ 0xB6, 0xB2, 0xAF, 0xAB, 0xA8, 0xA5, 0xA3, 0xA0, 0x9F, 0x9E, 0x9D, 0x9D, 0x9D, 0x9C, 0x9D, 0x9D,
+ 0x9E, 0x9E, 0x9F, 0x9F, 0xA0, 0xA0, 0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
+ 0xA3, 0xA5, 0xA5, 0xA7, 0xA8, 0xAB, 0xAD, 0xB0, 0xB2, 0xB6, 0xBA, 0xBF, 0xC3, 0xC8, 0xCE, 0xD3,
+ 0xD9, 0xDF, 0xE5, 0xEB, 0xF1, 0xF6, 0xFB, 0x00, 0x04, 0x08, 0x0B, 0x0D, 0x0E, 0x0E, 0x0E, 0x0C,
+ 0x0A, 0x08, 0x04, 0x00, 0xFA, 0xF5, 0xEF, 0xE8, 0xE2, 0xDC, 0xD6, 0xCF, 0xC9, 0xC3, 0xBE, 0xBA,
+ 0xB6, 0xB3, 0xB0, 0xAE, 0xAD, 0xAE, 0xAF, 0xB0, 0xB3, 0xB7, 0xBB, 0xBF, 0xC5, 0xCB, 0xD2, 0xD9,
+ 0xE1, 0xE8, 0xF0, 0xF9, 0x01, 0x09, 0x11, 0x18, 0x1F, 0x26, 0x2D, 0x32, 0x37, 0x3C, 0x40, 0x43,
+ 0x46, 0x48, 0x49, 0x4A, 0x4B, 0x4B, 0x4B, 0x4A, 0x4A, 0x49, 0x48, 0x47, 0x47, 0x46, 0x46, 0x45,
+ 0x45, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x46, 0x47, 0x47, 0x47, 0x48, 0x49,
+ 0x49, 0x49, 0x49, 0x4A, 0x49, 0x49, 0x49, 0x48, 0x48, 0x47, 0x46, 0x45, 0x45, 0x44, 0x43, 0x42,
+ 0x41, 0x41, 0x40, 0x40, 0x3F, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x3F, 0x3F, 0x3E, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39,
+ 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x31, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x30, 0x30,
+ 0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3A, 0x3B, 0x3D, 0x3D, 0x3E, 0x3F,
+ 0x3F, 0x3F, 0x3E, 0x3E, 0x3C, 0x3B, 0x38, 0x36, 0x33, 0x30, 0x2B, 0x27, 0x22, 0x1E, 0x19, 0x14,
+ 0x0E, 0x09, 0x04, 0xFE, 0xF8, 0xF3, 0xED, 0xE8, 0xE2, 0xDC, 0xD6, 0xD1, 0xCB, 0xC6, 0xC0, 0xBC,
+ 0xB7, 0xB2, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9B, 0x9A, 0x9A, 0x99,
+ 0x99, 0x99, 0x98, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95,
+ 0x96, 0x97, 0x99, 0x9B, 0x9E, 0xA0, 0xA4, 0xA8, 0xAD, 0xB2, 0xB7, 0xBD, 0xC3, 0xCA, 0xD1, 0xD7,
+ 0xDF, 0xE5, 0xEC, 0xF3, 0xF9, 0xFF, 0x04, 0x09, 0x0C, 0x0F, 0x11, 0x12, 0x12, 0x11, 0x10, 0x0D,
+ 0x09, 0x05, 0x00, 0xFB, 0xF5, 0xEF, 0xE9, 0xE2, 0xDC, 0xD6, 0xD0, 0xC9, 0xC4, 0xBF, 0xBB, 0xB7,
+ 0xB4, 0xB1, 0xB0, 0xAF, 0xAF, 0xAF, 0xB1, 0xB4, 0xB7, 0xBB, 0xBF, 0xC5, 0xCA, 0xD1, 0xD7, 0xDE,
+ 0xE5, 0xED, 0xF4, 0xFC, 0x03, 0x0B, 0x12, 0x19, 0x1F, 0x24, 0x29, 0x2E, 0x33, 0x36, 0x39, 0x3C,
+ 0x3E, 0x40, 0x41, 0x42, 0x42, 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45, 0x46, 0x47, 0x47, 0x47, 0x48,
+ 0x48, 0x48, 0x48, 0x48, 0x48, 0x47, 0x47, 0x46, 0x46, 0x45, 0x44, 0x43, 0x43, 0x42, 0x41, 0x40,
+ 0x40, 0x3F, 0x3F, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x40, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x40, 0x40, 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38,
+ 0x37, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x30, 0x2F, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
+ 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x35, 0x36, 0x37, 0x39, 0x3A, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x42, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3C, 0x39, 0x37, 0x34, 0x31, 0x2D, 0x29, 0x24,
+ 0x20, 0x1B, 0x16, 0x10, 0x0A, 0x05, 0xFE, 0xF8, 0xF2, 0xEC, 0xE6, 0xE0, 0xDA, 0xD4, 0xCE, 0xC9,
+ 0xC4, 0xBF, 0xBB, 0xB7, 0xB3, 0xB0, 0xAD, 0xAA, 0xA8, 0xA6, 0xA4, 0xA2, 0xA0, 0x9F, 0x9D, 0x9B,
+ 0x9A, 0x98, 0x96, 0x95, 0x93, 0x91, 0x8F, 0x8E, 0x8C, 0x8B, 0x89, 0x88, 0x88, 0x87, 0x87, 0x87,
+ 0x88, 0x89, 0x8A, 0x8C, 0x8F, 0x92, 0x96, 0x9B, 0xA0, 0xA6, 0xAC, 0xB3, 0xB9, 0xC1, 0xC8, 0xD0,
+ 0xD8, 0xDF, 0xE7, 0xEE, 0xF5, 0xFB, 0xFF, 0x04, 0x08, 0x0B, 0x0D, 0x0E, 0x0E, 0x0E, 0x0C, 0x09,
+ 0x06, 0x03, 0xFE, 0xFA, 0xF4, 0xEF, 0xE9, 0xE3, 0xDD, 0xD8, 0xD2, 0xCD, 0xC8, 0xC4, 0xC0, 0xBC,
+ 0xBA, 0xB8, 0xB7, 0xB6, 0xB6, 0xB7, 0xB9, 0xBC, 0xBF, 0xC2, 0xC7, 0xCB, 0xD0, 0xD6, 0xDC, 0xE2,
+ 0xE8, 0xEF, 0xF5, 0xFB, 0x01, 0x07, 0x0D, 0x12, 0x17, 0x1B, 0x1F, 0x23, 0x27, 0x29, 0x2C, 0x2E,
+ 0x30, 0x32, 0x33, 0x34, 0x35, 0x36, 0x36, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3A, 0x3B, 0x3B, 0x3C,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x48, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x48, 0x48, 0x47, 0x46, 0x46, 0x45, 0x44, 0x44, 0x43, 0x42, 0x42, 0x41,
+ 0x41, 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x42, 0x41, 0x41, 0x40, 0x40, 0x3F, 0x3E, 0x3E, 0x3D, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36,
+ 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2F, 0x2E, 0x2E, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2E, 0x2F,
+ 0x2F, 0x30, 0x31, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39, 0x3B, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x42,
+ 0x43, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x43, 0x42, 0x40, 0x3E, 0x3C, 0x39, 0x36, 0x32, 0x2E,
+ 0x2A, 0x26, 0x21, 0x1C, 0x16, 0x10, 0x0A, 0x04, 0xFE, 0xF8, 0xF2, 0xEC, 0xE6, 0xE0, 0xDB, 0xD6,
+ 0xD1, 0xCC, 0xC8, 0xC4, 0xC0, 0xBD, 0xB9, 0xB6, 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA3, 0xA0,
+ 0x9D, 0x9A, 0x98, 0x95, 0x92, 0x8F, 0x8D, 0x8A, 0x88, 0x86, 0x84, 0x83, 0x82, 0x82, 0x82, 0x82,
+ 0x82, 0x83, 0x84, 0x86, 0x86
+};
+
+const uint8_t SfxPlayer::_musicDataSample2[] = {
+ 0x0D, 0x90, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x22, 0x1E, 0x18, 0x14, 0x10, 0x10,
+ 0x12, 0x16, 0x18, 0x1E, 0x22, 0x22, 0x1E, 0x20, 0x24, 0x22, 0x28, 0x38, 0x30, 0x36, 0x38, 0x2A,
+ 0x38, 0x32, 0x48, 0x30, 0x36, 0x58, 0x2E, 0x78, 0x24, 0x1A, 0x60, 0x1A, 0x78, 0xF6, 0x7F, 0x80,
+ 0x7F, 0x00, 0xFE, 0x7F, 0xB8, 0x7E, 0xE8, 0x0A, 0x7C, 0x28, 0x80, 0x9A, 0x7F, 0x6C, 0x60, 0xE4,
+ 0x5E, 0x6C, 0x7F, 0x7F, 0x76, 0x7F, 0x7C, 0x7F, 0x7F, 0x42, 0x7E, 0x48, 0x9E, 0x7F, 0xE8, 0x6C,
+ 0x08, 0x1A, 0x7F, 0x20, 0xEC, 0xFE, 0x7F, 0x32, 0x1C, 0xD8, 0x3E, 0x18, 0xCA, 0x48, 0xE0, 0xD8,
+ 0x4C, 0x24, 0xDC, 0x80, 0x80, 0x02, 0xA0, 0xCA, 0xD8, 0x94, 0xF2, 0xE6, 0x80, 0xAE, 0xA0, 0x80,
+ 0xCA, 0xA2, 0x82, 0x88, 0xAE, 0x80, 0x80, 0xB8, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x8E, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x96, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x90, 0x80, 0x8E, 0x9A, 0x84, 0xD6, 0xB8, 0x82, 0x98, 0x80, 0x96, 0x90, 0xFE, 0x18,
+ 0xE4, 0xFE, 0x50, 0x90, 0xBE, 0x4C, 0x00, 0xE8, 0xFE, 0x18, 0xDA, 0x7F, 0x60, 0x46, 0x60, 0x3C,
+ 0x50, 0x34, 0x7F, 0x7A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x70, 0x54,
+ 0x58, 0x60, 0x3C, 0x3A, 0x40, 0x1C, 0x12, 0x08, 0x00, 0xE4, 0xCC, 0xCA, 0xC0, 0xE2, 0xD6, 0xBA,
+ 0x96, 0x80, 0x9A, 0x82, 0x80, 0x9C, 0x8E, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x82,
+ 0x88, 0x90, 0x8E, 0x92, 0x9E, 0xAE, 0xD8, 0xE0, 0xC2, 0xB0, 0xA8, 0xBA, 0xD8, 0xFC, 0x10, 0x02,
+ 0xF0, 0xEA, 0x0C, 0x3A, 0x48, 0x34, 0x24, 0x16, 0x1E, 0x3E, 0x6C, 0x7F, 0x7F, 0x62, 0x46, 0x3C,
+ 0x54, 0x76, 0x7E, 0x74, 0x7A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7A, 0x78, 0x72, 0x66, 0x6E, 0x6E, 0x6C, 0x70, 0x72, 0x66, 0x60,
+ 0x60, 0x58, 0x52, 0x5C, 0x54, 0x54, 0x50, 0x4A, 0x48, 0x4A, 0x40, 0x42, 0x3A, 0x2A, 0x2E, 0x30,
+ 0x34, 0x34, 0x28, 0x22, 0x1E, 0x1A, 0x18, 0x16, 0x14, 0x0E, 0x06, 0x0A, 0x0E, 0x0A, 0x00, 0xF4,
+ 0xF6, 0xF0, 0xF8, 0xF8, 0xF0, 0xE8, 0xD8, 0xD0, 0xCE, 0xD0, 0xD0, 0xCE, 0xCE, 0xCC, 0xCE, 0xC2,
+ 0xB2, 0xB0, 0xB4, 0xBA, 0xB4, 0xAE, 0xAE, 0xA8, 0xA6, 0xA8, 0x9A, 0x98, 0x94, 0x8E, 0x8E, 0x8E,
+ 0x8E, 0x88, 0x8C, 0x8A, 0x84, 0x86, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x84, 0x8E, 0x9A, 0x92, 0x90, 0x90, 0x9A, 0x98, 0x9E, 0xB6, 0xBA, 0xC0, 0xC0, 0xA8, 0xB0, 0xC0,
+ 0xCC, 0xE2, 0xE4, 0xD8, 0xDC, 0xD4, 0xE2, 0xF2, 0xF0, 0x00, 0x06, 0x02, 0x00, 0x06, 0x06, 0x0E,
+ 0x14, 0x16, 0x22, 0x30, 0x2A, 0x22, 0x28, 0x34, 0x3A, 0x4A, 0x4E, 0x52, 0x54, 0x4A, 0x56, 0x54,
+ 0x52, 0x5E, 0x5E, 0x64, 0x68, 0x6E, 0x78, 0x7F, 0x7A, 0x7C, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7C, 0x78, 0x76,
+ 0x72, 0x6E, 0x6C, 0x68, 0x64, 0x60, 0x5C, 0x58, 0x56, 0x52, 0x50, 0x4C, 0x44, 0x46, 0x3E, 0x38,
+ 0x38, 0x2E, 0x2A, 0x1C, 0x1E, 0x18, 0x0E, 0x16, 0x02, 0xF0, 0xFA, 0xFC, 0xEC, 0xEC, 0xDC, 0xE2,
+ 0xD4, 0xDA, 0xCC, 0xC8, 0xCC, 0xBE, 0xC6, 0xC0, 0xBA, 0xBC, 0xB6, 0xB0, 0xA2, 0xA6, 0x9E, 0x94,
+ 0x96, 0x8C, 0x98, 0x80, 0x92, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x86, 0x8E, 0x8C, 0x8C, 0x94, 0x90,
+ 0x98, 0xA0, 0xA6, 0xB4, 0xBA, 0xB8, 0xC4, 0xC4, 0xD0, 0xCE, 0xD2, 0xD8, 0xDC, 0xE2, 0xE4, 0xEA,
+ 0xEA, 0xEC, 0xF6, 0xFE, 0xFE, 0x04, 0x0E, 0x06, 0x0E, 0x1E, 0x1E, 0x24, 0x2A, 0x32, 0x30, 0x3C,
+ 0x42, 0x3E, 0x46, 0x46, 0x48, 0x4C, 0x54, 0x5C, 0x64, 0x66, 0x6C, 0x6E, 0x72, 0x76, 0x72, 0x76,
+ 0x7A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7A, 0x78, 0x78, 0x72, 0x72, 0x68, 0x68,
+ 0x68, 0x68, 0x64, 0x64, 0x60, 0x5A, 0x5E, 0x58, 0x56, 0x58, 0x58, 0x54, 0x56, 0x52, 0x50, 0x52,
+ 0x4A, 0x4E, 0x4A, 0x48, 0x4C, 0x46, 0x44, 0x3E, 0x3C, 0x34, 0x36, 0x38, 0x34, 0x36, 0x30, 0x34,
+ 0x2E, 0x30, 0x2C, 0x26, 0x32, 0x26, 0x26, 0x26, 0x24, 0x26, 0x22, 0x22, 0x1E, 0x20, 0x20, 0x22,
+ 0x1E, 0x1A, 0x18, 0x18, 0x1C, 0x18, 0x18, 0x1A, 0x10, 0x14, 0x12, 0x10, 0x14, 0x14, 0x18, 0x16,
+ 0x1A, 0x14, 0x14, 0x12, 0x18, 0x16, 0x0E, 0x16, 0x0C, 0x0C, 0x10, 0x04, 0x10, 0x04, 0x0E, 0x00,
+ 0x06, 0x0E, 0x06, 0x04, 0x04, 0x06, 0x0A, 0x08, 0xFC, 0x06, 0x0E, 0x0A, 0x0C, 0x04, 0x06, 0x08,
+ 0x10, 0x0A, 0x06, 0x08, 0x04, 0x04, 0x06, 0x02, 0x06, 0x00, 0xFE, 0x06, 0xFE, 0xFC, 0xFA, 0x02,
+ 0x02, 0x00, 0xF6, 0xF6, 0x00, 0xF6, 0xF8, 0xF4, 0xFA, 0xF8, 0xF2, 0xF6, 0xF0, 0xEC, 0xF4, 0xF0,
+ 0xE6, 0xEA, 0xEC, 0xF0, 0xF0, 0xE4, 0xEA, 0xEC, 0xEC, 0xF0, 0xE0, 0xE4, 0xE4, 0xDE, 0xE2, 0xE2,
+ 0xE4, 0xE0, 0xE4, 0xDE, 0xDA, 0xE6, 0xDA, 0xDC, 0xD6, 0xCE, 0xD8, 0xDA, 0xD4, 0xCE, 0xD8, 0xD4,
+ 0xD8, 0xDA, 0xD0, 0xD2, 0xD0, 0xCE, 0xCC, 0xD0, 0xD2, 0xCE, 0xD4, 0xCC, 0xCA, 0xCC, 0xC6, 0xC8,
+ 0xC6, 0xC2, 0xC6, 0xCE, 0xC6, 0xCE, 0xCC, 0xC0, 0xCA, 0xC4, 0xCC, 0xCC, 0xCA, 0xCC, 0xCA, 0xCC,
+ 0xCA, 0xC6, 0xC6, 0xC6, 0xC6, 0xC0, 0xC2, 0xC6, 0xC0, 0xC8, 0xCC, 0xCC, 0xD0, 0xD0, 0xCC, 0xCC,
+ 0xCA, 0xCE, 0xD8, 0xD2, 0xDC, 0xDC, 0xD8, 0xDC, 0xD4, 0xD2, 0xD2, 0xD4, 0xD8, 0xDA, 0xE0, 0xDA,
+ 0xE0, 0xEE, 0xEE, 0xF8, 0xF4, 0xEE, 0xF6, 0xFE, 0xF8, 0xFC, 0x00, 0x02, 0x04, 0x00, 0xFE, 0xFE,
+ 0x06, 0x08, 0x0E, 0x0C, 0x0C, 0x0E, 0x0E, 0x10, 0x18, 0x12, 0x14, 0x18, 0x20, 0x20, 0x24, 0x2A,
+ 0x2A, 0x2C, 0x28, 0x26, 0x2A, 0x32, 0x34, 0x3A, 0x3A, 0x38, 0x38, 0x38, 0x36, 0x38, 0x42, 0x46,
+ 0x48, 0x4A, 0x48, 0x4E, 0x50, 0x4C, 0x52, 0x4E, 0x50, 0x58, 0x52, 0x54, 0x54, 0x5A, 0x56, 0x5A,
+ 0x5A, 0x5C, 0x62, 0x64, 0x62, 0x60, 0x68, 0x64, 0x6A, 0x6C, 0x6E, 0x72, 0x66, 0x6C, 0x68, 0x6C,
+ 0x72, 0x6E, 0x72, 0x6E, 0x72, 0x78, 0x70, 0x70, 0x72, 0x74, 0x7A, 0x74, 0x74, 0x74, 0x74, 0x76,
+ 0x7A, 0x7A, 0x7C, 0x7F, 0x78, 0x7C, 0x78, 0x70, 0x78, 0x78, 0x7A, 0x7F, 0x78, 0x7A, 0x7F, 0x78,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7C, 0x7F, 0x7F, 0x7F, 0x7F, 0x7C, 0x7E,
+ 0x7C, 0x7C, 0x7F, 0x7F, 0x7A, 0x7C, 0x70, 0x72, 0x7C, 0x74, 0x70, 0x6E, 0x6E, 0x6E, 0x6E, 0x68,
+ 0x6E, 0x6A, 0x64, 0x64, 0x5C, 0x5E, 0x5A, 0x56, 0x50, 0x48, 0x48, 0x4E, 0x4A, 0x44, 0x3A, 0x38,
+ 0x32, 0x2A, 0x36, 0x34, 0x24, 0x26, 0x20, 0x1C, 0x1E, 0x1E, 0x1C, 0x18, 0x12, 0x0C, 0x06, 0xFC,
+ 0x02, 0xFA, 0xF6, 0xF8, 0xEE, 0xEE, 0xF0, 0xEE, 0xEA, 0xE0, 0xDE, 0xE0, 0xDE, 0xCE, 0xD6, 0xD0,
+ 0xC8, 0xD2, 0xC4, 0xBA, 0xC8, 0xBA, 0xB8, 0xC0, 0xAC, 0xB0, 0xB0, 0xA8, 0xB4, 0xAA, 0xA8, 0xA8,
+ 0xA0, 0x9A, 0xA2, 0xA0, 0x9C, 0x9C, 0x9C, 0x98, 0x94, 0x98, 0x8C, 0x92, 0x94, 0x8A, 0x8A, 0x88,
+ 0x80, 0x86, 0x84, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x82, 0x82, 0x80, 0x86, 0x80,
+ 0x82, 0x88, 0x82, 0x8E, 0x88, 0x8A, 0x8E, 0x8E, 0x96, 0x92, 0x96, 0x9A, 0x98, 0x9A, 0x9E, 0x9E,
+ 0xAA, 0xB0, 0xB0, 0xB0, 0xB8, 0xB2, 0xB8, 0xC4, 0xC2, 0xCC, 0xC6, 0xCC, 0xD6, 0xD0, 0xD0, 0xD6,
+ 0xDE, 0xE2, 0xE4, 0xF0, 0xEE, 0xE4, 0xF4, 0xF4, 0xF6, 0xFE, 0x00, 0x0A, 0x10, 0x10, 0x14, 0x1E,
+ 0x1A, 0x22, 0x2A, 0x22, 0x32, 0x36, 0x34, 0x3E, 0x3E, 0x3C, 0x40, 0x46, 0x4A, 0x50, 0x50, 0x56,
+ 0x54, 0x60, 0x6A, 0x6A, 0x6E, 0x6A, 0x6C, 0x76, 0x78, 0x7A, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7C, 0x78, 0x74,
+ 0x76, 0x76, 0x6A, 0x72, 0x62, 0x62, 0x68, 0x5C, 0x58, 0x52, 0x50, 0x44, 0x48, 0x4A, 0x42, 0x48,
+ 0x3A, 0x32, 0x3E, 0x34, 0x30, 0x38, 0x30, 0x2E, 0x2A, 0x2A, 0x26, 0x1E, 0x1A, 0x16, 0x10, 0x0C,
+ 0x0C, 0x00, 0xF0, 0xF4, 0xFA, 0xF8, 0xF6, 0xF2, 0xF0, 0xF0, 0xF0, 0xEA, 0xDC, 0xE2, 0xDE, 0xDC,
+ 0xE0, 0xD2, 0xCA, 0xDA, 0xCC, 0xD2, 0xD6, 0xCA, 0xDC, 0xD0, 0xC8, 0xD6, 0xC6, 0xC6, 0xC0, 0xBC,
+ 0xB8, 0xBA, 0xBA, 0xC0, 0xC2, 0xB8, 0xB8, 0xB4, 0xB0, 0xB4, 0xB0, 0xB2, 0xAE, 0xAC, 0xB2, 0xB2,
+ 0xAC, 0xA6, 0xAC, 0xAA, 0xAC, 0xAA, 0xAC, 0xA8, 0xA2, 0xA4, 0xA6, 0x9E, 0xA2, 0xA4, 0xA6, 0xA8,
+ 0x9E, 0xAC, 0xA4, 0xA6, 0xAC, 0xA4, 0xA8, 0xA6, 0xA2, 0xA0, 0xA2, 0xA4, 0xA0, 0xA0, 0x9C, 0x9C,
+ 0x98, 0x9C, 0x94, 0x9A, 0x9E, 0x9A, 0x9E, 0xA2, 0xA0, 0x9A, 0x98, 0x9A, 0x94, 0x98, 0x96, 0x8C,
+ 0x9E, 0x98, 0x9E, 0xA4, 0xA8, 0xA4, 0xA6, 0xA4, 0xA2, 0xAA, 0xA6, 0xAA, 0xAA, 0xA6, 0xAE, 0xB2,
+ 0xB2, 0xBA, 0xB0, 0xAA, 0xB2, 0xB8, 0xB2, 0xB6, 0xC2, 0xC8, 0xCE, 0xC8, 0xC8, 0xCA, 0xCA, 0xCC,
+ 0xD4, 0xD2, 0xD4, 0xD6, 0xE6, 0xE8, 0xE6, 0xE8, 0xE0, 0xE6, 0xEC, 0xEE, 0xF8, 0xF6, 0xF2, 0xFA,
+ 0xFC, 0xF6, 0xFE, 0x08, 0x08, 0x10, 0x10, 0x12, 0x18, 0x1C, 0x24, 0x22, 0x24, 0x2E, 0x2A, 0x34,
+ 0x34, 0x40, 0x42, 0x3E, 0x42, 0x3E, 0x46, 0x42, 0x46, 0x50, 0x4E, 0x56, 0x50, 0x4E, 0x5C, 0x5E,
+ 0x56, 0x5E, 0x60, 0x68, 0x62, 0x66, 0x60, 0x62, 0x6C, 0x66, 0x6C, 0x66, 0x60, 0x6A, 0x66, 0x6A,
+ 0x70, 0x68, 0x5E, 0x64, 0x68, 0x62, 0x6C, 0x68, 0x64, 0x68, 0x60, 0x66, 0x60, 0x5A, 0x58, 0x58,
+ 0x58, 0x50, 0x50, 0x4A, 0x46, 0x42, 0x44, 0x44, 0x48, 0x40, 0x3E, 0x42, 0x38, 0x3C, 0x30, 0x30,
+ 0x30, 0x2C, 0x34, 0x28, 0x28, 0x26, 0x1C, 0x28, 0x22, 0x1A, 0x16, 0x12, 0x0E, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x02, 0x06, 0x06, 0x00, 0x00, 0x00, 0xFA, 0xFA, 0xFC, 0xF2, 0xF6, 0xFA, 0xF6, 0xF4, 0xF0,
+ 0xF0, 0xE8, 0xE8, 0xF2, 0xF0, 0xF0, 0xE6, 0xE4, 0xE6, 0xEC, 0xEE, 0xEE, 0xE2, 0xE6, 0xEE, 0xE4,
+ 0xF0, 0xEC, 0xE6, 0xEC, 0xEA, 0xEC, 0xF0, 0xF0, 0xEA, 0xE8, 0xEA, 0xEC, 0xFA, 0xF0, 0xE8, 0xEE,
+ 0xEA, 0xF4, 0xFC, 0xFE, 0xFA, 0x00, 0xF8, 0xF8, 0xF8, 0xFC, 0x00, 0xFC, 0x02, 0x00, 0x06, 0x0A,
+ 0x0A, 0x0C, 0x10, 0x0C, 0x0E, 0x08, 0x0C, 0x10, 0x0E, 0x18, 0x14, 0x1E, 0x1C, 0x20, 0x1E, 0x1C,
+ 0x1E, 0x1E, 0x20, 0x26, 0x22, 0x1E, 0x20, 0x22, 0x28, 0x20, 0x26, 0x2A, 0x26, 0x2C, 0x26, 0x26,
+ 0x26, 0x28, 0x30, 0x38, 0x2E, 0x2E, 0x30, 0x2A, 0x34, 0x30, 0x32, 0x2E, 0x26, 0x2C, 0x2C, 0x26,
+ 0x26, 0x2A, 0x28, 0x2A, 0x28, 0x26, 0x2A, 0x24, 0x20, 0x28, 0x26, 0x28, 0x26, 0x22, 0x1E, 0x20,
+ 0x24, 0x1C, 0x12, 0x1C, 0x0E, 0x14, 0x14, 0x0E, 0x18, 0x12, 0x10, 0x12, 0x0C, 0x0C, 0x04, 0x0C,
+ 0x0A, 0x0C, 0x08, 0x02, 0x0C, 0x10, 0x0E, 0x0A, 0x02, 0xFE, 0x06, 0x06, 0x06, 0x04, 0xFC, 0x06,
+ 0x08, 0x02, 0x00, 0xF8, 0xFC, 0xFC, 0xF4, 0xFC, 0x00, 0x00, 0xFE, 0xF8, 0xF0, 0xF6, 0xFC, 0xF6,
+ 0xF4, 0xF2, 0xF6, 0xFA, 0xF2, 0xF8, 0xF8, 0xFA, 0xF6, 0xFC, 0xFC, 0xF6, 0xFC, 0xF2, 0xFC, 0xFA,
+ 0xFE, 0xFC, 0xFE, 0x00, 0xFC, 0xFE, 0x00, 0xFE, 0x06, 0x02, 0x04, 0x10, 0x0E, 0x12, 0x0C, 0x0E,
+ 0x0E, 0x0C, 0x0E, 0x10, 0x10, 0x1A, 0x0E, 0x08, 0x16, 0x1A, 0x20, 0x20, 0x22, 0x2C, 0x2C, 0x30,
+ 0x30, 0x38, 0x3E, 0x34, 0x36, 0x3E, 0x40, 0x3C, 0x42, 0x3C, 0x44, 0x46, 0x46, 0x4A, 0x4C, 0x4A,
+ 0x4A, 0x52, 0x50, 0x56, 0x5E, 0x5E, 0x60, 0x60, 0x62, 0x60, 0x62, 0x64, 0x60, 0x64, 0x64, 0x6A,
+ 0x72, 0x68, 0x66, 0x6C, 0x6E, 0x6E, 0x74, 0x70, 0x6C, 0x6C, 0x66, 0x70, 0x7A, 0x7A, 0x7A, 0x78,
+ 0x74, 0x72, 0x72, 0x78, 0x72, 0x76, 0x76, 0x74, 0x78, 0x72, 0x76, 0x72, 0x70, 0x74, 0x70, 0x72,
+ 0x70, 0x76, 0x74, 0x6E, 0x6A, 0x66, 0x68, 0x64, 0x64, 0x60, 0x64, 0x64, 0x64, 0x68, 0x60, 0x5A,
+ 0x5C, 0x58, 0x56, 0x54, 0x58, 0x4C, 0x50, 0x4E, 0x4A, 0x4A, 0x46, 0x46, 0x42, 0x42, 0x46, 0x46,
+ 0x42, 0x40, 0x40, 0x3C, 0x3A, 0x3A, 0x3A, 0x36, 0x3A, 0x36, 0x34, 0x30, 0x2E, 0x30, 0x28, 0x24,
+ 0x26, 0x1E, 0x26, 0x1E, 0x18, 0x1A, 0x14, 0x16, 0x1C, 0x12, 0x08, 0x02, 0x04, 0x04, 0x08, 0x04,
+ 0x00, 0x00, 0xFA, 0xF8, 0xF2, 0xF2, 0xEC, 0xE8, 0xEA, 0xE4, 0xE2, 0xE0, 0xDA, 0xDE, 0xDC, 0xD6,
+ 0xD2, 0xD2, 0xCE, 0xCC, 0xC4, 0xC0, 0xC4, 0xBC, 0xC0, 0xC0, 0xB8, 0xAE, 0xAA, 0xAC, 0xAE, 0xA4,
+ 0xA0, 0x9C, 0x9C, 0xA6, 0x9E, 0xA0, 0x9A, 0x9C, 0x9A, 0x94, 0x98, 0x94, 0x98, 0x96, 0x9C, 0x92,
+ 0x8E, 0x8E, 0x8E, 0x90, 0x8A, 0x84, 0x82, 0x82, 0x84, 0x80, 0x86, 0x86, 0x86, 0x8A, 0x88, 0x90,
+ 0x96, 0x94, 0x98, 0x8E, 0x90, 0x98, 0x9A, 0x9A, 0x98, 0x90, 0x9A, 0xA0, 0xA0, 0xAC, 0xA8, 0xAE,
+ 0xB2, 0xB0, 0xB2, 0xBE, 0xBC, 0xBC, 0xC2, 0xC4, 0xCC, 0xCC, 0xCE, 0xD4, 0xD8, 0xDA, 0xDC, 0xEA,
+ 0xEA, 0xEC, 0xF2, 0xF4, 0xFC, 0xFA, 0x00, 0x06, 0x0A, 0x12, 0x14, 0x16, 0x16, 0x2A, 0x36, 0x34,
+ 0x34, 0x3A, 0x3A, 0x46, 0x4C, 0x52, 0x5A, 0x5A, 0x60, 0x5C, 0x5E, 0x68, 0x6A, 0x66, 0x72, 0x76,
+ 0x78, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7C,
+ 0x76, 0x76, 0x72, 0x74, 0x70, 0x68, 0x68, 0x60, 0x5E, 0x5E, 0x56, 0x58, 0x56, 0x4C, 0x4C, 0x46,
+ 0x44, 0x46, 0x3C, 0x3A, 0x30, 0x30, 0x2A, 0x2C, 0x26, 0x20, 0x1E, 0x1E, 0x1E, 0x18, 0x16, 0x14,
+ 0x0E, 0x10, 0x08, 0x08, 0x06, 0x04, 0x00, 0xFC, 0xFA, 0xF6, 0xEE, 0xF0, 0xEE, 0xEA, 0xE4, 0xE6,
+ 0xE6, 0xE2, 0xDE, 0xE0, 0xE0, 0xDE, 0xE2, 0xDA, 0xD8, 0xD8, 0xD8, 0xD6, 0xDA, 0xD6, 0xD4, 0xD4,
+ 0xCE, 0xCA, 0xC8, 0xCA, 0xD0, 0xCE, 0xCA, 0xCC, 0xC6, 0xC2, 0xC6, 0xC8, 0xC8, 0xCE, 0xCA, 0xCA,
+ 0xC6, 0xCC, 0xC0, 0xC0, 0xC4, 0xC2, 0xC6, 0xC0, 0xBE, 0xC2, 0xC2, 0xBC, 0xB8, 0xBC, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC8, 0xC6, 0xC4, 0xC2, 0xC6, 0xC2, 0xC2, 0xC4, 0xC6, 0xC0, 0xBC, 0xC4, 0xC2,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC4, 0xC0, 0xC6, 0xCE, 0xC6, 0xC8, 0xC8, 0xC6, 0xC0, 0xC2, 0xC8, 0xCC,
+ 0xCA, 0xCC, 0xCA, 0xC4, 0xCC, 0xCE, 0xC8, 0xCC, 0xC8, 0xC6, 0xC6, 0xC6, 0xD0, 0xCA, 0xC8, 0xC6,
+ 0xC8, 0xD2, 0xD0, 0xCC, 0xCA, 0xCE, 0xD0, 0xD4, 0xD4, 0xD6, 0xD4, 0xD6, 0xD6, 0xD6, 0xD4, 0xD2,
+ 0xD4, 0xD8, 0xD2, 0xD6, 0xD8, 0xD6, 0xDA, 0xD4, 0xD4, 0xD2, 0xD8, 0xE0, 0xE0, 0xE0, 0xDC, 0xDE,
+ 0xDE, 0xE2, 0xE0, 0xDC, 0xE2, 0xE0, 0xE0, 0xE4, 0xE6, 0xE6, 0xE4, 0xE4, 0xE2, 0xE0, 0xE6, 0xEC,
+ 0xE8, 0xE6, 0xE8, 0xE8, 0xEA, 0xEC, 0xEE, 0xF0, 0xEC, 0xEA, 0xEA, 0xEC, 0xF4, 0xF2, 0xF2, 0xEC,
+ 0xEE, 0xF0, 0xEE, 0xF2, 0xF2, 0xF2, 0xF6, 0xF8, 0xF4, 0xF6, 0xFA, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC,
+ 0xF8, 0xF8, 0xFA, 0x00, 0x00, 0x04, 0x08, 0x04, 0x02, 0x02, 0x04, 0x10, 0x14, 0x10, 0x12, 0x0C,
+ 0x0C, 0x12, 0x12, 0x14, 0x16, 0x16, 0x18, 0x1A, 0x1E, 0x20, 0x20, 0x22, 0x20, 0x1E, 0x22, 0x28,
+ 0x28, 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x38, 0x36, 0x36, 0x36, 0x36, 0x3E, 0x42, 0x42, 0x42,
+ 0x42, 0x46, 0x48, 0x48, 0x4E, 0x4A, 0x54, 0x58, 0x58, 0x5A, 0x5A, 0x5C, 0x62, 0x62, 0x5E, 0x68,
+ 0x66, 0x6A, 0x70, 0x6E, 0x70, 0x72, 0x72, 0x76, 0x7A, 0x76, 0x74, 0x78, 0x78, 0x7C, 0x7F, 0x7A,
+ 0x7C, 0x7E, 0x7E, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7E, 0x7F, 0x7F, 0x7F, 0x7F, 0x7E, 0x7F, 0x7A, 0x7C,
+ 0x7C, 0x7C, 0x74, 0x6A, 0x6C, 0x6E, 0x6E, 0x6C, 0x60, 0x60, 0x5E, 0x5E, 0x5C, 0x56, 0x54, 0x56,
+ 0x54, 0x52, 0x54, 0x4C, 0x46, 0x44, 0x42, 0x40, 0x3C, 0x3C, 0x3C, 0x38, 0x32, 0x32, 0x2C, 0x2C,
+ 0x26, 0x24, 0x26, 0x20, 0x22, 0x1E, 0x1C, 0x18, 0x10, 0x18, 0x10, 0x10, 0x0C, 0x0C, 0x08, 0x0C,
+ 0x0C, 0x02, 0x00, 0xFC, 0x00, 0xFC, 0xF8, 0xF2, 0xF2, 0xEA, 0xEA, 0xEE, 0xF0, 0xF2, 0xE6, 0xE4,
+ 0xE4, 0xE6, 0xE8, 0xEA, 0xE6, 0xE2, 0xE4, 0xE0, 0xE2, 0xE0, 0xDC, 0xD2, 0xD6, 0xD8, 0xDA, 0xDA,
+ 0xD0, 0xD4, 0xD6, 0xD0, 0xCE, 0xD2, 0xD0, 0xCC, 0xCA, 0xCC, 0xCC, 0xCA, 0xCC, 0xCC, 0xCC, 0xCA,
+ 0xC6, 0xC6, 0xC4, 0xC4, 0xC4, 0xC4, 0xC0, 0xC6, 0xC2, 0xC6, 0xC8, 0xC2, 0xC2, 0xC2, 0xC0, 0xC6,
+ 0xC6, 0xC2, 0xC4, 0xC6, 0xC2, 0xC2, 0xC4, 0xC8, 0xC6, 0xC4, 0xC0, 0xC0, 0xBC, 0xBE, 0xBE, 0xC0,
+ 0xC2, 0xC0, 0xC4, 0xC0, 0xC0, 0xC2, 0xBE, 0xC2, 0xC6, 0xCA, 0xC6, 0xC4, 0xC0, 0xC0, 0xC0, 0xC2,
+ 0xC6, 0xC8, 0xC6, 0xC8, 0xC8, 0xC6, 0xC6, 0xCA, 0xCA, 0xCC, 0xCE, 0xCC, 0xCC, 0xD6, 0xDA, 0xDC,
+ 0xDC, 0xDE, 0xDA, 0xDA, 0xE2, 0xE2, 0xE8, 0xE6, 0xE6, 0xE6, 0xEC, 0xF0, 0xF2, 0xF2, 0xF2, 0xF4,
+ 0xF8, 0xFC, 0xFC, 0x02, 0x04, 0x04, 0x06, 0x0C, 0x0E, 0x10, 0x10, 0x16, 0x1A, 0x1A, 0x1E, 0x20,
+ 0x24, 0x24, 0x24, 0x26, 0x2A, 0x30, 0x2E, 0x32, 0x36, 0x38, 0x40, 0x3E, 0x3E, 0x3E, 0x42, 0x42,
+ 0x44, 0x4C, 0x50, 0x54, 0x54, 0x52, 0x50, 0x54, 0x5C, 0x5A, 0x5C, 0x5E, 0x5C, 0x5E, 0x62, 0x64,
+ 0x66, 0x64, 0x64, 0x66, 0x66, 0x66, 0x68, 0x6C, 0x6E, 0x6E, 0x6C, 0x6A, 0x6C, 0x6A, 0x6E, 0x6A,
+ 0x6E, 0x6A, 0x70, 0x70, 0x6A, 0x6C, 0x68, 0x6A, 0x6E, 0x6C, 0x6C, 0x64, 0x62, 0x64, 0x66, 0x6C,
+ 0x68, 0x62, 0x60, 0x5E, 0x64, 0x66, 0x60, 0x5E, 0x5C, 0x5C, 0x5C, 0x58, 0x54, 0x56, 0x50, 0x52,
+ 0x4C, 0x46, 0x48, 0x42, 0x46, 0x4A, 0x40, 0x3A, 0x38, 0x3A, 0x36, 0x30, 0x2A, 0x26, 0x2C, 0x30,
+ 0x2A, 0x26, 0x2A, 0x2A, 0x22, 0x1C, 0x18, 0x1C, 0x16, 0x14, 0x16, 0x0E, 0x12, 0x14, 0x0A, 0x06,
+ 0x08, 0x00, 0x04, 0x02, 0x00, 0xFC, 0xFC, 0xFE, 0xF8, 0xF6, 0xF2, 0xF0, 0xF2, 0xF0, 0xEC, 0xEA,
+ 0xEA, 0xEA, 0xEE, 0xEA, 0xE6, 0xE8, 0xE2, 0xE6, 0xE8, 0xE6, 0xEA, 0xE4, 0xE2, 0xE0, 0xE0, 0xE0,
+ 0xDE, 0xE2, 0xE4, 0xE0, 0xE0, 0xE0, 0xE2, 0xE2, 0xE0, 0xE2, 0xE4, 0xE0, 0xE0, 0xE2, 0xE2, 0xE4,
+ 0xE6, 0xE6, 0xE6, 0xE6, 0xEE, 0xE8, 0xE6, 0xE8, 0xE6, 0xE6, 0xEC, 0xF0, 0xEE, 0xEE, 0xEC, 0xEE,
+ 0xF2, 0xF4, 0xF8, 0xF4, 0xF8, 0xF8, 0xF8, 0xFA, 0xFE, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04,
+ 0x08, 0x0A, 0x08, 0x0C, 0x0A, 0x0E, 0x0E, 0x0C, 0x0C, 0x10, 0x10, 0x12, 0x16, 0x18, 0x1A, 0x18,
+ 0x16, 0x18, 0x18, 0x16, 0x1A, 0x1E, 0x1E, 0x1E, 0x18, 0x1C, 0x1E, 0x1E, 0x1C, 0x1A, 0x20, 0x1E,
+ 0x24, 0x24, 0x24, 0x22, 0x20, 0x22, 0x22, 0x26, 0x22, 0x20, 0x20, 0x26, 0x26, 0x20, 0x1E, 0x1E,
+ 0x1E, 0x1C, 0x1A, 0x1C, 0x20, 0x20, 0x22, 0x22, 0x24, 0x20, 0x1E, 0x20, 0x22, 0x26, 0x20, 0x22,
+ 0x24, 0x24, 0x1E, 0x1C, 0x1C, 0x22, 0x22, 0x1C, 0x20, 0x20, 0x1E, 0x1C, 0x1C, 0x1A, 0x1A, 0x1C,
+ 0x1E, 0x1C, 0x1A, 0x1A, 0x18, 0x1C, 0x1A, 0x18, 0x1E, 0x18, 0x1C, 0x14, 0x12, 0x12, 0x16, 0x10,
+ 0x0E, 0x16, 0x14, 0x16, 0x10, 0x0E, 0x12, 0x16, 0x16, 0x14, 0x18, 0x10, 0x10, 0x10, 0x12, 0x10,
+ 0x10, 0x08, 0x08, 0x06, 0x08, 0x08, 0x06, 0x0C, 0x08, 0x08, 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A,
+ 0x0C, 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x04, 0x02, 0x06, 0x06, 0x02, 0x04, 0x04, 0x06,
+ 0x08, 0x06, 0x04, 0x04, 0x06, 0x0C, 0x0A, 0x02, 0x02
+};
+
+const uint8_t SfxPlayer::_musicDataSample3[] = {
+ 0x11, 0x8C, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x42, 0x50, 0x43, 0x18, 0xF6, 0xEE,
+ 0xE5, 0xCF, 0xC7, 0xB7, 0xAC, 0xAA, 0xAB, 0xD9, 0x2E, 0x7B, 0x7F, 0x79, 0x27, 0xEC, 0xCD, 0xE6,
+ 0x03, 0xFC, 0xE9, 0xE1, 0xE2, 0xF5, 0xFF, 0x0E, 0x23, 0x29, 0x13, 0xD5, 0x98, 0x8B, 0xA1, 0xBB,
+ 0xDF, 0xE9, 0x03, 0x36, 0x65, 0x72, 0x55, 0x23, 0x01, 0xDF, 0xC2, 0xA0, 0x85, 0x90, 0xC3, 0xEF,
+ 0x18, 0x40, 0x53, 0x55, 0x26, 0xDB, 0x9E, 0x90, 0xC1, 0x0A, 0x3D, 0x59, 0x58, 0x54, 0x62, 0x68,
+ 0x57, 0x4A, 0x2B, 0xF3, 0xB5, 0x8C, 0x94, 0xC3, 0x02, 0x20, 0x04, 0xCD, 0xAF, 0xAC, 0xD9, 0x03,
+ 0x0D, 0x0D, 0x0F, 0x01, 0xFA, 0x06, 0x30, 0x5C, 0x75, 0x6F, 0x3A, 0x00, 0xF1, 0xFF, 0xFA, 0xE2,
+ 0xB2, 0xA3, 0xBC, 0xD8, 0xD7, 0xCD, 0xC5, 0xC6, 0xCA, 0xCE, 0xC7, 0xC1, 0xE8, 0x29, 0x46, 0x47,
+ 0x58, 0x73, 0x7F, 0x5F, 0x0E, 0xBE, 0xAC, 0xDA, 0x23, 0x50, 0x4F, 0x1F, 0xFE, 0xFB, 0xED, 0xCC,
+ 0xC6, 0xCB, 0xC0, 0xAB, 0xAB, 0xD6, 0x23, 0x7F, 0x7F, 0x7F, 0x3E, 0xEB, 0xCA, 0xE6, 0xFF, 0xF6,
+ 0xE8, 0xEB, 0xE7, 0xE5, 0xF6, 0x14, 0x22, 0x24, 0x17, 0xDC, 0x9D, 0x91, 0xB2, 0xDC, 0xED, 0xE2,
+ 0xEE, 0x21, 0x5A, 0x6E, 0x62, 0x3A, 0xFE, 0xCA, 0xBD, 0xAD, 0x93, 0x9D, 0xC7, 0xE8, 0xFF, 0x24,
+ 0x50, 0x60, 0x3A, 0xF1, 0xA9, 0x9A, 0xBE, 0x00, 0x48, 0x6D, 0x59, 0x48, 0x58, 0x5C, 0x4A, 0x38,
+ 0x24, 0xE7, 0x95, 0x84, 0x85, 0xC4, 0x13, 0x36, 0x1F, 0xE2, 0xA4, 0xA2, 0xD8, 0x02, 0x06, 0x01,
+ 0x0F, 0x15, 0x0E, 0x2E, 0x62, 0x73, 0x6A, 0x53, 0x19, 0xE0, 0xD2, 0xE4, 0xF1, 0xD0, 0xA6, 0xA6,
+ 0xCF, 0xF7, 0xEB, 0xD2, 0xC4, 0xB1, 0xA9, 0xC6, 0xD4, 0xD3, 0xFB, 0x3A, 0x56, 0x50, 0x4F, 0x6E,
+ 0x7C, 0x52, 0xFC, 0xA7, 0x9A, 0xC6, 0x0A, 0x44, 0x49, 0x18, 0x00, 0x0F, 0x09, 0xDF, 0xC4, 0xCB,
+ 0xCE, 0xB9, 0xC2, 0xE8, 0x26, 0x76, 0x7F, 0x7F, 0x3A, 0xD7, 0xBB, 0xE4, 0x01, 0xED, 0xCB, 0xCD,
+ 0xD8, 0xD9, 0xF2, 0x1C, 0x1F, 0x1B, 0x1E, 0xF2, 0xBF, 0xAC, 0xC6, 0xF6, 0xFD, 0xEC, 0xF0, 0x1B,
+ 0x58, 0x68, 0x58, 0x3E, 0xFE, 0xC5, 0xBA, 0xAD, 0x90, 0x98, 0xC2, 0xE7, 0xF7, 0x06, 0x39, 0x57,
+ 0x4A, 0x11, 0xBD, 0xA4, 0xC7, 0x03, 0x59, 0x7E, 0x5A, 0x3B, 0x41, 0x48, 0x37, 0x24, 0x18, 0xEA,
+ 0x95, 0x84, 0x8E, 0xC9, 0x20, 0x3F, 0x1F, 0xDE, 0x99, 0xAC, 0xFD, 0x3B, 0x42, 0x25, 0x23, 0x1D,
+ 0xFA, 0x05, 0x3E, 0x54, 0x57, 0x46, 0x0C, 0xDC, 0xD7, 0xF5, 0x11, 0xDA, 0x8A, 0x84, 0x8B, 0xDC,
+ 0xFB, 0xF1, 0xEF, 0xD7, 0xC5, 0xE5, 0xFB, 0xF2, 0xFA, 0x1F, 0x38, 0x35, 0x33, 0x6C, 0x7F, 0x78,
+ 0x1F, 0xA6, 0x84, 0x98, 0xD6, 0x23, 0x3B, 0x08, 0xE7, 0x02, 0x1A, 0x02, 0xE2, 0xE3, 0xE4, 0xB9,
+ 0xB1, 0xDA, 0x22, 0x7B, 0x7F, 0x7F, 0x34, 0xD3, 0xC7, 0x0C, 0x33, 0x0C, 0xC9, 0xB3, 0xC1, 0xC1,
+ 0xDD, 0x1D, 0x2E, 0x20, 0x14, 0xEF, 0xCB, 0xD0, 0xF7, 0x26, 0x0C, 0xC3, 0xA6, 0xD6, 0x36, 0x67,
+ 0x68, 0x59, 0x1B, 0xCD, 0xBA, 0xB8, 0x9C, 0x8F, 0xA6, 0xC2, 0xD0, 0xEC, 0x3B, 0x77, 0x6D, 0x29,
+ 0xC6, 0xA2, 0xC6, 0x07, 0x59, 0x7F, 0x5C, 0x2B, 0x2D, 0x41, 0x35, 0x25, 0x1F, 0xF5, 0x95, 0x84,
+ 0x8B, 0xD6, 0x2E, 0x43, 0x0E, 0xBC, 0x84, 0x84, 0xED, 0x3B, 0x41, 0x21, 0x22, 0x2A, 0x17, 0x24,
+ 0x64, 0x73, 0x4F, 0x29, 0xF5, 0xD7, 0xE9, 0x12, 0x29, 0xE5, 0x86, 0x84, 0x84, 0xDE, 0x06, 0xF9,
+ 0xF1, 0xD5, 0xB0, 0xC7, 0xE4, 0xDF, 0xE0, 0x01, 0x1B, 0x22, 0x32, 0x76, 0x7F, 0x7F, 0x3B, 0xB7,
+ 0x85, 0x9A, 0xD0, 0x17, 0x32, 0x01, 0xE2, 0xFB, 0x1A, 0x0B, 0xF1, 0xF0, 0xE4, 0xA0, 0x87, 0xAF,
+ 0xFE, 0x62, 0x7F, 0x79, 0x35, 0xE1, 0xDA, 0x26, 0x4E, 0x2B, 0xE4, 0xC8, 0xC8, 0xBA, 0xC8, 0x0A,
+ 0x1F, 0x13, 0x0E, 0xFB, 0xEB, 0xF8, 0x1A, 0x3F, 0x11, 0xB7, 0x95, 0xBD, 0x1C, 0x4E, 0x57, 0x53,
+ 0x21, 0xD8, 0xCB, 0xD1, 0xBA, 0xA7, 0xA8, 0xAC, 0xA7, 0xBA, 0x1E, 0x76, 0x7E, 0x45, 0xDC, 0xAA,
+ 0xBB, 0xEE, 0x44, 0x78, 0x5B, 0x36, 0x3A, 0x4A, 0x37, 0x27, 0x2D, 0x15, 0xBB, 0x86, 0x92, 0xC7,
+ 0x0C, 0x27, 0x04, 0xC7, 0x8F, 0x9D, 0xF8, 0x37, 0x2E, 0x05, 0x08, 0x15, 0x0D, 0x1C, 0x58, 0x67,
+ 0x4C, 0x2E, 0x12, 0x01, 0x0D, 0x2A, 0x35, 0xE7, 0x8A, 0x84, 0x84, 0xDA, 0x08, 0x11, 0x0D, 0xEC,
+ 0xBC, 0xBE, 0xD5, 0xD4, 0xD3, 0xED, 0xFF, 0x00, 0x13, 0x68, 0x7F, 0x7F, 0x61, 0xE1, 0x90, 0x83,
+ 0xA4, 0xEC, 0x1F, 0x0D, 0xF6, 0x0C, 0x2B, 0x1F, 0x0F, 0x14, 0x09, 0xC4, 0x98, 0xA9, 0xEC, 0x41,
+ 0x7C, 0x78, 0x39, 0xE8, 0xD8, 0x16, 0x46, 0x27, 0xE1, 0xC0, 0xAF, 0xA0, 0xB5, 0xFB, 0x23, 0x1F,
+ 0x16, 0x06, 0xF8, 0x05, 0x2D, 0x4E, 0x27, 0xC9, 0x8E, 0xAD, 0x05, 0x46, 0x68, 0x6A, 0x36, 0xE8,
+ 0xCA, 0xCA, 0xB8, 0xA4, 0xA5, 0xA4, 0x9A, 0xAE, 0x05, 0x66, 0x7F, 0x55, 0xF0, 0xAE, 0xA6, 0xD4,
+ 0x2A, 0x66, 0x55, 0x29, 0x2E, 0x49, 0x47, 0x40, 0x3D, 0x18, 0xC2, 0x86, 0x85, 0xBC, 0x06, 0x31,
+ 0x28, 0xE5, 0x9A, 0x8D, 0xD5, 0x2C, 0x37, 0x15, 0x04, 0x00, 0xFA, 0x18, 0x60, 0x7E, 0x6B, 0x3C,
+ 0x11, 0xF2, 0xF2, 0x16, 0x2B, 0xF8, 0x99, 0x84, 0x84, 0xC1, 0xFA, 0x10, 0x0D, 0xE7, 0xBC, 0xB6,
+ 0xD1, 0xDE, 0xDA, 0xE9, 0xFA, 0xFD, 0x15, 0x5A, 0x7F, 0x7F, 0x76, 0x0C, 0xB9, 0x91, 0xA5, 0xE1,
+ 0x0F, 0x01, 0xDE, 0xE6, 0x09, 0x13, 0x18, 0x25, 0x18, 0xE0, 0xB4, 0xB2, 0xE4, 0x28, 0x5E, 0x70,
+ 0x47, 0x05, 0xEE, 0x15, 0x46, 0x3A, 0x01, 0xD8, 0xBE, 0xA5, 0xAD, 0xDF, 0x0A, 0x17, 0x09, 0xF8,
+ 0xEC, 0xF5, 0x21, 0x45, 0x34, 0xEB, 0xA7, 0xB4, 0xF9, 0x34, 0x5E, 0x63, 0x35, 0xEF, 0xC2, 0xBB,
+ 0xBF, 0xB9, 0xB5, 0xAD, 0x94, 0x99, 0xD0, 0x1D, 0x58, 0x44, 0x03, 0xD5, 0xC5, 0xEA, 0x3A, 0x73,
+ 0x73, 0x42, 0x30, 0x3A, 0x3C, 0x3B, 0x43, 0x2B, 0xEC, 0xB2, 0x9C, 0xBF, 0xF4, 0x14, 0x14, 0xE0,
+ 0x9B, 0x89, 0xC1, 0x1E, 0x3F, 0x29, 0x14, 0x03, 0xF8, 0x17, 0x4C, 0x6C, 0x5F, 0x33, 0x0F, 0xFF,
+ 0xFC, 0x13, 0x1F, 0xFA, 0xB2, 0x84, 0x84, 0xB0, 0xE5, 0x10, 0x1B, 0xF5, 0xC3, 0xA8, 0xC0, 0xE6,
+ 0xF8, 0x04, 0x09, 0xFC, 0x0C, 0x3F, 0x79, 0x7F, 0x62, 0x08, 0xC2, 0x95, 0x98, 0xCF, 0x04, 0x19,
+ 0x03, 0xF9, 0x04, 0x0E, 0x1B, 0x30, 0x27, 0xFE, 0xD1, 0xC1, 0xED, 0x24, 0x45, 0x58, 0x3E, 0x0E,
+ 0xFA, 0x10, 0x3E, 0x3A, 0x0F, 0xE6, 0xBB, 0x94, 0x9A, 0xC0, 0xF3, 0x0B, 0x03, 0xF6, 0xFA, 0x0C,
+ 0x36, 0x52, 0x38, 0xEF, 0xA2, 0xA3, 0xDC, 0x1A, 0x51, 0x68, 0x3F, 0x03, 0xD3, 0xC8, 0xCD, 0xCE,
+ 0xC4, 0xB0, 0x8C, 0x86, 0xB6, 0x06, 0x4F, 0x4F, 0x23, 0xF8, 0xDD, 0xEF, 0x2F, 0x5B, 0x5B, 0x31,
+ 0x1B, 0x1D, 0x22, 0x2D, 0x3F, 0x2C, 0x05, 0xDE, 0xC0, 0xCA, 0xE7, 0xF6, 0xFA, 0xD9, 0xA8, 0xA2,
+ 0xD1, 0x22, 0x44, 0x38, 0x1F, 0x02, 0xF0, 0x11, 0x38, 0x4D, 0x48, 0x27, 0x0A, 0x03, 0x01, 0x15,
+ 0x1C, 0xFC, 0xBE, 0x85, 0x84, 0xA8, 0xE0, 0x18, 0x2C, 0x04, 0xD7, 0xC2, 0xD1, 0xED, 0xFF, 0x02,
+ 0x02, 0xFC, 0x19, 0x44, 0x6B, 0x7F, 0x5D, 0x1B, 0xDD, 0xA8, 0x9B, 0xBB, 0xD9, 0xE5, 0xD8, 0xDA,
+ 0xEC, 0x08, 0x29, 0x41, 0x2C, 0x08, 0xE9, 0xDB, 0xF9, 0x22, 0x37, 0x41, 0x32, 0x1A, 0x22, 0x3C,
+ 0x5F, 0x4E, 0x18, 0xDE, 0xA1, 0x84, 0x86, 0xA4, 0xC8, 0xE9, 0xF6, 0xFF, 0x0E, 0x21, 0x42, 0x4E,
+ 0x35, 0xFF, 0xC1, 0xC0, 0xED, 0x20, 0x55, 0x67, 0x3E, 0x14, 0xED, 0xD9, 0xCC, 0xC2, 0xB5, 0xA9,
+ 0x94, 0x9C, 0xBA, 0xE7, 0x20, 0x2B, 0x13, 0xF6, 0xDC, 0xF1, 0x32, 0x57, 0x5F, 0x3F, 0x2C, 0x2A,
+ 0x2A, 0x2A, 0x1F, 0xF7, 0xDE, 0xD8, 0xCD, 0xDC, 0xEF, 0xF7, 0xFB, 0xE1, 0xBC, 0xB7, 0xD7, 0x15,
+ 0x31, 0x26, 0x0B, 0xEE, 0xF8, 0x35, 0x5F, 0x64, 0x53, 0x33, 0x15, 0x03, 0xF6, 0xF1, 0xE7, 0xD3,
+ 0xB8, 0x8E, 0x89, 0xA8, 0xDE, 0x26, 0x40, 0x1A, 0xED, 0xCC, 0xC6, 0xD9, 0xEE, 0xFB, 0x01, 0x0B,
+ 0x2E, 0x4A, 0x58, 0x6C, 0x53, 0x27, 0xF5, 0xBC, 0xA0, 0xAF, 0xC2, 0xD6, 0xDC, 0xEC, 0x05, 0x1D,
+ 0x3D, 0x42, 0x20, 0x0B, 0xFD, 0xEF, 0xFE, 0x12, 0x1F, 0x22, 0x0F, 0xFB, 0x05, 0x23, 0x4F, 0x55,
+ 0x31, 0xF6, 0xAF, 0x8C, 0x9B, 0xB1, 0xD0, 0xF2, 0xFF, 0x01, 0x03, 0x1E, 0x4A, 0x66, 0x60, 0x2E,
+ 0xD5, 0xAB, 0xAE, 0xD9, 0x1F, 0x38, 0x1E, 0x07, 0xF3, 0xE6, 0xDD, 0xD4, 0xCE, 0xBC, 0xAD, 0xAC,
+ 0xAD, 0xC4, 0x02, 0x26, 0x2E, 0x25, 0x0B, 0x13, 0x38, 0x49, 0x41, 0x25, 0x17, 0x1B, 0x23, 0x2B,
+ 0x15, 0xE7, 0xDE, 0xEB, 0xEB, 0xF7, 0xFE, 0x01, 0x04, 0xE6, 0xC4, 0xBD, 0xD6, 0x16, 0x36, 0x31,
+ 0x12, 0xE6, 0xF1, 0x34, 0x5C, 0x55, 0x3A, 0x0F, 0xEF, 0xE1, 0xE6, 0xF8, 0x03, 0x01, 0xEB, 0xB7,
+ 0xA2, 0xAB, 0xD9, 0x2A, 0x4A, 0x24, 0xF5, 0xDB, 0xD8, 0xE2, 0xEC, 0xF2, 0xE3, 0xE2, 0xFA, 0x09,
+ 0x15, 0x2F, 0x36, 0x31, 0x19, 0xE5, 0xC7, 0xC3, 0xCA, 0xD2, 0xD8, 0xEB, 0x08, 0x29, 0x55, 0x5F,
+ 0x3A, 0x23, 0x1B, 0x0B, 0x0B, 0x0A, 0x04, 0xF8, 0xDC, 0xCF, 0xDF, 0x08, 0x3C, 0x47, 0x2F, 0x00,
+ 0xBA, 0xA5, 0xC7, 0xDE, 0xE0, 0xE3, 0xDE, 0xE0, 0xEF, 0x1B, 0x56, 0x77, 0x76, 0x48, 0xFA, 0xCB,
+ 0xBD, 0xD0, 0x02, 0x0D, 0xF0, 0xE0, 0xE9, 0xFB, 0x04, 0x01, 0xFE, 0xE6, 0xD3, 0xCD, 0xB8, 0xB3,
+ 0xD3, 0xF0, 0x0A, 0x13, 0x03, 0x13, 0x3B, 0x50, 0x3F, 0x1C, 0x08, 0x08, 0x12, 0x23, 0x0B, 0xD5,
+ 0xCF, 0xF1, 0x0A, 0x1F, 0x23, 0x1B, 0x10, 0xEE, 0xCD, 0xC3, 0xDB, 0x0C, 0x29, 0x27, 0x0A, 0xD6,
+ 0xDB, 0x25, 0x51, 0x4D, 0x32, 0x0A, 0xEE, 0xE6, 0xF4, 0x07, 0x0A, 0x04, 0xEF, 0xC7, 0xB0, 0xAE,
+ 0xCB, 0x13, 0x39, 0x22, 0x05, 0xF8, 0xF7, 0xFB, 0xFA, 0xEF, 0xD5, 0xD0, 0xF3, 0x08, 0x14, 0x2B,
+ 0x33, 0x30, 0x24, 0xFC, 0xE0, 0xD5, 0xCA, 0xBD, 0xB8, 0xC9, 0xE9, 0x15, 0x4D, 0x5B, 0x30, 0x1A,
+ 0x1A, 0x17, 0x1A, 0x18, 0x07, 0xF2, 0xD6, 0xCF, 0xEB, 0x18, 0x44, 0x50, 0x40, 0x1A, 0xD6, 0xB8,
+ 0xD0, 0xD8, 0xCC, 0xC9, 0xC8, 0xD1, 0xE6, 0x10, 0x47, 0x67, 0x71, 0x4F, 0x09, 0xD3, 0xBA, 0xBF,
+ 0xEC, 0x04, 0xF2, 0xEA, 0xFB, 0x0A, 0x0E, 0x05, 0xF7, 0xDC, 0xCB, 0xCB, 0xBA, 0xB4, 0xD5, 0xFB,
+ 0x1C, 0x29, 0x1C, 0x20, 0x3B, 0x48, 0x31, 0x13, 0x01, 0x02, 0x14, 0x2F, 0x22, 0xE9, 0xD4, 0xE6,
+ 0xF5, 0x01, 0x07, 0x06, 0x00, 0xED, 0xD6, 0xCE, 0xE6, 0x12, 0x2F, 0x31, 0x15, 0xDF, 0xD9, 0x16,
+ 0x42, 0x3F, 0x2A, 0x0E, 0xF8, 0xED, 0xF5, 0xFF, 0x01, 0x04, 0xF0, 0xC7, 0xA8, 0xA1, 0xC0, 0x09,
+ 0x37, 0x29, 0x0B, 0x01, 0xFD, 0xFE, 0xFF, 0xF4, 0xD9, 0xD1, 0xE9, 0xFA, 0x07, 0x21, 0x31, 0x34,
+ 0x29, 0x07, 0xE9, 0xDF, 0xD5, 0xC2, 0xB9, 0xC6, 0xE2, 0x0D, 0x47, 0x5B, 0x3C, 0x28, 0x28, 0x1E,
+ 0x0F, 0x05, 0xFA, 0xEF, 0xE2, 0xD7, 0xE2, 0x0D, 0x3A, 0x51, 0x4B, 0x24, 0xE0, 0xC0, 0xD6, 0xE0,
+ 0xCE, 0xC2, 0xC8, 0xDB, 0xF5, 0x19, 0x39, 0x51, 0x60, 0x48, 0x14, 0xDE, 0xBA, 0xBE, 0xE8, 0x01,
+ 0xEF, 0xE3, 0xF7, 0x0E, 0x17, 0x16, 0x06, 0xE8, 0xD8, 0xD1, 0xBA, 0xAC, 0xBC, 0xE7, 0x12, 0x29,
+ 0x24, 0x1D, 0x31, 0x3F, 0x2C, 0x11, 0xFF, 0xF5, 0xFC, 0x15, 0x14, 0xF2, 0xEF, 0x0B, 0x1A, 0x14,
+ 0x03, 0xFB, 0xFB, 0xFC, 0xED, 0xDD, 0xE7, 0xFE, 0x18, 0x28, 0x1D, 0xF6, 0xE3, 0x0D, 0x2E, 0x28,
+ 0x18, 0x0E, 0x02, 0xFC, 0xFE, 0xFF, 0xFC, 0x01, 0xEE, 0xD0, 0xB3, 0xA8, 0xBF, 0xFC, 0x27, 0x1D,
+ 0xFF, 0xF3, 0xF1, 0xEA, 0xF0, 0xF6, 0xEB, 0xE8, 0xF2, 0xF3, 0xFD, 0x12, 0x30, 0x40, 0x39, 0x19,
+ 0xF4, 0xE3, 0xDD, 0xCC, 0xC8, 0xDD, 0xEE, 0x0A, 0x2E, 0x3C, 0x28, 0x20, 0x26, 0x26, 0x11, 0xFA,
+ 0xF1, 0xEB, 0xEA, 0xEA, 0xF3, 0x19, 0x3A, 0x46, 0x45, 0x23, 0xEC, 0xCC, 0xD6, 0xDE, 0xD1, 0xC6,
+ 0xD6, 0xE7, 0xF8, 0x10, 0x21, 0x32, 0x46, 0x37, 0x14, 0xE8, 0xC5, 0xC2, 0xE3, 0x01, 0xFD, 0xF5,
+ 0xFD, 0x0A, 0x04, 0x02, 0xFE, 0xEC, 0xE2, 0xDD, 0xC2, 0xB2, 0xBA, 0xE2, 0x0F, 0x23, 0x20, 0x13,
+ 0x18, 0x2B, 0x29, 0x1E, 0x18, 0x08, 0x02, 0x0D, 0x0A, 0xF6, 0xFC, 0x13, 0x27, 0x17, 0xFF, 0xF3,
+ 0xEF, 0xF8, 0xF8, 0xE5, 0xE4, 0xF0, 0xFF, 0x15, 0x13, 0xFB, 0xF1, 0x09, 0x24, 0x28, 0x19, 0x17,
+ 0x0E, 0x01, 0xFD, 0xF6, 0xF5, 0x06, 0x00, 0xEC, 0xD1, 0xBC, 0xCC, 0xF9, 0x1E, 0x1C, 0xFF, 0xEB,
+ 0xE6, 0xDE, 0xE9, 0xF3, 0xF1, 0xF0, 0xF5, 0xED, 0xF1, 0x03, 0x27, 0x40, 0x37, 0x16, 0xEE, 0xDE,
+ 0xE1, 0xDE, 0xD6, 0xDC, 0xE5, 0xFA, 0x1F, 0x30, 0x2A, 0x2B, 0x2F, 0x30, 0x15, 0xF6, 0xEB, 0xEB,
+ 0xF5, 0xFF, 0xFD, 0x10, 0x2C, 0x3E, 0x43, 0x2A, 0xFA, 0xDA, 0xD8, 0xDD, 0xD1, 0xC1, 0xCD, 0xE1,
+ 0xF6, 0x12, 0x1F, 0x29, 0x39, 0x32, 0x18, 0xEF, 0xCB, 0xC8, 0xE0, 0xF8, 0xFA, 0xF3, 0xFF, 0x19,
+ 0x1F, 0x1C, 0x10, 0xF3, 0xE2, 0xD9, 0xBC, 0xA2, 0x9D, 0xBF, 0xF6, 0x1A, 0x29, 0x25, 0x20, 0x26,
+ 0x24, 0x16, 0x0C, 0xFE, 0xFA, 0x07, 0x0A, 0x01, 0x0C, 0x25, 0x3F, 0x38, 0x1B, 0x02, 0xEA, 0xE6,
+ 0xEA, 0xE2, 0xE1, 0xED, 0xFD, 0x12, 0x13, 0x04, 0xFE, 0x0A, 0x19, 0x18, 0x05, 0x00, 0xFF, 0xFA,
+ 0x01, 0xFD, 0xF7, 0x04, 0x0A, 0xFF, 0xE6, 0xCA, 0xCE, 0xE4, 0xFE, 0x09, 0x00, 0xFB, 0x02, 0xFE,
+ 0xFC, 0xFE, 0xF1, 0xF5, 0xFB, 0xEF, 0xE4, 0xE5, 0x02, 0x27, 0x32, 0x2C, 0x12, 0xF7, 0xEB, 0xE0,
+ 0xD1, 0xD3, 0xD9, 0xED, 0x0E, 0x1B, 0x1A, 0x21, 0x32, 0x44, 0x38, 0x14, 0xF7, 0xDD, 0xDE, 0xF1,
+ 0xFD, 0x11, 0x2A, 0x37, 0x3B, 0x23, 0xFF, 0xEF, 0xEF, 0xED, 0xD6, 0xB4, 0xAD, 0xC6, 0xE6, 0x12,
+ 0x20, 0x1E, 0x2A, 0x32, 0x2B, 0x0C, 0xE3, 0xD6, 0xD8, 0xE2, 0xEF, 0xF2, 0xFE, 0x18, 0x20, 0x1A,
+ 0x0A, 0xF0, 0xEB, 0xEC, 0xD7, 0xB8, 0xA4, 0xB3, 0xE6, 0x12, 0x30, 0x33, 0x21, 0x1D, 0x19, 0x10,
+ 0x14, 0x13, 0x0D, 0x0C, 0xFB, 0xEF, 0xF4, 0x0C, 0x2D, 0x31, 0x15, 0xFF, 0xE9, 0xED, 0xFE, 0xFD,
+ 0xF7, 0xF3, 0xF2, 0xFD, 0x01, 0x00, 0x0A, 0x16, 0x24, 0x25, 0x12, 0x0B, 0x06, 0xFA, 0xF9, 0xE9,
+ 0xE1, 0xEF, 0xFE, 0x00, 0xF2, 0xDC, 0xE0, 0xEB, 0xF5, 0xFB, 0xF3, 0xF0, 0xFF, 0xFB, 0xF7, 0xF8,
+ 0xF3, 0x03, 0x0C, 0xFE, 0xEF, 0xE8, 0xF8, 0x1C, 0x23, 0x21, 0x10, 0xFA, 0xF3, 0xE6, 0xCE, 0xD1,
+ 0xE1, 0xFF, 0x1C, 0x1A, 0x0F, 0x0B, 0x19, 0x34, 0x36, 0x17, 0xFD, 0xE1, 0xE2, 0xF8, 0x05, 0x14,
+ 0x2B, 0x33, 0x30, 0x14, 0xF7, 0xF3, 0xF9, 0x01, 0xF2, 0xC9, 0xB8, 0xC6, 0xE0, 0x07, 0x11, 0x0C,
+ 0x14, 0x23, 0x26, 0x18, 0xF9, 0xE8, 0xE0, 0xD9, 0xDA, 0xDB, 0xEE, 0x12, 0x21, 0x1A, 0x0C, 0xFB,
+ 0xFE, 0x03, 0xF2, 0xD0, 0xAD, 0xAA, 0xD1, 0xFB, 0x20, 0x2E, 0x22, 0x1B, 0x15, 0x08, 0x07, 0x0D,
+ 0x10, 0x14, 0x02, 0xF5, 0xF5, 0x09, 0x28, 0x32, 0x1C, 0x08, 0xF4, 0xF7, 0x08, 0x08, 0xFA, 0xF6,
+ 0xF2, 0xF3, 0xF1, 0xED, 0xFC, 0x08, 0x18, 0x1E, 0x0B, 0xFF, 0x00, 0x01, 0x04, 0xF7, 0xEA, 0xEC,
+ 0xFB, 0x00, 0xF8, 0xEF, 0xF0, 0xF7, 0xF7, 0xF7, 0xEB, 0xEC, 0xFF, 0x0B, 0x04, 0xF8, 0xE9, 0xEE,
+ 0xF7, 0xF7, 0xEE, 0xEB, 0xF7, 0x10, 0x1D, 0x22, 0x1E, 0x0E, 0x04, 0xF8, 0xDE, 0xD0, 0xE0, 0xFF,
+ 0x1D, 0x20, 0x17, 0x10, 0x14, 0x28, 0x2F, 0x18, 0xF8, 0xDD, 0xDA, 0xF3, 0x08, 0x0F, 0x1F, 0x26,
+ 0x1C, 0x07, 0xF6, 0xF8, 0x02, 0x0B, 0x02, 0xDE, 0xC2, 0xC9, 0xE6, 0x08, 0x10, 0x02, 0xFE, 0x0D,
+ 0x18, 0x17, 0x06, 0xF1, 0xE2, 0xD6, 0xDB, 0xE2, 0xEB, 0x09, 0x25, 0x27, 0x1A, 0x09, 0x03, 0x05,
+ 0xF9, 0xDD, 0xC1, 0xB7, 0xCC, 0xF1, 0x15, 0x25, 0x15, 0x06, 0x05, 0x00, 0xFB, 0x02, 0x07, 0x07,
+ 0xFC, 0xF7, 0xFF, 0x0F, 0x24, 0x34, 0x2C, 0x15, 0x04, 0x03, 0x13, 0x17, 0x01, 0xF1, 0xEC, 0xEA,
+ 0xED, 0xF5, 0x05, 0x0C, 0x12, 0x17, 0x0F, 0xFB, 0xF2, 0xF1, 0xF3, 0xEE, 0xE8, 0xEF, 0x05, 0x10,
+ 0x0A, 0x02, 0xFA, 0xF4, 0xEC, 0xED, 0xE9, 0xE3, 0xEC, 0x01, 0x0B, 0x08, 0x01, 0xFB, 0xF5, 0xED,
+ 0xE5, 0xEA, 0xF8, 0x07, 0x16, 0x1B, 0x1B, 0x0E, 0x05, 0x02, 0xED, 0xD5, 0xD6, 0xEF, 0x0D, 0x1A,
+ 0x1E, 0x1A, 0x15, 0x17, 0x1D, 0x18, 0x04, 0xF1, 0xEC, 0xFA, 0x0B, 0x0B, 0x15, 0x23, 0x1C, 0x08,
+ 0xF8, 0xF6, 0x00, 0x0A, 0x09, 0xF6, 0xD6, 0xCA, 0xDF, 0xFC, 0x09, 0x04, 0xFB, 0x06, 0x10, 0x10,
+ 0x0D, 0x02, 0xEE, 0xDB, 0xD5, 0xD7, 0xDE, 0xF6, 0x19, 0x2D, 0x24, 0x12, 0x03, 0xFB, 0xF4, 0xDF,
+ 0xCB, 0xC3, 0xCA, 0xE9, 0x0C, 0x21, 0x1E, 0x11, 0x10, 0x0B, 0xFE, 0xF9, 0xFF, 0xFF, 0xFB, 0xFF,
+ 0x06, 0x13, 0x1C, 0x25, 0x2A, 0x1B, 0x0D, 0x09, 0x15, 0x1B, 0x0A, 0xF9, 0xF3, 0xEE, 0xE9, 0xF0,
+ 0xFC, 0x03, 0x07, 0x0C, 0x0D, 0x04, 0xF3, 0xF4, 0xF6, 0xEF, 0xE6, 0xE2, 0xF3, 0x03, 0x06, 0x0D,
+ 0x11, 0x0B, 0x00, 0xF6, 0xEE, 0xE9, 0xEB, 0xFB, 0x09, 0x03, 0xFA, 0xF2, 0xEA, 0xE9, 0xE7, 0xEF,
+ 0xFD, 0xFF, 0x01, 0x03, 0x06, 0x08, 0x07, 0x06, 0xFB, 0xE6, 0xDF, 0xF2, 0x07, 0x17, 0x20, 0x1D,
+ 0x1B, 0x16, 0x10, 0x0D, 0xFC, 0xEC, 0xED, 0xF9, 0x08, 0x0D, 0x0D, 0x17, 0x18, 0x0E, 0x0B, 0x0E,
+ 0x12, 0x10, 0x04, 0xF3, 0xE0, 0xD5, 0xE7, 0xFE, 0x08, 0x04, 0xF6, 0xF5, 0xFE, 0x01, 0x03, 0x01,
+ 0xEF, 0xD9, 0xCE, 0xD1, 0xE7, 0x01, 0x1F, 0x33, 0x2B, 0x16, 0x03, 0xF5, 0xF4, 0xEA, 0xE0, 0xDE,
+ 0xDD, 0xEC, 0xFE, 0x0D, 0x11, 0x0A, 0x04, 0x03, 0xFB, 0xEE, 0xED, 0xF0, 0xFC, 0x0C, 0x17, 0x1F,
+ 0x20, 0x1A, 0x1F, 0x19, 0x11, 0x0D, 0x10, 0x17, 0x11, 0xFE, 0xF6, 0xF4, 0xF2, 0xF6, 0xFF, 0xFE,
+ 0xF9, 0xF5, 0xF9, 0xFF, 0xF5, 0xF4, 0xFA, 0xFC, 0xFE, 0xFB, 0xFF, 0x0B, 0x0C, 0x0A, 0x0B, 0x02,
+ 0xF5, 0xEC, 0xEB, 0xED, 0xEF, 0xF7, 0x0A, 0x0A, 0xFC, 0xEA, 0xDB, 0xDC, 0xE6, 0xF3, 0x04, 0x08,
+ 0x07, 0x0B, 0x10, 0x13, 0x11, 0x09, 0x03, 0xF4, 0xE1, 0xE3, 0xF0, 0x07, 0x1E, 0x25, 0x1F, 0x0D,
+ 0xFB, 0xFC, 0xFA, 0xF3, 0xF6, 0xFC, 0x0A, 0x10, 0x10, 0x10, 0x15, 0x13, 0x15, 0x13, 0x0E, 0x02,
+ 0xF7, 0xF3, 0xF0, 0xE3, 0xE9, 0xFA, 0x04, 0x02, 0xF5, 0xEF, 0xF5, 0xFF, 0x08, 0x0B, 0xFD, 0xEA,
+ 0xE1, 0xE2, 0xED, 0xF9, 0x09, 0x23, 0x24, 0x13, 0xFC, 0xE9, 0xE5, 0xE9, 0xEC, 0xEE, 0xE8, 0xE8,
+ 0xF1, 0xFA, 0x00, 0x00, 0x01, 0x08, 0x0B, 0xFB, 0xF3, 0xF1, 0xFE, 0x15, 0x24, 0x27, 0x1B, 0x0B,
+ 0x09, 0x06, 0x05, 0x0C, 0x14, 0x18, 0x0F, 0xFA, 0xE9, 0xEA, 0xF3, 0x01, 0x05, 0xFF, 0xF7, 0xF7,
+ 0x05, 0x0E, 0x05, 0x00, 0x03, 0x03, 0xFE, 0xF3, 0xED, 0xF2, 0x01, 0x0B, 0x11, 0x07, 0xF7, 0xEB,
+ 0xE5, 0xE4, 0xE3, 0xEA, 0x03, 0x11, 0x07, 0xF1, 0xE0, 0xE0, 0xF4, 0x0B, 0x15, 0x0D, 0x01, 0xFD,
+ 0x01, 0x06, 0x09, 0x09, 0x09, 0x04, 0xF1, 0xE5, 0xE9, 0xFC, 0x11, 0x19, 0x11, 0xFF, 0xF7, 0x00,
+ 0x04, 0x02, 0x01, 0x09, 0x17, 0x1F, 0x1B, 0x0A, 0x03, 0x01, 0x07, 0x0A, 0x09, 0x05, 0x01, 0xFF,
+ 0xF9, 0xE7, 0xE5, 0xF5, 0x01, 0xFD, 0xEF, 0xE3, 0xE5, 0xFD, 0x13, 0x19, 0x0B, 0xF7, 0xEA, 0xE9,
+ 0xF1, 0xF9, 0x01, 0x15, 0x1E, 0x0F, 0xF9, 0xE9, 0xE8, 0xF3, 0xFB, 0xF4, 0xE8, 0xE5, 0xEE, 0xF8,
+ 0xFE, 0xFF, 0xFF, 0x06, 0x0D, 0x04, 0xF7, 0xF8, 0x09, 0x1F, 0x29, 0x23, 0x12, 0x09, 0x09, 0x07,
+ 0xFD, 0xFD, 0x06, 0x10, 0x14, 0x03, 0xE9, 0xE2, 0xEE, 0x00, 0x09, 0x04, 0xFF, 0x00, 0x09, 0x0F,
+ 0x01, 0xF7, 0xFF, 0x06, 0x05, 0xF9, 0xEB, 0xEC, 0x03, 0x13, 0x13, 0x04, 0xF1, 0xE5, 0xDD, 0xDD,
+ 0xDD, 0xE7, 0x03, 0x1A, 0x11, 0xF7, 0xE1, 0xE5, 0xFD, 0x15, 0x13, 0x01, 0xF5, 0xF6, 0xFD, 0x05,
+ 0x0A, 0x08, 0x08, 0x09, 0xF9, 0xE7, 0xEA, 0x01, 0x1A, 0x23, 0x16, 0xFE, 0xF6, 0x00, 0x07, 0x04,
+ 0x04, 0x0E, 0x1C, 0x27, 0x22, 0x06, 0xF7, 0xF9, 0xFE, 0x02, 0x00, 0xFC, 0xFA, 0xFF, 0xFE, 0xF2,
+ 0xEB, 0xF9, 0x06, 0x03, 0xF3, 0xE1, 0xDD, 0xF8, 0x12, 0x16, 0x0B, 0xFC, 0xEF, 0xE9, 0xEF, 0xF4,
+ 0xFD, 0x10, 0x1B, 0x0B, 0xE9, 0xD6, 0xD5, 0xE8, 0xFD, 0xFA, 0xF2, 0xF1, 0xFC, 0x04, 0x09, 0x0B,
+ 0x05, 0x06, 0x0B, 0x01, 0xED, 0xEE, 0x0B, 0x23, 0x30, 0x27, 0x11, 0x05, 0x04, 0x00, 0xF8, 0xF4,
+ 0xFE, 0x0C, 0x15, 0x0F, 0xF5, 0xED, 0xFD, 0x0A, 0x0B, 0x04, 0x01, 0x01, 0x0B, 0x0E, 0xFE, 0xEF,
+ 0xF4, 0x03, 0x07, 0xFE, 0xE8, 0xE1, 0xF8, 0x0F, 0x11, 0x05, 0xF4, 0xE5, 0xDC, 0xDF, 0xE1, 0xEA,
+ 0x04, 0x1D, 0x18, 0xFC, 0xE7, 0xE6, 0xFC, 0x12, 0x0B, 0xFA, 0xEE, 0xF0, 0xFA, 0x03, 0x09, 0x03,
+ 0x01, 0x06, 0xFD, 0xE9, 0xEB, 0x05, 0x1D, 0x23, 0x16, 0xFC, 0xF2, 0xF9, 0x07, 0x0D, 0x0D, 0x12,
+ 0x1B, 0x27, 0x27, 0x0B, 0xF7, 0xF9, 0xF8, 0xF7, 0xF3, 0xF6, 0xF7, 0x01, 0x03, 0xFB, 0xF3, 0xFD,
+ 0x0B, 0x0A, 0xF8, 0xDF, 0xD4, 0xEE, 0x0C, 0x13, 0x11, 0x07, 0xF9, 0xF1, 0xF3, 0xF7, 0xFF, 0x0D,
+ 0x1B, 0x06, 0xE1, 0xCD, 0xCF, 0xE6, 0x00, 0x01, 0xF5, 0xF3, 0xFA, 0x03, 0x05, 0x05, 0xFD, 0xF9,
+ 0x01, 0xFD, 0xEA, 0xF3, 0x12, 0x2C, 0x35, 0x28, 0x10, 0x04, 0x03, 0x06, 0xFF, 0xF7, 0xFA, 0x06,
+ 0x15, 0x15, 0xFD, 0xEE, 0xFF, 0x09, 0x06, 0x00, 0xFC, 0xFE, 0x08, 0x09, 0xFB, 0xEE, 0xF3, 0x05,
+ 0x0A, 0x01, 0xEC, 0xE5, 0xFD, 0x13, 0x10, 0x02, 0xF3, 0xE9, 0xE2, 0xE2, 0xE0, 0xE5, 0xFD, 0x1C,
+ 0x1C, 0xFE, 0xE8, 0xE6, 0xFC, 0x14, 0x11, 0xFD, 0xF4, 0xF3, 0xF9, 0xFB, 0xFD, 0xF8, 0xF9, 0x04,
+ 0x02, 0xEA, 0xEC, 0x07, 0x1E, 0x25, 0x16, 0xF8, 0xEB, 0xF3, 0x00, 0x0A, 0x11, 0x1E, 0x28, 0x33,
+ 0x2E, 0x0F, 0xF8, 0xFE, 0x01, 0xF7, 0xEE, 0xEB, 0xF2, 0x03, 0x09, 0x01, 0xF3, 0xF3, 0xFC, 0xFA,
+ 0xEF, 0xDC, 0xD5, 0xED, 0x0C, 0x10, 0x0D, 0x0A, 0x08, 0x02, 0xFC, 0xF6, 0xF4, 0x03, 0x1B, 0x15,
+ 0xF0, 0xD7, 0xCE, 0xE2, 0xFE, 0x03, 0xF7, 0xF5, 0xF3, 0xF5, 0xF6, 0xFE, 0x03, 0x08, 0x10, 0x03,
+ 0xE5, 0xE5, 0x06, 0x27, 0x37, 0x2B, 0x0C, 0xFE, 0xFE, 0x04, 0x09, 0x06, 0x07, 0x08, 0x0B, 0x08,
+ 0xF4, 0xEB, 0x04, 0x15, 0x0D, 0x01, 0xF9, 0x02, 0x11, 0x14, 0x04, 0xF0, 0xED, 0xFF, 0x07, 0x03,
+ 0xEE, 0xE2, 0xF6, 0x11, 0x0D, 0x01, 0xF7, 0xED, 0xE1, 0xD8, 0xD5, 0xDD, 0xF9, 0x1C, 0x1F, 0x00,
+ 0xE7, 0xE1, 0xF9, 0x1B, 0x1E, 0x0B, 0xFC, 0xF4, 0xF0, 0xF1, 0xFA, 0x01, 0x0A, 0x10, 0x06, 0xE5,
+ 0xDB, 0xF6, 0x14, 0x24, 0x17, 0xF8, 0xE8, 0xED, 0xFD, 0x0D, 0x16, 0x1F, 0x23, 0x26, 0x23, 0x0A,
+ 0xF7, 0x03, 0x0C, 0xFF, 0xF2, 0xEC, 0xF3, 0x04, 0x10, 0x0B, 0xFD, 0xF7, 0xFE, 0x00, 0xF9, 0xE8,
+ 0xDA, 0xEA, 0x03, 0x07, 0x04, 0x0B, 0x0D, 0x08, 0xFB, 0xEE, 0xE9, 0xF8, 0x10, 0x11, 0xED, 0xD3,
+ 0xC9, 0xE0, 0x04, 0x13, 0x0C, 0x03, 0xF8, 0xEC, 0xE7, 0xEE, 0xFC, 0x08, 0x12, 0x09, 0xEA, 0xE2,
+ 0x02, 0x27, 0x3C, 0x31, 0x11, 0xF9, 0xF2, 0xF8, 0x01, 0x07, 0x10, 0x11, 0x10, 0x09, 0xF7, 0xEF,
+ 0x05, 0x15, 0x09, 0xFA, 0xF2, 0xF9, 0x07, 0x0F, 0x07, 0xF6, 0xF1, 0x01, 0x0C, 0x0F, 0xFD, 0xEC,
+ 0xF3, 0x07, 0x0A, 0x03, 0x01, 0xFB, 0xF2, 0xE5, 0xDD, 0xDE, 0xF3, 0x14, 0x1B, 0xFE, 0xE2, 0xD4,
+ 0xE6, 0x07, 0x17, 0x0E, 0x00, 0xF2, 0xE8, 0xE6, 0xEF, 0x01, 0x11, 0x1B, 0x14, 0xF3, 0xE3, 0xF7,
+ 0x10, 0x21, 0x1A, 0xFD, 0xE6, 0xE4, 0xF4, 0x09, 0x19, 0x25, 0x28, 0x26, 0x1C, 0x02, 0xF2, 0xFF,
+ 0x0D, 0x08, 0xFC, 0xF1, 0xF4, 0x05, 0x15, 0x15, 0x04, 0xF6, 0xF7, 0xF7, 0xF6, 0xE9, 0xDE, 0xE3,
+ 0xF6, 0xFC, 0xFB, 0x03, 0x0A, 0x0D, 0x05, 0xF9, 0xF1, 0xFA, 0x13, 0x18, 0xFC, 0xDF, 0xCD, 0xD4,
+ 0xF4, 0x0F, 0x13, 0x0B, 0xFB, 0xEA, 0xE2, 0xE4, 0xF4, 0x02, 0x0D, 0x05, 0xE6, 0xDB, 0xF6, 0x1E,
+ 0x3D, 0x40, 0x26, 0x08, 0xF7, 0xFA, 0x04, 0x0D, 0x11, 0x0E, 0x08, 0x01, 0xF5, 0xF2, 0x07, 0x1A,
+ 0x14, 0x02, 0xF0, 0xEE, 0xF9, 0x07, 0x04, 0xF5, 0xEE, 0xF7, 0x06, 0x12, 0x0E, 0xFE, 0xFB, 0x02,
+ 0x04, 0xFD, 0xFB, 0xFA, 0xF3, 0xE9, 0xE2, 0xDE, 0xEF, 0x0D, 0x19, 0x08, 0xEE, 0xDB, 0xE2, 0xFE,
+ 0x11, 0x13, 0x05, 0xF6, 0xE9, 0xE5, 0xEC, 0xFD, 0x0E, 0x1A, 0x16, 0xF9, 0xE5, 0xEE, 0x02, 0x17,
+ 0x13, 0xFF, 0xE9, 0xE2, 0xF1, 0x06, 0x19, 0x27, 0x2A, 0x25, 0x1E, 0x0A, 0xFC, 0x04, 0x11, 0x0D,
+ 0xFD, 0xEF, 0xF1, 0xFE, 0x10, 0x18, 0x0B, 0xFD, 0xF6, 0xF5, 0xF6, 0xEE, 0xE0, 0xDE, 0xE7, 0xEF,
+ 0xF5, 0x02, 0x12, 0x19, 0x13, 0x09, 0xFB, 0xF8, 0x08, 0x0B, 0xF7, 0xDB, 0xCB, 0xD4, 0xF2, 0x11,
+ 0x1E, 0x19, 0x0A, 0xF1, 0xE2, 0xDE, 0xE7, 0xF2, 0xFE, 0xFD, 0xEA, 0xE2, 0xF6, 0x1C, 0x37, 0x39,
+ 0x24, 0x07, 0xF3, 0xF2, 0xF8, 0x05, 0x0D, 0x0C, 0x0B, 0x0E, 0x06, 0x01, 0x0C, 0x1C, 0x18, 0x06,
+ 0xF6, 0xF2, 0xF5, 0xFB, 0xFE, 0xF4, 0xF1, 0xF9, 0x09, 0x14, 0x13, 0x03, 0xFE, 0xFE, 0xFD, 0xF4,
+ 0xF1, 0xF1, 0xF2, 0xEB, 0xE7, 0xE6, 0xEF, 0x05, 0x15, 0x0E, 0xF8, 0xE3, 0xE3, 0xF2, 0x02, 0x09,
+ 0x05, 0xFF, 0xF2, 0xE9, 0xE9, 0xF4, 0x04, 0x13, 0x19, 0x07, 0xF3, 0xEF, 0xFF, 0x10, 0x12, 0x03,
+ 0xF0, 0xE3, 0xE8, 0xF8, 0x11, 0x27, 0x30, 0x2E, 0x26, 0x12, 0x00, 0x00, 0x09, 0x09, 0xFB, 0xEC,
+ 0xEB, 0xF9, 0x0C, 0x1B, 0x17, 0x0A, 0xFC, 0xF5, 0xF3, 0xEF, 0xE4, 0xDF, 0xE2, 0xE7, 0xEC, 0xFD,
+ 0x14, 0x22, 0x1F, 0x10, 0x00, 0xF6, 0xFC, 0x01, 0xF7, 0xDE, 0xCB, 0xCC, 0xE5, 0x04, 0x17, 0x1B,
+ 0x13, 0xFF, 0xE9, 0xE0, 0xE2, 0xEA, 0xF4, 0xF7, 0xEE, 0xE7, 0xF5, 0x17, 0x37, 0x40, 0x2F, 0x15,
+ 0xFC, 0xF4, 0xF6, 0x00, 0x06, 0x09, 0x05, 0x06, 0x06, 0x06, 0x10, 0x1C, 0x1E, 0x0E, 0xF9, 0xF0,
+ 0xF1, 0xF9, 0x01, 0xFE, 0xFA, 0xF9, 0x00, 0x0A, 0x10, 0x08, 0x01, 0xFE, 0xFA, 0xF0, 0xEB, 0xED,
+ 0xF2, 0xF2, 0xED, 0xE9, 0xE9, 0xFD, 0x0E, 0x13, 0x06, 0xF3, 0xEA, 0xF2, 0xFE, 0x05, 0x01, 0xFB,
+ 0xF1, 0xEA, 0xE9, 0xF2, 0xFD, 0x0B, 0x13, 0x0B, 0xFA, 0xEE, 0xF2, 0x03, 0x0C, 0x07, 0xF8, 0xE9,
+ 0xED, 0xFD, 0x18, 0x2A, 0x30, 0x2B, 0x22, 0x16, 0x09, 0x07, 0x0A, 0x0A, 0xFF, 0xEF, 0xEA, 0xF6,
+ 0x0A, 0x1C, 0x1A, 0x0B, 0xFB, 0xF3, 0xF3, 0xF7, 0xEE, 0xE4, 0xDF, 0xE3, 0xEB, 0xFA, 0x0D, 0x1D,
+ 0x1E, 0x14, 0x03, 0xF5, 0xF2, 0xF7, 0xFA, 0xEB, 0xD7, 0xD0, 0xDF, 0xFB, 0x14, 0x1B, 0x13, 0x02,
+ 0xF3, 0xE8, 0xE8, 0xED, 0xF1, 0xF2, 0xEE, 0xE9, 0xF0, 0x0A, 0x26, 0x32, 0x2A, 0x14, 0xFE, 0xF7,
+ 0xFD, 0x05, 0x07, 0x01, 0xFB, 0xFF, 0x08, 0x12, 0x1A, 0x22, 0x23, 0x17, 0x03, 0xF7, 0xF7, 0xFE,
+ 0x04, 0xFF, 0xF6, 0xF0, 0xF8, 0x06, 0x10, 0x0E, 0x05, 0xFD, 0xF9, 0xF5, 0xEC, 0xE9, 0xEB, 0xEE,
+ 0xEE, 0xED, 0xEF, 0xFA, 0x08, 0x12, 0x0D, 0xFD, 0xF0, 0xEF, 0xF8, 0xFE, 0xFA, 0xF3, 0xEB, 0xE9,
+ 0xEA, 0xF3, 0xFF, 0x06, 0x0D, 0x0A, 0x00, 0xF3, 0xF4, 0x02, 0x0C, 0x0A, 0xFB, 0xEE, 0xF1, 0x03,
+ 0x19, 0x28, 0x2A, 0x24, 0x19, 0x11, 0x09, 0x06, 0x03, 0x05, 0xFC, 0xED, 0xE7, 0xF4, 0x0B, 0x22,
+ 0x26, 0x17, 0x00, 0xF3, 0xF6, 0xFD, 0xFF, 0xF0, 0xE3, 0xDE, 0xE7, 0xF6, 0x0B, 0x1B, 0x20, 0x13,
+ 0xFF, 0xF0, 0xE8, 0xEB, 0xF1, 0xED, 0xDC, 0xD4, 0xDA, 0xF5, 0x10, 0x1F, 0x1B, 0x0D, 0xFA, 0xEE,
+ 0xEB, 0xEF, 0xF1, 0xF0, 0xEF, 0xF1, 0xF6, 0x09, 0x22, 0x2D, 0x29, 0x12, 0xFB, 0xF1, 0xF4, 0xFC,
+ 0x03, 0x00, 0xFE, 0xFD, 0x07, 0x17, 0x21, 0x24, 0x24, 0x15, 0xFD, 0xF1, 0xF1, 0xFB, 0x03, 0x02,
+ 0xF9, 0xF0, 0xF4, 0x04, 0x11, 0x17, 0x0B, 0xFA, 0xF0, 0xEC, 0xEA, 0xF1, 0xF9, 0xFD, 0xF9, 0xF1,
+ 0xEF, 0xF5, 0x02, 0x14, 0x12, 0xFD, 0xEB, 0xE3, 0xEC, 0xFB, 0x00, 0xFB, 0xF3, 0xE8, 0xE7, 0xEC,
+ 0xF8, 0x04, 0x08, 0x0B, 0x03, 0xF3, 0xF3, 0x02, 0x10, 0x13, 0x04, 0xF4, 0xF1, 0x00, 0x17, 0x28,
+ 0x28, 0x1F, 0x12, 0x0B, 0x0D, 0x0B, 0x08, 0x06, 0xF8, 0xE8, 0xE3, 0xEC, 0x07, 0x1F, 0x26, 0x19,
+ 0xFF, 0xF2, 0xF6, 0xFE, 0x04, 0xF8, 0xE4, 0xDC, 0xE0, 0xF1, 0x0B, 0x1D, 0x23, 0x17, 0x01, 0xF1,
+ 0xE7, 0xE8, 0xF3, 0xEF, 0xDF, 0xD3, 0xD5, 0xEF, 0x0F, 0x21, 0x1F, 0x0D, 0xF7, 0xEC, 0xEB, 0xF2,
+ 0xF6, 0xF1, 0xED, 0xEE, 0xF0, 0x01, 0x1B, 0x2A, 0x2B, 0x14, 0xFD, 0xF2, 0xF6, 0x00, 0x07, 0x00,
+ 0xFB, 0xF7, 0x02, 0x18, 0x28, 0x2D, 0x2A, 0x1A, 0x05, 0xF6, 0xF1, 0xFB, 0x01, 0xFF, 0xF3, 0xE7,
+ 0xEB, 0x01, 0x14, 0x1F, 0x19, 0x00, 0xEC, 0xE4, 0xE2, 0xEA, 0xF3, 0xF8, 0xF8, 0xF3, 0xF3, 0xFB,
+ 0x09, 0x1B, 0x1C, 0x07, 0xF1, 0xE0, 0xE2, 0xF2, 0xFA, 0xF8, 0xF1, 0xE8, 0xE7, 0xEE, 0xF9, 0x06,
+ 0x09, 0x09, 0x06, 0xF7, 0xF1, 0xFD, 0x08, 0x0F, 0x04, 0xF6, 0xF3, 0x03, 0x1A, 0x29, 0x26, 0x19,
+ 0x09, 0x03, 0x0A, 0x0F, 0x09, 0x04, 0xF8, 0xEB, 0xE8, 0xF2, 0x09, 0x1E, 0x25, 0x17, 0xFB, 0xEB,
+ 0xF2, 0x01, 0x0C, 0x05, 0xEB, 0xD8, 0xDA, 0xEC, 0x06, 0x1B, 0x1F, 0x13, 0xFF, 0xF1, 0xE7, 0xE7,
+ 0xF2, 0xF7, 0xE8, 0xDA, 0xD5, 0xE9, 0x0C, 0x23, 0x25, 0x15, 0xFC, 0xF1, 0xED, 0xF1, 0xF4, 0xE8,
+ 0xE4, 0xE9, 0xEF, 0xFB, 0x12, 0x1F, 0x23, 0x15, 0x02, 0xF7, 0xFC, 0x05, 0x0D, 0x04, 0xF9, 0xF3,
+ 0xFB, 0x16, 0x2A, 0x30, 0x2A, 0x1B, 0x05, 0xF8, 0xF4, 0xFD, 0x03, 0x02, 0xF5, 0xE7, 0xE3, 0xF8,
+ 0x11, 0x21, 0x1E, 0x05, 0xED, 0xE4, 0xE3, 0xEC, 0xF6, 0xFD, 0xFC, 0xF4, 0xF3, 0xF3, 0xFB, 0x0E,
+ 0x18, 0x0B, 0xF5, 0xE4, 0xE5, 0xF5, 0xFF, 0xFB, 0xF0, 0xE5, 0xE6, 0xF1, 0xFF, 0x0A, 0x09, 0x09,
+ 0x08, 0xFD, 0xF4, 0xFA, 0x05, 0x0A, 0x00, 0xF1, 0xEC, 0xFD, 0x19, 0x2D, 0x2A, 0x18, 0x03, 0xFC,
+ 0x0A, 0x13, 0x12, 0x0B, 0x02, 0xF6, 0xF0, 0xF5, 0x08, 0x19, 0x21, 0x14, 0xF8, 0xE6, 0xEC, 0x01,
+ 0x10, 0x0A, 0xEC, 0xD5, 0xD8, 0xE9, 0x03, 0x13, 0x19, 0x11, 0x03, 0xF7, 0xEF, 0xED, 0xF6, 0xFC,
+ 0xEE, 0xDC, 0xD6, 0xE3, 0x01, 0x1A, 0x1B, 0x0A, 0xF5, 0xED, 0xEE, 0xF2, 0xF4, 0xEA, 0xE7, 0xED,
+ 0xF5, 0xFF, 0x11, 0x20, 0x25, 0x1B, 0x0A, 0x02, 0x03, 0x0C, 0x10, 0x03, 0xF4, 0xEC, 0xF5, 0x0F,
+ 0x25, 0x27, 0x21, 0x17, 0x09, 0xFB, 0xF7, 0xFD, 0x01, 0x01, 0xF9, 0xEC, 0xEA, 0xFD, 0x17, 0x26,
+ 0x22, 0x07, 0xEC, 0xE3, 0xE2, 0xE7, 0xEE, 0xF8, 0xFD, 0xF9, 0xF7, 0xF3, 0xF7, 0x07, 0x15, 0x0D,
+ 0xF7, 0xE5, 0xE1, 0xEF, 0xFD, 0xFF, 0xF8, 0xF3, 0xF3, 0xF5, 0xF8, 0xFD, 0xFD, 0x00, 0x03, 0xFC,
+ 0xF1, 0xEF, 0xFD, 0x06, 0x04, 0xF8, 0xF4, 0x01, 0x19, 0x27, 0x25, 0x15, 0x05, 0x01, 0x0F, 0x18,
+ 0x15, 0x0D, 0x07, 0x02, 0xFA, 0xF9, 0x03, 0x10, 0x19, 0x13, 0xFB, 0xE7, 0xE9, 0xFD, 0x0F, 0x0F,
+ 0xF4, 0xDC, 0xD7, 0xE6, 0xF9, 0x09, 0x12, 0x13, 0x08, 0xFD, 0xF3, 0xEE, 0xF8, 0x04, 0xFF, 0xEA,
+ 0xDB, 0xDD, 0xF4, 0x0D, 0x14, 0x0A, 0xFD, 0xF5, 0xF3, 0xF3, 0xF3, 0xEA, 0xE7, 0xEF, 0xF6, 0xF9,
+ 0x00, 0x0F, 0x19, 0x19, 0x10, 0x06, 0x04, 0x0D, 0x11, 0x06, 0xF6, 0xEF, 0xF4, 0x0D, 0x21, 0x27,
+ 0x22, 0x1A, 0x11, 0x04, 0xFB, 0xFB, 0x01, 0x02, 0xFB, 0xEC, 0xE5, 0xF3, 0x0D, 0x21, 0x22, 0x0E,
+ 0xF5, 0xE8, 0xE7, 0xEB, 0xEF, 0xF7, 0xFB, 0xF9, 0xF4, 0xF0, 0xF2, 0x02, 0x13, 0x13, 0xFD, 0xE8,
+ 0xE0, 0xE8, 0xF6, 0xFD, 0xFA, 0xF7, 0xF8, 0xFB, 0xFE, 0xFF, 0xFE, 0x00, 0x05, 0x02, 0xF4, 0xED,
+ 0xF5, 0x01, 0x05, 0xFE, 0xF9, 0xFF, 0x0F, 0x1B, 0x19, 0x0B, 0x00, 0x00, 0x0D, 0x1A, 0x1A, 0x13,
+ 0x0E, 0x09, 0xFF, 0xFB, 0x01, 0x10, 0x1C, 0x1A, 0x04, 0xEB, 0xE8, 0xFB, 0x0C, 0x0E, 0xF8, 0xE0,
+ 0xD8, 0xE3, 0xF5, 0x05, 0x11, 0x14, 0x0E, 0xFF, 0xF3, 0xE9, 0xF0, 0xFE, 0x03, 0xF3, 0xE3, 0xE1,
+ 0xF0, 0x03, 0x0E, 0x09, 0xFD, 0xF6, 0xF1, 0xED, 0xEA, 0xE7, 0xE9, 0xF6, 0xFD, 0xFD, 0xFF, 0x0B,
+ 0x16, 0x18, 0x11, 0x08, 0x08
+};
+
+const uint8_t SfxPlayer::_musicDataSample4[] = {
+ 0x01, 0xF8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0E, 0x0D, 0xF4, 0x0F, 0xFF, 0x0C,
+ 0x10, 0xE1, 0xC9, 0xD5, 0xF2, 0x17, 0x2C, 0x05, 0x1B, 0x50, 0x1D, 0x1F, 0x40, 0x1B, 0x09, 0x2B,
+ 0xFE, 0xE0, 0x0A, 0x27, 0xDF, 0xEB, 0x1F, 0x41, 0x56, 0x2E, 0x06, 0xEC, 0xC0, 0xA7, 0xCF, 0xE5,
+ 0x24, 0x2C, 0x2B, 0x53, 0x36, 0x2C, 0x15, 0x1F, 0x1E, 0x18, 0x18, 0x15, 0xD9, 0xD6, 0x03, 0xEE,
+ 0xEF, 0x3F, 0x38, 0x36, 0x36, 0x0F, 0xE8, 0xC9, 0xC6, 0xE0, 0x21, 0xF7, 0x08, 0x3C, 0x45, 0x14,
+ 0x33, 0x37, 0x2A, 0x17, 0x03, 0x21, 0x10, 0x15, 0xFC, 0xCD, 0xD5, 0xF6, 0x12, 0x46, 0x24, 0xFC,
+ 0xF3, 0x22, 0x0A, 0xD7, 0xE8, 0x02, 0xF9, 0x0C, 0x3D, 0x46, 0x25, 0x16, 0x30, 0x0C, 0xF2, 0x16,
+ 0x35, 0xF8, 0xF1, 0x01, 0x03, 0x07, 0xF6, 0x11, 0x08, 0x0E, 0x14, 0x1F, 0x0F, 0xF5, 0xFD, 0x03,
+ 0x0E, 0xE3, 0x11, 0x2B, 0x26, 0x23, 0x21, 0x18, 0xFF, 0x11, 0x0C, 0x08, 0x07, 0x05, 0x06, 0x0A,
+ 0x18, 0x0F, 0x0F, 0x0E, 0x0C, 0x05, 0x12, 0x2C, 0x01, 0xFD, 0x05, 0xF6, 0xF6, 0x15, 0x29, 0x1B,
+ 0x0C, 0x09, 0x2A, 0x12, 0x08, 0x14, 0x00, 0xF8, 0x03, 0x26, 0x14, 0x11, 0x0C, 0x1E, 0x00, 0xFA,
+ 0x14, 0x15, 0x0A, 0x04, 0x07, 0x05, 0x08, 0x09, 0x18, 0x03, 0x09, 0x1A, 0x1A, 0x21, 0x12, 0x11,
+ 0x06, 0x01, 0x0C, 0xF3, 0x1D, 0x1F, 0x15, 0x10, 0x11, 0x10, 0x05, 0x06, 0x15, 0x02, 0xF7, 0x0C,
+ 0x17, 0x16, 0x01, 0xFB, 0x09, 0x01, 0x13, 0x2D, 0x28, 0x0E, 0x07, 0x1C, 0xFB, 0x01, 0x17, 0x19,
+ 0x02, 0x07, 0x15, 0x14, 0x0D, 0x14, 0xFD, 0xF6, 0x05, 0x16, 0x23, 0x10, 0x0E, 0x08, 0xFD, 0x09,
+ 0x0B, 0x16, 0x1A, 0x11, 0x13, 0x07, 0x10, 0x18, 0x0B, 0x02, 0x0D, 0x0E, 0x13, 0x1E, 0x23, 0x0C,
+ 0xF8, 0x00, 0x05, 0x09, 0x06, 0x1A, 0x1B, 0x01, 0x0C, 0x0C, 0x08, 0x0C, 0x17, 0x18, 0x08, 0x0C,
+ 0x19, 0x13, 0x06, 0x06, 0x04, 0x04, 0x11, 0x23, 0x21, 0x14, 0x0C, 0x09, 0x03, 0x08, 0x0E, 0x12,
+ 0x08, 0x0A, 0x0A, 0x02, 0x10, 0x15, 0x0C, 0x0A, 0x0F, 0x16, 0x1F, 0x1C, 0x14, 0x05, 0xF5, 0x02,
+ 0x16, 0x14, 0x17, 0x1C, 0x1B, 0x08, 0x06, 0x0F, 0x0A, 0x03, 0x0C, 0x14, 0x09, 0x0E, 0x1B, 0x09,
+ 0xFB, 0x05, 0x0F, 0x10, 0x1D, 0x21, 0x1B, 0x09, 0x09, 0x02, 0x06, 0x07, 0x0E, 0x16, 0x10, 0x15,
+ 0x17, 0x0E, 0x0D, 0x0A, 0x08, 0x02, 0x0F, 0x21, 0x16, 0x0C, 0x09, 0x03, 0xFC, 0x07, 0x19, 0x19,
+ 0x0F, 0x22, 0x17, 0x06, 0x03, 0x0C, 0x0D, 0xFE, 0x11, 0x1C, 0x13, 0x14, 0x17, 0x0D, 0xFC, 0xFD,
+ 0x16, 0x16, 0x14, 0x19, 0x10, 0x02, 0x00, 0x0A, 0x0C, 0x0A, 0x17, 0x15, 0x16, 0x11, 0x12, 0x14,
+ 0x04, 0xFF, 0x0C, 0x10, 0x11, 0x1D, 0x1A, 0x0A, 0x06, 0x0E, 0x00, 0x07, 0x16, 0x12, 0x0F, 0x0F,
+ 0x12, 0x07, 0x02, 0x13, 0x0A, 0x09, 0x15, 0x1B, 0x19, 0x0D, 0x0C, 0x07, 0x00, 0x07, 0x15, 0x17,
+ 0x10, 0x14, 0x19, 0x06, 0x02, 0x10, 0x0C, 0x0A, 0x0F, 0x15, 0x11, 0x0C, 0x12, 0x0D, 0x06, 0x06,
+ 0x0E, 0x17, 0x13, 0x12, 0x16, 0x0A, 0x06, 0x0E, 0x12, 0x0C, 0x13, 0x1C, 0x0C, 0x0C, 0x14, 0x0C,
+ 0x07, 0x0F, 0x0D, 0x07, 0x0F, 0x19, 0x11, 0x0F, 0x10, 0x0D, 0x09, 0x0B, 0x13, 0x14, 0x10, 0x0E,
+ 0x11, 0x0A, 0x07, 0x0B, 0x17, 0x0F, 0x0D, 0x17, 0x14, 0x0B, 0x10, 0x11, 0x06, 0x06, 0x10, 0x13,
+ 0x0F, 0x10, 0x13, 0x0E, 0x07, 0x0E, 0x13, 0x0E, 0x0D, 0x13, 0x0F, 0x0E, 0x15, 0x11, 0x0B, 0x0D,
+ 0x0F, 0x0A, 0x0E, 0x14, 0x14, 0x0C, 0x0F, 0x0B, 0x0B, 0x11, 0x13, 0x10, 0x0C, 0x0B, 0x0F, 0x10,
+ 0x10
+};
+
+const uint8_t SfxPlayer::_musicDataSample5[] = {
+ 0x09, 0xE4, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x0C, 0x0C, 0x0C, 0x10, 0x14, 0x28, 0x28, 0x28,
+ 0x28, 0x2C, 0x28, 0x24, 0x24, 0x1C, 0x1C, 0x1C, 0x10, 0x14, 0x14, 0x10, 0x10, 0x08, 0x08, 0x04,
+ 0x0C, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x14, 0x04, 0x00, 0x14, 0x1C, 0x0C, 0x00, 0xF4, 0xE4, 0xC4,
+ 0xB8, 0xB4, 0xB0, 0xA8, 0xA4, 0xA0, 0xA0, 0xA0, 0xA4, 0xB0, 0xC4, 0xCC, 0xD4, 0xDC, 0xE0, 0xE8,
+ 0xEC, 0xF4, 0xF8, 0xFC, 0x04, 0x04, 0x24, 0x3C, 0x3C, 0x44, 0x50, 0x5C, 0x5C, 0x5C, 0x64, 0x68,
+ 0x68, 0x5C, 0x64, 0x64, 0x6C, 0x68, 0x6C, 0x78, 0x74, 0x68, 0x64, 0x6C, 0x6C, 0x58, 0x68, 0x58,
+ 0x34, 0x38, 0x48, 0x58, 0x58, 0x3C, 0x08, 0xDC, 0xC4, 0x9C, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x8C, 0x98, 0x9C, 0xA4, 0xA8, 0xBC, 0xD0, 0xD8, 0xF0, 0x08, 0x0C,
+ 0x0C, 0x10, 0x18, 0x20, 0x28, 0x48, 0x5C, 0x6C, 0x7C, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7C, 0x7F,
+ 0x7F, 0x74, 0x68, 0x5C, 0x4C, 0x3C, 0x2C, 0x28, 0x2C, 0x30, 0x34, 0x34, 0x24, 0x1C, 0x14, 0x1C,
+ 0x20, 0x20, 0x0C, 0x00, 0xF4, 0xE4, 0xCC, 0xBC, 0xB4, 0xB4, 0xA8, 0x94, 0x80, 0x80, 0x80, 0x80,
+ 0x84, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x84, 0x84, 0x8C, 0xA0, 0xC0, 0xD4, 0xD0, 0xE4, 0xEC, 0xF0,
+ 0xF8, 0x10, 0x20, 0x4C, 0x64, 0x68, 0x6C, 0x78, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x6C, 0x64, 0x58,
+ 0x34, 0x2C, 0x34, 0x38, 0x2C, 0x14, 0x14, 0x20, 0x2C, 0x38, 0x34, 0x34, 0x3C, 0x3C, 0x3C, 0x2C,
+ 0x38, 0x54, 0x70, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x74, 0x78, 0x78, 0x7C, 0x6C, 0x74, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x74, 0x4C, 0x4C, 0x4C, 0x30, 0x14, 0x14, 0x04, 0x10, 0x1C, 0xF4, 0xCC, 0xAC, 0x84, 0x88, 0x80,
+ 0x80, 0x80, 0x84, 0xA8, 0x80, 0x80, 0x80, 0x84, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xAC,
+ 0x80, 0x80, 0xA4, 0xFC, 0x14, 0x00, 0x00, 0xF8, 0x3C, 0x70, 0x64, 0x30, 0xEC, 0x34, 0x7F, 0x44,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x70, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x70, 0x68, 0x4C, 0x68, 0x7F, 0x7F, 0x7F, 0x48, 0x3C, 0x44, 0x2C, 0x5C,
+ 0x68, 0x30, 0x18, 0x30, 0xF8, 0x44, 0x4C, 0x54, 0x48, 0x20, 0x14, 0xEC, 0xE0, 0xF4, 0x0C, 0x20,
+ 0xFC, 0x1C, 0x1C, 0x04, 0x5C, 0x3C, 0x14, 0x40, 0xCC, 0xBC, 0xF4, 0x00, 0x2C, 0xEC, 0xEC, 0x84,
+ 0x80, 0x9C, 0xCC, 0x90, 0x80, 0x8C, 0x80, 0x80, 0x80, 0xB4, 0xEC, 0x90, 0xC4, 0x38, 0xAC, 0xBC,
+ 0xAC, 0x80, 0x84, 0xA4, 0x94, 0xCC, 0xCC, 0xD4, 0x10, 0x94, 0xA4, 0xDC, 0xAC, 0xCC, 0x08, 0xF4,
+ 0xE4, 0x04, 0xEC, 0x4C, 0x0C, 0x04, 0x34, 0x28, 0x24, 0x50, 0x28, 0x18, 0x1C, 0x00, 0x0C, 0x1C,
+ 0x48, 0x74, 0x54, 0x3C, 0x1C, 0xE0, 0xCC, 0x04, 0xD8, 0xD4, 0xD8, 0xF4, 0x48, 0x44, 0x3C, 0x54,
+ 0x3C, 0x7F, 0x40, 0x1C, 0x6C, 0x6C, 0x7F, 0x7F, 0x5C, 0x64, 0x48, 0x50, 0x20, 0x00, 0x30, 0x0C,
+ 0x14, 0x28, 0x2C, 0x50, 0x70, 0x6C, 0x54, 0x54, 0x6C, 0x54, 0x28, 0x5C, 0x3C, 0x7F, 0x74, 0x7F,
+ 0x7F, 0x5C, 0x7C, 0x58, 0x58, 0x3C, 0xD8, 0x10, 0xCC, 0xCC, 0xA0, 0x88, 0xA4, 0xBC, 0x8C, 0xCC,
+ 0xF0, 0xC8, 0xB0, 0x8C, 0xBC, 0xD4, 0x80, 0x80, 0x94, 0x94, 0x84, 0xA8, 0x80, 0xF8, 0xD0, 0xE0,
+ 0xBC, 0x80, 0x80, 0xB4, 0x84, 0xD4, 0x9C, 0xA0, 0xD4, 0xC8, 0x00, 0xCC, 0x14, 0xD4, 0x08, 0xE8,
+ 0x44, 0x4C, 0xEC, 0x10, 0x1C, 0x04, 0x24, 0x50, 0x2C, 0x54, 0x64, 0x74, 0x3C, 0x24, 0x00, 0x20,
+ 0x24, 0x50, 0x78, 0x68, 0x24, 0x28, 0x44, 0x5C, 0x58, 0x54, 0x5C, 0x7C, 0x7F, 0x64, 0xFC, 0x2C,
+ 0x08, 0x58, 0x24, 0x50, 0xD4, 0x04, 0x48, 0x4C, 0x50, 0x4C, 0xE0, 0xDC, 0xDC, 0x4C, 0xD8, 0x28,
+ 0x60, 0xC8, 0x2C, 0xCC, 0x94, 0xC0, 0x5C, 0x54, 0x44, 0x1C, 0xEC, 0x24, 0xF0, 0xCC, 0x1C, 0xE4,
+ 0x7F, 0x1C, 0xD4, 0xAC, 0xA0, 0x9C, 0xEC, 0xD8, 0x1C, 0xF8, 0x20, 0x04, 0xD8, 0xD8, 0xE4, 0xC4,
+ 0x14, 0xCC, 0xD4, 0xD0, 0xA0, 0xDC, 0xB8, 0x80, 0xE8, 0x00, 0x2C, 0xEC, 0xE4, 0x24, 0x7F, 0xE8,
+ 0x14, 0xD4, 0xDC, 0xF4, 0xEC, 0x44, 0x74, 0x1C, 0xA0, 0x9C, 0xCC, 0xCC, 0x04, 0xC4, 0x14, 0x6C,
+ 0x7F, 0x10, 0xA0, 0x1C, 0x7F, 0x58, 0x44, 0x58, 0x4C, 0x1C, 0x08, 0x34, 0xF4, 0xCC, 0x10, 0xE4,
+ 0xF8, 0x50, 0x18, 0x10, 0x3C, 0x0C, 0x30, 0x44, 0xCC, 0xD4, 0x48, 0x70, 0xC8, 0x20, 0x54, 0x0C,
+ 0xD0, 0xF8, 0x60, 0xAC, 0xE4, 0xE8, 0x38, 0xE8, 0xFC, 0xF4, 0xD4, 0x34, 0x54, 0x0C, 0x14, 0x74,
+ 0x44, 0x14, 0x0C, 0x00, 0x0C, 0xC8, 0x34, 0x54, 0x6C, 0x7F, 0x30, 0xE8, 0x18, 0xD0, 0xB0, 0x08,
+ 0x20, 0xD0, 0x38, 0x34, 0xCC, 0x7F, 0x1C, 0x14, 0x2C, 0x30, 0xDC, 0xE0, 0xF4, 0x34, 0x28, 0xC8,
+ 0xAC, 0xA8, 0x14, 0xAC, 0x90, 0xBC, 0xCC, 0xD4, 0xD4, 0xD4, 0xE4, 0x0C, 0x14, 0xFC, 0xD0, 0xEC,
+ 0x1C, 0x24, 0x0C, 0x08, 0xEC, 0x14, 0x70, 0x2C, 0xC4, 0x84, 0xCC, 0xA4, 0x2C, 0x24, 0xA0, 0x0C,
+ 0x74, 0x04, 0xE4, 0x0C, 0x04, 0xDC, 0x1C, 0xF4, 0xD4, 0xFC, 0xCC, 0x94, 0xD4, 0x54, 0x24, 0x08,
+ 0xCC, 0xD4, 0xF4, 0x44, 0x54, 0x0C, 0x18, 0x28, 0xF0, 0x18, 0x68, 0x28, 0x60, 0x6C, 0x44, 0xC4,
+ 0x14, 0x64, 0x74, 0x7C, 0x5C, 0x7F, 0x7F, 0x7F, 0x20, 0x58, 0x7F, 0x28, 0x7F, 0x58, 0x68, 0x18,
+ 0x54, 0x04, 0x08, 0xE4, 0x14, 0x34, 0x08, 0xDC, 0xE4, 0x08, 0x3C, 0x24, 0xAC, 0xEC, 0xF4, 0xCC,
+ 0xF4, 0x1C, 0xE4, 0x0C, 0xF4, 0xD0, 0xE8, 0xD0, 0xDC, 0xBC, 0xA0, 0xEC, 0xB4, 0xB4, 0x28, 0xD8,
+ 0xF4, 0xDC, 0xBC, 0x28, 0x44, 0xF0, 0xF8, 0xE0, 0xFC, 0xC8, 0x1C, 0x4C, 0xEC, 0x00, 0xF8, 0x00,
+ 0xC8, 0xCC, 0xDC, 0xBC, 0xD0, 0xAC, 0xE0, 0xCC, 0xF4, 0xF8, 0xF0, 0x08, 0x10, 0x1C, 0xEC, 0x30,
+ 0x28, 0x44, 0x34, 0x90, 0x34, 0x3C, 0xC4, 0xE0, 0xCC, 0x00, 0x34, 0xF8, 0x34, 0xB4, 0x34, 0x3C,
+ 0x34, 0xEC, 0xFC, 0x7C, 0x34, 0xCC, 0x0C, 0x4C, 0x10, 0x44, 0x20, 0x14, 0x3C, 0x78, 0x64, 0x50,
+ 0x20, 0x4C, 0x7F, 0x20, 0x24, 0x34, 0x0C, 0x1C, 0x28, 0x04, 0x48, 0x04, 0x5C, 0x60, 0x10, 0x1C,
+ 0x18, 0x10, 0xEC, 0x20, 0x10, 0xAC, 0xE0, 0x10, 0x0C, 0xD0, 0xCC, 0x24, 0xE4, 0xBC, 0xE8, 0x58,
+ 0x00, 0xBC, 0x00, 0x4C, 0xF4, 0xBC, 0xF4, 0x28, 0xDC, 0xB4, 0xEC, 0x24, 0xF0, 0x04, 0xE4, 0xB0,
+ 0xF0, 0xB0, 0xC8, 0x3C, 0x2C, 0xB8, 0xB8, 0xDC, 0xF0, 0x10, 0xD8, 0xEC, 0x2C, 0x08, 0xF8, 0xC8,
+ 0xF4, 0x2C, 0x0C, 0x0C, 0x10, 0xE0, 0xDC, 0x28, 0x1C, 0x20, 0x38, 0xFC, 0x34, 0xF4, 0x08, 0x3C,
+ 0x64, 0x2C, 0xC4, 0xE4, 0xE4, 0xCC, 0x08, 0x7F, 0x3C, 0xEC, 0x14, 0xD8, 0x14, 0x48, 0x1C, 0x74,
+ 0x1C, 0x18, 0x74, 0x34, 0xF4, 0xE0, 0x44, 0x44, 0x58, 0x4C, 0x50, 0x28, 0x4C, 0x48, 0x08, 0x08,
+ 0x40, 0x64, 0x3C, 0x2C, 0x14, 0x4C, 0x40, 0x5C, 0x10, 0xFC, 0x3C, 0x28, 0xF4, 0xF4, 0x08, 0xEC,
+ 0x00, 0x34, 0x28, 0x80, 0xF0, 0xDC, 0xF4, 0xFC, 0xD4, 0xF0, 0x34, 0xE8, 0xEC, 0xBC, 0x90, 0x88,
+ 0x34, 0xF4, 0x9C, 0xAC, 0xC4, 0xDC, 0xD4, 0xCC, 0xF4, 0xE4, 0xE4, 0x2C, 0xD4, 0x08, 0xEC, 0x3C,
+ 0x10, 0x14, 0x24, 0x00, 0x44, 0x34, 0x2C, 0xF8, 0x0C, 0x1C, 0x44, 0x5C, 0xFC, 0x24, 0x14, 0xD4,
+ 0x24, 0x7F, 0xF0, 0x34, 0xE4, 0xC8, 0xE8, 0xF0, 0x2C, 0xDC, 0x0C, 0x28, 0xA4, 0xBC, 0x14, 0x60,
+ 0xF4, 0x2C, 0xF4, 0xE8, 0x14, 0xE8, 0x1C, 0x04, 0x28, 0x60, 0x0C, 0x0C, 0x28, 0x44, 0x3C, 0x18,
+ 0x4C, 0x4C, 0x68, 0x04, 0xE8, 0x28, 0x0C, 0x2C, 0x7C, 0x58, 0x5C, 0x4C, 0x68, 0x7F, 0x60, 0x6C,
+ 0x30, 0xEC, 0x0C, 0xFC, 0xE0, 0x30, 0x34, 0x00, 0x08, 0x1C, 0xF8, 0xAC, 0xCC, 0x0C, 0x08, 0x2C,
+ 0xE8, 0x08, 0x0C, 0xB4, 0xD4, 0xC4, 0x00, 0xEC, 0xCC, 0xE4, 0x10, 0xE4, 0xF8, 0xA0, 0xAC, 0xD0,
+ 0xF4, 0x14, 0x04, 0xC4, 0xE8, 0xDC, 0x00, 0x08, 0xF0, 0xD0, 0xD8, 0xD4, 0x10, 0xE0, 0x08, 0x1C,
+ 0xF8, 0xCC, 0xF4, 0xF8, 0x14, 0x04, 0x1C, 0x20, 0x04, 0xD8, 0xEC, 0x00, 0x14, 0x14, 0xEC, 0x24,
+ 0xF4, 0x10, 0x04, 0xC4, 0x14, 0x30, 0x28, 0x3C, 0xCC, 0x30, 0x44, 0x44, 0x10, 0x3C, 0x4C, 0x0C,
+ 0x4C, 0x2C, 0x48, 0x50, 0x5C, 0x2C, 0x24, 0x7F, 0x48, 0x4C, 0x24, 0x30, 0x18, 0x40, 0x24, 0x0C,
+ 0xF4, 0x44, 0x30, 0x48, 0x28, 0x18, 0xFC, 0xDC, 0xDC, 0x34, 0xFC, 0xE8, 0xEC, 0x4C, 0x50, 0xF4,
+ 0xE8, 0x20, 0x18, 0x0C, 0x20, 0x20, 0x2C, 0xE8, 0xEC, 0x10, 0xE0, 0xFC, 0x1C, 0x3C, 0x24, 0x1C,
+ 0x3C, 0x1C, 0x0C, 0x1C, 0xBC, 0xAC, 0x04, 0x50, 0x14, 0xE4, 0xF8, 0xEC, 0xCC, 0xE4, 0xD4, 0xE0,
+ 0xD8, 0xF4, 0xF4, 0xD4, 0xB4, 0xBC, 0xC8, 0xFC, 0xCC, 0xD0, 0xEC, 0xE4, 0xF0, 0xEC, 0xCC, 0xD0,
+ 0xE0, 0x94, 0xB8, 0xE8, 0x24, 0x04, 0xCC, 0x0C, 0xE4, 0xEC, 0xD4, 0x00, 0xE4, 0x08, 0x18, 0x00,
+ 0xEC, 0xEC, 0xEC, 0x28, 0xD4, 0xEC, 0x2C, 0x44, 0x44, 0x2C, 0x30, 0x54, 0x78, 0x70, 0x3C, 0x34,
+ 0x7C, 0x7F, 0x44, 0x2C, 0x5C, 0x54, 0x4C, 0x44, 0x5C, 0x20, 0x14, 0x1C, 0x5C, 0x78, 0x34, 0x3C,
+ 0x34, 0x40, 0x40, 0x54, 0x3C, 0x04, 0x14, 0x14, 0x2C, 0x2C, 0x2C, 0x2C, 0x0C, 0xD4, 0x34, 0x08,
+ 0xE4, 0x00, 0x14, 0x14, 0x04, 0x0C, 0xDC, 0xE4, 0xF4, 0x24, 0xEC, 0xC8, 0xB4, 0xCC, 0xD8, 0xBC,
+ 0xD0, 0xE0, 0xEC, 0xC4, 0xF8, 0xC4, 0xE4, 0xD4, 0xC4, 0x14, 0xF4, 0xDC, 0xDC, 0xB0, 0xA0, 0xE4,
+ 0x0C, 0xF8, 0x0C, 0xEC, 0xB4, 0xAC, 0xEC, 0x0C, 0xD8, 0x1C, 0x30, 0x3C, 0x0C, 0xD4, 0x0C, 0xF8,
+ 0xF4, 0xFC, 0x28, 0x3C, 0x28, 0x30, 0x3C, 0x38, 0x04, 0x04, 0xF4, 0x18, 0x50, 0x0C, 0xF8, 0x24,
+ 0xF0, 0x34, 0x20, 0x0C, 0x08, 0xF4, 0x18, 0xD8, 0xDC, 0x14, 0x24, 0xEC, 0x04, 0x2C, 0xF8, 0x30,
+ 0x1C, 0x2C, 0x0C, 0x0C, 0x1C, 0x18, 0x24, 0x34, 0x3C, 0x2C, 0x38, 0x3C, 0x1C, 0x38, 0x3C, 0x28,
+ 0x58, 0x54, 0x24, 0x24, 0x44, 0x30, 0x10, 0xEC, 0x2C, 0x1C, 0x1C, 0x14, 0xF8, 0x0C, 0x08, 0x00,
+ 0x04, 0xF8, 0xE8, 0x00, 0x14, 0xDC, 0xF4, 0xE4, 0xDC, 0xF0, 0xF4, 0xEC, 0xE4, 0x20, 0x1C, 0xE4,
+ 0x00, 0xDC, 0xF4, 0xF4, 0xE8, 0xF8, 0x28, 0x14, 0x00, 0x04, 0x5C, 0x1C, 0xE0, 0x04, 0xF0, 0xF4,
+ 0x0C, 0x24, 0xE4, 0xF0, 0xDC, 0xF4, 0xF8, 0xE0, 0x0C, 0xEC, 0xEC, 0xF8, 0xE4, 0xD4, 0x08, 0x04,
+ 0xE4, 0xF0, 0x14, 0xF4, 0xF4, 0xF0, 0x08, 0x08, 0x04, 0x04, 0xE4, 0xE8, 0xFC, 0x14, 0x14, 0x0C,
+ 0x24, 0x2C, 0x34, 0x14, 0x0C, 0x0C, 0x2C, 0x14, 0xF8, 0x1C, 0x10, 0x0C, 0x14, 0x14, 0x1C, 0x44,
+ 0x30, 0x14, 0x1C, 0x04, 0x24, 0x44, 0x18, 0x24, 0x1C, 0xFC, 0xF0, 0xEC, 0xFC, 0xEC, 0x0C, 0xF8,
+ 0x04, 0xFC, 0xF0, 0xE8, 0x0C, 0x2C, 0x20, 0xE4, 0xFC, 0x18, 0xF4, 0xFC, 0x0C, 0x18, 0x08, 0xF0,
+ 0x04, 0x0C, 0x00, 0x0C, 0x0C, 0x28, 0x1C, 0xF4, 0x08, 0x0C, 0x10, 0x14, 0x1C, 0x28, 0x2C, 0xFC,
+ 0x1C, 0x18, 0x10, 0x04, 0x0C, 0x24, 0x34, 0x14, 0x0C, 0x1C, 0x1C, 0x00, 0xE4, 0xFC, 0x0C, 0x28,
+ 0xF0, 0xEC, 0xE8, 0xFC, 0x00, 0xE4, 0x00, 0xF4, 0x24, 0x18, 0xE0, 0x0C, 0xFC, 0xF0, 0x14, 0x04,
+ 0x14, 0xE8, 0xEC, 0x0C, 0x08, 0x10, 0x00, 0xF0, 0xEC, 0x04, 0x14, 0xEC, 0x1C, 0x10, 0x0C, 0x14,
+ 0xE0, 0xF4, 0x00, 0x18, 0x04, 0xFC, 0xE4, 0xE4, 0xE0, 0x00, 0x04, 0xF0, 0xF0, 0x10, 0x00, 0x04,
+ 0x10, 0x0C, 0x1C, 0x08, 0x00, 0x10, 0x04, 0x0C, 0xF8, 0x04, 0x14, 0x04, 0xFC, 0x20, 0x24, 0x14,
+ 0x1C, 0x2C, 0x1C, 0xF0, 0x28, 0x44, 0x0C, 0x14, 0x40, 0x34, 0x1C, 0x08, 0x0C, 0x28, 0x20, 0x20,
+ 0x14, 0x0C, 0x04, 0x0C, 0x2C, 0x1C, 0x0C, 0x04, 0x10, 0x18, 0x14, 0x10, 0x2C, 0x2C, 0x1C, 0x04,
+ 0x00, 0xFC, 0x18, 0x10, 0x1C, 0x24, 0x0C, 0x28, 0x14, 0x04, 0xF8, 0x1C, 0x0C, 0x18, 0x18, 0xF8,
+ 0xFC, 0x08, 0xD4, 0xFC, 0xEC, 0xE4, 0xE0, 0xF4, 0x0C, 0xE8, 0xE8, 0xE8, 0xBC, 0xEC, 0x04, 0xEC,
+ 0xEC, 0xE0, 0xE4, 0x04, 0x10, 0x0C, 0xF8, 0xF8, 0xEC, 0xDC, 0xF4, 0x0C, 0x0C, 0xF4, 0x0C, 0x04,
+ 0xF0, 0xFC, 0x0C, 0x20, 0x14, 0x1C, 0x28, 0x34, 0x28, 0x18, 0x20, 0x54, 0x3C, 0x1C, 0x24, 0x24,
+ 0x28, 0x3C, 0x28, 0x1C, 0x18, 0x1C, 0x14, 0x00, 0x0C, 0x14, 0xF0, 0xFC, 0x24, 0x0C, 0x00, 0xF4,
+ 0x04, 0x24, 0x1C, 0xF4, 0x08, 0xEC, 0xF4, 0x0C, 0xF8, 0xEC, 0xF4, 0x0C, 0xF4, 0xEC, 0xEC, 0x18,
+ 0x18, 0x08, 0xE0, 0xF4, 0x0C, 0x20, 0x0C, 0x00, 0x00, 0x10, 0x1C, 0x00, 0xEC, 0x0C, 0x10, 0x14,
+ 0x10, 0x0C, 0xF8, 0xF8, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x04, 0x1C, 0x30, 0x24, 0x0C, 0xE4, 0xF4,
+ 0x08, 0x14, 0x0C, 0x00, 0x00, 0x0C, 0x08, 0x00, 0xEC, 0x04, 0x1C, 0x14, 0x08, 0x1C, 0x24, 0x2C,
+ 0x18, 0x10, 0x20, 0x0C, 0x20, 0x3C, 0x24, 0x20, 0x20, 0x38, 0x38, 0x18, 0x14, 0x1C, 0x18, 0x24,
+ 0x2C, 0x0C, 0x14, 0x24, 0x00, 0xEC, 0xF4, 0xEC, 0xD8, 0xD8, 0xE8, 0xE0, 0xB4, 0xC4, 0xF0, 0xEC,
+ 0xD0, 0xD4, 0xE0, 0xE4, 0xE0, 0xE4, 0xDC, 0x0C, 0x0C, 0x00, 0x00, 0x10, 0x20, 0x14, 0x14, 0x18,
+ 0x14, 0x14, 0x14, 0x10, 0x08, 0x24, 0x2C, 0x28, 0x24, 0x34, 0x30, 0x30, 0x34, 0x34, 0x38, 0x2C,
+ 0x1C, 0x1C, 0x34, 0x18, 0x04, 0x14, 0x10, 0x14, 0x14, 0x00, 0xE4, 0xEC, 0xE4, 0xFC, 0x10, 0x0C,
+ 0x0C, 0x14, 0x20, 0x04, 0x0C, 0x2C, 0x20, 0x14, 0x04, 0x08, 0x10, 0x2C, 0x2C, 0x14, 0x24, 0x00,
+ 0xEC, 0xFC, 0x10, 0x0C, 0x00, 0x10, 0x08, 0xF4, 0x00, 0xF4, 0x00, 0xFC, 0x08, 0x18, 0xF4, 0x00,
+ 0x0C, 0x0C, 0xF8, 0xF8, 0x10, 0x0C, 0x10, 0xE4, 0xE8, 0xFC, 0x04, 0x18, 0x0C, 0x0C, 0x04, 0x18,
+ 0x18, 0x14, 0x04, 0x0C, 0x10, 0x20, 0x0C, 0x10, 0x28, 0x34, 0x30, 0x34, 0x2C, 0x20, 0x1C, 0x1C,
+ 0x2C, 0x40, 0x3C, 0x24, 0x24, 0x1C, 0x18, 0x14, 0x24, 0x14, 0xEC, 0xFC, 0x04, 0xF8, 0xF4, 0xE4,
+ 0xE4, 0xFC, 0x04, 0xF8, 0xEC, 0xF8, 0xF8, 0xF4, 0x00, 0xF0, 0x00, 0xF4, 0xEC, 0x10, 0x04, 0xFC,
+ 0x08, 0x04, 0x00, 0xEC, 0x00, 0x00, 0x00, 0x14, 0x10, 0x0C, 0x04, 0x20, 0x1C, 0x24, 0x14, 0xF8,
+ 0x08, 0x28, 0x14, 0x0C, 0x24, 0x2C, 0x18, 0x0C, 0x24, 0x34, 0x04, 0xF8, 0xEC, 0x0C, 0x1C, 0x18,
+ 0x00, 0x04, 0x28, 0x1C, 0x14, 0x24, 0x18, 0x14, 0x20, 0x10, 0x10, 0x24, 0x1C, 0x04, 0x0C, 0x14,
+ 0x1C, 0x1C, 0x1C, 0x28, 0x24, 0x20, 0x2C, 0x24, 0x14, 0x04, 0x1C, 0x2C, 0x24, 0x24, 0x00, 0xF8,
+ 0xFC, 0x18, 0xF4, 0xEC, 0xFC, 0x04, 0xE4, 0xE4, 0xF4, 0xF0, 0xF8, 0x1C, 0x14, 0x14, 0x04, 0x04,
+ 0x00, 0x04, 0x1C, 0x1C, 0x08, 0xF4, 0xF0, 0xF8, 0x14, 0xFC, 0xF4, 0x10, 0x10, 0x18, 0x20, 0x24,
+ 0x14, 0x1C, 0x38, 0x28, 0x24, 0x14, 0x34, 0x44, 0x20, 0x24, 0x14, 0x10, 0x28, 0x24, 0x0C, 0x18,
+ 0x04, 0xF4, 0xF8, 0x14, 0xF8, 0xDC, 0xE4, 0xEC, 0xE4, 0x04, 0xFC, 0xEC, 0xF4, 0xFC, 0xFC, 0xFC,
+ 0xE4, 0xE4, 0xF0, 0xE0, 0xD4, 0xE8, 0xE4, 0xE4, 0xF8, 0xF0, 0xE4, 0xEC, 0xE4, 0xE4, 0xF4, 0xF8,
+ 0xFC, 0x04, 0x14, 0x04, 0x00, 0xF8, 0x14, 0x10, 0x14, 0x20, 0x20, 0x14, 0x08, 0x04, 0x20, 0x2C,
+ 0x1C, 0x0C, 0x1C, 0x1C, 0x0C, 0x1C, 0x1C, 0x00, 0x04, 0xF8, 0x20, 0x24, 0x2C, 0x3C, 0x1C, 0x28,
+ 0x34, 0x20, 0x2C, 0x20, 0x30, 0x2C, 0x28, 0x28, 0x24, 0x24, 0x3C, 0x3C, 0x34, 0x34, 0x34, 0x3C,
+ 0x24, 0x3C, 0x3C, 0x3C, 0x34, 0x34, 0x2C, 0x24, 0x18, 0x0C, 0x1C, 0x1C, 0x14, 0xF4, 0xFC, 0x0C,
+ 0x0C, 0x00, 0xF8, 0xFC, 0x04, 0x0C, 0x00, 0xF8, 0xF8, 0xEC, 0xEC, 0xE8, 0xF0, 0xDC, 0xE4, 0xF4,
+ 0xF0, 0xF0, 0xF4, 0x04, 0xDC, 0xEC, 0xEC, 0xDC, 0xE0, 0xEC, 0xEC, 0xF4, 0xEC, 0xE8, 0xF0, 0xE4,
+ 0xDC, 0xC4, 0xC4, 0xE4, 0xF4, 0x04, 0xF4, 0xF0, 0x08, 0x24, 0x14, 0x1C, 0x1C, 0x14, 0x30, 0x2C,
+ 0x08, 0x08, 0x1C, 0x14, 0x0C, 0x00, 0x08, 0x18, 0x10, 0x04, 0x04, 0x08, 0x14, 0x04, 0x10, 0x0C,
+ 0x00, 0x2C, 0x34, 0x1C, 0x0C, 0x1C, 0x20, 0x2C, 0x1C, 0x2C, 0x38, 0x44, 0x2C, 0x1C, 0x20, 0x44,
+ 0x48, 0x1C, 0x18, 0x1C, 0x24, 0x3C, 0x28, 0x24, 0x38, 0x28, 0x18, 0x1C, 0x1C, 0x1C, 0x2C, 0x14,
+ 0x04, 0x10, 0x24, 0x18, 0xF4, 0xFC, 0x24, 0x24, 0x14, 0xFC, 0x04, 0xF0, 0xF4, 0xF8, 0xEC, 0xE4,
+ 0xEC, 0xF8, 0xF4, 0xEC, 0xE4, 0x04, 0xF4, 0xEC, 0xE8, 0xFC, 0xF4, 0xF4, 0x0C, 0x0C, 0x04, 0x04,
+ 0x00, 0x00, 0x0C, 0x00, 0xFC, 0x00, 0x04, 0xEC, 0xEC, 0xEC, 0xF4, 0x04, 0x14, 0x0C, 0x04, 0xE0,
+ 0xE4, 0xF4, 0xDC, 0xE8, 0x08, 0xEC, 0xF4, 0xEC, 0xE4, 0xF4, 0x08, 0x0C, 0x08, 0xFC, 0xF0, 0xF0,
+ 0x00, 0xF8, 0xFC, 0xFC, 0xF8, 0xF8, 0x08, 0x0C, 0xFC, 0xF8, 0x04, 0x14, 0x18, 0x0C, 0x0C, 0x20,
+ 0x28, 0x34, 0x24, 0x24, 0x1C, 0x28, 0x34, 0x38, 0x2C, 0x28, 0x20, 0x1C, 0x1C, 0x1C, 0x20, 0x20,
+ 0x24, 0x18, 0x0C, 0x20, 0x28, 0x24, 0x0C, 0x0C, 0x2C, 0x1C, 0x14, 0x04, 0x08, 0x1C, 0x24, 0x10,
+ 0x04, 0x18, 0x18, 0x08, 0x04, 0x18, 0x24, 0x14, 0x04, 0xF8, 0xE4, 0x00, 0x00, 0x04, 0x08, 0xFC,
+ 0xF4, 0xFC, 0xF0, 0xF0, 0x00, 0x08, 0xF4, 0xE4, 0xF4, 0xEC, 0xEC, 0xEC, 0xE8, 0xF4, 0xE8, 0xD8,
+ 0xDC, 0xE4, 0xF0, 0xEC, 0xF0, 0x04, 0xF4, 0xE8, 0xFC, 0xFC, 0xE4, 0xE8, 0xF4, 0xF4, 0x04, 0xEC,
+ 0xF0, 0xE4, 0xE8, 0x10, 0x0C, 0xF4, 0xEC, 0x00, 0x14, 0x0C, 0x0C, 0x04, 0x04
+};
+
+const uint8_t SfxPlayer::_musicDataSample6[] = {
+ 0x09, 0x2E, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x03, 0x03, 0x06, 0x06, 0x0A,
+ 0x00, 0x10, 0x05, 0x0C, 0x04, 0x07, 0x08, 0xEF, 0xF4, 0xEB, 0xFC, 0xE3, 0x21, 0x10, 0x10, 0x08,
+ 0x22, 0x0E, 0x27, 0x3A, 0x35, 0x38, 0x2D, 0x38, 0x19, 0x0B, 0xCE, 0xDA, 0xCA, 0xD2, 0xCE, 0xEB,
+ 0x0B, 0x16, 0x14, 0x05, 0x04, 0xED, 0xF1, 0xB8, 0xCD, 0xCB, 0xD5, 0xE9, 0xF3, 0x22, 0x29, 0x2A,
+ 0x13, 0x1A, 0x3A, 0x32, 0x1F, 0x3B, 0x42, 0x4F, 0x3C, 0x2E, 0x08, 0x14, 0xFF, 0xE7, 0xF0, 0xF6,
+ 0x0D, 0xF5, 0x0E, 0xFE, 0x08, 0x05, 0xDD, 0xC4, 0xC9, 0xB1, 0xB7, 0xCC, 0xE6, 0xF8, 0x0D, 0x20,
+ 0xFF, 0x3A, 0x40, 0x4F, 0x2F, 0x57, 0x4C, 0x4A, 0x39, 0xF6, 0xF4, 0xDA, 0xD1, 0xBF, 0xD4, 0xE8,
+ 0x02, 0xFE, 0x0B, 0xF8, 0x06, 0xF0, 0xC6, 0xB8, 0xCA, 0xB3, 0xCF, 0xDF, 0x09, 0x27, 0x2D, 0x21,
+ 0x1F, 0x46, 0x59, 0x40, 0x5F, 0x67, 0x6C, 0x62, 0x3A, 0x0E, 0x08, 0xE9, 0xCF, 0xCC, 0xCE, 0xED,
+ 0xE4, 0xF3, 0xF0, 0xF3, 0x00, 0xE5, 0xB9, 0xDD, 0xB0, 0xBF, 0xC3, 0xDF, 0x01, 0x13, 0x2D, 0x06,
+ 0x3C, 0x49, 0x58, 0x37, 0x65, 0x5A, 0x5F, 0x50, 0x0C, 0xFE, 0xDF, 0xC5, 0xB9, 0xB5, 0xCB, 0xE4,
+ 0xE2, 0x0B, 0xE7, 0x17, 0x02, 0xDA, 0xD2, 0xD8, 0xC2, 0xD7, 0xE2, 0x0D, 0x24, 0x3F, 0x2E, 0x2D,
+ 0x3B, 0x58, 0x36, 0x4E, 0x60, 0x56, 0x6A, 0x31, 0x15, 0xF8, 0xE0, 0xCA, 0xBC, 0xC1, 0xD8, 0xD1,
+ 0xF5, 0xE1, 0xF3, 0x04, 0xED, 0xC7, 0xDE, 0xC2, 0xC9, 0xC9, 0xE3, 0x09, 0x1F, 0x39, 0x1C, 0x31,
+ 0x4E, 0x46, 0x3A, 0x55, 0x54, 0x66, 0x5C, 0x2D, 0x14, 0xF6, 0xDA, 0xC4, 0xBF, 0xC5, 0xD2, 0xDB,
+ 0xF4, 0xE3, 0x0C, 0x0F, 0xE6, 0xD9, 0xD4, 0xCA, 0xCB, 0xD9, 0x03, 0x0E, 0x3F, 0x2C, 0x29, 0x33,
+ 0x43, 0x36, 0x39, 0x55, 0x4E, 0x6B, 0x45, 0x24, 0x04, 0xE6, 0xCC, 0xBB, 0xB9, 0xCA, 0xC7, 0xE7,
+ 0xDE, 0xE9, 0x03, 0x00, 0xDC, 0xE2, 0xD8, 0xCC, 0xCF, 0xEB, 0xF9, 0x25, 0x2C, 0x2B, 0x1E, 0x3B,
+ 0x3B, 0x2E, 0x43, 0x4C, 0x5B, 0x6A, 0x44, 0x2A, 0x0C, 0xE8, 0xD1, 0xC0, 0xC9, 0xC9, 0xD7, 0xE7,
+ 0xE6, 0xF8, 0x1B, 0xF0, 0xE7, 0xE0, 0xCC, 0xC6, 0xCF, 0xEC, 0xFF, 0x25, 0x2D, 0x20, 0x23, 0x37,
+ 0x2D, 0x2A, 0x46, 0x42, 0x66, 0x5A, 0x38, 0x25, 0x00, 0xE3, 0xCA, 0xC0, 0xCD, 0xC7, 0xDE, 0xE4,
+ 0xDA, 0x07, 0x04, 0xEA, 0xE9, 0xD4, 0xD1, 0xBF, 0xE2, 0xEB, 0x19, 0x27, 0x35, 0x1C, 0x39, 0x3A,
+ 0x2D, 0x3F, 0x43, 0x53, 0x6B, 0x4C, 0x3A, 0x20, 0xF8, 0xE8, 0xC3, 0xD3, 0xC6, 0xD1, 0xDE, 0xDC,
+ 0xE5, 0x0E, 0xF1, 0xEF, 0xDA, 0xD7, 0xBC, 0xC9, 0xD7, 0xF3, 0x13, 0x31, 0x1C, 0x21, 0x32, 0x28,
+ 0x29, 0x38, 0x3E, 0x5D, 0x62, 0x45, 0x3B, 0x10, 0xFE, 0xD4, 0xCF, 0xD0, 0xCD, 0xD7, 0xE7, 0xD6,
+ 0xFB, 0x04, 0xF2, 0xF0, 0xDA, 0xD8, 0xBF, 0xDB, 0xE1, 0x06, 0x23, 0x36, 0x24, 0x32, 0x39, 0x2C,
+ 0x35, 0x38, 0x47, 0x5D, 0x58, 0x42, 0x2E, 0x08, 0xF3, 0xCF, 0xD4, 0xC9, 0xCA, 0xD8, 0xDB, 0xD6,
+ 0xFF, 0xF3, 0xF5, 0xDC, 0xE0, 0xC2, 0xCB, 0xD2, 0xED, 0x07, 0x2D, 0x2A, 0x22, 0x32, 0x2C, 0x26,
+ 0x31, 0x37, 0x49, 0x63, 0x4A, 0x48, 0x21, 0x0C, 0xE6, 0xD8, 0xD3, 0xD0, 0xCF, 0xE7, 0xD3, 0xEB,
+ 0x00, 0xFB, 0xEE, 0xE4, 0xD8, 0xC5, 0xD0, 0xDD, 0xF7, 0x17, 0x33, 0x28, 0x29, 0x3C, 0x28, 0x33,
+ 0x34, 0x3A, 0x57, 0x57, 0x4C, 0x38, 0x17, 0x00, 0xE0, 0xD5, 0xD2, 0xC4, 0xD5, 0xDC, 0xCB, 0xF4,
+ 0xF7, 0xF8, 0xE6, 0xE2, 0xC9, 0xC5, 0xC9, 0xE1, 0xF6, 0x22, 0x2D, 0x1E, 0x33, 0x2A, 0x27, 0x2E,
+ 0x30, 0x3F, 0x59, 0x54, 0x51, 0x30, 0x19, 0xF8, 0xDE, 0xDD, 0xD2, 0xCB, 0xEB, 0xD0, 0xE7, 0xF6,
+ 0x03, 0xF5, 0xF1, 0xE0, 0xCE, 0xC4, 0xD7, 0xE0, 0x03, 0x25, 0x26, 0x1F, 0x34, 0x26, 0x2C, 0x32,
+ 0x2C, 0x4B, 0x50, 0x58, 0x42, 0x2C, 0x11, 0xF1, 0xDE, 0xDB, 0xC6, 0xDA, 0xDA, 0xD5, 0xE4, 0xF7,
+ 0xFB, 0xF1, 0xEA, 0xD6, 0xC6, 0xC6, 0xD4, 0xE3, 0x0B, 0x27, 0x1B, 0x2D, 0x2C, 0x26, 0x32, 0x2A,
+ 0x3A, 0x4B, 0x5B, 0x55, 0x41, 0x28, 0x0A, 0xEA, 0xDE, 0xD8, 0xC7, 0xE8, 0xD7, 0xE2, 0xED, 0x03,
+ 0xF6, 0xF8, 0xE3, 0xD6, 0xC1, 0xD1, 0xD2, 0xEF, 0x15, 0x21, 0x1B, 0x2A, 0x24, 0x23, 0x30, 0x22,
+ 0x3F, 0x49, 0x5A, 0x4E, 0x3A, 0x22, 0x06, 0xE4, 0xEA, 0xC4, 0xDB, 0xDA, 0xDC, 0xDB, 0xF6, 0xFC,
+ 0xFA, 0xF2, 0xE2, 0xCC, 0xC7, 0xCE, 0xD9, 0xF7, 0x22, 0x1E, 0x25, 0x31, 0x20, 0x35, 0x24, 0x33,
+ 0x3F, 0x55, 0x5B, 0x4B, 0x36, 0x1D, 0xF8, 0xEB, 0xDC, 0xC9, 0xDE, 0xDB, 0xDA, 0xE3, 0xFB, 0xF8,
+ 0xFB, 0xE8, 0xE0, 0xC5, 0xCC, 0xCF, 0xD9, 0x07, 0x1C, 0x1B, 0x27, 0x24, 0x24, 0x2C, 0x23, 0x33,
+ 0x43, 0x57, 0x58, 0x48, 0x31, 0x1C, 0xF0, 0xF6, 0xCA, 0xD7, 0xDB, 0xDD, 0xD5, 0xEA, 0xF7, 0xFB,
+ 0xF2, 0xEC, 0xD0, 0xCA, 0xC9, 0xCC, 0xDF, 0x0F, 0x1B, 0x1C, 0x30, 0x1F, 0x34, 0x28, 0x2B, 0x38,
+ 0x47, 0x5D, 0x54, 0x41, 0x34, 0x04, 0xFB, 0xE2, 0xCF, 0xD7, 0xDF, 0xD7, 0xDB, 0xF1, 0xF8, 0xF9,
+ 0xF2, 0xE2, 0xD0, 0xC7, 0xCF, 0xC9, 0xF3, 0x12, 0x13, 0x25, 0x20, 0x28, 0x2A, 0x28, 0x2C, 0x3A,
+ 0x51, 0x5B, 0x51, 0x40, 0x2C, 0x02, 0x00, 0xDB, 0xD5, 0xDF, 0xE0, 0xD5, 0xE3, 0xF1, 0xFD, 0xF4,
+ 0xF2, 0xDA, 0xCC, 0xCB, 0xC5, 0xCF, 0xFD, 0x12, 0x17, 0x26, 0x21, 0x2A, 0x2C, 0x24, 0x2F, 0x3D,
+ 0x53, 0x5C, 0x44, 0x46, 0x12, 0x0A, 0xEE, 0xD7, 0xD4, 0xDF, 0xD8, 0xD6, 0xE3, 0xF8, 0xF4, 0xFA,
+ 0xE8, 0xDB, 0xC9, 0xD0, 0xC3, 0xDB, 0x09, 0x0B, 0x23, 0x1E, 0x27, 0x2C, 0x29, 0x29, 0x32, 0x44,
+ 0x5D, 0x52, 0x4F, 0x38, 0x17, 0x04, 0xEE, 0xD6, 0xDE, 0xE3, 0xD6, 0xDD, 0xE9, 0xF8, 0xF6, 0xF4,
+ 0xE8, 0xD0, 0xCF, 0xC6, 0xC0, 0xEB, 0x01, 0x15, 0x1C, 0x22, 0x26, 0x2C, 0x26, 0x27, 0x35, 0x46,
+ 0x5E, 0x49, 0x52, 0x28, 0x16, 0x00, 0xE2, 0xD4, 0xE1, 0xD8, 0xD8, 0xD8, 0xF3, 0xF0, 0xF9, 0xF0,
+ 0xE0, 0xD0, 0xCF, 0xC4, 0xC7, 0xF9, 0x05, 0x1B, 0x1F, 0x23, 0x2D, 0x2C, 0x26, 0x2E, 0x33, 0x59,
+ 0x4D, 0x57, 0x44, 0x28, 0x12, 0xFC, 0xDE, 0xDC, 0xE3, 0xDB, 0xD6, 0xE5, 0xF1, 0xF7, 0xF5, 0xF2,
+ 0xD9, 0xD2, 0xD0, 0xB6, 0xDD, 0xF1, 0x0D, 0x16, 0x1D, 0x25, 0x29, 0x28, 0x24, 0x2A, 0x3D, 0x54,
+ 0x4D, 0x53, 0x3C, 0x20, 0x0E, 0xF4, 0xD8, 0xE2, 0xDD, 0xDB, 0xD6, 0xEA, 0xF3, 0xF4, 0xF9, 0xE8,
+ 0xD8, 0xD5, 0xC4, 0xBF, 0xE3, 0xFD, 0x11, 0x1C, 0x21, 0x29, 0x2E, 0x24, 0x2E, 0x27, 0x4F, 0x4B,
+ 0x56, 0x50, 0x34, 0x1E, 0x0A, 0xE8, 0xDD, 0xDE, 0xE0, 0xD1, 0xDE, 0xE8, 0xF3, 0xF5, 0xF6, 0xE6,
+ 0xD4, 0xD8, 0xB9, 0xCB, 0xE5, 0xFE, 0x12, 0x18, 0x22, 0x29, 0x26, 0x2A, 0x20, 0x37, 0x47, 0x4E,
+ 0x53, 0x49, 0x2C, 0x1B, 0x02, 0xE2, 0xE0, 0xE3, 0xDB, 0xD7, 0xDF, 0xF2, 0xEF, 0xF9, 0xF4, 0xDA,
+ 0xDE, 0xC8, 0xBF, 0xD1, 0xED, 0x05, 0x15, 0x1E, 0x25, 0x2D, 0x27, 0x2C, 0x23, 0x3F, 0x4A, 0x51,
+ 0x57, 0x42, 0x28, 0x1A, 0xF5, 0xE4, 0xDD, 0xE4, 0xD4, 0xD8, 0xE4, 0xED, 0xF1, 0xF9, 0xEC, 0xDB,
+ 0xDB, 0xC2, 0xC0, 0xD7, 0xEF, 0x07, 0x16, 0x19, 0x2C, 0x21, 0x32, 0x1E, 0x2F, 0x3F, 0x4A, 0x53,
+ 0x54, 0x38, 0x29, 0x10, 0xF3, 0xDE, 0xE6, 0xDC, 0xD9, 0xDB, 0xEB, 0xEF, 0xF4, 0xFE, 0xE0, 0xE5,
+ 0xD2, 0xC1, 0xC7, 0xDD, 0xF7, 0x0D, 0x13, 0x23, 0x24, 0x2B, 0x28, 0x21, 0x34, 0x44, 0x4B, 0x58,
+ 0x4E, 0x33, 0x28, 0x07, 0xEE, 0xE1, 0xE4, 0xDC, 0xD6, 0xDF, 0xEB, 0xEB, 0xFD, 0xF2, 0xE3, 0xE0,
+ 0xCE, 0xBF, 0xCB, 0xE2, 0xFA, 0x12, 0x13, 0x29, 0x20, 0x31, 0x21, 0x26, 0x37, 0x42, 0x4D, 0x59,
+ 0x42, 0x37, 0x1D, 0x06, 0xE5, 0xE5, 0xE2, 0xD8, 0xD8, 0xE1, 0xEB, 0xEF, 0x00, 0xEB, 0xE7, 0xE0,
+ 0xC9, 0xC3, 0xD2, 0xE6, 0x06, 0x0A, 0x1F, 0x1F, 0x29, 0x2B, 0x21, 0x29, 0x3A, 0x43, 0x54, 0x54,
+ 0x3F, 0x30, 0x1C, 0xFA, 0xE7, 0xE5, 0xE1, 0xD8, 0xD9, 0xE9, 0xE4, 0xFA, 0xF8, 0xE9, 0xE7, 0xD8,
+ 0xC6, 0xC5, 0xD5, 0xEF, 0x06, 0x0F, 0x20, 0x1E, 0x2C, 0x26, 0x20, 0x2D, 0x3A, 0x43, 0x58, 0x49,
+ 0x3E, 0x2B, 0x16, 0xF3, 0xE6, 0xE6, 0xDD, 0xD5, 0xDE, 0xE4, 0xE9, 0xFC, 0xF2, 0xE9, 0xE6, 0xD4,
+ 0xC3, 0xCB, 0xD7, 0xFB, 0x02, 0x18, 0x1A, 0x23, 0x2C, 0x23, 0x23, 0x34, 0x39, 0x4F, 0x54, 0x4B,
+ 0x38, 0x2C, 0x0C, 0xF0, 0xE8, 0xE6, 0xDD, 0xD8, 0xE6, 0xE2, 0xF3, 0xFC, 0xEE, 0xEA, 0xE4, 0xCD,
+ 0xC7, 0xC8, 0xE1, 0xF8, 0x07, 0x16, 0x19, 0x25, 0x2A, 0x1E, 0x27, 0x31, 0x3D, 0x51, 0x51, 0x44,
+ 0x38, 0x26, 0x04, 0xEE, 0xE8, 0xE6, 0xD8, 0xDF, 0xE2, 0xE6, 0xF9, 0xF8, 0xEE, 0xEC, 0xE0, 0xCB,
+ 0xC7, 0xCA, 0xE9, 0xF8, 0x0D, 0x13, 0x1B, 0x27, 0x25, 0x1C, 0x2D, 0x2F, 0x46, 0x51, 0x50, 0x40,
+ 0x38, 0x20, 0xFE, 0xEC, 0xEA, 0xE1, 0xD8, 0xE2, 0xDF, 0xED, 0xFB, 0xF6, 0xED, 0xEE, 0xD8, 0xCE,
+ 0xC1, 0xD6, 0xE9, 0xFF, 0x0D, 0x14, 0x1D, 0x2B, 0x1E, 0x24, 0x2A, 0x35, 0x48, 0x52, 0x4A, 0x3E,
+ 0x34, 0x14, 0xFA, 0xEB, 0xED, 0xDB, 0xDF, 0xE0, 0xE1, 0xF1, 0xFB, 0xEF, 0xF0, 0xE6, 0xD6, 0xC8,
+ 0xC5, 0xDC, 0xED, 0x05, 0x0E, 0x14, 0x23, 0x27, 0x1D, 0x28, 0x2B, 0x3B, 0x4B, 0x53, 0x45, 0x40,
+ 0x2C, 0x10, 0xF2, 0xEF, 0xE8, 0xDB, 0xE3, 0xDE, 0xE6, 0xF6, 0xF8, 0xEE, 0xF2, 0xE0, 0xD7, 0xC2,
+ 0xCD, 0xDD, 0xF4, 0x06, 0x0F, 0x17, 0x2A, 0x21, 0x22, 0x27, 0x2E, 0x3E, 0x4F, 0x4E, 0x44, 0x3D,
+ 0x26, 0x06, 0xF0, 0xF0, 0xE0, 0xDD, 0xDF, 0xDE, 0xE9, 0xFA, 0xF1, 0xF3, 0xEC, 0xE1, 0xCE, 0xC2,
+ 0xD1, 0xE1, 0xF9, 0x09, 0x0E, 0x1F, 0x27, 0x21, 0x24, 0x27, 0x32, 0x43, 0x51, 0x49, 0x45, 0x39,
+ 0x20, 0x00, 0xF2, 0xEE, 0xDE, 0xE1, 0xDF, 0xDF, 0xF2, 0xF8, 0xF3, 0xF4, 0xEA, 0xE0, 0xC8, 0xC7,
+ 0xD2, 0xE5, 0xFC, 0x08, 0x0F, 0x23, 0x24, 0x21, 0x24, 0x29, 0x33, 0x47, 0x4C, 0x47, 0x41, 0x34,
+ 0x16, 0xF8, 0xF5, 0xE8, 0xE0, 0xE1, 0xDE, 0xE3, 0xF7, 0xF4, 0xF6, 0xF2, 0xEB, 0xD9, 0xC7, 0xC8,
+ 0xD7, 0xE9, 0x03, 0x04, 0x17, 0x24, 0x22, 0x22, 0x25, 0x2A, 0x39, 0x4A, 0x4B, 0x46, 0x40, 0x2E,
+ 0x0C, 0xF9, 0xF3, 0xE5, 0xE0, 0xE4, 0xDA, 0xED, 0xF5, 0xF6, 0xF7, 0xF1, 0xEA, 0xD4, 0xC7, 0xCC,
+ 0xD7, 0xF2, 0x00, 0x06, 0x19, 0x21, 0x21, 0x20, 0x26, 0x28, 0x3E, 0x47, 0x49, 0x44, 0x3E, 0x28,
+ 0x06, 0xFB, 0xF0, 0xE4, 0xE5, 0xE0, 0xDF, 0xF1, 0xF4, 0xF8, 0xF4, 0xF3, 0xE4, 0xD2, 0xC6, 0xD0,
+ 0xDB, 0xF9, 0xFD, 0x0B, 0x1B, 0x20, 0x1F, 0x23, 0x23, 0x2F, 0x40, 0x4A, 0x48, 0x43, 0x3E, 0x20,
+ 0x06, 0xF9, 0xF0, 0xE4, 0xE9, 0xDC, 0xE7, 0xF2, 0xF6, 0xF8, 0xF5, 0xF1, 0xE0, 0xCA, 0xCB, 0xCC,
+ 0xE5, 0xF9, 0xFD, 0x0F, 0x1A, 0x1F, 0x1D, 0x24, 0x21, 0x32, 0x43, 0x49, 0x44, 0x44, 0x38, 0x16,
+ 0x02, 0xFA, 0xE8, 0xEA, 0xE4, 0xDF, 0xED, 0xF2, 0xFB, 0xF5, 0xF8, 0xEE, 0xDA, 0xCB, 0xCA, 0xCF,
+ 0xEC, 0xF7, 0x02, 0x12, 0x1D, 0x1C, 0x22, 0x1F, 0x25, 0x36, 0x45, 0x49, 0x43, 0x47, 0x2D, 0x13,
+ 0x01, 0xF6, 0xE7, 0xEB, 0xDF, 0xE2, 0xED, 0xF6, 0xF8, 0xF8, 0xF5, 0xED, 0xD3, 0xCD, 0xC7, 0xD7,
+ 0xEF, 0xF6, 0x05, 0x13, 0x1C, 0x1D, 0x20, 0x1F, 0x28, 0x3B, 0x48, 0x46, 0x47, 0x42, 0x2A, 0x0D,
+ 0x03, 0xF0, 0xEB, 0xE8, 0xDD, 0xE7, 0xED, 0xF8, 0xF7, 0xF7, 0xF6, 0xE4, 0xD3, 0xCA, 0xC7, 0xDD,
+ 0xEE, 0xF8, 0x06, 0x17, 0x19, 0x20, 0x1F, 0x20, 0x2E, 0x3F, 0x4A, 0x45, 0x4C, 0x40, 0x20, 0x0F,
+ 0xFE, 0xEE, 0xED, 0xE3, 0xE1, 0xE7, 0xF3, 0xF6, 0xF8, 0xF6, 0xF4, 0xDD, 0xD1, 0xC5, 0xC9, 0xE3,
+ 0xEF, 0xF9, 0x0C, 0x16, 0x1C, 0x1F, 0x1F, 0x22, 0x31, 0x46, 0x46, 0x49, 0x4B, 0x3A, 0x1C, 0x0D,
+ 0xF8, 0xEE, 0xEC, 0xE0, 0xE2, 0xEB, 0xF3, 0xF9, 0xF5, 0xFB, 0xEC, 0xDC, 0xCE, 0xC2, 0xD2, 0xE5,
+ 0xEF, 0xFD, 0x0F, 0x16, 0x1D, 0x20, 0x1D, 0x24, 0x37, 0x46, 0x46, 0x49, 0x4C, 0x2E, 0x1C, 0x07,
+ 0xF4, 0xF0, 0xE7, 0xE2, 0xE3, 0xEE, 0xF6, 0xF6, 0xF9, 0xF8, 0xE8, 0xDA, 0xC8, 0xC6, 0xD7, 0xE9,
+ 0xEF, 0x05, 0x0F, 0x19, 0x1E, 0x1E, 0x1E, 0x25, 0x3E, 0x43, 0x45, 0x4E, 0x45, 0x2B, 0x19, 0x01,
+ 0xF4, 0xEE, 0xE7, 0xDE, 0xE7, 0xEE, 0xF9, 0xF5, 0xFD, 0xF5, 0xE6, 0xD9, 0xC5, 0xC9, 0xDC, 0xE8,
+ 0xF5, 0x05, 0x11, 0x19, 0x1E, 0x1F, 0x1B, 0x2D, 0x3C, 0x44, 0x43, 0x4E, 0x3B, 0x27, 0x13, 0xFB,
+ 0xF4, 0xEC, 0xE3, 0xE1, 0xE7, 0xF4, 0xF6, 0xF9, 0xFE, 0xF1, 0xE8, 0xD2, 0xC7, 0xCD, 0xE1, 0xE9,
+ 0xFA, 0x09, 0x14, 0x1D, 0x20, 0x1D, 0x1F, 0x31, 0x3F, 0x3E, 0x48, 0x4A, 0x34, 0x24, 0x0A, 0xFA,
+ 0xF0, 0xEB, 0xDF, 0xE2, 0xE9, 0xF5, 0xF6, 0xFC, 0xFC, 0xF0, 0xE4, 0xCE, 0xC6, 0xD3, 0xE1, 0xED,
+ 0xFE, 0x0B, 0x17, 0x1C, 0x22, 0x19, 0x24, 0x35, 0x3F, 0x3F, 0x4C, 0x45, 0x32, 0x20, 0x06, 0xF8,
+ 0xF1, 0xE5, 0xE1, 0xE1, 0xEF, 0xF5, 0xF7, 0xFF, 0xF8, 0xF2, 0xE0, 0xCC, 0xC8, 0xD7, 0xE3, 0xEF,
+ 0xFF, 0x0D, 0x17, 0x1F, 0x1D, 0x1B, 0x25, 0x3A, 0x3B, 0x43, 0x4D, 0x3E, 0x30, 0x19, 0x04, 0xF6,
+ 0xEE, 0xE5, 0xE0, 0xE5, 0xF2, 0xF5, 0xFB, 0xFE, 0xF9, 0xEE, 0xDC, 0xC9, 0xCC, 0xDA, 0xE4, 0xF3,
+ 0x01, 0x0F, 0x17, 0x1F, 0x1B, 0x1A, 0x2B, 0x39, 0x3B, 0x47, 0x4A, 0x3E, 0x2C, 0x16, 0x00, 0xF7,
+ 0xEB, 0xE5, 0xDF, 0xE9, 0xF4, 0xF6, 0xFE, 0xFD, 0xF8, 0xEC, 0xD5, 0xC8, 0xCF, 0xDC, 0xE7, 0xF5,
+ 0x06, 0x0E, 0x1B, 0x1C, 0x18, 0x1B, 0x30, 0x37, 0x3D, 0x4B, 0x48, 0x3B, 0x2A, 0x10, 0x00, 0xF4,
+ 0xEB, 0xE0, 0xDF, 0xED, 0xF2, 0xF8, 0xFD, 0xFD, 0xF6, 0xE8, 0xD0, 0xC8, 0xD2, 0xDC, 0xE7, 0xF9,
+ 0x05, 0x12, 0x1B, 0x1D, 0x16, 0x22, 0x33, 0x36, 0x41, 0x4B, 0x46, 0x38, 0x26, 0x0C, 0xFF, 0xF2,
+ 0xEA, 0xDF, 0xE5, 0xEF, 0xF3, 0xF9, 0xFF, 0xFB, 0xF6, 0xE1, 0xCC, 0xCB, 0xD4, 0xDF, 0xEB, 0xFD,
+ 0x06, 0x15, 0x1C, 0x1A, 0x16, 0x27, 0x32, 0x37, 0x45, 0x4C, 0x42, 0x38, 0x20, 0x0B, 0xFC, 0xF2,
+ 0xE6, 0xDE, 0xE8, 0xEE, 0xF4, 0xFB, 0xFD, 0xFB, 0xF2, 0xDC, 0xCB, 0xCD, 0xD7, 0xDF, 0xEF, 0xFC,
+ 0x09, 0x15, 0x1D, 0x16, 0x1A, 0x2C, 0x32, 0x3B, 0x48, 0x4A, 0x42, 0x34, 0x1A, 0x08, 0xF9, 0xF1,
+ 0xE2, 0xE3, 0xE9, 0xF0, 0xF6, 0xFD, 0xFC, 0xFB, 0xEE, 0xD5, 0xCB, 0xCE, 0xD8, 0xE3, 0xF3, 0xFF,
+ 0x0C, 0x19, 0x1B, 0x14, 0x1F, 0x2C, 0x32, 0x3D, 0x49, 0x47, 0x40, 0x2C, 0x16, 0x03, 0xF8, 0xEC,
+ 0xE1, 0xE4, 0xEB, 0xF1, 0xF9, 0xFC, 0xFD, 0xFA, 0xE8, 0xD2, 0xCA, 0xD1, 0xD7, 0xE7, 0xF5, 0x01,
+ 0x0F, 0x1B, 0x18, 0x15, 0x23, 0x2D, 0x33, 0x43, 0x49, 0x49, 0x3E, 0x29, 0x13, 0x01, 0xF7, 0xE8,
+ 0xE1, 0xE5, 0xEB, 0xF2, 0xF9, 0xFC, 0xFD, 0xF8, 0xE2, 0xCF, 0xCD, 0xD1, 0xDC, 0xEA, 0xF7, 0x04,
+ 0x13, 0x1C, 0x15, 0x18, 0x27, 0x2D, 0x37, 0x45, 0x49, 0x48, 0x39, 0x24, 0x0D, 0x00, 0xF4, 0xE6,
+ 0xE1, 0xE7, 0xEC, 0xF4, 0xF9, 0xFB, 0xFE, 0xF3, 0xDD, 0xCE, 0xCF, 0xD2, 0xDF, 0xEC, 0xFA, 0x06,
+ 0x17, 0x1A, 0x15, 0x1C, 0x29, 0x2D, 0x3B, 0x46, 0x4B, 0x45, 0x36, 0x20, 0x0B, 0xFE, 0xF1, 0xE4,
+ 0xE4, 0xE8, 0xED, 0xF5, 0xF9, 0xFD, 0xFB, 0xEE, 0xD6, 0xCF, 0xCD, 0xD5, 0xE1, 0xEF, 0xFB, 0x0A,
+ 0x18, 0x18, 0x15, 0x1F, 0x27, 0x2F, 0x3F, 0x47, 0x4B, 0x42, 0x33, 0x1A, 0x0A, 0xFC, 0xEE, 0xE4,
+ 0xE6, 0xE9, 0xF0, 0xF6, 0xFA, 0xFD, 0xFA, 0xE8, 0xD4, 0xCE, 0xCE, 0xD7, 0xE3, 0xF2, 0xFD, 0x0E,
+ 0x19, 0x15, 0x16, 0x21, 0x26, 0x33, 0x3F, 0x48, 0x49, 0x41, 0x2E, 0x18, 0x08, 0xFA, 0xEB, 0xE4,
+ 0xE7, 0xEA, 0xF2, 0xF7, 0xFB, 0xFD, 0xF8, 0xE1, 0xD3, 0xCB, 0xD0, 0xD7, 0xE7, 0xF2, 0xFF, 0x12,
+ 0x19, 0x13, 0x1A, 0x21, 0x28, 0x36, 0x40, 0x49, 0x47, 0x3D, 0x29, 0x14, 0x06, 0xF8, 0xE9, 0xE6,
+ 0xE7, 0xED, 0xF3, 0xF8, 0xFB, 0xFE, 0xF2, 0xDF, 0xD2, 0xCD, 0xD1, 0xDB, 0xE9, 0xF3, 0x02, 0x14,
+ 0x16, 0x13, 0x1D, 0x21, 0x2C, 0x37, 0x44, 0x49, 0x47, 0x3A, 0x25, 0x12, 0x04, 0xF4, 0xE9, 0xE7,
+ 0xE8, 0xEE, 0xF5, 0xF8, 0xFC, 0xFD, 0xEE, 0xDC, 0xD0, 0xCE, 0xD2, 0xDF, 0xEB, 0xF6, 0x07, 0x16,
+ 0x13, 0x17, 0x1D, 0x23, 0x2E, 0x3B, 0x45, 0x4A, 0x45, 0x36, 0x21, 0x10, 0x01, 0xF0, 0xEA, 0xE6,
+ 0xEB, 0xEF, 0xF7, 0xF8, 0xFF, 0xFA, 0xEA, 0xD8, 0xD0, 0xCD, 0xD4, 0xE0, 0xEC, 0xF7, 0x0C, 0x15,
+ 0x12, 0x19, 0x1D, 0x26, 0x30, 0x3E, 0x47, 0x49, 0x44, 0x32, 0x1E, 0x0F, 0xFE, 0xF0, 0xE8, 0xE7,
+ 0xEA, 0xF2, 0xF5, 0xFA, 0xFF, 0xF8, 0xE6, 0xD6, 0xCF, 0xCD, 0xD5, 0xE3, 0xEB, 0xFB, 0x0F, 0x12,
+ 0x15, 0x19, 0x1F, 0x27, 0x34, 0x3F, 0x3F
+};
+
+const uint8_t SfxPlayer::_musicDataSample7[] = {
+ 0x03, 0x46, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0F, 0x0A, 0x0F, 0x08, 0x15, 0x0D,
+ 0x11, 0x16, 0x08, 0x0B, 0x17, 0xFA, 0x0E, 0x17, 0x06, 0x0F, 0x0F, 0x13, 0x11, 0xFA, 0x28, 0xFF,
+ 0x0E, 0x23, 0xFD, 0x14, 0x1F, 0xF2, 0x1C, 0x0F, 0x00, 0x37, 0xF7, 0x04, 0x1B, 0xF3, 0x1C, 0x0F,
+ 0x06, 0x0F, 0x12, 0xFF, 0x14, 0x0D, 0x10, 0x0B, 0xF4, 0x4F, 0xCF, 0x28, 0xEA, 0x2B, 0xFF, 0x10,
+ 0x2F, 0xE4, 0x13, 0xFF, 0x12, 0x0F, 0x16, 0x07, 0x2F, 0xD4, 0x24, 0xFF, 0x00, 0x18, 0x11, 0x00,
+ 0x17, 0x02, 0x11, 0xFA, 0x2F, 0xEA, 0x18, 0xFF, 0x0C, 0x04, 0x30, 0xFF, 0x24, 0xE3, 0x30, 0xFF,
+ 0x00, 0x3F, 0xEF, 0x1C, 0xFC, 0x17, 0xEF, 0x28, 0xF7, 0x2B, 0x03, 0x07, 0x10, 0x22, 0xEF, 0x18,
+ 0x2F, 0xD9, 0x21, 0x08, 0x1F, 0xEC, 0x2C, 0xFC, 0x05, 0x0C, 0x2C, 0xF0, 0x1F, 0x0A, 0x02, 0x17,
+ 0x0C, 0xF2, 0x34, 0xFF, 0xF8, 0x19, 0x13, 0x09, 0xFC, 0x55, 0xAF, 0x10, 0x37, 0xD2, 0x31, 0x08,
+ 0x07, 0x09, 0x0C, 0x17, 0x04, 0xFE, 0x24, 0x00, 0x1D, 0x10, 0x10, 0x07, 0x19, 0x03, 0x05, 0x06,
+ 0x07, 0x0F, 0x18, 0x17, 0x00, 0x24, 0xDF, 0x20, 0x07, 0xF8, 0x1F, 0x00, 0x3F, 0xD2, 0x2A, 0x07,
+ 0x0C, 0x05, 0x20, 0x0F, 0xE8, 0x27, 0x0D, 0x0C, 0x0F, 0x1D, 0xEF, 0x1C, 0x00, 0x13, 0x0E, 0x00,
+ 0x2B, 0xF5, 0x08, 0x1F, 0xD0, 0x50, 0xFB, 0xE8, 0x3F, 0xE0, 0x20, 0x05, 0x1C, 0xEE, 0x1C, 0x02,
+ 0x2B, 0xE3, 0x20, 0x17, 0xE0, 0x58, 0xDF, 0x20, 0x11, 0xEF, 0x1C, 0x06, 0x27, 0xFA, 0x07, 0x1F,
+ 0xE1, 0x2C, 0xFF, 0x0A, 0x1F, 0x06, 0xFF, 0x00, 0x2F, 0xEB, 0x1A, 0x08, 0x2B, 0xDB, 0x20, 0x1B,
+ 0xE8, 0x30, 0xF7, 0x08, 0x23, 0xEF, 0x20, 0xFF, 0x27, 0xFB, 0x12, 0x0A, 0x15, 0xFE, 0x0E, 0x17,
+ 0x11, 0xF7, 0x11, 0x09, 0x15, 0xFF, 0x10, 0x1F, 0xEA, 0x1A, 0x0C, 0xFF, 0x19, 0x1C, 0xFF, 0x15,
+ 0x06, 0x05, 0x11, 0x19, 0xFA, 0x12, 0x0B, 0x04, 0x1B, 0x0E, 0x04, 0x13, 0x15, 0xFF, 0x04, 0x27,
+ 0xEC, 0x24, 0xFF, 0x00, 0x2B, 0xE6, 0x20, 0x08, 0x06, 0x0B, 0x08, 0x1B, 0x00, 0x1C, 0x0B, 0x04,
+ 0x09, 0x0C, 0x0F, 0x06, 0x0C, 0x13, 0x07, 0x03, 0x1F, 0xF3, 0x20, 0x0D, 0xF8, 0x20, 0x0B, 0xF8,
+ 0x26, 0xFF, 0x14, 0x0F, 0x09, 0x09, 0x0E, 0x1B, 0xE4, 0x40, 0xF7, 0x00, 0x22, 0xFF, 0x11, 0x00,
+ 0x2B, 0xFA, 0x0A, 0x11, 0x16, 0x03, 0x0C, 0x1B, 0xFC, 0x07, 0x08, 0x1F, 0xE2, 0x40, 0xFB, 0x00,
+ 0x23, 0xFB, 0x10, 0x16, 0x05, 0x12, 0x06, 0x06, 0x2C, 0xEF, 0x10, 0x17, 0xF8, 0x20, 0xFF, 0x10,
+ 0x0A, 0x0B, 0x12, 0x05, 0x17, 0x0C, 0x0D, 0x08, 0x0E, 0x12, 0x08, 0x17, 0x05, 0x0C, 0x0F, 0x04,
+ 0x10, 0x15, 0x04, 0x1D, 0xEF, 0x2C, 0xFF, 0x00, 0x1F, 0x03, 0x12, 0x08, 0x09, 0x18, 0x0B, 0x00,
+ 0x1E, 0xFF, 0x08, 0xFF, 0x2C, 0xFD, 0x08, 0x1F, 0xF2, 0x14, 0x17, 0xF4, 0x2D, 0xFF, 0x02, 0x2F,
+ 0xF0, 0x07, 0x10, 0x17, 0xFD, 0x20, 0xFF, 0x0C, 0x0E, 0x06, 0x08, 0x19, 0xFB, 0x12, 0x17, 0xF8,
+ 0x18, 0x0B, 0x17, 0xF8, 0x16, 0x07, 0x0C, 0x13, 0x08, 0x07, 0x04, 0x0F, 0x09, 0x10, 0x08, 0x1F,
+ 0xEC, 0x18, 0x17, 0xF8, 0x1F, 0x05, 0x04, 0x17, 0xFF, 0x18, 0x0F, 0x08, 0x0C, 0x08, 0x10, 0x04,
+ 0x16, 0x09, 0x16, 0x02, 0x0E, 0x12, 0x0F, 0xF6, 0x32, 0xEF, 0x10, 0x1F, 0xF7, 0x16, 0x0C, 0x0E,
+ 0x16, 0xFB, 0x13, 0x04, 0x11, 0x11, 0x06, 0x1F, 0xFB, 0x12, 0x0F, 0x04, 0x14, 0x07, 0x04, 0x1F,
+ 0xF3, 0x18, 0x09, 0x16, 0x06, 0x0A, 0x13, 0xFC, 0x1A, 0x07, 0x0C, 0x1C, 0xEF, 0x14, 0x15, 0xF1,
+ 0x30, 0xFF, 0x08, 0x1C, 0xEF, 0x18, 0x08, 0x13, 0x09, 0x0C, 0x17, 0xF0, 0x28, 0x07, 0x08, 0x1D,
+ 0xFD, 0x10, 0x15, 0xFD, 0x28, 0xFF, 0x04, 0x1C, 0xF7, 0x18, 0x07, 0x1E, 0x07, 0x08, 0x17, 0xF4,
+ 0x1C, 0x07, 0x0B, 0x0C, 0x1A, 0x06, 0x06, 0x19, 0x04, 0x10, 0x04, 0x14, 0x07, 0x0A, 0x1F, 0xEE,
+ 0x28, 0xFF, 0x09, 0x0F, 0x10, 0x07, 0x08, 0x18, 0x02, 0x14, 0x00, 0x1C, 0x05, 0x0B, 0x06, 0x1F,
+ 0xEF, 0x18, 0x0F, 0x0C, 0x0E, 0x06, 0x13, 0x02, 0x0D, 0x14, 0x04, 0x13, 0x0B, 0x0F, 0x04, 0x1B,
+ 0xFF, 0x0C, 0x13, 0x06, 0x0E, 0x0E, 0x0F, 0x09, 0x0B, 0x0E, 0x06, 0x12, 0x0B, 0x0A, 0x11, 0x0B,
+ 0x09, 0x0C, 0x0E, 0x07, 0x11, 0x08, 0x11, 0x0F, 0x09, 0x0C, 0x17, 0xFA, 0x1A, 0x07, 0x16, 0xFF,
+ 0x18, 0x0F, 0x02, 0x17, 0x05, 0x10, 0x04, 0x19, 0x06, 0x11, 0x02, 0x1D, 0xFF, 0x08, 0x1B, 0xFE,
+ 0x18, 0x0A, 0x11, 0x07, 0x14, 0x0E, 0x0C, 0x0D, 0x0D, 0x0E, 0x03, 0x16, 0x09, 0x10, 0x03, 0x1A,
+ 0x06, 0x08, 0x1B, 0xFF, 0x11, 0x0B, 0x0A, 0x0E, 0x0A, 0x0F, 0x06, 0x16, 0x06, 0x06, 0x15, 0x05,
+ 0x14, 0x0B, 0x07, 0x12, 0x0A, 0x11, 0x02, 0x1C, 0x09, 0x07, 0x1E, 0x00, 0x10, 0x0D, 0x0C, 0x12,
+ 0x0A, 0x0E, 0x0D, 0x12, 0x07, 0x08, 0x0F, 0x0E, 0x11, 0x08, 0x17, 0x06, 0x0E, 0x0D, 0x0F, 0x10,
+ 0x07, 0x10, 0x10, 0x08, 0x0E, 0x09, 0x10, 0x0B, 0x10, 0x0A, 0x14, 0x06, 0x10, 0x0F, 0x0D, 0x09,
+ 0x0E, 0x0B, 0x12, 0x07, 0x0E, 0x13, 0x05, 0x15, 0x08, 0x0D, 0x0D, 0x0E, 0x0B, 0x12, 0x09, 0x0B,
+ 0x10, 0x0E, 0x0B, 0x0B, 0x10, 0x08, 0x17, 0x03, 0x13, 0x0A, 0x15, 0x03, 0x10, 0x0F, 0x05, 0x14,
+ 0x0D, 0x0E, 0x0B, 0x13, 0x0A, 0x0E, 0x10, 0x07, 0x10, 0x17, 0xFC, 0x1C, 0x0D, 0x02, 0x1A, 0x0B,
+ 0x0B, 0x0F, 0x0F, 0x0C, 0x0E, 0x0A, 0x11, 0x0A, 0x11, 0x09, 0x10, 0x0F, 0x0B, 0x17, 0x0B, 0x0C,
+ 0x0E, 0x0F, 0x0A, 0x11, 0x0B, 0x0E, 0x0C, 0x10, 0x0E, 0x08, 0x14, 0x0B, 0x0E, 0x14, 0x04, 0x16,
+ 0x0A, 0x10, 0x0E, 0x0C, 0x0F, 0x02, 0x1B, 0x07, 0x10, 0x13, 0x08, 0x14, 0x07, 0x12, 0x07, 0x10,
+ 0x0F, 0x08, 0x14, 0x0B, 0x0E, 0x0F, 0x0E, 0x10, 0x0B, 0x11, 0x10, 0x0E, 0x0D, 0x08, 0x14, 0x0B,
+ 0x0E, 0x0F, 0x10, 0x0D, 0x0C, 0x13, 0x0C, 0x10, 0x0F, 0x0C, 0x0E, 0x0E, 0x0F, 0x00, 0x00
+};
+
+const uint8_t SfxPlayer::_musicDataSample8[] = {
+ 0x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00
+};
+
+const SfxPlayer::Module SfxPlayer::_module68 = {
+ { _musicDataSample1, _musicDataSample8, _musicDataSample3, _musicDataSample4, _musicDataSample8 },
+ _musicData68
+};
+
+const SfxPlayer::Module SfxPlayer::_module70 = {
+ { _musicDataSample1, _musicDataSample2, _musicDataSample3, _musicDataSample3, _musicDataSample8 },
+ _musicData70
+};
+
+const SfxPlayer::Module SfxPlayer::_module72 = {
+ { _musicDataSample1, _musicDataSample2, _musicDataSample5, _musicDataSample4, _musicDataSample8 },
+ _musicData72
+};
+
+const SfxPlayer::Module SfxPlayer::_module73 = {
+ { _musicDataSample1, _musicDataSample2, _musicDataSample4, _musicDataSample3, _musicDataSample8 },
+ _musicData73
+};
+
+const SfxPlayer::Module SfxPlayer::_module74 = {
+ { _musicDataSample1, _musicDataSample2, _musicDataSample5, _musicDataSample6, _musicDataSample7 },
+ _musicData74
+};
+
+const SfxPlayer::Module SfxPlayer::_module75 = {
+ { _musicDataSample1, _musicDataSample2, _musicDataSample5, _musicDataSample6, _musicDataSample7 },
+ _musicData75
+};
+
+const uint16_t SfxPlayer::_periodTable[] = {
+ 0x434, 0x3F8, 0x3C0, 0x38A, 0x358, 0x328, 0x2FA, 0x2D0, 0x2A6, 0x280,
+ 0x25C, 0x23A, 0x21A, 0x1FC, 0x1E0, 0x1C5, 0x1AC, 0x194, 0x17D, 0x168,
+ 0x153, 0x140, 0x12E, 0x11D, 0x10D, 0x0FE, 0x0F0, 0x0E2, 0x0D6, 0x0CA,
+ 0x0BE, 0x0B4, 0x0AA, 0x0A0, 0x097, 0x08F, 0x087, 0x07F, 0x078, 0x071
+};
diff --git a/systemstub.h b/systemstub.h
new file mode 100644
index 0000000..d1560d5
--- /dev/null
+++ b/systemstub.h
@@ -0,0 +1,100 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 SYSTEMSTUB_H__
+#define SYSTEMSTUB_H__
+
+#include "intern.h"
+
+struct PlayerInput {
+ enum {
+ DIR_UP = 1 << 0,
+ DIR_DOWN = 1 << 1,
+ DIR_LEFT = 1 << 2,
+ DIR_RIGHT = 1 << 3
+ };
+ enum {
+ DF_FASTMODE = 1 << 0,
+ DF_DBLOCKS = 1 << 1,
+ DF_SETLIFE = 1 << 2
+ };
+
+ uint8_t dirMask;
+ bool enter;
+ bool space;
+ bool shift;
+ bool backspace;
+ bool escape;
+
+ char lastChar;
+
+ bool save;
+ bool load;
+ int stateSlot;
+
+ bool inpRecord;
+ bool inpReplay;
+
+ bool mirrorMode;
+
+ uint8_t dbgMask;
+ bool quit;
+};
+
+struct SystemStub {
+ typedef void (*AudioCallback)(void *param, int8_t *stream, int len);
+
+ PlayerInput _pi;
+
+ virtual ~SystemStub() {}
+
+ virtual void init(const char *title, int w, int h) = 0;
+ virtual void destroy() = 0;
+
+ virtual void setPalette(const uint8_t *pal, int n) = 0;
+ virtual void setPaletteEntry(int i, const Color *c) = 0;
+ virtual void getPaletteEntry(int i, Color *c) = 0;
+ virtual void setOverscanColor(int i) = 0;
+ virtual void copyRect(int x, int y, int w, int h, const uint8_t *buf, int pitch) = 0;
+ virtual void fadeScreen() = 0;
+ virtual void updateScreen(int shakeOffset) = 0;
+
+ virtual void processEvents() = 0;
+ virtual void sleep(int duration) = 0;
+ virtual uint32_t getTimeStamp() = 0;
+
+ virtual void startAudio(AudioCallback callback, void *param) = 0;
+ virtual void stopAudio() = 0;
+ virtual uint32_t getOutputSampleRate() = 0;
+ virtual void lockAudio() = 0;
+ virtual void unlockAudio() = 0;
+};
+
+struct LockAudioStack {
+ LockAudioStack(SystemStub *stub)
+ : _stub(stub) {
+ _stub->lockAudio();
+ }
+ ~LockAudioStack() {
+ _stub->unlockAudio();
+ }
+ SystemStub *_stub;
+};
+
+extern SystemStub *SystemStub_SDL_create();
+
+#endif // SYSTEMSTUB_H__
diff --git a/systemstub_sdl.cpp b/systemstub_sdl.cpp
new file mode 100644
index 0000000..2e78613
--- /dev/null
+++ b/systemstub_sdl.cpp
@@ -0,0 +1,619 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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
+#include "scaler.h"
+#include "systemstub.h"
+
+
+struct SystemStub_SDL : SystemStub {
+ enum {
+ MAX_BLIT_RECTS = 200,
+ SOUND_SAMPLE_RATE = 22050,
+ JOYSTICK_COMMIT_VALUE = 3200
+ };
+
+ uint16_t *_screenBuffer;
+ uint16_t *_fadeScreenBuffer;
+ SDL_Surface *_screenSurface;
+ bool _fullscreen;
+ int _currentScaler;
+ uint8_t _overscanColor;
+ uint16_t _pal[256];
+ int _screenW, _screenH;
+ SDL_Joystick *_joystick;
+ SDL_Rect _blitRects[MAX_BLIT_RECTS];
+ int _numBlitRects;
+ bool _fadeOnUpdateScreen;
+ void (*_audioCbProc)(void *, int8_t *, int);
+ void *_audioCbData;
+
+ virtual ~SystemStub_SDL() {}
+ virtual void init(const char *title, int w, int h);
+ virtual void destroy();
+ virtual void setPalette(const uint8_t *pal, int n);
+ virtual void setPaletteEntry(int i, const Color *c);
+ virtual void getPaletteEntry(int i, Color *c);
+ virtual void setOverscanColor(int i);
+ virtual void copyRect(int x, int y, int w, int h, const uint8_t *buf, int pitch);
+ virtual void fadeScreen();
+ virtual void updateScreen(int shakeOffset);
+ virtual void processEvents();
+ virtual void sleep(int duration);
+ virtual uint32_t getTimeStamp();
+ virtual void startAudio(AudioCallback callback, void *param);
+ virtual void stopAudio();
+ virtual uint32_t getOutputSampleRate();
+ virtual void lockAudio();
+ virtual void unlockAudio();
+
+ void processEvent(const SDL_Event &ev, bool &paused);
+ void updateScreen_GL(int shakeOffset);
+ void updateScreen_SW(int shakeOffset);
+ void prepareGfxMode();
+ void cleanupGfxMode();
+ void switchGfxMode(bool fullscreen, uint8_t scaler);
+ void flipGfx();
+ void forceGfxRedraw();
+ void drawRect(SDL_Rect *rect, uint8_t color, uint16_t *dst, uint16_t dstPitch);
+};
+
+SystemStub *SystemStub_SDL_create() {
+ return new SystemStub_SDL();
+}
+
+void SystemStub_SDL::init(const char *title, int w, int h) {
+ SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
+ SDL_ShowCursor(SDL_DISABLE);
+ SDL_WM_SetCaption(title, NULL);
+ memset(&_pi, 0, sizeof(_pi));
+ _screenW = w;
+ _screenH = h;
+ // allocate some extra bytes for the scaling routines
+ const int screenBufferSize = (w + 2) * (h + 2) * sizeof(uint16_t);
+ _screenBuffer = (uint16_t *)malloc(screenBufferSize);
+ if (!_screenBuffer) {
+ error("SystemStub_SDL::init() Unable to allocate offscreen buffer");
+ }
+ memset(_screenBuffer, 0, screenBufferSize);
+ _fadeScreenBuffer = 0;
+ _fadeOnUpdateScreen = false;
+ _fullscreen = false;
+ _currentScaler = SCALER_SCALE_3X;
+ memset(_pal, 0, sizeof(_pal));
+ prepareGfxMode();
+ _joystick = NULL;
+ if (SDL_NumJoysticks() > 0) {
+ _joystick = SDL_JoystickOpen(0);
+ }
+}
+
+void SystemStub_SDL::destroy() {
+ cleanupGfxMode();
+ if (SDL_JoystickOpened(0)) {
+ SDL_JoystickClose(_joystick);
+ }
+ SDL_Quit();
+}
+
+void SystemStub_SDL::setPalette(const uint8_t *pal, int n) {
+ assert(n <= 256);
+ for (int i = 0; i < n; ++i) {
+ uint8_t r = pal[i * 3 + 0];
+ uint8_t g = pal[i * 3 + 1];
+ uint8_t b = pal[i * 3 + 2];
+ _pal[i] = SDL_MapRGB(_screenSurface->format, r, g, b);
+ }
+}
+
+void SystemStub_SDL::setPaletteEntry(int i, const Color *c) {
+ uint8_t r = (c->r << 2) | (c->r & 3);
+ uint8_t g = (c->g << 2) | (c->g & 3);
+ uint8_t b = (c->b << 2) | (c->b & 3);
+ _pal[i] = SDL_MapRGB(_screenSurface->format, r, g, b);
+}
+
+void SystemStub_SDL::getPaletteEntry(int i, Color *c) {
+ SDL_GetRGB(_pal[i], _screenSurface->format, &c->r, &c->g, &c->b);
+ c->r >>= 2;
+ c->g >>= 2;
+ c->b >>= 2;
+}
+
+void SystemStub_SDL::setOverscanColor(int i) {
+ _overscanColor = i;
+}
+
+void SystemStub_SDL::copyRect(int x, int y, int w, int h, const uint8_t *buf, int pitch) {
+ if (_numBlitRects >= MAX_BLIT_RECTS) {
+ warning("SystemStub_SDL::copyRect() Too many blit rects, you may experience graphical glitches");
+ } else {
+ // extend the dirty region by 1 pixel for scalers accessing 'outer' pixels
+ --x;
+ --y;
+ w += 2;
+ h += 2;
+
+ if (x < 0) {
+ x = 0;
+ } else if (x >= _screenW) {
+ return;
+ }
+ if (y < 0) {
+ y = 0;
+ } else if (y >= _screenH) {
+ return;
+ }
+ if (x + w > _screenW) {
+ w = _screenW - x;
+ }
+ if (y + h > _screenH) {
+ h = _screenH - y;
+ }
+ SDL_Rect *br = &_blitRects[_numBlitRects];
+
+ br->x = _pi.mirrorMode ? _screenW - (x + w) : x;
+ br->y = y;
+ br->w = w;
+ br->h = h;
+ ++_numBlitRects;
+
+ uint16_t *p = _screenBuffer + (br->y + 1) * _screenW + (br->x + 1);
+ buf += y * pitch + x;
+
+ if (_pi.mirrorMode) {
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ p[i] = _pal[buf[w - 1 - i]];
+ }
+ p += _screenW;
+ buf += pitch;
+ }
+ } else {
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ p[i] = _pal[buf[i]];
+ }
+ p += _screenW;
+ buf += pitch;
+ }
+ }
+ if (_pi.dbgMask & PlayerInput::DF_DBLOCKS) {
+ drawRect(br, 0xE7, _screenBuffer + _screenW + 1, _screenW * 2);
+ }
+ }
+}
+
+void SystemStub_SDL::fadeScreen() {
+ const int fadeScreenBufferSize = _screenH * _screenW * sizeof(uint16_t);
+ if (!_fadeScreenBuffer) {
+ _fadeScreenBuffer = (uint16_t *)malloc(fadeScreenBufferSize);
+ assert(_fadeScreenBuffer);
+ }
+ _fadeOnUpdateScreen = true;
+ memcpy(_fadeScreenBuffer, _screenBuffer + _screenW + 1, fadeScreenBufferSize);
+}
+
+static uint16_t blendPixel16(uint16_t colorSrc, uint16_t colorDst, uint32_t mask, int step) {
+ const uint32_t pSrc = (colorSrc | (colorSrc << 16)) & mask;
+ const uint32_t pDst = (colorDst | (colorDst << 16)) & mask;
+ const uint32_t pRes = ((pDst - pSrc) * step / 16 + pSrc) & mask;
+ return pRes | (pRes >> 16);
+}
+
+void SystemStub_SDL::updateScreen(int shakeOffset) {
+ const int mul = _scalers[_currentScaler].factor;
+ if (_fadeOnUpdateScreen) {
+ const int tempScreenBufferSize = (_screenH + 2) * (_screenW + 2) * sizeof(uint16_t);
+ uint16_t *tempScreenBuffer = (uint16_t *)calloc(tempScreenBufferSize, 1);
+ assert(tempScreenBuffer);
+ const SDL_PixelFormat *pf = _screenSurface->format;
+ const uint32_t colorMask = (pf->Gmask << 16) | (pf->Rmask | pf->Bmask);
+ const uint16_t *screenBuffer = _screenBuffer + _screenW + 1;
+ for (int i = 1; i <= 16; ++i) {
+ for (int x = 0; x < _screenH * _screenW; ++x) {
+ tempScreenBuffer[_screenW + 1 + x] = blendPixel16(_fadeScreenBuffer[x], screenBuffer[x], colorMask, i);
+ }
+ SDL_LockSurface(_screenSurface);
+ uint16_t *dst = (uint16_t *)_screenSurface->pixels;
+ const uint16_t *src = tempScreenBuffer + _screenW + 1;
+ (*_scalers[_currentScaler].proc)(dst, _screenSurface->pitch, src, _screenW, _screenW, _screenH);
+ SDL_UnlockSurface(_screenSurface);
+ SDL_UpdateRect(_screenSurface, 0, 0, _screenW * mul, _screenH * mul);
+ SDL_Delay(30);
+ }
+ free(tempScreenBuffer);
+ _fadeOnUpdateScreen = false;
+ return;
+ }
+ if (shakeOffset == 0) {
+ for (int i = 0; i < _numBlitRects; ++i) {
+ SDL_Rect *br = &_blitRects[i];
+ int dx = br->x * mul;
+ int dy = br->y * mul;
+ SDL_LockSurface(_screenSurface);
+ uint16_t *dst = (uint16_t *)_screenSurface->pixels + dy * _screenSurface->pitch / 2 + dx;
+ const uint16_t *src = _screenBuffer + (br->y + 1) * _screenW + (br->x + 1);
+ (*_scalers[_currentScaler].proc)(dst, _screenSurface->pitch, src, _screenW, br->w, br->h);
+ SDL_UnlockSurface(_screenSurface);
+ br->x *= mul;
+ br->y *= mul;
+ br->w *= mul;
+ br->h *= mul;
+ }
+ SDL_UpdateRects(_screenSurface, _numBlitRects, _blitRects);
+ } else {
+ SDL_LockSurface(_screenSurface);
+ int w = _screenW;
+ int h = _screenH - shakeOffset;
+ uint16_t *dst = (uint16_t *)_screenSurface->pixels + shakeOffset * mul * _screenSurface->pitch / 2;
+ const uint16_t *src = _screenBuffer + _screenW + 1;
+ (*_scalers[_currentScaler].proc)(dst, _screenSurface->pitch, src, _screenW, w, h);
+ SDL_UnlockSurface(_screenSurface);
+
+ SDL_Rect r;
+ r.x = 0;
+ r.y = 0;
+ r.w = _screenW * mul;
+ r.h = shakeOffset * mul;
+ SDL_FillRect(_screenSurface, &r, _pal[_overscanColor]);
+
+ SDL_UpdateRect(_screenSurface, 0, 0, _screenW * mul, _screenH * mul);
+ }
+ _numBlitRects = 0;
+}
+
+void SystemStub_SDL::processEvents() {
+ while (true) {
+ bool paused = false;
+ SDL_Event ev;
+ while (SDL_PollEvent(&ev)) {
+ processEvent(ev, paused);
+ if (_pi.quit) {
+ return;
+ }
+ }
+ if (!paused) {
+ break;
+ }
+ SDL_Delay(100);
+ }
+}
+
+void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
+ switch (ev.type) {
+ case SDL_QUIT:
+ _pi.quit = true;
+ break;
+ case SDL_ACTIVEEVENT:
+ if (ev.active.state & SDL_APPINPUTFOCUS) {
+ paused = ev.active.gain == 0;
+ SDL_PauseAudio(paused ? 1 : 0);
+ }
+ break;
+ case SDL_JOYHATMOTION:
+ _pi.dirMask = 0;
+ if (ev.jhat.value & SDL_HAT_UP) {
+ _pi.dirMask |= PlayerInput::DIR_UP;
+ }
+ if (ev.jhat.value & SDL_HAT_DOWN) {
+ _pi.dirMask |= PlayerInput::DIR_DOWN;
+ }
+ if (ev.jhat.value & SDL_HAT_LEFT) {
+ _pi.dirMask |= PlayerInput::DIR_LEFT;
+ }
+ if (ev.jhat.value & SDL_HAT_RIGHT) {
+ _pi.dirMask |= PlayerInput::DIR_RIGHT;
+ }
+ break;
+ case SDL_JOYAXISMOTION:
+ switch (ev.jaxis.axis) {
+ case 0:
+ if (ev.jaxis.value > JOYSTICK_COMMIT_VALUE) {
+ _pi.dirMask |= PlayerInput::DIR_RIGHT;
+ if (_pi.dirMask & PlayerInput::DIR_LEFT) {
+ _pi.dirMask &= ~PlayerInput::DIR_LEFT;
+ }
+ } else if (ev.jaxis.value < -JOYSTICK_COMMIT_VALUE) {
+ _pi.dirMask |= PlayerInput::DIR_LEFT;
+ if (_pi.dirMask & PlayerInput::DIR_RIGHT) {
+ _pi.dirMask &= ~PlayerInput::DIR_RIGHT;
+ }
+ } else {
+ _pi.dirMask &= ~(PlayerInput::DIR_RIGHT | PlayerInput::DIR_LEFT);
+ }
+ break;
+ case 1:
+ if (ev.jaxis.value > JOYSTICK_COMMIT_VALUE) {
+ _pi.dirMask |= PlayerInput::DIR_DOWN;
+ if (_pi.dirMask & PlayerInput::DIR_UP) {
+ _pi.dirMask &= ~PlayerInput::DIR_UP;
+ }
+ } else if (ev.jaxis.value < -JOYSTICK_COMMIT_VALUE) {
+ _pi.dirMask |= PlayerInput::DIR_UP;
+ if (_pi.dirMask & PlayerInput::DIR_DOWN) {
+ _pi.dirMask &= ~PlayerInput::DIR_DOWN;
+ }
+ } else {
+ _pi.dirMask &= ~(PlayerInput::DIR_UP | PlayerInput::DIR_DOWN);
+ }
+ break;
+ }
+ break;
+ case SDL_JOYBUTTONDOWN:
+ switch (ev.jbutton.button) {
+ case 0:
+ _pi.space = true;
+ break;
+ case 1:
+ _pi.shift = true;
+ break;
+ case 2:
+ _pi.enter = true;
+ break;
+ case 3:
+ _pi.backspace = true;
+ break;
+ }
+ break;
+ case SDL_JOYBUTTONUP:
+ switch (ev.jbutton.button) {
+ case 0:
+ _pi.space = false;
+ break;
+ case 1:
+ _pi.shift = false;
+ break;
+ case 2:
+ _pi.enter = false;
+ break;
+ case 3:
+ _pi.backspace = false;
+ break;
+ }
+ break;
+ case SDL_KEYUP:
+ switch (ev.key.keysym.sym) {
+ case SDLK_LEFT:
+ _pi.dirMask &= ~PlayerInput::DIR_LEFT;
+ break;
+ case SDLK_RIGHT:
+ _pi.dirMask &= ~PlayerInput::DIR_RIGHT;
+ break;
+ case SDLK_UP:
+ _pi.dirMask &= ~PlayerInput::DIR_UP;
+ break;
+ case SDLK_DOWN:
+ _pi.dirMask &= ~PlayerInput::DIR_DOWN;
+ break;
+ case SDLK_SPACE:
+ _pi.space = false;
+ break;
+ case SDLK_RSHIFT:
+ case SDLK_LSHIFT:
+ _pi.shift = false;
+ break;
+ case SDLK_RETURN:
+ _pi.enter = false;
+ break;
+ case SDLK_ESCAPE:
+ _pi.escape = false;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SDL_KEYDOWN:
+ if (ev.key.keysym.mod & KMOD_ALT) {
+ if (ev.key.keysym.sym == SDLK_RETURN) {
+ switchGfxMode(!_fullscreen, _currentScaler);
+ } else if (ev.key.keysym.sym == SDLK_KP_PLUS || ev.key.keysym.sym == SDLK_PAGEUP) {
+ uint8_t s = _currentScaler + 1;
+ if (s < NUM_SCALERS) {
+ switchGfxMode(_fullscreen, s);
+ }
+ } else if (ev.key.keysym.sym == SDLK_KP_MINUS || ev.key.keysym.sym == SDLK_PAGEDOWN) {
+ int8_t s = _currentScaler - 1;
+ if (_currentScaler > 0) {
+ switchGfxMode(_fullscreen, s);
+ }
+ }
+ break;
+ } else if (ev.key.keysym.mod & KMOD_CTRL) {
+ if (ev.key.keysym.sym == SDLK_f) {
+ _pi.dbgMask ^= PlayerInput::DF_FASTMODE;
+ } else if (ev.key.keysym.sym == SDLK_b) {
+ _pi.dbgMask ^= PlayerInput::DF_DBLOCKS;
+ } else if (ev.key.keysym.sym == SDLK_i) {
+ _pi.dbgMask ^= PlayerInput::DF_SETLIFE;
+ } else if (ev.key.keysym.sym == SDLK_m) {
+ _pi.mirrorMode = !_pi.mirrorMode;
+ flipGfx();
+ } else if (ev.key.keysym.sym == SDLK_s) {
+ _pi.save = true;
+ } else if (ev.key.keysym.sym == SDLK_l) {
+ _pi.load = true;
+ } else if (ev.key.keysym.sym == SDLK_KP_PLUS || ev.key.keysym.sym == SDLK_PAGEUP) {
+ _pi.stateSlot = 1;
+ } else if (ev.key.keysym.sym == SDLK_KP_MINUS || ev.key.keysym.sym == SDLK_PAGEDOWN) {
+ _pi.stateSlot = -1;
+ } else if (ev.key.keysym.sym == SDLK_r) {
+ _pi.inpRecord = true;
+ } else if (ev.key.keysym.sym == SDLK_p) {
+ _pi.inpReplay = true;
+ }
+ }
+ _pi.lastChar = ev.key.keysym.sym;
+ switch (ev.key.keysym.sym) {
+ case SDLK_LEFT:
+ _pi.dirMask |= PlayerInput::DIR_LEFT;
+ break;
+ case SDLK_RIGHT:
+ _pi.dirMask |= PlayerInput::DIR_RIGHT;
+ break;
+ case SDLK_UP:
+ _pi.dirMask |= PlayerInput::DIR_UP;
+ break;
+ case SDLK_DOWN:
+ _pi.dirMask |= PlayerInput::DIR_DOWN;
+ break;
+ case SDLK_BACKSPACE:
+ case SDLK_TAB:
+ _pi.backspace = true;
+ break;
+ case SDLK_SPACE:
+ _pi.space = true;
+ break;
+ case SDLK_RSHIFT:
+ case SDLK_LSHIFT:
+ _pi.shift = true;
+ break;
+ case SDLK_RETURN:
+ _pi.enter = true;
+ break;
+ case SDLK_ESCAPE:
+ _pi.escape = true;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void SystemStub_SDL::sleep(int duration) {
+ SDL_Delay(duration);
+}
+
+uint32_t SystemStub_SDL::getTimeStamp() {
+ return SDL_GetTicks();
+}
+
+static void mixAudioS8ToU8(void *param, uint8_t *buf, int len) {
+ SystemStub_SDL *stub = (SystemStub_SDL *)param;
+ stub->_audioCbProc(stub->_audioCbData, (int8_t *)buf, len);
+ for (int i = 0; i < len; ++i) {
+ buf[i] ^= 0x80;
+ }
+}
+
+void SystemStub_SDL::startAudio(AudioCallback callback, void *param) {
+ SDL_AudioSpec desired, obtained;
+ memset(&desired, 0, sizeof(desired));
+ desired.freq = SOUND_SAMPLE_RATE;
+ desired.format = AUDIO_U8;
+ desired.channels = 1;
+ desired.samples = 2048;
+ desired.callback = mixAudioS8ToU8;
+ desired.userdata = this;
+ if (SDL_OpenAudio(&desired, &obtained) == 0) {
+ _audioCbProc = callback;
+ _audioCbData = param;
+ SDL_PauseAudio(0);
+ } else {
+ error("SystemStub_SDL::startAudio() Unable to open sound device");
+ }
+}
+
+void SystemStub_SDL::stopAudio() {
+ SDL_CloseAudio();
+}
+
+uint32_t SystemStub_SDL::getOutputSampleRate() {
+ return SOUND_SAMPLE_RATE;
+}
+
+void SystemStub_SDL::lockAudio() {
+ SDL_LockAudio();
+}
+
+void SystemStub_SDL::unlockAudio() {
+ SDL_UnlockAudio();
+}
+
+void SystemStub_SDL::prepareGfxMode() {
+ int w = _screenW * _scalers[_currentScaler].factor;
+ int h = _screenH * _scalers[_currentScaler].factor;
+ _screenSurface = SDL_SetVideoMode(w, h, 16, _fullscreen ? (SDL_FULLSCREEN | SDL_HWSURFACE) : SDL_HWSURFACE);
+ if (!_screenSurface) {
+ error("SystemStub_SDL::prepareGfxMode() Unable to allocate _screen buffer");
+ }
+ forceGfxRedraw();
+}
+
+void SystemStub_SDL::cleanupGfxMode() {
+ if (_screenBuffer) {
+ free(_screenBuffer);
+ _screenBuffer = 0;
+ }
+ if (_fadeScreenBuffer) {
+ free(_fadeScreenBuffer);
+ _fadeScreenBuffer = 0;
+ }
+ if (_screenSurface) {
+ // freed by SDL_Quit()
+ _screenSurface = 0;
+ }
+}
+
+void SystemStub_SDL::switchGfxMode(bool fullscreen, uint8_t scaler) {
+ SDL_FreeSurface(_screenSurface);
+ _fullscreen = fullscreen;
+ _currentScaler = scaler;
+ prepareGfxMode();
+ forceGfxRedraw();
+}
+
+void SystemStub_SDL::flipGfx() {
+ uint16_t scanline[256];
+ assert(_screenW <= 256);
+ uint16_t *p = _screenBuffer + _screenW + 1;
+ for (int y = 0; y < _screenH; ++y) {
+ p += _screenW;
+ for (int x = 0; x < _screenW; ++x) {
+ scanline[x] = *--p;
+ }
+ memcpy(p, scanline, _screenW * sizeof(uint16_t));
+ p += _screenW;
+ }
+ forceGfxRedraw();
+}
+
+void SystemStub_SDL::forceGfxRedraw() {
+ _numBlitRects = 1;
+ _blitRects[0].x = 0;
+ _blitRects[0].y = 0;
+ _blitRects[0].w = _screenW;
+ _blitRects[0].h = _screenH;
+}
+
+void SystemStub_SDL::drawRect(SDL_Rect *rect, uint8_t color, uint16_t *dst, uint16_t dstPitch) {
+ dstPitch >>= 1;
+ int x1 = rect->x;
+ int y1 = rect->y;
+ int x2 = rect->x + rect->w - 1;
+ int y2 = rect->y + rect->h - 1;
+ assert(x1 >= 0 && x2 < _screenW && y1 >= 0 && y2 < _screenH);
+ for (int i = x1; i <= x2; ++i) {
+ *(dst + y1 * dstPitch + i) = *(dst + y2 * dstPitch + i) = _pal[color];
+ }
+ for (int j = y1; j <= y2; ++j) {
+ *(dst + j * dstPitch + x1) = *(dst + j * dstPitch + x2) = _pal[color];
+ }
+}
diff --git a/unpack.cpp b/unpack.cpp
new file mode 100644
index 0000000..e9444dc
--- /dev/null
+++ b/unpack.cpp
@@ -0,0 +1,108 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "unpack.h"
+
+struct UnpackCtx {
+ int size, datasize;
+ uint32_t crc;
+ uint32_t bits;
+ uint8_t *dst;
+ const uint8_t *src;
+};
+
+static int shiftBit(UnpackCtx *uc, int CF) {
+ int rCF = (uc->bits & 1);
+ uc->bits >>= 1;
+ if (CF) {
+ uc->bits |= 0x80000000;
+ }
+ return rCF;
+}
+
+static int nextBit(UnpackCtx *uc) {
+ int CF = shiftBit(uc, 0);
+ if (uc->bits == 0) {
+ uc->bits = READ_BE_UINT32(uc->src); uc->src -= 4;
+ uc->crc ^= uc->bits;
+ CF = shiftBit(uc, 1);
+ }
+ return CF;
+}
+
+static uint16_t getBits(UnpackCtx *uc, uint8_t num_bits) {
+ uint16_t c = 0;
+ while (num_bits--) {
+ c <<= 1;
+ if (nextBit(uc)) {
+ c |= 1;
+ }
+ }
+ return c;
+}
+
+static void unpackHelper1(UnpackCtx *uc, uint8_t num_bits, uint8_t add_count) {
+ uint16_t count = getBits(uc, num_bits) + add_count + 1;
+ uc->datasize -= count;
+ while (count--) {
+ *uc->dst = (uint8_t)getBits(uc, 8);
+ --uc->dst;
+ }
+}
+
+static void unpackHelper2(UnpackCtx *uc, uint8_t num_bits) {
+ uint16_t i = getBits(uc, num_bits);
+ uint16_t count = uc->size + 1;
+ uc->datasize -= count;
+ while (count--) {
+ *uc->dst = *(uc->dst + i);
+ --uc->dst;
+ }
+}
+
+bool delphine_unpack(uint8_t *dst, const uint8_t *src, int len) {
+ UnpackCtx uc;
+ uc.src = src + len - 4;
+ uc.datasize = READ_BE_UINT32(uc.src); uc.src -= 4;
+ uc.dst = dst + uc.datasize - 1;
+ uc.size = 0;
+ uc.crc = READ_BE_UINT32(uc.src); uc.src -= 4;
+ uc.bits = READ_BE_UINT32(uc.src); uc.src -= 4;
+ uc.crc ^= uc.bits;
+ do {
+ if (!nextBit(&uc)) {
+ uc.size = 1;
+ if (!nextBit(&uc)) {
+ unpackHelper1(&uc, 3, 0);
+ } else {
+ unpackHelper2(&uc, 8);
+ }
+ } else {
+ uint16_t c = getBits(&uc, 2);
+ if (c == 3) {
+ unpackHelper1(&uc, 8, 8);
+ } else if (c < 2) {
+ uc.size = c + 2;
+ unpackHelper2(&uc, c + 9);
+ } else {
+ uc.size = getBits(&uc, 8);
+ unpackHelper2(&uc, 12);
+ }
+ }
+ } while (uc.datasize > 0);
+ return uc.crc == 0;
+}
diff --git a/unpack.h b/unpack.h
new file mode 100644
index 0000000..b0e06a1
--- /dev/null
+++ b/unpack.h
@@ -0,0 +1,25 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 UNPACK_H__
+#define UNPACK_H__
+
+#include "intern.h"
+
+extern bool delphine_unpack(uint8_t *dst, const uint8_t *src, int len);
+
+#endif // UNPACK_H__
diff --git a/util.cpp b/util.cpp
new file mode 100644
index 0000000..195a69b
--- /dev/null
+++ b/util.cpp
@@ -0,0 +1,61 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 .
+ */
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include
+#endif
+#include
+#include "util.h"
+
+
+uint16_t g_debugMask;
+
+void debug(uint16_t cm, const char *msg, ...) {
+ char buf[1024];
+ if (cm & g_debugMask) {
+ va_list va;
+ va_start(va, msg);
+ vsprintf(buf, msg, va);
+ va_end(va);
+ printf("%s\n", buf);
+ fflush(stdout);
+ }
+}
+
+void error(const char *msg, ...) {
+ char buf[1024];
+ va_list va;
+ va_start(va, msg);
+ vsnprintf(buf, sizeof(buf), msg, va);
+ va_end(va);
+ fprintf(stderr, "ERROR: %s!\n", buf);
+#ifdef _WIN32
+ MessageBox(0, buf, g_caption, MB_ICONERROR);
+#endif
+ exit(-1);
+}
+
+void warning(const char *msg, ...) {
+ char buf[1024];
+ va_list va;
+ va_start(va, msg);
+ vsnprintf(buf, sizeof(buf), msg, va);
+ va_end(va);
+ fprintf(stderr, "WARNING: %s!\n", buf);
+}
+
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..b4e7d16
--- /dev/null
+++ b/util.h
@@ -0,0 +1,45 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 UTIL_H__
+#define UTIL_H__
+
+#include "intern.h"
+
+enum {
+ DBG_INFO = 1 << 0,
+ DBG_RES = 1 << 1,
+ DBG_MENU = 1 << 2,
+ DBG_UNPACK = 1 << 3,
+ DBG_PGE = 1 << 4,
+ DBG_VIDEO = 1 << 5,
+ DBG_GAME = 1 << 6,
+ DBG_COL = 1 << 7,
+ DBG_SND = 1 << 8,
+ DBG_CUT = 1 << 9,
+ DBG_MOD = 1 << 10,
+ DBG_SFX = 1 << 11,
+ DBG_FILE = 1 << 12
+};
+
+extern uint16_t g_debugMask;
+
+extern void debug(uint16_t cm, const char *msg, ...);
+extern void error(const char *msg, ...);
+extern void warning(const char *msg, ...);
+
+#endif // UTIL_H__
diff --git a/video.cpp b/video.cpp
new file mode 100644
index 0000000..8bbb9bf
--- /dev/null
+++ b/video.cpp
@@ -0,0 +1,831 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 "resource.h"
+#include "systemstub.h"
+#include "unpack.h"
+#include "video.h"
+
+
+Video::Video(Resource *res, SystemStub *stub)
+ : _res(res), _stub(stub) {
+ _frontLayer = (uint8_t *)malloc(GAMESCREEN_W * GAMESCREEN_H);
+ memset(_frontLayer, 0, GAMESCREEN_W * GAMESCREEN_H);
+ _backLayer = (uint8_t *)malloc(GAMESCREEN_W * GAMESCREEN_H);
+ memset(_backLayer, 0, GAMESCREEN_W * GAMESCREEN_H);
+ _tempLayer = (uint8_t *)malloc(GAMESCREEN_W * GAMESCREEN_H);
+ memset(_tempLayer, 0, GAMESCREEN_W * GAMESCREEN_H);
+ _tempLayer2 = (uint8_t *)malloc(GAMESCREEN_W * GAMESCREEN_H);
+ memset(_tempLayer2, 0, GAMESCREEN_W * GAMESCREEN_H);
+ _screenBlocks = (uint8_t *)malloc((GAMESCREEN_W / SCREENBLOCK_W) * (GAMESCREEN_H / SCREENBLOCK_H));
+ memset(_screenBlocks, 0, (GAMESCREEN_W / SCREENBLOCK_W) * (GAMESCREEN_H / SCREENBLOCK_H));
+ _fullRefresh = true;
+ _shakeOffset = 0;
+ _charFrontColor = 0;
+ _charTransparentColor = 0;
+ _charShadowColor = 0;
+}
+
+Video::~Video() {
+ free(_frontLayer);
+ free(_backLayer);
+ free(_tempLayer);
+ free(_tempLayer2);
+ free(_screenBlocks);
+}
+
+void Video::markBlockAsDirty(int16_t x, int16_t y, uint16_t w, uint16_t h) {
+ debug(DBG_VIDEO, "Video::markBlockAsDirty(%d, %d, %d, %d)", x, y, w, h);
+ assert(x >= 0 && x + w <= GAMESCREEN_W && y >= 0 && y + h <= GAMESCREEN_H);
+ int bx1 = x / SCREENBLOCK_W;
+ int by1 = y / SCREENBLOCK_H;
+ int bx2 = (x + w - 1) / SCREENBLOCK_W;
+ int by2 = (y + h - 1) / SCREENBLOCK_H;
+ assert(bx2 < GAMESCREEN_W / SCREENBLOCK_W && by2 < GAMESCREEN_H / SCREENBLOCK_H);
+ for (; by1 <= by2; ++by1) {
+ for (int i = bx1; i <= bx2; ++i) {
+ _screenBlocks[by1 * (GAMESCREEN_W / SCREENBLOCK_W) + i] = 2;
+ }
+ }
+}
+
+void Video::updateScreen() {
+ debug(DBG_VIDEO, "Video::updateScreen()");
+// _fullRefresh = true;
+ if (_fullRefresh) {
+ _stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _frontLayer, 256);
+ _stub->updateScreen(_shakeOffset);
+ _fullRefresh = false;
+ } else {
+ int i, j;
+ int count = 0;
+ uint8_t *p = _screenBlocks;
+ for (j = 0; j < GAMESCREEN_H / SCREENBLOCK_H; ++j) {
+ uint16_t nh = 0;
+ for (i = 0; i < GAMESCREEN_W / SCREENBLOCK_W; ++i) {
+ if (p[i] != 0) {
+ --p[i];
+ ++nh;
+ } else if (nh != 0) {
+ int16_t x = (i - nh) * SCREENBLOCK_W;
+ _stub->copyRect(x, j * SCREENBLOCK_H, nh * SCREENBLOCK_W, SCREENBLOCK_H, _frontLayer, 256);
+ nh = 0;
+ ++count;
+ }
+ }
+ if (nh != 0) {
+ int16_t x = (i - nh) * SCREENBLOCK_W;
+ _stub->copyRect(x, j * SCREENBLOCK_H, nh * SCREENBLOCK_W, SCREENBLOCK_H, _frontLayer, 256);
+ ++count;
+ }
+ p += GAMESCREEN_W / SCREENBLOCK_W;
+ }
+ if (count != 0) {
+ _stub->updateScreen(_shakeOffset);
+ }
+ }
+ if (_shakeOffset != 0) {
+ _shakeOffset = 0;
+ _fullRefresh = true;
+ }
+}
+
+void Video::fullRefresh() {
+ debug(DBG_VIDEO, "Video::fullRefresh()");
+ _fullRefresh = true;
+ memset(_screenBlocks, 0, (GAMESCREEN_W / SCREENBLOCK_W) * (GAMESCREEN_H / SCREENBLOCK_H));
+}
+
+void Video::fadeOut() {
+ debug(DBG_VIDEO, "Video::fadeOut()");
+ _stub->fadeScreen();
+// fadeOutPalette();
+}
+
+void Video::fadeOutPalette() {
+ for (int step = 16; step >= 0; --step) {
+ for (int c = 0; c < 256; ++c) {
+ Color col;
+ _stub->getPaletteEntry(c, &col);
+ col.r = col.r * step >> 4;
+ col.g = col.g * step >> 4;
+ col.b = col.b * step >> 4;
+ _stub->setPaletteEntry(c, &col);
+ }
+ fullRefresh();
+ updateScreen();
+ _stub->sleep(50);
+ }
+}
+
+void Video::setPaletteColorBE(int num, int offset) {
+ const int color = READ_BE_UINT16(_res->_pal + offset * 2);
+ Color c;
+ c.r = (color & 0x00F) << 2;
+ c.g = (color & 0x0F0) >> 2;
+ c.b = (color & 0xF00) >> 6;
+ if (color != 0) {
+ c.r |= 3;
+ c.g |= 3;
+ c.b |= 3;
+ }
+ _stub->setPaletteEntry(num, &c);
+}
+
+void Video::setPaletteSlotBE(int palSlot, int palNum) {
+ debug(DBG_VIDEO, "Video::setPaletteSlotBE()");
+ const uint8_t *p = _res->_pal + palNum * 0x20;
+ for (int i = 0; i < 16; ++i) {
+ const int color = READ_BE_UINT16(p); p += 2;
+ Color c;
+ c.r = (color & 0x00F) << 2;
+ c.g = (color & 0x0F0) >> 2;
+ c.b = (color & 0xF00) >> 6;
+ if (color != 0) {
+ c.r |= 3;
+ c.g |= 3;
+ c.b |= 3;
+ }
+ _stub->setPaletteEntry(palSlot * 0x10 + i, &c);
+ }
+}
+
+void Video::setPaletteSlotLE(int palSlot, const uint8_t *palData) {
+ debug(DBG_VIDEO, "Video::setPaletteSlotLE()");
+ for (int i = 0; i < 16; ++i) {
+ uint16_t color = READ_LE_UINT16(palData); palData += 2;
+ Color c;
+ c.b = (color & 0x00F) << 2;
+ c.g = (color & 0x0F0) >> 2;
+ c.r = (color & 0xF00) >> 6;
+ _stub->setPaletteEntry(palSlot * 0x10 + i, &c);
+ }
+}
+
+void Video::setTextPalette() {
+ debug(DBG_VIDEO, "Video::setTextPalette()");
+ setPaletteSlotLE(0xE, _textPal);
+}
+
+void Video::setPalette0xF() {
+ debug(DBG_VIDEO, "Video::setPalette0xF()");
+ const uint8_t *p = _palSlot0xF;
+ for (int i = 0; i < 16; ++i) {
+ Color c;
+ c.r = *p++ >> 2;
+ c.g = *p++ >> 2;
+ c.b = *p++ >> 2;
+ _stub->setPaletteEntry(0xF0 + i, &c);
+ }
+}
+
+static void PC_decodeMapHelper(int sz, const uint8_t *src, uint8_t *dst) {
+ const uint8_t *end = src + sz;
+ while (src < end) {
+ int16_t code = (int8_t)*src++;
+ if (code < 0) {
+ const int len = 1 - code;
+ memset(dst, *src++, len);
+ dst += len;
+ } else {
+ ++code;
+ memcpy(dst, src, code);
+ src += code;
+ dst += code;
+ }
+ }
+}
+
+void Video::PC_decodeMap(int level, int room) {
+ debug(DBG_VIDEO, "Video::PC_decodeMap(%d)", room);
+ assert(room < 0x40);
+ int32_t off = READ_LE_UINT32(_res->_map + room * 6);
+ if (off == 0) {
+ error("Invalid room %d", room);
+ }
+ bool packed = true;
+ if (off < 0) {
+ off = -off;
+ packed = false;
+ }
+ const uint8_t *p = _res->_map + off;
+ _mapPalSlot1 = *p++;
+ _mapPalSlot2 = *p++;
+ _mapPalSlot3 = *p++;
+ _mapPalSlot4 = *p++;
+ if (level == 4 && room == 60) {
+ // workaround for wrong palette colors (fire)
+ _mapPalSlot4 = 5;
+ }
+ if (packed) {
+ uint8_t *vid = _frontLayer;
+ for (int i = 0; i < 4; ++i) {
+ const int sz = READ_LE_UINT16(p); p += 2;
+ PC_decodeMapHelper(sz, p, _res->_memBuf); p += sz;
+ memcpy(vid, _res->_memBuf, 256 * 56);
+ vid += 256 * 56;
+ }
+ } else {
+ for (int i = 0; i < 4; ++i) {
+ for (int y = 0; y < 224; ++y) {
+ for (int x = 0; x < 64; ++x) {
+ _frontLayer[i + x * 4 + 256 * y] = p[256 * 56 * i + x + 64 * y];
+ }
+ }
+ }
+ }
+ memcpy(_backLayer, _frontLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+}
+
+void Video::PC_setLevelPalettes() {
+ debug(DBG_VIDEO, "Video::PC_setLevelPalettes()");
+ if (_unkPalSlot2 == 0) {
+ _unkPalSlot2 = _mapPalSlot3;
+ }
+ if (_unkPalSlot1 == 0) {
+ _unkPalSlot1 = _mapPalSlot3;
+ }
+ setPaletteSlotBE(0x0, _mapPalSlot1);
+ setPaletteSlotBE(0x1, _mapPalSlot2);
+ setPaletteSlotBE(0x2, _mapPalSlot3);
+ setPaletteSlotBE(0x3, _mapPalSlot4);
+ if (_unkPalSlot1 == _mapPalSlot3) {
+ setPaletteSlotLE(4, _conradPal1);
+ } else {
+ setPaletteSlotLE(4, _conradPal2);
+ }
+ // slot 5 is monster palette
+ setPaletteSlotBE(0x8, _mapPalSlot1);
+ setPaletteSlotBE(0x9, _mapPalSlot2);
+ setPaletteSlotBE(0xA, _unkPalSlot2);
+ setPaletteSlotBE(0xB, _mapPalSlot4);
+ // slots 0xC and 0xD are cutscene palettes
+ setTextPalette();
+}
+
+void Video::PC_decodeIcn(const uint8_t *src, int num, uint8_t *dst) {
+ const int offset = READ_LE_UINT16(src + num * 2);
+ const uint8_t *p = src + offset + 2;
+ for (int i = 0; i < 16 * 16 / 2; ++i) {
+ *dst++ = p[i] >> 4;
+ *dst++ = p[i] & 15;
+ }
+}
+
+void Video::PC_decodeSpc(const uint8_t *src, int w, int h, uint8_t *dst) {
+ const int size = w * h / 2;
+ for (int i = 0; i < size; ++i) {
+ *dst++ = src[i] >> 4;
+ *dst++ = src[i] & 15;
+ }
+}
+
+static void AMIGA_blit3pNxN(uint8_t *dst, int pitch, int w, int h, const uint8_t *src) {
+ const int planarSize = w * 2 * h;
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ for (int i = 0; i < 16; ++i) {
+ int color = 0;
+ const int mask = 1 << (15 - i);
+ for (int bit = 0; bit < 3; ++bit) {
+ if (READ_BE_UINT16(src + bit * planarSize) & mask) {
+ color |= 1 << bit;
+ }
+ }
+ dst[x * 16 + i] = color;
+ }
+ src += 2;
+ }
+ dst += pitch;
+ }
+}
+
+static void AMIGA_blit4p16xN(uint8_t *dst, int w, int h, const uint8_t *src) {
+ const int planarSize = w * 2 * h;
+ assert(w == 1);
+ for (int y = 0; y < h; ++y) {
+ for (int i = 0; i < 16; ++i) {
+ int color = 0;
+ const int mask = 1 << (15 - i);
+ for (int bit = 0; bit < 4; ++bit) {
+ if (READ_BE_UINT16(src + bit * planarSize) & mask) {
+ color |= 1 << bit;
+ }
+ }
+ dst[i] = color;
+ }
+ src += 2;
+ dst += 16;
+ }
+}
+
+static void AMIGA_blit4p8xN(uint8_t *dst, int w, int h, const uint8_t *src) {
+ assert(w == 8);
+ for (int y = 0; y < h; ++y) {
+ for (int i = 0; i < 8; ++i) {
+ int color = 0;
+ const int mask = 1 << (7 - i);
+ for (int bit = 0; bit < 4; ++bit) {
+ if (src[bit] & mask) {
+ color |= 1 << bit;
+ }
+ }
+ dst[i] = color;
+ }
+ src += 4;
+ dst += w;
+ }
+}
+
+static void AMIGA_blit4pNxN(uint8_t *dst, int w, int h, const uint8_t *src) {
+ const int planarSize = w / 8 * h;
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w / 8; ++x) {
+ for (int i = 0; i < 8; ++i) {
+ int color = 0;
+ const int mask = 1 << (7 - i);
+ for (int bit = 0; bit < 4; ++bit) {
+ if (src[bit * planarSize] & mask) {
+ color |= 1 << bit;
+ }
+ }
+ dst[x * 8 + i] = color;
+ }
+ ++src;
+ }
+ dst += w;
+ }
+}
+
+static void AMIGA_blit4pNxN_mask(uint8_t *dst, int x0, int y0, int w, int h, uint8_t *src, uint8_t *mask, int size) {
+ dst += y0 * 256 + x0;
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w * 2; ++x) {
+ for (int i = 0; i < 8; ++i) {
+ const int c_mask = 1 << (7 - i);
+ int color = 0;
+ for (int j = 0; j < 4; ++j) {
+ if (mask[j * size] & c_mask) {
+ color |= 1 << j;
+ }
+ }
+ if (*src & c_mask) {
+ const int px = x0 + 8 * x + i;
+ const int py = y0 + y;
+ if (px >= 0 && px < 256 && py >= 0 && py < 224) {
+ dst[8 * x + i] = color;
+ }
+ }
+ }
+ ++src;
+ ++mask;
+ }
+ dst += 256;
+ }
+}
+
+static void AMIGA_decodeRLE(uint8_t *dst, const uint8_t *src) {
+ int code = READ_BE_UINT16(src) & 0x7FFF; src += 2;
+ const uint8_t *end = src + code;
+ do {
+ code = *src++;
+ if ((code & 0x80) == 0) {
+ ++code;
+ memcpy(dst, src, code);
+ src += code;
+ } else {
+ code = 1 - ((int8_t)code);
+ memset(dst, *src, code);
+ ++src;
+ }
+ dst += code;
+ } while (src < end);
+ assert(src == end);
+}
+
+static void AMIGA_decodeSgd(uint8_t *dst, const uint8_t *src, const uint8_t *data) {
+ int num = -1;
+ uint8_t buf[256 * 32];
+ int count = READ_BE_UINT16(src) - 1; src += 2;
+ do {
+ int d2 = READ_BE_UINT16(src); src += 2;
+ int d0 = READ_BE_UINT16(src); src += 2;
+ int d1 = READ_BE_UINT16(src); src += 2;
+ if (d2 != 0xFFFF) {
+ d2 &= ~(1 << 15);
+ const int offset = READ_BE_UINT32(data + d2 * 4);
+ if (offset < 0) {
+ const uint8_t *ptr = data - offset;
+ const int size = READ_BE_UINT16(ptr); ptr += 2;
+ if (num != d2) {
+ num = d2;
+ assert(size <= (int)sizeof(buf));
+ memcpy(buf, ptr, size);
+ }
+ } else {
+ if (num != d2) {
+ num = d2;
+ const int size = READ_BE_UINT16(data + offset) & 0x7FFF;
+ assert(size <= (int)sizeof(buf));
+ AMIGA_decodeRLE(buf, data + offset);
+ }
+ }
+ }
+ const int w = (buf[0] + 1) >> 1;
+ const int h = buf[1] + 1;
+ const int planarSize = READ_BE_UINT16(buf + 2);
+ AMIGA_blit4pNxN_mask(dst, (int16_t)d0, (int16_t)d1, w, h, buf + 4, buf + 4 + planarSize, planarSize);
+ } while (--count >= 0);
+}
+
+static const uint8_t *AMIGA_mirrorY(const uint8_t *a2) {
+ static uint8_t buf[32];
+
+ a2 += 24;
+ for (int j = 0; j < 4; ++j) {
+ for (int i = 0; i < 8; ++i) {
+ buf[31 - j * 8 - i] = *a2++;
+ }
+ a2 -= 16;
+ }
+ return buf;
+}
+
+static const uint8_t *AMIGA_mirrorX(const uint8_t *a2) {
+ static uint8_t buf[32];
+
+ for (int i = 0; i < 32; ++i) {
+ uint8_t mask = 0;
+ for (int bit = 0; bit < 8; ++bit) {
+ if (a2[i] & (1 << bit)) {
+ mask |= 1 << (7 - bit);
+ }
+ }
+ buf[i] = mask;
+ }
+ return buf;
+}
+
+static void AMIGA_blit4p8x8(uint8_t *dst, int pitch, const uint8_t *src, int pal, int colorKey = -1) {
+ for (int y = 0; y < 8; ++y) {
+ for (int i = 0; i < 8; ++i) {
+ const int mask = 1 << (7 - i);
+ int color = 0;
+ for (int bit = 0; bit < 4; ++bit) {
+ if (src[8 * bit] & mask) {
+ color |= 1 << bit;
+ }
+ }
+ if (color != colorKey) {
+ dst[i] = pal + color;
+ }
+ }
+ ++src;
+ dst += pitch;
+ }
+}
+
+static void AMIGA_decodeLevHelper(uint8_t *dst, const uint8_t *src, int offset10, int offset12, const uint8_t *a5, bool sgdBuf) {
+ if (offset10 != 0) {
+ const uint8_t *a0 = src + offset10;
+ for (int y = 0; y < 224; y += 8) {
+ for (int x = 0; x < 256; x += 8) {
+ const int d3 = READ_BE_UINT16(a0); a0 += 2;
+ const int d0 = d3 & 0x7FF;
+ if (d0 != 0) {
+ const uint8_t *a2 = a5 + d0 * 32;
+ if ((d3 & (1 << 12)) != 0) {
+ a2 = AMIGA_mirrorY(a2);
+ }
+ if ((d3 & (1 << 11)) != 0) {
+ a2 = AMIGA_mirrorX(a2);
+ }
+ int mask = 0;
+ if ((d3 < (1 << 15)) == 0) {
+ mask = 0x80;
+ }
+ AMIGA_blit4p8x8(dst + y * 256 + x, 256, a2, mask);
+ }
+ }
+ }
+ }
+ if (offset12 != 0) {
+ const uint8_t *a0 = src + offset12;
+ for (int y = 0; y < 224; y += 8) {
+ for (int x = 0; x < 256; x += 8) {
+ int d3 = READ_BE_UINT16(a0); a0 += 2;
+ int d0 = d3 & 0x7FF;
+ if (d0 != 0 && sgdBuf) {
+ d0 -= 896;
+ }
+ if (d0 != 0) {
+ const uint8_t *a2 = a5 + d0 * 32;
+ if ((d3 & (1 << 12)) != 0) {
+ a2 = AMIGA_mirrorY(a2);
+ }
+ if ((d3 & (1 << 11)) != 0) {
+ a2 = AMIGA_mirrorX(a2);
+ }
+ int mask = 0;
+ if ((d3 & 0x6000) != 0 && sgdBuf) {
+ mask = 0x10;
+ } else if ((d3 < (1 << 15)) == 0) {
+ mask = 0x80;
+ }
+ AMIGA_blit4p8x8(dst + y * 256 + x, 256, a2, mask, 0);
+ }
+ }
+ }
+ }
+}
+
+void Video::AMIGA_decodeLev(int level, int room) {
+ uint8_t *tmp = _res->_memBuf;
+ const int offset = READ_BE_UINT32(_res->_lev + room * 4);
+ if (!delphine_unpack(tmp, _res->_lev, offset)) {
+ error("Bad CRC for level %d room %d", level, room);
+ }
+ uint16_t offset10 = READ_BE_UINT16(tmp + 10);
+ const uint16_t offset12 = READ_BE_UINT16(tmp + 12);
+ const uint16_t offset14 = READ_BE_UINT16(tmp + 14);
+ static const int kTempMbkSize = 1024;
+ uint8_t *buf = (uint8_t *)malloc(kTempMbkSize * 32);
+ if (!buf) {
+ error("Unable to allocate mbk temporary buffer");
+ }
+ int sz = 0;
+ memset(buf, 0, 32);
+ sz += 32;
+ const uint8_t *a1 = tmp + offset14;
+ for (bool loop = true; loop;) {
+ int d0 = READ_BE_UINT16(a1); a1 += 2;
+ if (d0 & 0x8000) {
+ d0 &= ~0x8000;
+ loop = false;
+ }
+ const int d1 = _res->getBankDataSize(d0);
+ const uint8_t *a6 = _res->findBankData(d0);
+ if (!a6) {
+ a6 = _res->loadBankData(d0);
+ }
+ const int d3 = *a1++;
+ if (d3 == 255) {
+ assert(sz + d1 < kTempMbkSize * 32);
+ memcpy(buf + sz, a6, d1);
+ sz += d1;
+ } else {
+ for (int i = 0; i < d3 + 1; ++i) {
+ const int d4 = *a1++;
+ assert(sz + 32 < kTempMbkSize * 32);
+ memcpy(buf + sz, a6 + d4 * 32, 32);
+ sz += 32;
+ }
+ }
+ }
+ memset(_frontLayer, 0, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ if (tmp[1] != 0) {
+ assert(_res->_sgd);
+ AMIGA_decodeSgd(_frontLayer, tmp + offset10, _res->_sgd);
+ offset10 = 0;
+ }
+ AMIGA_decodeLevHelper(_frontLayer, tmp, offset10, offset12, buf, tmp[1] != 0);
+ memcpy(_backLayer, _frontLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
+ uint16_t num[4];
+ for (int i = 0; i < 4; ++i) {
+ num[i] = READ_BE_UINT16(tmp + 2 + i * 2);
+ }
+ _mapPalSlot1 = num[1];
+ _mapPalSlot2 = num[2];
+ setPaletteSlotBE(0x0, num[0]);
+ for (int i = 1; i < 5; ++i) {
+ setPaletteSlotBE(i, _mapPalSlot2);
+ }
+ setPaletteSlotBE(0x6, _mapPalSlot2);
+ setPaletteSlotBE(0x8, num[0]);
+ setPaletteSlotBE(0xA, _mapPalSlot2);
+}
+
+void Video::AMIGA_decodeSpm(const uint8_t *src, uint8_t *dst) {
+ uint8_t buf[256 * 32];
+ const int size = READ_BE_UINT16(src + 3) & 0x7FFF;
+ assert(size <= (int)sizeof(buf));
+ AMIGA_decodeRLE(buf, src + 3);
+ const int w = (src[2] >> 7) + 1;
+ const int h = src[2] & 0x7F;
+ AMIGA_blit3pNxN(dst, w * 16, w, h, buf);
+}
+
+void Video::AMIGA_decodeIcn(const uint8_t *src, int num, uint8_t *dst) {
+ for (int i = 0; i < num; ++i) {
+ const int h = 1 + *src++;
+ const int w = 1 + *src++;
+ const int size = w * h * 8;
+ src += 4 + size;
+ }
+ const int h = 1 + *src++;
+ const int w = 1 + *src++;
+ AMIGA_blit4p16xN(dst, w, h, src + 4);
+}
+
+void Video::AMIGA_decodeSpc(const uint8_t *src, int w, int h, uint8_t *dst) {
+ switch (w) {
+ case 8:
+ AMIGA_blit4p8xN(dst, w, h, src);
+ break;
+ default:
+ AMIGA_blit4pNxN(dst, w, h, src);
+ break;
+ }
+}
+
+void Video::drawSpriteSub1(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask) {
+ debug(DBG_VIDEO, "Video::drawSpriteSub1(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ if (src[i] != 0) {
+ dst[i] = src[i] | colMask;
+ }
+ }
+ src += pitch;
+ dst += 256;
+ }
+}
+
+void Video::drawSpriteSub2(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask) {
+ debug(DBG_VIDEO, "Video::drawSpriteSub2(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ if (src[-i] != 0) {
+ dst[i] = src[-i] | colMask;
+ }
+ }
+ src += pitch;
+ dst += 256;
+ }
+}
+
+void Video::drawSpriteSub3(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask) {
+ debug(DBG_VIDEO, "Video::drawSpriteSub3(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ if (src[i] != 0 && !(dst[i] & 0x80)) {
+ dst[i] = src[i] | colMask;
+ }
+ }
+ src += pitch;
+ dst += 256;
+ }
+}
+
+void Video::drawSpriteSub4(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask) {
+ debug(DBG_VIDEO, "Video::drawSpriteSub4(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ if (src[-i] != 0 && !(dst[i] & 0x80)) {
+ dst[i] = src[-i] | colMask;
+ }
+ }
+ src += pitch;
+ dst += 256;
+ }
+}
+
+void Video::drawSpriteSub5(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask) {
+ debug(DBG_VIDEO, "Video::drawSpriteSub5(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ if (src[i * pitch] != 0 && !(dst[i] & 0x80)) {
+ dst[i] = src[i * pitch] | colMask;
+ }
+ }
+ ++src;
+ dst += 256;
+ }
+}
+
+void Video::drawSpriteSub6(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask) {
+ debug(DBG_VIDEO, "Video::drawSpriteSub6(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ if (src[-i * pitch] != 0 && !(dst[i] & 0x80)) {
+ dst[i] = src[-i * pitch] | colMask;
+ }
+ }
+ ++src;
+ dst += 256;
+ }
+}
+
+void Video::PC_drawChar(uint8_t c, int16_t y, int16_t x) {
+ debug(DBG_VIDEO, "Video::PC_drawChar(0x%X, %d, %d)", c, y, x);
+ y *= 8;
+ x *= 8;
+ const uint8_t *src = _res->_fnt + (c - 32) * 32;
+ uint8_t *dst = _frontLayer + x + 256 * y;
+ for (int h = 0; h < 8; ++h) {
+ for (int i = 0; i < 4; ++i) {
+ uint8_t c1 = (*src & 0xF0) >> 4;
+ uint8_t c2 = (*src & 0x0F) >> 0;
+ ++src;
+
+ if (c1 != 0) {
+ if (c1 != 2) {
+ *dst = _charFrontColor;
+ } else {
+ *dst = _charShadowColor;
+ }
+ } else if (_charTransparentColor != 0xFF) {
+ *dst = _charTransparentColor;
+ }
+ ++dst;
+
+ if (c2 != 0) {
+ if (c2 != 2) {
+ *dst = _charFrontColor;
+ } else {
+ *dst = _charShadowColor;
+ }
+ } else if (_charTransparentColor != 0xFF) {
+ *dst = _charTransparentColor;
+ }
+ ++dst;
+ }
+ dst += 256 - 8;
+ }
+}
+
+void Video::AMIGA_drawStringChar(uint8_t *dst, int pitch, const uint8_t *src, uint8_t color, uint8_t chr) {
+ assert(chr >= 32);
+ AMIGA_decodeIcn(src, chr - 32, _res->_memBuf);
+ src = _res->_memBuf;
+ for (int y = 0; y < 8; ++y) {
+ for (int x = 0; x < 8; ++x) {
+ if (src[x] != 0) {
+ dst[x] = 0x1D;
+ }
+ }
+ src += 16;
+ dst += pitch;
+ }
+}
+
+void Video::PC_drawStringChar(uint8_t *dst, int pitch, const uint8_t *src, uint8_t color, uint8_t chr) {
+ assert(chr >= 32);
+ src += (chr - 32) * 8 * 4;
+ for (int y = 0; y < 8; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ const uint8_t c1 = src[x] >> 4;
+ if (c1 != 0) {
+ *dst = (c1 == 15) ? color : (0xE0 + c1);
+ }
+ ++dst;
+ const uint8_t c2 = src[x] & 15;
+ if (c2 != 0) {
+ *dst = (c2 == 15) ? color : (0xE0 + c2);
+ }
+ ++dst;
+ }
+ src += 4;
+ dst += pitch - CHAR_W;
+ }
+}
+
+const char *Video::drawString(const char *str, int16_t x, int16_t y, uint8_t col) {
+ debug(DBG_VIDEO, "Video::drawString('%s', %d, %d, 0x%X)", str, x, y, col);
+ void (Video::*drawCharFunc)(uint8_t *, int, const uint8_t *, uint8_t, uint8_t) = 0;
+ switch (_res->_type) {
+ case kResourceTypeAmiga:
+ drawCharFunc = &Video::AMIGA_drawStringChar;
+ break;
+ case kResourceTypePC:
+ drawCharFunc = &Video::PC_drawStringChar;
+ break;
+ }
+ int len = 0;
+ uint8_t *dst = _frontLayer + y * 256 + x;
+ while (1) {
+ const uint8_t c = *str++;
+ if (c == 0 || c == 0xB || c == 0xA) {
+ break;
+ }
+ (this->*drawCharFunc)(dst, 256, _res->_fnt, col, c);
+ dst += CHAR_W;
+ ++len;
+ }
+ markBlockAsDirty(x, y, len * 8, 8);
+ return str - 1;
+}
diff --git a/video.h b/video.h
new file mode 100644
index 0000000..c232e95
--- /dev/null
+++ b/video.h
@@ -0,0 +1,90 @@
+/* REminiscence - Flashback interpreter
+ * Copyright (C) 2005-2015 Gregory Montoir
+ *
+ * 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 VIDEO_H__
+#define VIDEO_H__
+
+#include "intern.h"
+
+struct Resource;
+struct SystemStub;
+
+struct Video {
+ enum {
+ GAMESCREEN_W = 256,
+ GAMESCREEN_H = 224,
+ SCREENBLOCK_W = 8,
+ SCREENBLOCK_H = 8,
+ CHAR_W = 8,
+ CHAR_H = 8
+ };
+
+ static const uint8_t _conradPal1[];
+ static const uint8_t _conradPal2[];
+ static const uint8_t _textPal[];
+ static const uint8_t _palSlot0xF[];
+
+ Resource *_res;
+ SystemStub *_stub;
+
+ uint8_t *_frontLayer;
+ uint8_t *_backLayer;
+ uint8_t *_tempLayer;
+ uint8_t *_tempLayer2;
+ uint8_t _unkPalSlot1, _unkPalSlot2;
+ uint8_t _mapPalSlot1, _mapPalSlot2, _mapPalSlot3, _mapPalSlot4;
+ uint8_t _charFrontColor;
+ uint8_t _charTransparentColor;
+ uint8_t _charShadowColor;
+ uint8_t *_screenBlocks;
+ bool _fullRefresh;
+ uint8_t _shakeOffset;
+
+ Video(Resource *res, SystemStub *stub);
+ ~Video();
+
+ void markBlockAsDirty(int16_t x, int16_t y, uint16_t w, uint16_t h);
+ void updateScreen();
+ void fullRefresh();
+ void fadeOut();
+ void fadeOutPalette();
+ void setPaletteColorBE(int num, int offset);
+ void setPaletteSlotBE(int palSlot, int palNum);
+ void setPaletteSlotLE(int palSlot, const uint8_t *palData);
+ void setTextPalette();
+ void setPalette0xF();
+ void PC_decodeMap(int level, int room);
+ void PC_setLevelPalettes();
+ void PC_decodeIcn(const uint8_t *src, int num, uint8_t *dst);
+ void PC_decodeSpc(const uint8_t *src, int w, int h, uint8_t *dst);
+ void AMIGA_decodeLev(int level, int room);
+ void AMIGA_decodeSpm(const uint8_t *src, uint8_t *dst);
+ void AMIGA_decodeIcn(const uint8_t *src, int num, uint8_t *dst);
+ void AMIGA_decodeSpc(const uint8_t *src, int w, int h, uint8_t *dst);
+ void drawSpriteSub1(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
+ void drawSpriteSub2(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
+ void drawSpriteSub3(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
+ void drawSpriteSub4(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
+ void drawSpriteSub5(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
+ void drawSpriteSub6(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
+ void PC_drawChar(uint8_t c, int16_t y, int16_t x);
+ void PC_drawStringChar(uint8_t *dst, int pitch, const uint8_t *src, uint8_t color, uint8_t chr);
+ void AMIGA_drawStringChar(uint8_t *dst, int pitch, const uint8_t *src, uint8_t color, uint8_t chr);
+ const char *drawString(const char *str, int16_t x, int16_t y, uint8_t col);
+};
+
+#endif // VIDEO_H__