2016-03-20 17:00:00 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* REminiscence - Flashback interpreter
|
2019-10-27 17:00:00 +01:00
|
|
|
* Copyright (C) 2005-2019 Gregory Montoir (cyx@users.sourceforge.net)
|
2015-08-02 18:00:00 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef RESOURCE_H__
|
|
|
|
#define RESOURCE_H__
|
|
|
|
|
|
|
|
#include "intern.h"
|
2016-03-20 17:00:00 +01:00
|
|
|
#include "resource_aba.h"
|
2018-02-10 17:00:00 +01:00
|
|
|
#include "resource_mac.h"
|
2015-08-02 18:00:00 +02:00
|
|
|
|
2018-02-10 17:00:00 +01:00
|
|
|
struct DecodeBuffer;
|
2015-08-02 18:00:00 +02:00
|
|
|
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,
|
2018-01-14 17:00:00 +01:00
|
|
|
LI_23_DEMO,
|
2015-08-02 18:00:00 +02:00
|
|
|
|
|
|
|
LI_NUM
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *_textsTableFR[];
|
|
|
|
static const char *_textsTableEN[];
|
|
|
|
static const char *_textsTableDE[];
|
|
|
|
static const char *_textsTableSP[];
|
|
|
|
static const char *_textsTableIT[];
|
2017-12-06 17:00:00 +01:00
|
|
|
|
2015-08-02 18:00:00 +02:00
|
|
|
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[];
|
2017-12-06 17:00:00 +01:00
|
|
|
static const uint8_t _stringsTableJP[];
|
|
|
|
|
|
|
|
static const uint8_t _level1TbnJP[];
|
|
|
|
static const uint8_t _level2TbnJP[];
|
|
|
|
static const uint8_t _level3TbnJP[];
|
|
|
|
static const uint8_t _level41TbnJP[];
|
|
|
|
static const uint8_t _level42TbnJP[];
|
|
|
|
static const uint8_t _level51TbnJP[];
|
|
|
|
static const uint8_t _level52TbnJP[];
|
|
|
|
|
|
|
|
static const uint8_t _cineBinJP[];
|
|
|
|
static const uint8_t _cineTxtJP[];
|
2015-08-02 18:00:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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,
|
2016-03-20 17:00:00 +01:00
|
|
|
OT_BNQ,
|
2015-08-02 18:00:00 +02:00
|
|
|
OT_SPM
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
NUM_SFXS = 66,
|
2016-03-20 17:00:00 +01:00
|
|
|
NUM_BANK_BUFFERS = 50,
|
2016-05-09 18:00:00 +02:00
|
|
|
NUM_CUTSCENE_TEXTS = 117,
|
2015-08-02 18:00:00 +02:00
|
|
|
NUM_SPRITES = 1287
|
|
|
|
};
|
|
|
|
|
2018-02-10 17:00:00 +01:00
|
|
|
enum {
|
2018-02-24 17:00:00 +01:00
|
|
|
kPaulaFreq = 3546897,
|
2018-03-28 18:00:00 +02:00
|
|
|
kClutSize = 1024,
|
|
|
|
kScratchBufferSize = 320 * 224 + 1024
|
2018-02-10 17:00:00 +01:00
|
|
|
};
|
|
|
|
|
2015-08-02 18:00:00 +02:00
|
|
|
static const uint16_t _voicesOffsetsTable[];
|
|
|
|
static const uint32_t _spmOffsetsTable[];
|
|
|
|
static const char *_splNames[];
|
2019-10-27 17:00:00 +01:00
|
|
|
static const uint8_t _gameSavedSoundData[];
|
|
|
|
static const uint16_t _gameSavedSoundLen;
|
2015-08-02 18:00:00 +02:00
|
|
|
|
|
|
|
FileSystem *_fs;
|
|
|
|
ResourceType _type;
|
|
|
|
Language _lang;
|
2016-03-20 17:00:00 +01:00
|
|
|
bool _isDemo;
|
|
|
|
ResourceAba *_aba;
|
2018-02-10 17:00:00 +01:00
|
|
|
ResourceMac *_mac;
|
2016-03-20 17:00:00 +01:00
|
|
|
uint16_t (*_readUint16)(const void *);
|
|
|
|
uint32_t (*_readUint32)(const void *);
|
2015-08-02 18:00:00 +02:00
|
|
|
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;
|
2016-03-20 17:00:00 +01:00
|
|
|
uint8_t *_bnq;
|
2015-08-02 18:00:00 +02:00
|
|
|
uint16_t _numObjectNodes;
|
|
|
|
ObjectNode *_objectNodesMap[255];
|
2018-01-14 17:00:00 +01:00
|
|
|
uint8_t *_scratchBuffer;
|
2015-08-02 18:00:00 +02:00
|
|
|
SoundFx *_sfxList;
|
|
|
|
uint8_t _numSfx;
|
|
|
|
uint8_t *_cmd;
|
|
|
|
uint8_t *_pol;
|
2016-05-09 18:00:00 +02:00
|
|
|
uint8_t *_cineStrings[NUM_CUTSCENE_TEXTS];
|
2015-08-02 18:00:00 +02:00
|
|
|
uint8_t *_cine_off;
|
|
|
|
uint8_t *_cine_txt;
|
|
|
|
const char **_textsTable;
|
|
|
|
const uint8_t *_stringsTable;
|
|
|
|
uint8_t *_bankData;
|
|
|
|
uint8_t *_bankDataHead;
|
|
|
|
uint8_t *_bankDataTail;
|
2016-03-20 17:00:00 +01:00
|
|
|
BankSlot _bankBuffers[NUM_BANK_BUFFERS];
|
2015-08-02 18:00:00 +02:00
|
|
|
int _bankBuffersCount;
|
2016-08-07 18:00:00 +02:00
|
|
|
uint8_t *_dem;
|
|
|
|
int _demLen;
|
2018-02-10 17:00:00 +01:00
|
|
|
uint32_t _resourceMacDataSize;
|
|
|
|
int _clutSize;
|
|
|
|
Color _clut[kClutSize];
|
|
|
|
uint8_t *_perso;
|
|
|
|
uint8_t *_monster;
|
|
|
|
uint8_t *_str;
|
2019-10-27 17:00:00 +01:00
|
|
|
uint8_t *_credits;
|
2015-08-02 18:00:00 +02:00
|
|
|
|
|
|
|
Resource(FileSystem *fs, ResourceType type, Language lang);
|
|
|
|
~Resource();
|
|
|
|
|
2016-03-20 17:00:00 +01:00
|
|
|
void init();
|
|
|
|
void fini();
|
|
|
|
|
2018-03-18 17:00:00 +01:00
|
|
|
void setLanguage(Language lang);
|
|
|
|
|
2016-03-20 17:00:00 +01:00
|
|
|
bool isDOS() const { return _type == kResourceTypeDOS; }
|
|
|
|
bool isAmiga() const { return _type == kResourceTypeAmiga; }
|
2018-03-28 18:00:00 +02:00
|
|
|
bool isMac() const { return _type == kResourceTypeMac; }
|
2016-03-20 17:00:00 +01:00
|
|
|
|
2018-02-10 17:00:00 +01:00
|
|
|
bool fileExists(const char *filename);
|
|
|
|
|
2015-08-02 18:00:00 +02:00
|
|
|
void clearLevelRes();
|
2016-08-07 18:00:00 +02:00
|
|
|
void load_DEM(const char *filename);
|
2015-08-02 18:00:00 +02:00
|
|
|
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);
|
2018-03-28 18:00:00 +02:00
|
|
|
void load_CMP_menu(const char *fileName);
|
2015-08-02 18:00:00 +02:00
|
|
|
void load_SPR_OFF(const char *fileName, uint8_t *sprData);
|
|
|
|
void load_CINE();
|
2018-03-18 17:00:00 +01:00
|
|
|
void free_CINE();
|
2015-08-02 18:00:00 +02:00
|
|
|
void load_TEXT();
|
|
|
|
void free_TEXT();
|
2018-01-20 17:00:00 +01:00
|
|
|
void unload(int objType);
|
2015-08-02 18:00:00 +02:00
|
|
|
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);
|
2016-03-20 17:00:00 +01:00
|
|
|
void decodePGE(const uint8_t *, int);
|
2015-08-02 18:00:00 +02:00
|
|
|
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);
|
2016-03-20 17:00:00 +01:00
|
|
|
void load_BNQ(File *pf);
|
2015-08-02 18:00:00 +02:00
|
|
|
void load_SPM(File *f);
|
|
|
|
const uint8_t *getAniData(int num) const {
|
2018-02-10 17:00:00 +01:00
|
|
|
if (_type == kResourceTypeMac) {
|
|
|
|
const int count = READ_BE_UINT16(_ani);
|
|
|
|
assert(num < count);
|
|
|
|
const int offset = READ_BE_UINT16(_ani + 2 + num * 2);
|
|
|
|
return _ani + offset;
|
|
|
|
}
|
2016-03-20 17:00:00 +01:00
|
|
|
const int offset = _readUint16(_ani + 2 + num * 2);
|
|
|
|
return _ani + 2 + offset;
|
|
|
|
}
|
2018-02-10 17:00:00 +01:00
|
|
|
const uint8_t *getTextString(int level, int num) const {
|
2018-02-24 17:00:00 +01:00
|
|
|
if (_type == kResourceTypeMac) {
|
|
|
|
const int count = READ_BE_UINT16(_tbn);
|
|
|
|
assert(num < count);
|
|
|
|
const int offset = READ_BE_UINT16(_tbn + 2 + num * 2);
|
|
|
|
return _tbn + offset;
|
|
|
|
}
|
2017-12-06 17:00:00 +01:00
|
|
|
if (_lang == LANG_JP) {
|
|
|
|
const uint8_t *p = 0;
|
|
|
|
switch (level) {
|
|
|
|
case 0:
|
|
|
|
p = LocaleData::_level1TbnJP;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
p = LocaleData::_level2TbnJP;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
p = LocaleData::_level3TbnJP;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
p = LocaleData::_level41TbnJP;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
p = LocaleData::_level42TbnJP;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
p = LocaleData::_level51TbnJP;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
p = LocaleData::_level52TbnJP;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return p + READ_LE_UINT16(p + num * 2);
|
|
|
|
}
|
2016-03-20 17:00:00 +01:00
|
|
|
return _tbn + _readUint16(_tbn + num * 2);
|
2015-08-02 18:00:00 +02:00
|
|
|
}
|
2018-02-10 17:00:00 +01:00
|
|
|
const uint8_t *getGameString(int num) const {
|
|
|
|
if (_type == kResourceTypeMac) {
|
|
|
|
const int count = READ_BE_UINT16(_str);
|
|
|
|
assert(num < count);
|
|
|
|
const int offset = READ_BE_UINT16(_str + 2 + num * 2);
|
|
|
|
return _str + offset;
|
|
|
|
}
|
2015-08-02 18:00:00 +02:00
|
|
|
return _stringsTable + READ_LE_UINT16(_stringsTable + num * 2);
|
|
|
|
}
|
2018-02-10 17:00:00 +01:00
|
|
|
const uint8_t *getCineString(int num) const {
|
|
|
|
if (_type == kResourceTypeMac) {
|
|
|
|
const int count = READ_BE_UINT16(_cine_txt);
|
|
|
|
assert(num < count);
|
|
|
|
const int offset = READ_BE_UINT16(_cine_txt + 2 + num * 2);
|
|
|
|
return _cine_txt + offset;
|
|
|
|
}
|
2018-02-24 17:00:00 +01:00
|
|
|
if (_lang == LANG_JP) {
|
|
|
|
const int offset = READ_BE_UINT16(LocaleData::_cineBinJP + num * 2);
|
|
|
|
return LocaleData::_cineTxtJP + offset;
|
|
|
|
}
|
2015-08-02 18:00:00 +02:00
|
|
|
if (_cine_off) {
|
|
|
|
const int offset = READ_BE_UINT16(_cine_off + num * 2);
|
|
|
|
return _cine_txt + offset;
|
|
|
|
}
|
2016-05-09 18:00:00 +02:00
|
|
|
return (num >= 0 && num < NUM_CUTSCENE_TEXTS) ? _cineStrings[num] : 0;
|
2015-08-02 18:00:00 +02:00
|
|
|
}
|
2018-02-10 17:00:00 +01:00
|
|
|
const char *getMenuString(int num) const {
|
2015-08-02 18:00:00 +02:00
|
|
|
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);
|
2018-02-10 17:00:00 +01:00
|
|
|
|
|
|
|
uint8_t *decodeResourceMacData(const char *name, bool decompressLzss);
|
|
|
|
void MAC_decodeImageData(const uint8_t *ptr, int i, DecodeBuffer *dst);
|
|
|
|
void MAC_decodeDataCLUT(const uint8_t *ptr);
|
|
|
|
void MAC_loadClutData();
|
|
|
|
void MAC_loadFontData();
|
|
|
|
void MAC_loadIconData();
|
|
|
|
void MAC_loadPersoData();
|
|
|
|
void MAC_loadMonsterData(const char *name, Color *clut);
|
|
|
|
void MAC_loadTitleImage(int i, DecodeBuffer *buf);
|
|
|
|
void MAC_unloadLevelData();
|
|
|
|
void MAC_loadLevelData(int level);
|
|
|
|
void MAC_loadLevelRoom(int level, int i, DecodeBuffer *dst);
|
|
|
|
void MAC_clearClut16(Color *clut, uint8_t dest);
|
|
|
|
void MAC_copyClut16(Color *clut, uint8_t dest, uint8_t src);
|
|
|
|
void MAC_setupRoomClut(int level, int room, Color *clut);
|
|
|
|
const uint8_t *MAC_getImageData(const uint8_t *ptr, int i);
|
|
|
|
bool MAC_hasLevelMap(int level, int room) const;
|
|
|
|
void MAC_unloadCutscene();
|
|
|
|
void MAC_loadCutscene(const char *cutscene);
|
|
|
|
void MAC_loadCutsceneText();
|
2019-10-27 17:00:00 +01:00
|
|
|
void MAC_loadCreditsText();
|
2018-02-24 17:00:00 +01:00
|
|
|
void MAC_loadSounds();
|
2018-02-10 17:00:00 +01:00
|
|
|
|
|
|
|
int MAC_getPersoFrame(int anim) const {
|
|
|
|
static const int data[] = {
|
|
|
|
0x000, 0x22E,
|
|
|
|
0x28E, 0x2E9,
|
|
|
|
0x4E9, 0x506,
|
|
|
|
-1
|
|
|
|
};
|
|
|
|
int offset = 0;
|
|
|
|
for (int i = 0; data[i] != -1; i += 2) {
|
|
|
|
if (anim >= data[i] && anim <= data[i + 1]) {
|
|
|
|
return offset + anim - data[i];
|
|
|
|
}
|
|
|
|
const int count = data[i + 1] + 1 - data[i];
|
|
|
|
offset += count;
|
|
|
|
}
|
|
|
|
assert(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int MAC_getMonsterFrame(int anim) const {
|
|
|
|
static const int data[] = {
|
|
|
|
0x22F, 0x28D, // junky - 94
|
|
|
|
0x2EA, 0x385, // mercenai - 156
|
|
|
|
0x387, 0x42F, // replican - 169
|
|
|
|
0x430, 0x4E8, // glue - 185
|
|
|
|
-1
|
|
|
|
};
|
|
|
|
for (int i = 0; data[i] != -1; i += 2) {
|
|
|
|
if (anim >= data[i] && anim <= data[i + 1]) {
|
|
|
|
return anim - data[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(0);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-08-02 18:00:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // RESOURCE_H__
|