Import 0.4.8
This commit is contained in:
parent
bc1337da63
commit
315bb9bcff
|
@ -1,3 +1,8 @@
|
||||||
|
* release 0.4.8
|
||||||
|
- added detection for DOS version with .ABA files
|
||||||
|
- added Macintosh credits
|
||||||
|
- fixed ESPIONS cutscene timing with Amiga music
|
||||||
|
|
||||||
* release 0.4.7
|
* release 0.4.7
|
||||||
- added detection for Macintosh CD version
|
- added detection for Macintosh CD version
|
||||||
- restored some content from MEMO cutscene
|
- restored some content from MEMO cutscene
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
REminiscence README
|
REminiscence README
|
||||||
Release version: 0.4.7
|
Release version: 0.4.8
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
102
cutscene.cpp
102
cutscene.cpp
|
@ -147,8 +147,14 @@ uint16_t Cutscene::findTextSeparators(const uint8_t *p, int len) {
|
||||||
void Cutscene::drawText(int16_t x, int16_t y, const uint8_t *p, uint16_t color, uint8_t *page, int textJustify) {
|
void Cutscene::drawText(int16_t x, int16_t y, const uint8_t *p, uint16_t color, uint8_t *page, int textJustify) {
|
||||||
debug(DBG_CUT, "Cutscene::drawText(x=%d, y=%d, c=%d, justify=%d)", x, y, color, textJustify);
|
debug(DBG_CUT, "Cutscene::drawText(x=%d, y=%d, c=%d, justify=%d)", x, y, color, textJustify);
|
||||||
int len = 0;
|
int len = 0;
|
||||||
if (_res->_type == kResourceTypeMac) {
|
if (_res->isMac()) {
|
||||||
|
if (p == _textBuf) {
|
||||||
|
while (p[len] != 0xA) {
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
len = *p++;
|
len = *p++;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
len = strlen((const char *)p);
|
len = strlen((const char *)p);
|
||||||
}
|
}
|
||||||
|
@ -197,16 +203,39 @@ void Cutscene::clearBackPage() {
|
||||||
|
|
||||||
void Cutscene::drawCreditsText() {
|
void Cutscene::drawCreditsText() {
|
||||||
if (_creditsSequence) {
|
if (_creditsSequence) {
|
||||||
if (_creditsKeepText != 0) {
|
if (_creditsKeepText) {
|
||||||
if (_creditsSlowText == 0) {
|
if (_creditsSlowText) {
|
||||||
_creditsKeepText = 0;
|
|
||||||
} else {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_creditsKeepText = false;
|
||||||
}
|
}
|
||||||
if (_creditsTextCounter <= 0) {
|
if (_creditsTextCounter <= 0) {
|
||||||
const uint8_t code = *_textCurPtr;
|
uint8_t code;
|
||||||
if (code == 0xFF) {
|
const bool isMac = _res->isMac();
|
||||||
|
if (isMac && _creditsTextLen <= 0) {
|
||||||
|
const uint8_t *p = _res->getCreditsString(_creditsTextIndex++);
|
||||||
|
if (!p) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_creditsTextCounter = 60;
|
||||||
|
_creditsTextPosX = p[0];
|
||||||
|
_creditsTextPosY = p[1];
|
||||||
|
_creditsTextLen = p[2];
|
||||||
|
_textCurPtr = p + 2;
|
||||||
|
code = 0;
|
||||||
|
} else {
|
||||||
|
code = *_textCurPtr;
|
||||||
|
}
|
||||||
|
if (code == 0x7D && isMac) {
|
||||||
|
++_textCurPtr;
|
||||||
|
code = *_textCurPtr++;
|
||||||
|
_creditsTextLen -= 2;
|
||||||
|
assert(code > 0x30);
|
||||||
|
for (int i = 0; i < (code - 0x30); ++i) {
|
||||||
|
*_textCurBuf++ = ' ';
|
||||||
|
}
|
||||||
|
*_textCurBuf = 0xA;
|
||||||
|
} else if (code == 0xFF) {
|
||||||
_textBuf[0] = 0xA;
|
_textBuf[0] = 0xA;
|
||||||
} else if (code == 0xFE) {
|
} else if (code == 0xFE) {
|
||||||
++_textCurPtr;
|
++_textCurPtr;
|
||||||
|
@ -219,13 +248,19 @@ void Cutscene::drawCreditsText() {
|
||||||
_textCurBuf = _textBuf;
|
_textCurBuf = _textBuf;
|
||||||
_textBuf[0] = 0xA;
|
_textBuf[0] = 0xA;
|
||||||
++_textCurPtr;
|
++_textCurPtr;
|
||||||
if (_creditsSlowText != 0) {
|
if (_creditsSlowText) {
|
||||||
_creditsKeepText = 0xFF;
|
_creditsKeepText = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*_textCurBuf++ = code;
|
*_textCurBuf++ = code;
|
||||||
*_textCurBuf = 0xA;
|
*_textCurBuf = 0xA;
|
||||||
++_textCurPtr;
|
++_textCurPtr;
|
||||||
|
if (isMac) {
|
||||||
|
--_creditsTextLen;
|
||||||
|
if (_creditsTextLen == 0) {
|
||||||
|
_creditsTextCounter = 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_creditsTextCounter -= 10;
|
_creditsTextCounter -= 10;
|
||||||
|
@ -276,7 +311,7 @@ void Cutscene::op_markCurPos() {
|
||||||
_frameDelay = 5;
|
_frameDelay = 5;
|
||||||
updateScreen();
|
updateScreen();
|
||||||
clearBackPage();
|
clearBackPage();
|
||||||
_creditsSlowText = 0;
|
_creditsSlowText = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cutscene::op_refreshScreen() {
|
void Cutscene::op_refreshScreen() {
|
||||||
|
@ -284,7 +319,7 @@ void Cutscene::op_refreshScreen() {
|
||||||
_clearScreen = fetchNextCmdByte();
|
_clearScreen = fetchNextCmdByte();
|
||||||
if (_clearScreen != 0) {
|
if (_clearScreen != 0) {
|
||||||
clearBackPage();
|
clearBackPage();
|
||||||
_creditsSlowText = 0;
|
_creditsSlowText = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,17 +328,17 @@ void Cutscene::op_waitForSync() {
|
||||||
if (_creditsSequence) {
|
if (_creditsSequence) {
|
||||||
uint16_t n = fetchNextCmdByte() * 2;
|
uint16_t n = fetchNextCmdByte() * 2;
|
||||||
do {
|
do {
|
||||||
_creditsSlowText = 0xFF;
|
_creditsSlowText = true;
|
||||||
_frameDelay = 3;
|
_frameDelay = 3;
|
||||||
if (_textBuf == _textCurBuf) {
|
if (_textBuf == _textCurBuf) {
|
||||||
_creditsTextCounter = _res->isAmiga() ? 60 : 20;
|
_creditsTextCounter = _res->isDOS() ? 20 : 60;
|
||||||
}
|
}
|
||||||
memcpy(_backPage, _frontPage, _vid->_layerSize);
|
memcpy(_backPage, _frontPage, _vid->_layerSize);
|
||||||
drawCreditsText();
|
drawCreditsText();
|
||||||
updateScreen();
|
updateScreen();
|
||||||
} while (--n);
|
} while (--n);
|
||||||
clearBackPage();
|
clearBackPage();
|
||||||
_creditsSlowText = 0;
|
_creditsSlowText = false;
|
||||||
} else {
|
} else {
|
||||||
_frameDelay = fetchNextCmdByte() * 4;
|
_frameDelay = fetchNextCmdByte() * 4;
|
||||||
sync(); // XXX handle input
|
sync(); // XXX handle input
|
||||||
|
@ -418,15 +453,6 @@ void Cutscene::op_drawCaptionText() {
|
||||||
uint16_t strId = fetchNextCmdWord();
|
uint16_t strId = fetchNextCmdWord();
|
||||||
if (!_creditsSequence) {
|
if (!_creditsSequence) {
|
||||||
|
|
||||||
// 'espions' - ignore last call, allows caption to be displayed longer on the screen
|
|
||||||
if (_id == 0x39 && strId == 0xFFFF) {
|
|
||||||
if ((_res->isDOS() && (_cmdPtr - _cmdPtrBak) == 0x10) || (_res->isAmiga() && (_cmdPtr - getCommandData()) == 0x9F3)) {
|
|
||||||
_frameDelay = 100;
|
|
||||||
updateScreen();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const int h = 45 * _vid->_layerScale;
|
const int h = 45 * _vid->_layerScale;
|
||||||
const int y = Video::GAMESCREEN_H * _vid->_layerScale - h;
|
const int y = Video::GAMESCREEN_H * _vid->_layerScale - h;
|
||||||
|
|
||||||
|
@ -439,6 +465,10 @@ void Cutscene::op_drawCaptionText() {
|
||||||
drawText(0, 129, str, 0xEF, _backPage, kTextJustifyAlign);
|
drawText(0, 129, str, 0xEF, _backPage, kTextJustifyAlign);
|
||||||
drawText(0, 129, str, 0xEF, _auxPage, kTextJustifyAlign);
|
drawText(0, 129, str, 0xEF, _auxPage, kTextJustifyAlign);
|
||||||
}
|
}
|
||||||
|
} else if (_id == kCineEspions) {
|
||||||
|
// cutscene relies on drawCaptionText opcodes for timing
|
||||||
|
_frameDelay = 100;
|
||||||
|
sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,7 +487,7 @@ void Cutscene::op_refreshAll() {
|
||||||
_frameDelay = 5;
|
_frameDelay = 5;
|
||||||
updateScreen();
|
updateScreen();
|
||||||
clearBackPage();
|
clearBackPage();
|
||||||
_creditsSlowText = 0xFF;
|
_creditsSlowText = true;
|
||||||
op_handleKeys();
|
op_handleKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,7 +664,7 @@ void Cutscene::op_drawShapeScale() {
|
||||||
_hasAlphaColor = (verticesOffset & 0x4000) != 0;
|
_hasAlphaColor = (verticesOffset & 0x4000) != 0;
|
||||||
uint8_t color = *shapeData++;
|
uint8_t color = *shapeData++;
|
||||||
if (_clearScreen == 0) {
|
if (_clearScreen == 0) {
|
||||||
color += 0x10; // 2nd paletter buffer
|
color += 0x10; // 2nd palette buffer
|
||||||
}
|
}
|
||||||
_primitiveColor = 0xC0 + color;
|
_primitiveColor = 0xC0 + color;
|
||||||
drawShapeScale(p, zoom, dx, dy, x, y, 0, 0);
|
drawShapeScale(p, zoom, dx, dy, x, y, 0, 0);
|
||||||
|
@ -908,7 +938,7 @@ static int findSetPaletteColor(const uint16_t color, const uint16_t *paletteBuff
|
||||||
|
|
||||||
void Cutscene::op_copyScreen() {
|
void Cutscene::op_copyScreen() {
|
||||||
debug(DBG_CUT, "Cutscene::op_copyScreen()");
|
debug(DBG_CUT, "Cutscene::op_copyScreen()");
|
||||||
_creditsSlowText = 0xFF;
|
_creditsSlowText = true;
|
||||||
if (_textCurBuf == _textBuf) {
|
if (_textCurBuf == _textBuf) {
|
||||||
++_creditsTextCounter;
|
++_creditsTextCounter;
|
||||||
}
|
}
|
||||||
|
@ -954,11 +984,11 @@ void Cutscene::op_drawTextAtPos() {
|
||||||
if (!_creditsSequence) {
|
if (!_creditsSequence) {
|
||||||
const uint8_t *str = _res->getCineString(strId & 0xFFF);
|
const uint8_t *str = _res->getCineString(strId & 0xFFF);
|
||||||
if (str) {
|
if (str) {
|
||||||
uint8_t color = 0xD0 + (strId >> 0xC);
|
const uint8_t color = 0xD0 + (strId >> 0xC);
|
||||||
drawText(x, y, str, color, _backPage, kTextJustifyCenter);
|
drawText(x, y, str, color, _backPage, kTextJustifyCenter);
|
||||||
}
|
}
|
||||||
// 'voyage' - cutscene script redraws the string to refresh the screen
|
// 'voyage' - cutscene script redraws the string to refresh the screen
|
||||||
if (_id == 0x34 && (strId & 0xFFF) == 0x45) {
|
if (_id == kCineVoyage && (strId & 0xFFF) == 0x45) {
|
||||||
if ((_cmdPtr - _cmdPtrBak) == 0xA) {
|
if ((_cmdPtr - _cmdPtrBak) == 0xA) {
|
||||||
_stub->copyRect(0, 0, _vid->_w, _vid->_h, _backPage, _vid->_w);
|
_stub->copyRect(0, 0, _vid->_w, _vid->_h, _backPage, _vid->_w);
|
||||||
_stub->updateScreen(0);
|
_stub->updateScreen(0);
|
||||||
|
@ -1099,9 +1129,9 @@ bool Cutscene::load(uint16_t cutName) {
|
||||||
name = "SERRURE";
|
name = "SERRURE";
|
||||||
}
|
}
|
||||||
_res->load(name, Resource::OT_CMP);
|
_res->load(name, Resource::OT_CMP);
|
||||||
if (_id == 0x39 && _res->_lang != LANG_FR) {
|
if (_id == kCineEspions) {
|
||||||
//
|
//
|
||||||
// 'espions' - '... the power which we need' caption is missing in Amiga English.
|
// '... the power which we need' caption is missing.
|
||||||
// fixed in DOS version, opcodes order is wrong
|
// fixed in DOS version, opcodes order is wrong
|
||||||
//
|
//
|
||||||
// opcode 0 pos 0x323
|
// opcode 0 pos 0x323
|
||||||
|
@ -1167,15 +1197,17 @@ void Cutscene::prepare() {
|
||||||
|
|
||||||
void Cutscene::playCredits() {
|
void Cutscene::playCredits() {
|
||||||
if (_res->isMac()) {
|
if (_res->isMac()) {
|
||||||
warning("Cutscene::playCredits() unimplemented");
|
_res->MAC_loadCreditsText();
|
||||||
return;
|
_creditsTextIndex = 0;
|
||||||
}
|
_creditsTextLen = 0;
|
||||||
|
} else {
|
||||||
_textCurPtr = _res->isAmiga() ? _creditsDataAmiga : _creditsDataDOS;
|
_textCurPtr = _res->isAmiga() ? _creditsDataAmiga : _creditsDataDOS;
|
||||||
|
}
|
||||||
_textBuf[0] = 0xA;
|
_textBuf[0] = 0xA;
|
||||||
_textCurBuf = _textBuf;
|
_textCurBuf = _textBuf;
|
||||||
_creditsSequence = true;
|
_creditsSequence = true;
|
||||||
_creditsSlowText = 0;
|
_creditsSlowText = false;
|
||||||
_creditsKeepText = 0;
|
_creditsKeepText = false;
|
||||||
_creditsTextCounter = 0;
|
_creditsTextCounter = 0;
|
||||||
_interrupted = false;
|
_interrupted = false;
|
||||||
const uint16_t *cut_seq = _creditsCutSeq;
|
const uint16_t *cut_seq = _creditsCutSeq;
|
||||||
|
|
10
cutscene.h
10
cutscene.h
|
@ -30,7 +30,9 @@ struct Cutscene {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kCineMemo = 48
|
kCineMemo = 48,
|
||||||
|
kCineVoyage = 52,
|
||||||
|
kCineEspions = 57
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SetShape {
|
struct SetShape {
|
||||||
|
@ -104,11 +106,13 @@ struct Cutscene {
|
||||||
uint8_t _textBuf[500];
|
uint8_t _textBuf[500];
|
||||||
const uint8_t *_textCurPtr;
|
const uint8_t *_textCurPtr;
|
||||||
uint8_t *_textCurBuf;
|
uint8_t *_textCurBuf;
|
||||||
uint8_t _creditsSlowText;
|
bool _creditsSlowText;
|
||||||
uint8_t _creditsKeepText;
|
bool _creditsKeepText;
|
||||||
uint8_t _creditsTextPosX;
|
uint8_t _creditsTextPosX;
|
||||||
uint8_t _creditsTextPosY;
|
uint8_t _creditsTextPosY;
|
||||||
int16_t _creditsTextCounter;
|
int16_t _creditsTextCounter;
|
||||||
|
int _creditsTextIndex; /* MAC has the credits data in a resource */
|
||||||
|
int _creditsTextLen;
|
||||||
uint8_t *_frontPage, *_backPage, *_auxPage;
|
uint8_t *_frontPage, *_backPage, *_auxPage;
|
||||||
|
|
||||||
Cutscene(Resource *res, SystemStub *stub, Video *vid);
|
Cutscene(Resource *res, SystemStub *stub, Video *vid);
|
||||||
|
|
|
@ -3,11 +3,15 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "decode_mac.h"
|
#include "decode_mac.h"
|
||||||
#include "file.h"
|
#include "util.h"
|
||||||
|
|
||||||
uint8_t *decodeLzss(File &f, uint32_t &decodedSize) {
|
uint8_t *decodeLzss(File &f, uint32_t &decodedSize) {
|
||||||
decodedSize = f.readUint32BE();
|
decodedSize = f.readUint32BE();
|
||||||
uint8_t *dst = (uint8_t *)malloc(decodedSize);
|
uint8_t *dst = (uint8_t *)malloc(decodedSize);
|
||||||
|
if (!dst) {
|
||||||
|
warning("Failed to allocate %d bytes for LZSS", decodedSize);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
while (count < decodedSize) {
|
while (count < decodedSize) {
|
||||||
const int code = f.readByte();
|
const int code = f.readByte();
|
||||||
|
|
6
game.cpp
6
game.cpp
|
@ -11,7 +11,6 @@
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "seq_player.h"
|
#include "seq_player.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
#include "unpack.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
Game::Game(SystemStub *stub, FileSystem *fs, const char *savePath, int level, ResourceType ver, Language lang, WidescreenMode widescreenMode, bool autoSave)
|
Game::Game(SystemStub *stub, FileSystem *fs, const char *savePath, int level, ResourceType ver, Language lang, WidescreenMode widescreenMode, bool autoSave)
|
||||||
|
@ -557,7 +556,8 @@ void Game::playCutscene(int id) {
|
||||||
_stub->setPaletteEntry(0xC0 + i, &palette[i]);
|
_stub->setPaletteEntry(0xC0 + i, &palette[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (id == 0x3D) {
|
if (_cut._id == 0x3D) {
|
||||||
|
_mix.playMusic(Mixer::MUSIC_TRACK + 9);
|
||||||
_cut.playCredits();
|
_cut.playCredits();
|
||||||
}
|
}
|
||||||
_mix.stopMusic();
|
_mix.stopMusic();
|
||||||
|
@ -1678,7 +1678,7 @@ void Game::loadLevelData() {
|
||||||
_res.load(lvl->name, Resource::OT_CT);
|
_res.load(lvl->name, Resource::OT_CT);
|
||||||
_res.load(lvl->name, Resource::OT_PAL);
|
_res.load(lvl->name, Resource::OT_PAL);
|
||||||
_res.load(lvl->name, Resource::OT_RP);
|
_res.load(lvl->name, Resource::OT_RP);
|
||||||
if (_res._isDemo || g_options.use_tile_data) { // use .BNQ/.LEV/(.SGD) instead of .MAP (PC demo)
|
if (_res._isDemo || g_options.use_tile_data || _res._aba) { // use .BNQ/.LEV/(.SGD) instead of .MAP (PC demo)
|
||||||
if (_currentLevel == 0) {
|
if (_currentLevel == 0) {
|
||||||
_res.load(lvl->name, Resource::OT_SGD);
|
_res.load(lvl->name, Resource::OT_SGD);
|
||||||
}
|
}
|
||||||
|
|
4
main.cpp
4
main.cpp
|
@ -35,6 +35,7 @@ static int detectVersion(FileSystem *fs) {
|
||||||
const char *name;
|
const char *name;
|
||||||
} table[] = {
|
} table[] = {
|
||||||
{ "DEMO_UK.ABA", kResourceTypeDOS, "DOS (Demo)" },
|
{ "DEMO_UK.ABA", kResourceTypeDOS, "DOS (Demo)" },
|
||||||
|
{ "GLOB_FR.ABA", kResourceTypeDOS, "DOS" },
|
||||||
{ "INTRO.SEQ", kResourceTypeDOS, "DOS CD" },
|
{ "INTRO.SEQ", kResourceTypeDOS, "DOS CD" },
|
||||||
{ "MENU1SSI.MAP", kResourceTypeDOS, "DOS SSI" },
|
{ "MENU1SSI.MAP", kResourceTypeDOS, "DOS SSI" },
|
||||||
{ "LEVEL1.MAP", kResourceTypeDOS, "DOS" },
|
{ "LEVEL1.MAP", kResourceTypeDOS, "DOS" },
|
||||||
|
@ -60,7 +61,8 @@ static Language detectLanguage(FileSystem *fs) {
|
||||||
const char *filename;
|
const char *filename;
|
||||||
Language language;
|
Language language;
|
||||||
} table[] = {
|
} table[] = {
|
||||||
// PC
|
// DOS
|
||||||
|
{ "GLOB_FR.ABA", LANG_FR },
|
||||||
{ "ENGCINE.TXT", LANG_EN },
|
{ "ENGCINE.TXT", LANG_EN },
|
||||||
{ "FR_CINE.TXT", LANG_FR },
|
{ "FR_CINE.TXT", LANG_FR },
|
||||||
{ "GERCINE.TXT", LANG_DE },
|
{ "GERCINE.TXT", LANG_DE },
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
* Copyright (C) 2005-2019 Gregory Montoir (cyx@users.sourceforge.net)
|
* Copyright (C) 2005-2019 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cutscene.h"
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
|
|
94
resource.cpp
94
resource.cpp
|
@ -56,16 +56,27 @@ Resource::~Resource() {
|
||||||
delete _mac;
|
delete _mac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *_demoAba = "DEMO_UK.ABA";
|
||||||
|
|
||||||
|
static const char *_joystickAba[] = {
|
||||||
|
"GLOB1_FB.ABA", "GLOB2_FB.ABA", "GLOB_FR.ABA", 0
|
||||||
|
};
|
||||||
|
|
||||||
void Resource::init() {
|
void Resource::init() {
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case kResourceTypeAmiga:
|
case kResourceTypeAmiga:
|
||||||
_isDemo = _fs->exists("demo.lev");
|
_isDemo = _fs->exists("demo.lev");
|
||||||
break;
|
break;
|
||||||
case kResourceTypeDOS:
|
case kResourceTypeDOS:
|
||||||
if (_fs->exists(ResourceAba::FILENAME)) { // fbdemous
|
if (_fs->exists(_demoAba)) { // fbdemous
|
||||||
_aba = new ResourceAba(_fs);
|
_aba = new ResourceAba(_fs);
|
||||||
_aba->readEntries();
|
_aba->readEntries(_demoAba);
|
||||||
_isDemo = true;
|
_isDemo = true;
|
||||||
|
} else if (_fs->exists(_joystickAba[0])) { // Joystick "Hors Serie" April 1996
|
||||||
|
_aba = new ResourceAba(_fs);
|
||||||
|
for (int i = 0; _joystickAba[i]; ++i) {
|
||||||
|
_aba->readEntries(_joystickAba[i]);
|
||||||
|
}
|
||||||
} else if (!fileExists("LEVEL2.MAP")) { // fbdemofr (no cutscenes)
|
} else if (!fileExists("LEVEL2.MAP")) { // fbdemofr (no cutscenes)
|
||||||
_isDemo = true;
|
_isDemo = true;
|
||||||
}
|
}
|
||||||
|
@ -403,7 +414,7 @@ void Resource::load_CINE() {
|
||||||
case kResourceTypeDOS:
|
case kResourceTypeDOS:
|
||||||
if (_cine_off == 0) {
|
if (_cine_off == 0) {
|
||||||
snprintf(_entryName, sizeof(_entryName), "%sCINE.BIN", prefix);
|
snprintf(_entryName, sizeof(_entryName), "%sCINE.BIN", prefix);
|
||||||
if (!_fs->exists(_entryName)) {
|
if (!fileExists(_entryName)) {
|
||||||
strcpy(_entryName, "ENGCINE.BIN");
|
strcpy(_entryName, "ENGCINE.BIN");
|
||||||
}
|
}
|
||||||
File f;
|
File f;
|
||||||
|
@ -428,7 +439,7 @@ void Resource::load_CINE() {
|
||||||
}
|
}
|
||||||
if (_cine_txt == 0) {
|
if (_cine_txt == 0) {
|
||||||
snprintf(_entryName, sizeof(_entryName), "%sCINE.TXT", prefix);
|
snprintf(_entryName, sizeof(_entryName), "%sCINE.TXT", prefix);
|
||||||
if (!_fs->exists(_entryName)) {
|
if (!fileExists(_entryName)) {
|
||||||
strcpy(_entryName, "ENGCINE.TXT");
|
strcpy(_entryName, "ENGCINE.TXT");
|
||||||
}
|
}
|
||||||
File f;
|
File f;
|
||||||
|
@ -699,7 +710,7 @@ void Resource::load(const char *objName, int objType, const char *ext) {
|
||||||
_numSpc = READ_BE_UINT16(_spc) / 2;
|
_numSpc = READ_BE_UINT16(_spc) / 2;
|
||||||
break;
|
break;
|
||||||
case OT_RP:
|
case OT_RP:
|
||||||
if (size != 0x4A) {
|
if (size != sizeof(_rp)) {
|
||||||
error("Unexpected size %d for '%s'", size, _entryName);
|
error("Unexpected size %d for '%s'", size, _entryName);
|
||||||
}
|
}
|
||||||
memcpy(_rp, dat, size);
|
memcpy(_rp, dat, size);
|
||||||
|
@ -728,6 +739,10 @@ void Resource::load(const char *objName, int objType, const char *ext) {
|
||||||
case OT_POL:
|
case OT_POL:
|
||||||
_pol = dat;
|
_pol = dat;
|
||||||
break;
|
break;
|
||||||
|
case OT_SGD:
|
||||||
|
_sgd = dat;
|
||||||
|
_sgd[0] = 0; // clear number of entries, fix first offset
|
||||||
|
break;
|
||||||
case OT_BNQ:
|
case OT_BNQ:
|
||||||
_bnq = dat;
|
_bnq = dat;
|
||||||
break;
|
break;
|
||||||
|
@ -825,7 +840,7 @@ void Resource::load_SPRM(File *f) {
|
||||||
|
|
||||||
void Resource::load_RP(File *f) {
|
void Resource::load_RP(File *f) {
|
||||||
debug(DBG_RES, "Resource::load_RP()");
|
debug(DBG_RES, "Resource::load_RP()");
|
||||||
f->read(_rp, 0x4A);
|
f->read(_rp, sizeof(_rp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::load_SPC(File *f) {
|
void Resource::load_SPC(File *f) {
|
||||||
|
@ -1430,7 +1445,7 @@ uint8_t *Resource::decodeResourceMacText(const char *name, const char *suffix) {
|
||||||
snprintf(buf, sizeof(buf), "%s %s", name, suffix);
|
snprintf(buf, sizeof(buf), "%s %s", name, suffix);
|
||||||
const ResourceMacEntry *entry = _mac->findEntry(buf);
|
const ResourceMacEntry *entry = _mac->findEntry(buf);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
return decodeResourceMacData(buf, false);
|
return decodeResourceMacData(entry, false);
|
||||||
} else { // CD version
|
} else { // CD version
|
||||||
if (strcmp(name, "Flashback") == 0) {
|
if (strcmp(name, "Flashback") == 0) {
|
||||||
name = "Game";
|
name = "Game";
|
||||||
|
@ -1442,23 +1457,35 @@ uint8_t *Resource::decodeResourceMacText(const char *name, const char *suffix) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *Resource::decodeResourceMacData(const char *name, bool decompressLzss) {
|
uint8_t *Resource::decodeResourceMacData(const char *name, bool decompressLzss) {
|
||||||
_resourceMacDataSize = 0;
|
|
||||||
uint8_t *data = 0;
|
uint8_t *data = 0;
|
||||||
const ResourceMacEntry *entry = _mac->findEntry(name);
|
const ResourceMacEntry *entry = _mac->findEntry(name);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
|
data = decodeResourceMacData(entry, decompressLzss);
|
||||||
|
} else {
|
||||||
|
_resourceMacDataSize = 0;
|
||||||
|
error("Resource '%s' not found", name);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *Resource::decodeResourceMacData(const ResourceMacEntry *entry, bool decompressLzss) {
|
||||||
|
assert(entry);
|
||||||
_mac->_f.seek(_mac->_dataOffset + entry->dataOffset);
|
_mac->_f.seek(_mac->_dataOffset + entry->dataOffset);
|
||||||
_resourceMacDataSize = _mac->_f.readUint32BE();
|
_resourceMacDataSize = _mac->_f.readUint32BE();
|
||||||
|
uint8_t *data = 0;
|
||||||
if (decompressLzss) {
|
if (decompressLzss) {
|
||||||
data = decodeLzss(_mac->_f, _resourceMacDataSize);
|
data = decodeLzss(_mac->_f, _resourceMacDataSize);
|
||||||
|
if (!data) {
|
||||||
|
error("Failed to decompress '%s'", entry->name);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
data = (uint8_t *)malloc(_resourceMacDataSize);
|
data = (uint8_t *)malloc(_resourceMacDataSize);
|
||||||
if (data) {
|
if (!data) {
|
||||||
|
error("Failed to allocate %d bytes for '%s'", _resourceMacDataSize, entry->name);
|
||||||
|
} else {
|
||||||
_mac->_f.read(data, _resourceMacDataSize);
|
_mac->_f.read(data, _resourceMacDataSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
error("Resource '%s' not found", name);
|
|
||||||
}
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1501,10 +1528,8 @@ void Resource::MAC_decodeDataCLUT(const uint8_t *ptr) {
|
||||||
|
|
||||||
void Resource::MAC_loadClutData() {
|
void Resource::MAC_loadClutData() {
|
||||||
uint8_t *ptr = decodeResourceMacData("Flashback colors", false);
|
uint8_t *ptr = decodeResourceMacData("Flashback colors", false);
|
||||||
if (ptr) {
|
|
||||||
MAC_decodeDataCLUT(ptr);
|
MAC_decodeDataCLUT(ptr);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::MAC_loadFontData() {
|
void Resource::MAC_loadFontData() {
|
||||||
|
@ -1575,46 +1600,36 @@ static const char *_macLevelNumbers[] = { "1", "2", "3", "4-1", "4-2", "5-1", "5
|
||||||
|
|
||||||
void Resource::MAC_loadLevelData(int level) {
|
void Resource::MAC_loadLevelData(int level) {
|
||||||
char name[64];
|
char name[64];
|
||||||
|
|
||||||
// .PGE
|
// .PGE
|
||||||
snprintf(name, sizeof(name), "Level %s objects", _macLevelNumbers[level]);
|
snprintf(name, sizeof(name), "Level %s objects", _macLevelNumbers[level]);
|
||||||
uint8_t *ptr = decodeResourceMacData(name, true);
|
uint8_t *ptr = decodeResourceMacData(name, true);
|
||||||
if (ptr) {
|
|
||||||
decodePGE(ptr, _resourceMacDataSize);
|
decodePGE(ptr, _resourceMacDataSize);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
} else {
|
|
||||||
error("Failed to load '%s'", name);
|
|
||||||
}
|
|
||||||
// .ANI
|
// .ANI
|
||||||
snprintf(name, sizeof(name), "Level %s sequences", _macLevelNumbers[level]);
|
snprintf(name, sizeof(name), "Level %s sequences", _macLevelNumbers[level]);
|
||||||
_ani = decodeResourceMacData(name, true);
|
_ani = decodeResourceMacData(name, true);
|
||||||
if (_ani) {
|
|
||||||
assert(READ_BE_UINT16(_ani) == 0x48D);
|
assert(READ_BE_UINT16(_ani) == 0x48D);
|
||||||
} else {
|
|
||||||
error("Failed to load '%s'", name);
|
|
||||||
}
|
|
||||||
// .OBJ
|
// .OBJ
|
||||||
snprintf(name, sizeof(name), "Level %s conditions", _macLevelNumbers[level]);
|
snprintf(name, sizeof(name), "Level %s conditions", _macLevelNumbers[level]);
|
||||||
ptr = decodeResourceMacData(name, true);
|
ptr = decodeResourceMacData(name, true);
|
||||||
if (ptr) {
|
|
||||||
assert(READ_BE_UINT16(ptr) == 0xE6);
|
assert(READ_BE_UINT16(ptr) == 0xE6);
|
||||||
decodeOBJ(ptr, _resourceMacDataSize);
|
decodeOBJ(ptr, _resourceMacDataSize);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
} else {
|
|
||||||
error("Failed to load '%s'", name);
|
|
||||||
}
|
|
||||||
// .CT
|
// .CT
|
||||||
snprintf(name, sizeof(name), "Level %c map", _macLevelNumbers[level][0]);
|
snprintf(name, sizeof(name), "Level %c map", _macLevelNumbers[level][0]);
|
||||||
ptr = decodeResourceMacData(name, true);
|
ptr = decodeResourceMacData(name, true);
|
||||||
if (ptr) {
|
|
||||||
assert(_resourceMacDataSize == 0x1D00);
|
assert(_resourceMacDataSize == 0x1D00);
|
||||||
memcpy(_ctData, ptr, _resourceMacDataSize);
|
memcpy(_ctData, ptr, _resourceMacDataSize);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
} else {
|
|
||||||
error("Failed to load '%s'", name);
|
|
||||||
}
|
|
||||||
// .SPC
|
// .SPC
|
||||||
snprintf(name, sizeof(name), "Objects %c", _macLevelNumbers[level][0]);
|
snprintf(name, sizeof(name), "Objects %c", _macLevelNumbers[level][0]);
|
||||||
_spc = decodeResourceMacData(name, true);
|
_spc = decodeResourceMacData(name, true);
|
||||||
|
|
||||||
// .TBN
|
// .TBN
|
||||||
snprintf(name, sizeof(name), "Level %s", _macLevelNumbers[level]);
|
snprintf(name, sizeof(name), "Level %s", _macLevelNumbers[level]);
|
||||||
_tbn = decodeResourceMacText(name, "names");
|
_tbn = decodeResourceMacText(name, "names");
|
||||||
|
@ -1626,10 +1641,8 @@ void Resource::MAC_loadLevelRoom(int level, int i, DecodeBuffer *dst) {
|
||||||
char name[64];
|
char name[64];
|
||||||
snprintf(name, sizeof(name), "Level %c Room %d", _macLevelNumbers[level][0], i);
|
snprintf(name, sizeof(name), "Level %c Room %d", _macLevelNumbers[level][0], i);
|
||||||
uint8_t *ptr = decodeResourceMacData(name, true);
|
uint8_t *ptr = decodeResourceMacData(name, true);
|
||||||
if (ptr) {
|
|
||||||
MAC_decodeImageData(ptr, 0, dst);
|
MAC_decodeImageData(ptr, 0, dst);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::MAC_clearClut16(Color *clut, uint8_t dest) {
|
void Resource::MAC_clearClut16(Color *clut, uint8_t dest) {
|
||||||
|
@ -1704,15 +1717,24 @@ void Resource::MAC_unloadCutscene() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::MAC_loadCutscene(const char *cutscene) {
|
void Resource::MAC_loadCutscene(const char *cutscene) {
|
||||||
|
MAC_unloadCutscene();
|
||||||
char name[32];
|
char name[32];
|
||||||
free(_cmd);
|
|
||||||
snprintf(name, sizeof(name), "%s movie", cutscene);
|
snprintf(name, sizeof(name), "%s movie", cutscene);
|
||||||
stringLowerCase(name);
|
stringLowerCase(name);
|
||||||
_cmd = decodeResourceMacData(name, true);
|
const ResourceMacEntry *cmdEntry = _mac->findEntry(name);
|
||||||
free(_pol);
|
if (!cmdEntry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_cmd = decodeResourceMacData(cmdEntry, true);
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "%s polygons", cutscene);
|
snprintf(name, sizeof(name), "%s polygons", cutscene);
|
||||||
stringLowerCase(name);
|
stringLowerCase(name);
|
||||||
_pol = decodeResourceMacData(name, true);
|
const ResourceMacEntry *polEntry = _mac->findEntry(name);
|
||||||
|
if (!polEntry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_pol = decodeResourceMacData(polEntry, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::MAC_loadCutsceneText() {
|
void Resource::MAC_loadCutsceneText() {
|
||||||
|
|
18
resource.h
18
resource.h
|
@ -137,13 +137,13 @@ struct Resource {
|
||||||
uint8_t *_icn;
|
uint8_t *_icn;
|
||||||
int _icnLen;
|
int _icnLen;
|
||||||
uint8_t *_tab;
|
uint8_t *_tab;
|
||||||
uint8_t *_spc; // BE
|
uint8_t *_spc;
|
||||||
uint16_t _numSpc;
|
uint16_t _numSpc;
|
||||||
uint8_t _rp[0x4A];
|
uint8_t _rp[74];
|
||||||
uint8_t *_pal; // BE
|
uint8_t *_pal;
|
||||||
uint8_t *_ani;
|
uint8_t *_ani;
|
||||||
uint8_t *_tbn;
|
uint8_t *_tbn;
|
||||||
int8_t _ctData[0x1D00];
|
int8_t _ctData[256 + 112 * 64];
|
||||||
uint8_t *_spr1;
|
uint8_t *_spr1;
|
||||||
uint8_t *_sprData[NUM_SPRITES]; // 0-0x22F + 0x28E-0x2E9 ... conrad, 0x22F-0x28D : junkie
|
uint8_t *_sprData[NUM_SPRITES]; // 0-0x22F + 0x28E-0x2E9 ... conrad, 0x22F-0x28D : junkie
|
||||||
uint8_t _sprm[0x10000];
|
uint8_t _sprm[0x10000];
|
||||||
|
@ -313,6 +313,15 @@ struct Resource {
|
||||||
const char *getMenuString(int num) const {
|
const char *getMenuString(int num) const {
|
||||||
return (num >= 0 && num < LocaleData::LI_NUM) ? _textsTable[num] : "";
|
return (num >= 0 && num < LocaleData::LI_NUM) ? _textsTable[num] : "";
|
||||||
}
|
}
|
||||||
|
const uint8_t *getCreditsString(int num) {
|
||||||
|
assert(_type == kResourceTypeMac);
|
||||||
|
const int count = READ_BE_UINT16(_credits);
|
||||||
|
if (num < count) {
|
||||||
|
const int offset = READ_BE_UINT16(_credits + 2 + num * 2);
|
||||||
|
return _credits + offset;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
void clearBankData();
|
void clearBankData();
|
||||||
int getBankDataSize(uint16_t num);
|
int getBankDataSize(uint16_t num);
|
||||||
uint8_t *findBankData(uint16_t num);
|
uint8_t *findBankData(uint16_t num);
|
||||||
|
@ -320,6 +329,7 @@ struct Resource {
|
||||||
|
|
||||||
uint8_t *decodeResourceMacText(const char *name, const char *suffix);
|
uint8_t *decodeResourceMacText(const char *name, const char *suffix);
|
||||||
uint8_t *decodeResourceMacData(const char *name, bool decompressLzss);
|
uint8_t *decodeResourceMacData(const char *name, bool decompressLzss);
|
||||||
|
uint8_t *decodeResourceMacData(const ResourceMacEntry *entry, bool decompressLzss);
|
||||||
void MAC_decodeImageData(const uint8_t *ptr, int i, DecodeBuffer *dst);
|
void MAC_decodeImageData(const uint8_t *ptr, int i, DecodeBuffer *dst);
|
||||||
void MAC_decodeDataCLUT(const uint8_t *ptr);
|
void MAC_decodeDataCLUT(const uint8_t *ptr);
|
||||||
void MAC_loadClutData();
|
void MAC_loadClutData();
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
#include "unpack.h"
|
#include "unpack.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
const char *ResourceAba::FILENAME = "DEMO_UK.ABA";
|
|
||||||
|
|
||||||
ResourceAba::ResourceAba(FileSystem *fs)
|
ResourceAba::ResourceAba(FileSystem *fs)
|
||||||
: _fs(fs) {
|
: _fs(fs) {
|
||||||
|
_filesCount = 0;
|
||||||
_entries = 0;
|
_entries = 0;
|
||||||
_entriesCount = 0;
|
_entriesCount = 0;
|
||||||
}
|
}
|
||||||
|
@ -19,31 +18,38 @@ static int compareAbaEntry(const void *a, const void *b) {
|
||||||
return strcasecmp(((ResourceAbaEntry *)a)->name, ((ResourceAbaEntry *)b)->name);
|
return strcasecmp(((ResourceAbaEntry *)a)->name, ((ResourceAbaEntry *)b)->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceAba::readEntries() {
|
void ResourceAba::readEntries(const char *aba) {
|
||||||
if (_f.open(FILENAME, "rb", _fs)) {
|
assert(_filesCount < 3);
|
||||||
_entriesCount = _f.readUint16BE();
|
if (_f[_filesCount].open(aba, "rb", _fs)) {
|
||||||
_entries = (ResourceAbaEntry *)calloc(_entriesCount, sizeof(ResourceAbaEntry));
|
File &f = _f[_filesCount];
|
||||||
|
const int currentCount = _entriesCount;
|
||||||
|
const int entriesCount = f.readUint16BE();
|
||||||
|
_entries = (ResourceAbaEntry *)realloc(_entries, (currentCount + entriesCount) * sizeof(ResourceAbaEntry));
|
||||||
if (!_entries) {
|
if (!_entries) {
|
||||||
error("Failed to allocate %d _entries", _entriesCount);
|
error("Failed to allocate %d _entries", currentCount + entriesCount);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const int entrySize = _f.readUint16BE();
|
_entriesCount = currentCount + entriesCount;
|
||||||
|
const int entrySize = f.readUint16BE();
|
||||||
assert(entrySize == 30);
|
assert(entrySize == 30);
|
||||||
uint32_t nextOffset = 0;
|
uint32_t nextOffset = 0;
|
||||||
for (int i = 0; i < _entriesCount; ++i) {
|
for (int i = 0; i < entriesCount; ++i) {
|
||||||
_f.read(_entries[i].name, sizeof(_entries[i].name));
|
const int j = currentCount + i;
|
||||||
_entries[i].offset = _f.readUint32BE();
|
f.read(_entries[j].name, sizeof(_entries[j].name));
|
||||||
_entries[i].compressedSize = _f.readUint32BE();
|
_entries[j].offset = f.readUint32BE();
|
||||||
_entries[i].size = _f.readUint32BE();
|
_entries[j].compressedSize = f.readUint32BE();
|
||||||
const uint32_t tag = _f.readUint32BE();
|
_entries[j].size = f.readUint32BE();
|
||||||
|
_entries[j].fileIndex = _filesCount;
|
||||||
|
const uint32_t tag = f.readUint32BE();
|
||||||
assert(tag == TAG);
|
assert(tag == TAG);
|
||||||
debug(DBG_RES, "'%s' offset 0x%X size %d/%d", _entries[i].name, _entries[i].offset, _entries[i].compressedSize, _entries[i].size);
|
debug(DBG_RES, "'%s' offset 0x%X size %d/%d", _entries[j].name, _entries[j].offset, _entries[j].compressedSize, _entries[j].size);
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
assert(nextOffset == _entries[i].offset);
|
assert(nextOffset == _entries[j].offset);
|
||||||
}
|
}
|
||||||
nextOffset = _entries[i].offset + _entries[i].compressedSize;
|
nextOffset = _entries[j].offset + _entries[j].compressedSize;
|
||||||
}
|
}
|
||||||
qsort(_entries, _entriesCount, sizeof(ResourceAbaEntry), compareAbaEntry);
|
qsort(_entries, _entriesCount, sizeof(ResourceAbaEntry), compareAbaEntry);
|
||||||
|
++_filesCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,8 +71,8 @@ uint8_t *ResourceAba::loadEntry(const char *name, uint32_t *size) {
|
||||||
error("Failed to allocate %d bytes", e->compressedSize);
|
error("Failed to allocate %d bytes", e->compressedSize);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
_f.seek(e->offset);
|
_f[e->fileIndex].seek(e->offset);
|
||||||
_f.read(tmp, e->compressedSize);
|
_f[e->fileIndex].read(tmp, e->compressedSize);
|
||||||
if (e->compressedSize == e->size) {
|
if (e->compressedSize == e->size) {
|
||||||
dst = tmp;
|
dst = tmp;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,22 +11,23 @@ struct ResourceAbaEntry {
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint32_t compressedSize;
|
uint32_t compressedSize;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
int fileIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ResourceAba {
|
struct ResourceAba {
|
||||||
|
|
||||||
static const char *FILENAME;
|
|
||||||
static const int TAG = 0x442E4D2E;
|
static const int TAG = 0x442E4D2E;
|
||||||
|
|
||||||
FileSystem *_fs;
|
FileSystem *_fs;
|
||||||
File _f;
|
File _f[3];
|
||||||
|
int _filesCount;
|
||||||
ResourceAbaEntry *_entries;
|
ResourceAbaEntry *_entries;
|
||||||
int _entriesCount;
|
int _entriesCount;
|
||||||
|
|
||||||
ResourceAba(FileSystem *fs);
|
ResourceAba(FileSystem *fs);
|
||||||
~ResourceAba();
|
~ResourceAba();
|
||||||
|
|
||||||
void readEntries();
|
void readEntries(const char *aba);
|
||||||
const ResourceAbaEntry *findEntry(const char *name) const;
|
const ResourceAbaEntry *findEntry(const char *name) const;
|
||||||
uint8_t *loadEntry(const char *name, uint32_t *size = 0);
|
uint8_t *loadEntry(const char *name, uint32_t *size = 0);
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,8 +30,10 @@ static bool nextBit(UnpackCtx *uc) {
|
||||||
template<int count>
|
template<int count>
|
||||||
static uint32_t getBits(UnpackCtx *uc) { // rdd1bits
|
static uint32_t getBits(UnpackCtx *uc) { // rdd1bits
|
||||||
uint32_t bits = 0;
|
uint32_t bits = 0;
|
||||||
for (int i = 0; i < count; ++i) {
|
for (uint32_t mask = 1 << (count - 1); mask != 0; mask >>= 1) {
|
||||||
bits |= (nextBit(uc) ? 1 : 0) << (count - 1 - i);
|
if (nextBit(uc)) {
|
||||||
|
bits |= mask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue