Import 0.4.3
This commit is contained in:
parent
a4c4ed8fef
commit
514785d0a1
8
Makefile
8
Makefile
|
@ -7,15 +7,17 @@ MODPLUG_LIBS := -lmodplug
|
||||||
TREMOR_LIBS := -lvorbisidec -logg
|
TREMOR_LIBS := -lvorbisidec -logg
|
||||||
ZLIB_LIBS := -lz
|
ZLIB_LIBS := -lz
|
||||||
|
|
||||||
CXXFLAGS += -O2 -Wall -MMD $(SDL_CFLAGS) -DUSE_MODPLUG -DUSE_TREMOR -DUSE_ZLIB
|
CXXFLAGS += -O2 -Wall -MMD $(SDL_CFLAGS) -DUSE_MODPLUG -DUSE_STATIC_SCALER -DUSE_TREMOR -DUSE_ZLIB
|
||||||
|
|
||||||
SRCS = collision.cpp cutscene.cpp decode_mac.cpp dynlib.cpp file.cpp fs.cpp game.cpp graphics.cpp main.cpp \
|
SRCS = collision.cpp cutscene.cpp decode_mac.cpp dynlib.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 resource_aba.cpp \
|
menu.cpp mixer.cpp mod_player.cpp ogg_player.cpp piege.cpp resource.cpp resource_aba.cpp \
|
||||||
resource_mac.cpp scaler.cpp screenshot.cpp seq_player.cpp \
|
resource_mac.cpp scaler.cpp screenshot.cpp seq_player.cpp \
|
||||||
sfx_player.cpp staticres.cpp systemstub_sdl.cpp unpack.cpp util.cpp video.cpp
|
sfx_player.cpp staticres.cpp systemstub_sdl.cpp unpack.cpp util.cpp video.cpp
|
||||||
|
|
||||||
OBJS = $(SRCS:.cpp=.o)
|
SCALERS := scalers/scaler_nearest.cpp scalers/scaler_tv2x.cpp scalers/scaler_xbrz.cpp scalers/xbrz/xbrz.cpp
|
||||||
DEPS = $(SRCS:.cpp=.d)
|
|
||||||
|
OBJS = $(SRCS:.cpp=.o) $(SCALERS:.cpp=.o)
|
||||||
|
DEPS = $(SRCS:.cpp=.d) $(SCALERS:.cpp=.d)
|
||||||
|
|
||||||
LIBS = $(SDL_LIBS) $(DL_LIBS) $(MODPLUG_LIBS) $(TREMOR_LIBS) $(ZLIB_LIBS)
|
LIBS = $(SDL_LIBS) $(DL_LIBS) $(MODPLUG_LIBS) $(TREMOR_LIBS) $(ZLIB_LIBS)
|
||||||
|
|
||||||
|
|
11
README.txt
11
README.txt
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
REminiscence README
|
REminiscence README
|
||||||
Release version: 0.4.2
|
Release version: 0.4.3
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ These paths can be changed using command line switches :
|
||||||
--savepath=PATH Path to save files (default '.')
|
--savepath=PATH Path to save files (default '.')
|
||||||
--levelnum=NUM Level to start from (default '0')
|
--levelnum=NUM Level to start from (default '0')
|
||||||
--fullscreen Fullscreen display
|
--fullscreen Fullscreen display
|
||||||
--widescreen 16:9 display
|
--widescreen=MODE 16:9 display
|
||||||
--scaler=NAME@X Graphics scaler (default 'scale@3')
|
--scaler=NAME@X Graphics scaler (default 'scale@3')
|
||||||
--language=LANG Language (fr,en,de,sp,it,jp)
|
--language=LANG Language (fr,en,de,sp,it,jp)
|
||||||
|
|
||||||
|
@ -52,6 +52,10 @@ addition to a scaling factor. External scalers are also supported, the suffix
|
||||||
shall be used as the name. Eg. If you have scaler_xbrz.dll, you can pass
|
shall be used as the name. Eg. If you have scaler_xbrz.dll, you can pass
|
||||||
'--scaler xbrz@2' to use that algorithm with a doubled window size (512x448).
|
'--scaler xbrz@2' to use that algorithm with a doubled window size (512x448).
|
||||||
|
|
||||||
|
The widescreen option accepts two modes :
|
||||||
|
'adjacent' : left and right rooms bitmaps will be drawn (default)
|
||||||
|
'mirror' : the current room bitmap will be drawn mirrored
|
||||||
|
|
||||||
In-game hotkeys :
|
In-game hotkeys :
|
||||||
|
|
||||||
Arrow Keys move Conrad
|
Arrow Keys move Conrad
|
||||||
|
@ -60,11 +64,12 @@ In-game hotkeys :
|
||||||
Escape display the options
|
Escape display the options
|
||||||
Backspace display the inventory
|
Backspace display the inventory
|
||||||
Alt Enter toggle windowed/fullscreen mode
|
Alt Enter toggle windowed/fullscreen mode
|
||||||
Alt + and - change video scaler
|
Alt + and - increase or decrease game screen scaler factor
|
||||||
Alt S write screenshot as .tga
|
Alt S write screenshot as .tga
|
||||||
Ctrl S save game state
|
Ctrl S save game state
|
||||||
Ctrl L load game state
|
Ctrl L load game state
|
||||||
Ctrl + and - change game state slot
|
Ctrl + and - change game state slot
|
||||||
|
Function Keys change game screen scaler
|
||||||
|
|
||||||
Debug hotkeys :
|
Debug hotkeys :
|
||||||
|
|
||||||
|
|
25
cutscene.cpp
25
cutscene.cpp
|
@ -938,7 +938,12 @@ void Cutscene::op_handleKeys() {
|
||||||
_cmdPtr = getCommandData();
|
_cmdPtr = getCommandData();
|
||||||
n = READ_BE_UINT16(_cmdPtr + n * 2 + 2);
|
n = READ_BE_UINT16(_cmdPtr + n * 2 + 2);
|
||||||
}
|
}
|
||||||
_cmdPtr = _cmdPtrBak = getCommandData() + n + _startOffset;
|
if (_res->isMac()) {
|
||||||
|
_cmdPtr = getCommandData();
|
||||||
|
_baseOffset = READ_BE_UINT16(_cmdPtr + 2 + n * 2);
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
_cmdPtr = _cmdPtrBak = getCommandData() + n + _baseOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Cutscene::fetchNextCmdByte() {
|
uint8_t Cutscene::fetchNextCmdByte() {
|
||||||
|
@ -951,7 +956,7 @@ uint16_t Cutscene::fetchNextCmdWord() {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cutscene::mainLoop(uint16_t offset) {
|
void Cutscene::mainLoop(uint16_t num) {
|
||||||
_frameDelay = 5;
|
_frameDelay = 5;
|
||||||
_tstamp = _stub->getTimeStamp();
|
_tstamp = _stub->getTimeStamp();
|
||||||
|
|
||||||
|
@ -963,14 +968,20 @@ void Cutscene::mainLoop(uint16_t offset) {
|
||||||
_newPal = false;
|
_newPal = false;
|
||||||
_hasAlphaColor = false;
|
_hasAlphaColor = false;
|
||||||
const uint8_t *p = getCommandData();
|
const uint8_t *p = getCommandData();
|
||||||
if (offset != 0) {
|
int offset = 0;
|
||||||
offset = READ_BE_UINT16(p + (offset + 1) * 2);
|
if (_res->isMac()) {
|
||||||
|
// const int count = READ_BE_UINT16(p);
|
||||||
|
_baseOffset = READ_BE_UINT16(p + 2 + num * 2);
|
||||||
|
} else {
|
||||||
|
if (num != 0) {
|
||||||
|
offset = READ_BE_UINT16(p + 2 + num * 2);
|
||||||
|
}
|
||||||
|
_baseOffset = (READ_BE_UINT16(p) + 1) * 2;
|
||||||
}
|
}
|
||||||
_startOffset = (READ_BE_UINT16(p) + 1) * 2;
|
|
||||||
_varKey = 0;
|
_varKey = 0;
|
||||||
_cmdPtr = _cmdPtrBak = p + _startOffset + offset;
|
_cmdPtr = _cmdPtrBak = p + _baseOffset + offset;
|
||||||
_polPtr = getPolygonData();
|
_polPtr = getPolygonData();
|
||||||
debug(DBG_CUT, "_startOffset = %d offset = %d", _startOffset, offset);
|
debug(DBG_CUT, "_baseOffset = %d offset = %d", _baseOffset, offset);
|
||||||
|
|
||||||
while (!_stub->_pi.quit && !_interrupted && !_stop) {
|
while (!_stub->_pi.quit && !_interrupted && !_stop) {
|
||||||
uint8_t op = fetchNextCmdByte();
|
uint8_t op = fetchNextCmdByte();
|
||||||
|
|
|
@ -71,7 +71,7 @@ struct Cutscene {
|
||||||
uint8_t _frameDelay;
|
uint8_t _frameDelay;
|
||||||
bool _newPal;
|
bool _newPal;
|
||||||
uint8_t _palBuf[0x20 * 2];
|
uint8_t _palBuf[0x20 * 2];
|
||||||
uint16_t _startOffset;
|
uint16_t _baseOffset;
|
||||||
bool _creditsSequence;
|
bool _creditsSequence;
|
||||||
uint32_t _rotMat[4];
|
uint32_t _rotMat[4];
|
||||||
uint8_t _primitiveColor;
|
uint8_t _primitiveColor;
|
||||||
|
@ -139,7 +139,7 @@ struct Cutscene {
|
||||||
|
|
||||||
uint8_t fetchNextCmdByte();
|
uint8_t fetchNextCmdByte();
|
||||||
uint16_t fetchNextCmdWord();
|
uint16_t fetchNextCmdWord();
|
||||||
void mainLoop(uint16_t offset);
|
void mainLoop(uint16_t num);
|
||||||
bool load(uint16_t cutName);
|
bool load(uint16_t cutName);
|
||||||
void unload();
|
void unload();
|
||||||
void prepare();
|
void prepare();
|
||||||
|
|
102
game.cpp
102
game.cpp
|
@ -14,7 +14,7 @@
|
||||||
#include "unpack.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)
|
Game::Game(SystemStub *stub, FileSystem *fs, const char *savePath, int level, ResourceType ver, Language lang, WidescreenMode widescreenMode)
|
||||||
: _cut(&_res, stub, &_vid), _menu(&_res, stub, &_vid),
|
: _cut(&_res, stub, &_vid), _menu(&_res, stub, &_vid),
|
||||||
_mix(fs, stub), _res(fs, ver, lang), _seq(stub, &_mix), _vid(&_res, stub),
|
_mix(fs, stub), _res(fs, ver, lang), _seq(stub, &_mix), _vid(&_res, stub),
|
||||||
_stub(stub), _fs(fs), _savePath(savePath) {
|
_stub(stub), _fs(fs), _savePath(savePath) {
|
||||||
|
@ -23,6 +23,7 @@ Game::Game(SystemStub *stub, FileSystem *fs, const char *savePath, int level, Re
|
||||||
_skillLevel = _menu._skill = kSkillNormal;
|
_skillLevel = _menu._skill = kSkillNormal;
|
||||||
_currentLevel = _menu._level = level;
|
_currentLevel = _menu._level = level;
|
||||||
_demoBin = -1;
|
_demoBin = -1;
|
||||||
|
_widescreenMode = widescreenMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::run() {
|
void Game::run() {
|
||||||
|
@ -63,6 +64,12 @@ void Game::run() {
|
||||||
_mix.init();
|
_mix.init();
|
||||||
_mix._mod._isAmiga = _res.isAmiga();
|
_mix._mod._isAmiga = _res.isAmiga();
|
||||||
|
|
||||||
|
if (_res.isMac()) {
|
||||||
|
displayTitleScreenMac(Menu::kMacTitleScreen_MacPlay);
|
||||||
|
if (!_stub->_pi.quit) {
|
||||||
|
displayTitleScreenMac(Menu::kMacTitleScreen_Presage);
|
||||||
|
}
|
||||||
|
}
|
||||||
playCutscene(0x40);
|
playCutscene(0x40);
|
||||||
playCutscene(0x0D);
|
playCutscene(0x0D);
|
||||||
|
|
||||||
|
@ -86,7 +93,7 @@ void Game::run() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool presentMenu = (_res._type == kResourceTypeAmiga) || (_res._type == kResourceTypeDOS && _res.fileExists("MENU1.MAP"));
|
bool presentMenu = ((_res._type != kResourceTypeDOS) || _res.fileExists("MENU1.MAP"));
|
||||||
while (!_stub->_pi.quit) {
|
while (!_stub->_pi.quit) {
|
||||||
if (presentMenu) {
|
if (presentMenu) {
|
||||||
_mix.playMusic(1);
|
_mix.playMusic(1);
|
||||||
|
@ -121,7 +128,7 @@ void Game::run() {
|
||||||
_stub->setScreenSize(Video::GAMESCREEN_W, Video::GAMESCREEN_H);
|
_stub->setScreenSize(Video::GAMESCREEN_W, Video::GAMESCREEN_H);
|
||||||
break;
|
break;
|
||||||
case kResourceTypeMac:
|
case kResourceTypeMac:
|
||||||
// TODO:
|
displayTitleScreenMac(Menu::kMacTitleScreen_Flashback);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (_stub->_pi.quit) {
|
if (_stub->_pi.quit) {
|
||||||
|
@ -172,10 +179,10 @@ void Game::run() {
|
||||||
|
|
||||||
void Game::displayTitleScreenAmiga() {
|
void Game::displayTitleScreenAmiga() {
|
||||||
static const char *FILENAME = "present.cmp";
|
static const char *FILENAME = "present.cmp";
|
||||||
_res.load_CMP_menu(FILENAME, _res._scratchBuffer);
|
_res.load_CMP_menu(FILENAME);
|
||||||
static const int kW = 320;
|
static const int kW = 320;
|
||||||
static const int kH = 224;
|
static const int kH = 224;
|
||||||
uint8_t *buf = (uint8_t *)calloc(kW * kH, 1);
|
uint8_t *buf = (uint8_t *)calloc(1, kW * kH);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
error("Failed to allocate screen buffer w=%d h=%d", kW, kH);
|
error("Failed to allocate screen buffer w=%d h=%d", kW, kH);
|
||||||
}
|
}
|
||||||
|
@ -190,13 +197,13 @@ void Game::displayTitleScreenAmiga() {
|
||||||
_stub->setPaletteEntry(i, &c);
|
_stub->setPaletteEntry(i, &c);
|
||||||
}
|
}
|
||||||
_stub->setScreenSize(kW, kH);
|
_stub->setScreenSize(kW, kH);
|
||||||
|
// fill with black
|
||||||
_stub->copyRect(0, 0, kW, kH, buf, kW);
|
_stub->copyRect(0, 0, kW, kH, buf, kW);
|
||||||
_stub->updateScreen(0);
|
_stub->updateScreen(0);
|
||||||
_vid.AMIGA_decodeCmp(_res._scratchBuffer + 6, buf);
|
_vid.AMIGA_decodeCmp(_res._scratchBuffer + 6, buf);
|
||||||
free(buf);
|
|
||||||
int h = 0;
|
int h = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (h < kH / 2) {
|
if (h <= kH / 2) {
|
||||||
const int y = kH / 2 - h;
|
const int y = kH / 2 - h;
|
||||||
_stub->copyRect(0, y, kW, h * 2, buf, kW);
|
_stub->copyRect(0, y, kW, h * 2, buf, kW);
|
||||||
_stub->updateScreen(0);
|
_stub->updateScreen(0);
|
||||||
|
@ -212,6 +219,72 @@ void Game::displayTitleScreenAmiga() {
|
||||||
}
|
}
|
||||||
_stub->sleep(30);
|
_stub->sleep(30);
|
||||||
}
|
}
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::displayTitleScreenMac(int num) {
|
||||||
|
const int w = 512;
|
||||||
|
int h = 384;
|
||||||
|
int clutBaseColor = 0;
|
||||||
|
switch (num) {
|
||||||
|
case Menu::kMacTitleScreen_MacPlay:
|
||||||
|
break;
|
||||||
|
case Menu::kMacTitleScreen_Presage:
|
||||||
|
clutBaseColor = 12;
|
||||||
|
break;
|
||||||
|
case Menu::kMacTitleScreen_Flashback:
|
||||||
|
case Menu::kMacTitleScreen_LeftEye:
|
||||||
|
case Menu::kMacTitleScreen_RightEye:
|
||||||
|
h = 448;
|
||||||
|
break;
|
||||||
|
case Menu::kMacTitleScreen_Controls:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DecodeBuffer buf;
|
||||||
|
memset(&buf, 0, sizeof(buf));
|
||||||
|
buf.ptr = _vid._frontLayer;
|
||||||
|
buf.pitch = buf.w = _vid._w;
|
||||||
|
buf.h = _vid._h;
|
||||||
|
buf.x = (_vid._w - w) / 2;
|
||||||
|
buf.y = (_vid._h - h) / 2;
|
||||||
|
buf.setPixel = Video::MAC_drawBuffer;
|
||||||
|
memset(_vid._frontLayer, 0, _vid._layerSize);
|
||||||
|
_res.MAC_loadTitleImage(num, &buf);
|
||||||
|
for (int i = 0; i < 12; ++i) {
|
||||||
|
Color palette[16];
|
||||||
|
_res.MAC_copyClut16(palette, 0, clutBaseColor + i);
|
||||||
|
const int basePaletteColor = i * 16;
|
||||||
|
for (int j = 0; j < 16; ++j) {
|
||||||
|
_stub->setPaletteEntry(basePaletteColor + j, &palette[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num == Menu::kMacTitleScreen_MacPlay) {
|
||||||
|
Color palette[16];
|
||||||
|
_res.MAC_copyClut16(palette, 0, 56);
|
||||||
|
for (int i = 12; i < 16; ++i) {
|
||||||
|
const int basePaletteColor = i * 16;
|
||||||
|
for (int j = 0; j < 16; ++j) {
|
||||||
|
_stub->setPaletteEntry(basePaletteColor + j, &palette[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (num == Menu::kMacTitleScreen_Presage) {
|
||||||
|
Color c;
|
||||||
|
c.r = c.g = c.b = 0;
|
||||||
|
_stub->setPaletteEntry(0, &c);
|
||||||
|
}
|
||||||
|
_stub->copyRect(0, 0, _vid._w, _vid._h, _vid._frontLayer, _vid._w);
|
||||||
|
_stub->updateScreen(0);
|
||||||
|
while (1) {
|
||||||
|
_stub->processEvents();
|
||||||
|
if (_stub->_pi.quit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (_stub->_pi.enter) {
|
||||||
|
_stub->_pi.enter = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_stub->sleep(30);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::resetGameState() {
|
void Game::resetGameState() {
|
||||||
|
@ -496,8 +569,12 @@ bool Game::handleConfigPanel() {
|
||||||
|
|
||||||
switch (_res._type) {
|
switch (_res._type) {
|
||||||
case kResourceTypeAmiga:
|
case kResourceTypeAmiga:
|
||||||
// TODO
|
for (int i = 0; i < h; ++i) {
|
||||||
return true;
|
for (int j = 0; j < w; ++j) {
|
||||||
|
_vid.fillRect(Video::CHAR_W * (x + j), Video::CHAR_H * (y + i), Video::CHAR_W, Video::CHAR_H, 0xE2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case kResourceTypeDOS:
|
case kResourceTypeDOS:
|
||||||
// top-left rounded corner
|
// top-left rounded corner
|
||||||
_vid.PC_drawChar(0x81, y, x, kUseDefaultFont);
|
_vid.PC_drawChar(0x81, y, x, kUseDefaultFont);
|
||||||
|
@ -543,7 +620,7 @@ bool Game::handleConfigPanel() {
|
||||||
_vid.MAC_drawStringChar(_vid._frontLayer, _vid._w, Video::CHAR_W * x, Video::CHAR_H * (y + i), _res._fnt, _vid._charFrontColor, 0x86);
|
_vid.MAC_drawStringChar(_vid._frontLayer, _vid._w, Video::CHAR_W * x, Video::CHAR_H * (y + i), _res._fnt, _vid._charFrontColor, 0x86);
|
||||||
_vid.MAC_drawStringChar(_vid._frontLayer, _vid._w, Video::CHAR_W * (x + w), Video::CHAR_H * (y + i), _res._fnt, _vid._charFrontColor, 0x87);
|
_vid.MAC_drawStringChar(_vid._frontLayer, _vid._w, Video::CHAR_W * (x + w), Video::CHAR_H * (y + i), _res._fnt, _vid._charFrontColor, 0x87);
|
||||||
for (int j = 1; j < w; ++j) {
|
for (int j = 1; j < w; ++j) {
|
||||||
_vid.MAC_fillRect(Video::CHAR_W * (x + j), Video::CHAR_H * (y + i), Video::CHAR_W, Video::CHAR_H, 0xE2);
|
_vid.fillRect(Video::CHAR_W * (x + j), Video::CHAR_H * (y + i), Video::CHAR_W, Video::CHAR_H, 0xE2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1523,7 +1600,7 @@ void Game::loadLevelMap() {
|
||||||
_vid.AMIGA_decodeLev(_currentLevel, _currentRoom);
|
_vid.AMIGA_decodeLev(_currentLevel, _currentRoom);
|
||||||
break;
|
break;
|
||||||
case kResourceTypeDOS:
|
case kResourceTypeDOS:
|
||||||
if (_stub->hasWidescreen()) { // draw adjacent rooms
|
if (_stub->hasWidescreen() && _widescreenMode == kWidescreenAdjacentRooms) {
|
||||||
const int leftRoom = _res._ctData[CT_LEFT_ROOM + _currentRoom];
|
const int leftRoom = _res._ctData[CT_LEFT_ROOM + _currentRoom];
|
||||||
if (leftRoom > 0 && hasLevelMap(_currentLevel, leftRoom)) {
|
if (leftRoom > 0 && hasLevelMap(_currentLevel, leftRoom)) {
|
||||||
_vid.PC_decodeMap(_currentLevel, leftRoom);
|
_vid.PC_decodeMap(_currentLevel, leftRoom);
|
||||||
|
@ -1540,6 +1617,9 @@ void Game::loadLevelMap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_vid.PC_decodeMap(_currentLevel, _currentRoom);
|
_vid.PC_decodeMap(_currentLevel, _currentRoom);
|
||||||
|
if (_stub->hasWidescreen() && _widescreenMode == kWidescreenMirrorRoom) {
|
||||||
|
_stub->copyRectMirrorBorders(Video::GAMESCREEN_W, Video::GAMESCREEN_H, _vid._backLayer);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case kResourceTypeMac:
|
case kResourceTypeMac:
|
||||||
_vid.MAC_decodeMap(_currentLevel, _currentRoom);
|
_vid.MAC_decodeMap(_currentLevel, _currentRoom);
|
||||||
|
|
4
game.h
4
game.h
|
@ -86,11 +86,13 @@ struct Game {
|
||||||
bool _saveStateCompleted;
|
bool _saveStateCompleted;
|
||||||
bool _endLoop;
|
bool _endLoop;
|
||||||
uint32_t _frameTimestamp;
|
uint32_t _frameTimestamp;
|
||||||
|
WidescreenMode _widescreenMode;
|
||||||
|
|
||||||
Game(SystemStub *, FileSystem *, const char *savePath, int level, ResourceType ver, Language lang);
|
Game(SystemStub *, FileSystem *, const char *savePath, int level, ResourceType ver, Language lang, WidescreenMode widescreenMode);
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
void displayTitleScreenAmiga();
|
void displayTitleScreenAmiga();
|
||||||
|
void displayTitleScreenMac(int num);
|
||||||
void resetGameState();
|
void resetGameState();
|
||||||
void mainLoop();
|
void mainLoop();
|
||||||
void updateTiming();
|
void updateTiming();
|
||||||
|
|
6
intern.h
6
intern.h
|
@ -100,6 +100,12 @@ enum Skill {
|
||||||
kSkillExpert,
|
kSkillExpert,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum WidescreenMode {
|
||||||
|
kWidescreenNone,
|
||||||
|
kWidescreenAdjacentRooms,
|
||||||
|
kWidescreenMirrorRoom,
|
||||||
|
};
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
bool bypass_protection;
|
bool bypass_protection;
|
||||||
bool enable_password_menu;
|
bool enable_password_menu;
|
||||||
|
|
49
main.cpp
49
main.cpp
|
@ -22,7 +22,7 @@ static const char *USAGE =
|
||||||
" --savepath=PATH Path to save files (default '.')\n"
|
" --savepath=PATH Path to save files (default '.')\n"
|
||||||
" --levelnum=NUM Start to level, bypass introduction\n"
|
" --levelnum=NUM Start to level, bypass introduction\n"
|
||||||
" --fullscreen Fullscreen display\n"
|
" --fullscreen Fullscreen display\n"
|
||||||
" --widescreen 16:9 display\n"
|
" --widescreen=MODE 16:9 display\n"
|
||||||
" --scaler=NAME@X Graphics scaler (default 'scale@3')\n"
|
" --scaler=NAME@X Graphics scaler (default 'scale@3')\n"
|
||||||
" --language=LANG Language (fr,en,de,sp,it,jp)\n"
|
" --language=LANG Language (fr,en,de,sp,it,jp)\n"
|
||||||
;
|
;
|
||||||
|
@ -74,6 +74,7 @@ static Language detectLanguage(FileSystem *fs) {
|
||||||
return table[i].language;
|
return table[i].language;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
warning("Unable to detect language, defaults to English");
|
||||||
return LANG_EN;
|
return LANG_EN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,12 +127,17 @@ static void initOptions() {
|
||||||
}
|
}
|
||||||
if (*p) {
|
if (*p) {
|
||||||
const bool value = (*p == 't' || *p == 'T' || *p == '1');
|
const bool value = (*p == 't' || *p == 'T' || *p == '1');
|
||||||
|
bool foundOption = false;
|
||||||
for (int i = 0; opts[i].name; ++i) {
|
for (int i = 0; opts[i].name; ++i) {
|
||||||
if (strncmp(buf, opts[i].name, strlen(opts[i].name)) == 0) {
|
if (strncmp(buf, opts[i].name, strlen(opts[i].name)) == 0) {
|
||||||
*opts[i].value = value;
|
*opts[i].value = value;
|
||||||
|
foundOption = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!foundOption) {
|
||||||
|
warning("Unhandled option '%s', ignoring", buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,10 +149,16 @@ static void parseScaler(char *name, ScalerParameters *scalerParameters) {
|
||||||
struct {
|
struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
|
const Scaler *scaler;
|
||||||
} scalers[] = {
|
} scalers[] = {
|
||||||
{ "point", kScalerTypePoint },
|
{ "point", kScalerTypePoint, 0 },
|
||||||
{ "linear", kScalerTypeLinear },
|
{ "linear", kScalerTypeLinear, 0 },
|
||||||
{ "scale", kScalerTypeInternal },
|
{ "scale", kScalerTypeInternal, &_internalScaler },
|
||||||
|
#ifdef USE_STATIC_SCALER
|
||||||
|
{ "nearest", kScalerTypeInternal, &scaler_nearest },
|
||||||
|
{ "tv2x", kScalerTypeInternal, &scaler_tv2x },
|
||||||
|
{ "xbrz", kScalerTypeInternal, &scaler_xbrz },
|
||||||
|
#endif
|
||||||
{ 0, -1 }
|
{ 0, -1 }
|
||||||
};
|
};
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -157,6 +169,7 @@ static void parseScaler(char *name, ScalerParameters *scalerParameters) {
|
||||||
for (int i = 0; scalers[i].name; ++i) {
|
for (int i = 0; scalers[i].name; ++i) {
|
||||||
if (strcmp(scalers[i].name, name) == 0) {
|
if (strcmp(scalers[i].name, name) == 0) {
|
||||||
scalerParameters->type = (ScalerType)scalers[i].type;
|
scalerParameters->type = (ScalerType)scalers[i].type;
|
||||||
|
scalerParameters->scaler = scalers[i].scaler;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -179,12 +192,30 @@ static void parseScaler(char *name, ScalerParameters *scalerParameters) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WidescreenMode parseWidescreen(const char *mode) {
|
||||||
|
static const struct {
|
||||||
|
const char *name;
|
||||||
|
WidescreenMode mode;
|
||||||
|
} modes[] = {
|
||||||
|
{ "adjacent", kWidescreenAdjacentRooms },
|
||||||
|
{ "mirror", kWidescreenMirrorRoom },
|
||||||
|
{ 0, kWidescreenNone },
|
||||||
|
};
|
||||||
|
for (int i = 0; modes[i].name; ++i) {
|
||||||
|
if (strcasecmp(modes[i].name, mode) == 0) {
|
||||||
|
return modes[i].mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
warning("Unhandled widecreen mode '%s', defaults to adjacent rooms", mode);
|
||||||
|
return kWidescreenAdjacentRooms; // default value
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
const char *dataPath = "DATA";
|
const char *dataPath = "DATA";
|
||||||
const char *savePath = ".";
|
const char *savePath = ".";
|
||||||
int levelNum = 0;
|
int levelNum = 0;
|
||||||
bool fullscreen = false;
|
bool fullscreen = false;
|
||||||
bool widescreen = false;
|
WidescreenMode widescreen = kWidescreenNone;
|
||||||
ScalerParameters scalerParameters = ScalerParameters::defaults();
|
ScalerParameters scalerParameters = ScalerParameters::defaults();
|
||||||
int forcedLanguage = -1;
|
int forcedLanguage = -1;
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
|
@ -202,7 +233,7 @@ int main(int argc, char *argv[]) {
|
||||||
{ "fullscreen", no_argument, 0, 4 },
|
{ "fullscreen", no_argument, 0, 4 },
|
||||||
{ "scaler", required_argument, 0, 5 },
|
{ "scaler", required_argument, 0, 5 },
|
||||||
{ "language", required_argument, 0, 6 },
|
{ "language", required_argument, 0, 6 },
|
||||||
{ "widescreen", no_argument, 0, 7 },
|
{ "widescreen", required_argument, 0, 7 },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
int index;
|
int index;
|
||||||
|
@ -248,7 +279,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
widescreen = true;
|
widescreen = parseWidescreen(optarg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf(USAGE, argv[0]);
|
printf(USAGE, argv[0]);
|
||||||
|
@ -265,8 +296,8 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
const Language language = (forcedLanguage == -1) ? detectLanguage(&fs) : (Language)forcedLanguage;
|
const Language language = (forcedLanguage == -1) ? detectLanguage(&fs) : (Language)forcedLanguage;
|
||||||
SystemStub *stub = SystemStub_SDL_create();
|
SystemStub *stub = SystemStub_SDL_create();
|
||||||
Game *g = new Game(stub, &fs, savePath, levelNum, (ResourceType)version, language);
|
Game *g = new Game(stub, &fs, savePath, levelNum, (ResourceType)version, language, widescreen);
|
||||||
stub->init(g_caption, g->_vid._w, g->_vid._h, fullscreen, widescreen, &scalerParameters);
|
stub->init(g_caption, g->_vid._w, g->_vid._h, fullscreen, widescreen != kWidescreenNone, &scalerParameters);
|
||||||
g->run();
|
g->run();
|
||||||
delete g;
|
delete g;
|
||||||
stub->destroy();
|
stub->destroy();
|
||||||
|
|
7
menu.cpp
7
menu.cpp
|
@ -68,6 +68,11 @@ void Menu::drawString2(const char *str, int16_t y, int16_t x) {
|
||||||
int h = Video::CHAR_H;
|
int h = Video::CHAR_H;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
switch (_res->_type) {
|
switch (_res->_type) {
|
||||||
|
case kResourceTypeAmiga:
|
||||||
|
for (; str[len]; ++len) {
|
||||||
|
_vid->AMIGA_drawStringChar(_vid->_frontLayer, _vid->_w, Video::CHAR_W * (x + len), Video::CHAR_H * y, _res->_fnt, _vid->_charFrontColor, (uint8_t)str[len]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case kResourceTypeDOS:
|
case kResourceTypeDOS:
|
||||||
for (; str[len]; ++len) {
|
for (; str[len]; ++len) {
|
||||||
_vid->PC_drawChar((uint8_t)str[len], y, x + len, true);
|
_vid->PC_drawChar((uint8_t)str[len], y, x + len, true);
|
||||||
|
@ -77,8 +82,6 @@ void Menu::drawString2(const char *str, int16_t y, int16_t x) {
|
||||||
for (; str[len]; ++len) {
|
for (; str[len]; ++len) {
|
||||||
_vid->MAC_drawStringChar(_vid->_frontLayer, _vid->_w, Video::CHAR_W * (x + len), Video::CHAR_H * y, _res->_fnt, _vid->_charFrontColor, (uint8_t)str[len]);
|
_vid->MAC_drawStringChar(_vid->_frontLayer, _vid->_w, Video::CHAR_W * (x + len), Video::CHAR_H * y, _res->_fnt, _vid->_charFrontColor, (uint8_t)str[len]);
|
||||||
}
|
}
|
||||||
w *= _vid->_layerScale;
|
|
||||||
h *= _vid->_layerScale;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_vid->markBlockAsDirty(x * w, y * h, len * w, h);
|
_vid->markBlockAsDirty(x * w, y * h, len * w, h);
|
||||||
|
|
8
menu.h
8
menu.h
|
@ -30,6 +30,14 @@ struct Menu {
|
||||||
SCREEN_LEVEL,
|
SCREEN_LEVEL,
|
||||||
SCREEN_INFO
|
SCREEN_INFO
|
||||||
};
|
};
|
||||||
|
enum {
|
||||||
|
kMacTitleScreen_MacPlay = 1,
|
||||||
|
kMacTitleScreen_Presage = 2,
|
||||||
|
kMacTitleScreen_Flashback = 3,
|
||||||
|
kMacTitleScreen_LeftEye = 4,
|
||||||
|
kMacTitleScreen_RightEye = 5,
|
||||||
|
kMacTitleScreen_Controls = 6
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
EVENTS_DELAY = 80
|
EVENTS_DELAY = 80
|
||||||
|
|
28
resource.cpp
28
resource.cpp
|
@ -21,7 +21,7 @@ Resource::Resource(FileSystem *fs, ResourceType ver, Language lang) {
|
||||||
_mac = 0;
|
_mac = 0;
|
||||||
_readUint16 = (_type == kResourceTypeDOS) ? READ_LE_UINT16 : READ_BE_UINT16;
|
_readUint16 = (_type == kResourceTypeDOS) ? READ_LE_UINT16 : READ_BE_UINT16;
|
||||||
_readUint32 = (_type == kResourceTypeDOS) ? READ_LE_UINT32 : READ_BE_UINT32;
|
_readUint32 = (_type == kResourceTypeDOS) ? READ_LE_UINT32 : READ_BE_UINT32;
|
||||||
_scratchBuffer = (uint8_t *)malloc(320 * 224 + 1024);
|
_scratchBuffer = (uint8_t *)malloc(kScratchBufferSize);
|
||||||
if (!_scratchBuffer) {
|
if (!_scratchBuffer) {
|
||||||
error("Unable to allocate temporary memory buffer");
|
error("Unable to allocate temporary memory buffer");
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,9 @@ Resource::Resource(FileSystem *fs, ResourceType ver, Language lang) {
|
||||||
|
|
||||||
Resource::~Resource() {
|
Resource::~Resource() {
|
||||||
clearLevelRes();
|
clearLevelRes();
|
||||||
|
MAC_unloadLevelData();
|
||||||
free(_fnt);
|
free(_fnt);
|
||||||
free(_icn); _icn = 0;
|
free(_icn);
|
||||||
_icnLen = 0;
|
|
||||||
free(_tab);
|
free(_tab);
|
||||||
free(_spc);
|
free(_spc);
|
||||||
free(_spr1);
|
free(_spr1);
|
||||||
|
@ -268,7 +268,7 @@ void Resource::load_PAL_menu(const char *fileName, uint8_t *dstPtr) {
|
||||||
error("Cannot load '%s'", _entryName);
|
error("Cannot load '%s'", _entryName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::load_CMP_menu(const char *fileName, uint8_t *dstPtr) {
|
void Resource::load_CMP_menu(const char *fileName) {
|
||||||
File f;
|
File f;
|
||||||
if (f.open(fileName, "rb", _fs)) {
|
if (f.open(fileName, "rb", _fs)) {
|
||||||
const uint32_t size = f.readUint32BE();
|
const uint32_t size = f.readUint32BE();
|
||||||
|
@ -277,7 +277,7 @@ void Resource::load_CMP_menu(const char *fileName, uint8_t *dstPtr) {
|
||||||
error("Failed to allocate CMP temporary buffer");
|
error("Failed to allocate CMP temporary buffer");
|
||||||
}
|
}
|
||||||
f.read(tmp, size);
|
f.read(tmp, size);
|
||||||
if (!delphine_unpack(dstPtr, tmp, size)) {
|
if (!delphine_unpack(_scratchBuffer, kScratchBufferSize, tmp, size)) {
|
||||||
error("Bad CRC for %s", fileName);
|
error("Bad CRC for %s", fileName);
|
||||||
}
|
}
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
@ -668,7 +668,7 @@ void Resource::load(const char *objName, int objType, const char *ext) {
|
||||||
_pal = dat;
|
_pal = dat;
|
||||||
break;
|
break;
|
||||||
case OT_CT:
|
case OT_CT:
|
||||||
if (!delphine_unpack((uint8_t *)_ctData, dat, size)) {
|
if (!delphine_unpack((uint8_t *)_ctData, sizeof(_ctData), dat, size)) {
|
||||||
error("Bad CRC for '%s'", _entryName);
|
error("Bad CRC for '%s'", _entryName);
|
||||||
}
|
}
|
||||||
free(dat);
|
free(dat);
|
||||||
|
@ -736,7 +736,7 @@ void Resource::load_CT(File *pf) {
|
||||||
error("Unable to allocate CT buffer");
|
error("Unable to allocate CT buffer");
|
||||||
} else {
|
} else {
|
||||||
pf->read(tmp, len);
|
pf->read(tmp, len);
|
||||||
if (!delphine_unpack((uint8_t *)_ctData, tmp, len)) {
|
if (!delphine_unpack((uint8_t *)_ctData, sizeof(_ctData), tmp, len)) {
|
||||||
error("Bad CRC for collision data");
|
error("Bad CRC for collision data");
|
||||||
}
|
}
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
@ -936,7 +936,7 @@ void Resource::load_OBC(File *f) {
|
||||||
}
|
}
|
||||||
f->seek(4);
|
f->seek(4);
|
||||||
f->read(packedData, packedSize);
|
f->read(packedData, packedSize);
|
||||||
if (!delphine_unpack(tmp, packedData, packedSize)) {
|
if (!delphine_unpack(tmp, unpackedSize, packedData, packedSize)) {
|
||||||
error("Bad CRC for compressed object data");
|
error("Bad CRC for compressed object data");
|
||||||
}
|
}
|
||||||
free(packedData);
|
free(packedData);
|
||||||
|
@ -1153,7 +1153,7 @@ void Resource::load_CMP(File *pf) {
|
||||||
}
|
}
|
||||||
if (data[0].packedSize == data[0].size) {
|
if (data[0].packedSize == data[0].size) {
|
||||||
memcpy(_pol, tmp + data[0].offset, data[0].packedSize);
|
memcpy(_pol, tmp + data[0].offset, data[0].packedSize);
|
||||||
} else if (!delphine_unpack(_pol, tmp + data[0].offset, data[0].packedSize)) {
|
} else if (!delphine_unpack(_pol, data[0].size, tmp + data[0].offset, data[0].packedSize)) {
|
||||||
error("Bad CRC for cutscene polygon data");
|
error("Bad CRC for cutscene polygon data");
|
||||||
}
|
}
|
||||||
_cmd = (uint8_t *)malloc(data[1].size);
|
_cmd = (uint8_t *)malloc(data[1].size);
|
||||||
|
@ -1162,7 +1162,7 @@ void Resource::load_CMP(File *pf) {
|
||||||
}
|
}
|
||||||
if (data[1].packedSize == data[1].size) {
|
if (data[1].packedSize == data[1].size) {
|
||||||
memcpy(_cmd, tmp + data[1].offset, data[1].packedSize);
|
memcpy(_cmd, tmp + data[1].offset, data[1].packedSize);
|
||||||
} else if (!delphine_unpack(_cmd, tmp + data[1].offset, data[1].packedSize)) {
|
} else if (!delphine_unpack(_cmd, data[1].size, tmp + data[1].offset, data[1].packedSize)) {
|
||||||
error("Bad CRC for cutscene command data");
|
error("Bad CRC for cutscene command data");
|
||||||
}
|
}
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
@ -1278,7 +1278,7 @@ void Resource::load_SGD(File *f) {
|
||||||
if (!_sgd) {
|
if (!_sgd) {
|
||||||
error("Unable to allocate SGD buffer");
|
error("Unable to allocate SGD buffer");
|
||||||
}
|
}
|
||||||
if (!delphine_unpack(_sgd, tmp, len)) {
|
if (!delphine_unpack(_sgd, size, tmp, len)) {
|
||||||
error("Bad CRC for SGD data");
|
error("Bad CRC for SGD data");
|
||||||
}
|
}
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
@ -1310,12 +1310,12 @@ void Resource::load_SPM(File *f) {
|
||||||
if (!_spr1) {
|
if (!_spr1) {
|
||||||
error("Unable to allocate SPR1 buffer");
|
error("Unable to allocate SPR1 buffer");
|
||||||
}
|
}
|
||||||
if (!delphine_unpack(_spr1, tmp, len)) {
|
if (!delphine_unpack(_spr1, size, tmp, len)) {
|
||||||
error("Bad CRC for SPM data");
|
error("Bad CRC for SPM data");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(size <= sizeof(_sprm));
|
assert(size <= sizeof(_sprm));
|
||||||
if (!delphine_unpack(_sprm, tmp, len)) {
|
if (!delphine_unpack(_sprm, sizeof(_sprm), tmp, len)) {
|
||||||
error("Bad CRC for SPM data");
|
error("Bad CRC for SPM data");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1391,7 +1391,7 @@ uint8_t *Resource::loadBankData(uint16_t num) {
|
||||||
} else {
|
} else {
|
||||||
assert(dataOffset > 4);
|
assert(dataOffset > 4);
|
||||||
assert(size == (int)READ_BE_UINT32(data - 4));
|
assert(size == (int)READ_BE_UINT32(data - 4));
|
||||||
if (!delphine_unpack(_bankDataHead, data, 0)) {
|
if (!delphine_unpack(_bankDataHead, _bankDataTail - _bankDataHead, data, 0)) {
|
||||||
error("Bad CRC for bank data %d", num);
|
error("Bad CRC for bank data %d", num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,8 @@ struct Resource {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kPaulaFreq = 3546897,
|
kPaulaFreq = 3546897,
|
||||||
kClutSize = 1024
|
kClutSize = 1024,
|
||||||
|
kScratchBufferSize = 320 * 224 + 1024
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint16_t _voicesOffsetsTable[];
|
static const uint16_t _voicesOffsetsTable[];
|
||||||
|
@ -187,6 +188,7 @@ struct Resource {
|
||||||
|
|
||||||
bool isDOS() const { return _type == kResourceTypeDOS; }
|
bool isDOS() const { return _type == kResourceTypeDOS; }
|
||||||
bool isAmiga() const { return _type == kResourceTypeAmiga; }
|
bool isAmiga() const { return _type == kResourceTypeAmiga; }
|
||||||
|
bool isMac() const { return _type == kResourceTypeMac; }
|
||||||
|
|
||||||
bool fileExists(const char *filename);
|
bool fileExists(const char *filename);
|
||||||
|
|
||||||
|
@ -196,7 +198,7 @@ struct Resource {
|
||||||
void load_SPL_demo();
|
void load_SPL_demo();
|
||||||
void load_MAP_menu(const char *fileName, uint8_t *dstPtr);
|
void load_MAP_menu(const char *fileName, uint8_t *dstPtr);
|
||||||
void load_PAL_menu(const char *fileName, uint8_t *dstPtr);
|
void load_PAL_menu(const char *fileName, uint8_t *dstPtr);
|
||||||
void load_CMP_menu(const char *fileName, uint8_t *dstPtr);
|
void load_CMP_menu(const char *fileName);
|
||||||
void load_SPR_OFF(const char *fileName, uint8_t *sprData);
|
void load_SPR_OFF(const char *fileName, uint8_t *sprData);
|
||||||
void load_CINE();
|
void load_CINE();
|
||||||
void free_CINE();
|
void free_CINE();
|
||||||
|
|
|
@ -74,7 +74,7 @@ uint8_t *ResourceAba::loadEntry(const char *name, uint32_t *size) {
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const bool ret = delphine_unpack(dst, tmp, e->compressedSize);
|
const bool ret = delphine_unpack(dst, e->size, tmp, e->compressedSize);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
error("Bad CRC for '%s'", name);
|
error("Bad CRC for '%s'", name);
|
||||||
}
|
}
|
||||||
|
|
2
rs.cfg
2
rs.cfg
|
@ -16,7 +16,7 @@ use_tiledata=false
|
||||||
# display text instead of playing the polygon cutscenes
|
# display text instead of playing the polygon cutscenes
|
||||||
use_text_cutscenes=false
|
use_text_cutscenes=false
|
||||||
|
|
||||||
# enable playback of .SEQ cutscenes (use polygonal if false)
|
# enable playback of .SEQ cutscenes (always use polygon cutscenes if false)
|
||||||
use_seq_cutscenes=true
|
use_seq_cutscenes=true
|
||||||
|
|
||||||
# enable playback of 'ASC' cutscene
|
# enable playback of 'ASC' cutscene
|
||||||
|
|
6
scaler.h
6
scaler.h
|
@ -31,4 +31,10 @@ extern const Scaler _internalScaler;
|
||||||
|
|
||||||
const Scaler *findScaler(const char *name);
|
const Scaler *findScaler(const char *name);
|
||||||
|
|
||||||
|
#ifdef USE_STATIC_SCALER
|
||||||
|
extern const Scaler scaler_nearest;
|
||||||
|
extern const Scaler scaler_tv2x;
|
||||||
|
extern const Scaler scaler_xbrz;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // SCALER_H__
|
#endif // SCALER_H__
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct SystemStub {
|
||||||
virtual void copyRectRgb24(int x, int y, int w, int h, const uint8_t *rgb) = 0;
|
virtual void copyRectRgb24(int x, int y, int w, int h, const uint8_t *rgb) = 0;
|
||||||
virtual void copyRectLeftBorder(int w, int h, const uint8_t *buf) = 0;
|
virtual void copyRectLeftBorder(int w, int h, const uint8_t *buf) = 0;
|
||||||
virtual void copyRectRightBorder(int w, int h, const uint8_t *buf) = 0;
|
virtual void copyRectRightBorder(int w, int h, const uint8_t *buf) = 0;
|
||||||
|
virtual void copyRectMirrorBorders(int w, int h, const uint8_t *buf) = 0;
|
||||||
virtual void fadeScreen() = 0;
|
virtual void fadeScreen() = 0;
|
||||||
virtual void updateScreen(int shakeOffset) = 0;
|
virtual void updateScreen(int shakeOffset) = 0;
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ struct SystemStub_SDL : SystemStub {
|
||||||
virtual void copyRectRgb24(int x, int y, int w, int h, const uint8_t *rgb);
|
virtual void copyRectRgb24(int x, int y, int w, int h, const uint8_t *rgb);
|
||||||
virtual void copyRectLeftBorder(int w, int h, const uint8_t *buf);
|
virtual void copyRectLeftBorder(int w, int h, const uint8_t *buf);
|
||||||
virtual void copyRectRightBorder(int w, int h, const uint8_t *buf);
|
virtual void copyRectRightBorder(int w, int h, const uint8_t *buf);
|
||||||
|
virtual void copyRectMirrorBorders(int w, int h, const uint8_t *buf);
|
||||||
virtual void fadeScreen();
|
virtual void fadeScreen();
|
||||||
virtual void updateScreen(int shakeOffset);
|
virtual void updateScreen(int shakeOffset);
|
||||||
virtual void processEvents();
|
virtual void processEvents();
|
||||||
|
@ -82,6 +83,7 @@ struct SystemStub_SDL : SystemStub {
|
||||||
void prepareGraphics();
|
void prepareGraphics();
|
||||||
void cleanupGraphics();
|
void cleanupGraphics();
|
||||||
void changeGraphics(bool fullscreen, int scaleFactor);
|
void changeGraphics(bool fullscreen, int scaleFactor);
|
||||||
|
void changeScaler(int scaler);
|
||||||
void drawRect(int x, int y, int w, int h, uint8_t color);
|
void drawRect(int x, int y, int w, int h, uint8_t color);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,13 +99,13 @@ void SystemStub_SDL::init(const char *title, int w, int h, bool fullscreen, bool
|
||||||
_window = 0;
|
_window = 0;
|
||||||
_renderer = 0;
|
_renderer = 0;
|
||||||
_texture = 0;
|
_texture = 0;
|
||||||
_fmt = 0;
|
_fmt = SDL_AllocFormat(kPixelFormat);
|
||||||
_screenBuffer = 0;
|
_screenBuffer = 0;
|
||||||
_fadeOnUpdateScreen = false;
|
_fadeOnUpdateScreen = false;
|
||||||
_fullscreen = fullscreen;
|
_fullscreen = fullscreen;
|
||||||
_scalerType = scalerParameters->type;
|
_scalerType = scalerParameters->type;
|
||||||
_scaler = scalerParameters->scaler;
|
_scaler = scalerParameters->scaler;
|
||||||
_scaleFactor = CLIP(scalerParameters->factor, _scaler->factorMin, _scaler->factorMax);
|
_scaleFactor = _scaler ? CLIP(scalerParameters->factor, _scaler->factorMin, _scaler->factorMax) : 1;
|
||||||
memset(_rgbPalette, 0, sizeof(_rgbPalette));
|
memset(_rgbPalette, 0, sizeof(_rgbPalette));
|
||||||
memset(_darkPalette, 0, sizeof(_darkPalette));
|
memset(_darkPalette, 0, sizeof(_darkPalette));
|
||||||
_screenW = _screenH = 0;
|
_screenW = _screenH = 0;
|
||||||
|
@ -127,6 +129,14 @@ void SystemStub_SDL::init(const char *title, int w, int h, bool fullscreen, bool
|
||||||
|
|
||||||
void SystemStub_SDL::destroy() {
|
void SystemStub_SDL::destroy() {
|
||||||
cleanupGraphics();
|
cleanupGraphics();
|
||||||
|
if (_screenBuffer) {
|
||||||
|
free(_screenBuffer);
|
||||||
|
_screenBuffer = 0;
|
||||||
|
}
|
||||||
|
if (_fmt) {
|
||||||
|
SDL_FreeFormat(_fmt);
|
||||||
|
_fmt = 0;
|
||||||
|
}
|
||||||
if (_controller) {
|
if (_controller) {
|
||||||
SDL_GameControllerClose(_controller);
|
SDL_GameControllerClose(_controller);
|
||||||
_controller = 0;
|
_controller = 0;
|
||||||
|
@ -147,6 +157,10 @@ void SystemStub_SDL::setScreenSize(int w, int h) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cleanupGraphics();
|
cleanupGraphics();
|
||||||
|
if (_screenBuffer) {
|
||||||
|
free(_screenBuffer);
|
||||||
|
_screenBuffer = 0;
|
||||||
|
}
|
||||||
const int screenBufferSize = w * h * sizeof(uint32_t);
|
const int screenBufferSize = w * h * sizeof(uint32_t);
|
||||||
_screenBuffer = (uint32_t *)calloc(1, screenBufferSize);
|
_screenBuffer = (uint32_t *)calloc(1, screenBufferSize);
|
||||||
if (!_screenBuffer) {
|
if (!_screenBuffer) {
|
||||||
|
@ -232,6 +246,19 @@ void SystemStub_SDL::copyRectRgb24(int x, int y, int w, int h, const uint8_t *rg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clearTexture(SDL_Texture *texture, int h, SDL_PixelFormat *fmt) {
|
||||||
|
void *dst = 0;
|
||||||
|
int pitch = 0;
|
||||||
|
if (SDL_LockTexture(texture, 0, &dst, &pitch) == 0) {
|
||||||
|
assert((pitch & 3) == 0);
|
||||||
|
const uint32_t color = SDL_MapRGB(fmt, 0, 0, 0);
|
||||||
|
for (uint32_t i = 0; i < h * pitch / sizeof(uint32_t); ++i) {
|
||||||
|
((uint32_t *)dst)[i] = color;
|
||||||
|
}
|
||||||
|
SDL_UnlockTexture(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::copyRectLeftBorder(int w, int h, const uint8_t *buf) {
|
void SystemStub_SDL::copyRectLeftBorder(int w, int h, const uint8_t *buf) {
|
||||||
assert(w >= _wideMargin);
|
assert(w >= _wideMargin);
|
||||||
uint32_t *rgb = (uint32_t *)malloc(w * h * sizeof(uint32_t));
|
uint32_t *rgb = (uint32_t *)malloc(w * h * sizeof(uint32_t));
|
||||||
|
@ -241,7 +268,10 @@ void SystemStub_SDL::copyRectLeftBorder(int w, int h, const uint8_t *buf) {
|
||||||
rgb[i] = _darkPalette[buf[i]];
|
rgb[i] = _darkPalette[buf[i]];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memset(rgb, 0, w * h * sizeof(uint32_t));
|
const uint32_t color = SDL_MapRGB(_fmt, 0, 0, 0);
|
||||||
|
for (int i = 0; i < w * h; ++i) {
|
||||||
|
rgb[i] = color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const int xOffset = w - _wideMargin;
|
const int xOffset = w - _wideMargin;
|
||||||
SDL_Rect r;
|
SDL_Rect r;
|
||||||
|
@ -263,7 +293,10 @@ void SystemStub_SDL::copyRectRightBorder(int w, int h, const uint8_t *buf) {
|
||||||
rgb[i] = _darkPalette[buf[i]];
|
rgb[i] = _darkPalette[buf[i]];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memset(rgb, 0, w * h * sizeof(uint32_t));
|
const uint32_t color = SDL_MapRGB(_fmt, 0, 0, 0);
|
||||||
|
for (int i = 0; i < w * h; ++i) {
|
||||||
|
rgb[i] = color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const int xOffset = 0;
|
const int xOffset = 0;
|
||||||
SDL_Rect r;
|
SDL_Rect r;
|
||||||
|
@ -276,6 +309,35 @@ void SystemStub_SDL::copyRectRightBorder(int w, int h, const uint8_t *buf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemStub_SDL::copyRectMirrorBorders(int w, int h, const uint8_t *buf) {
|
||||||
|
assert(w >= _wideMargin);
|
||||||
|
uint32_t *rgb = (uint32_t *)malloc(w * h * sizeof(uint32_t));
|
||||||
|
if (rgb) {
|
||||||
|
for (int i = 0; i < w * h; ++i) {
|
||||||
|
rgb[i] = _darkPalette[buf[i]];
|
||||||
|
}
|
||||||
|
void *dst = 0;
|
||||||
|
int pitch = 0;
|
||||||
|
if (SDL_LockTexture(_wideTexture, 0, &dst, &pitch) == 0) {
|
||||||
|
assert((pitch & 3) == 0);
|
||||||
|
uint32_t *p = (uint32_t *)dst;
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for (int x = 0; x < _wideMargin; ++x) {
|
||||||
|
// left side
|
||||||
|
const int xLeft = _wideMargin - 1 - x;
|
||||||
|
p[x] = rgb[y * w + xLeft];
|
||||||
|
// right side
|
||||||
|
const int xRight = w - 1 - x;
|
||||||
|
p[_wideMargin + _screenW + x] = rgb[y * w + xRight];
|
||||||
|
}
|
||||||
|
p += pitch / sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
SDL_UnlockTexture(_wideTexture);
|
||||||
|
}
|
||||||
|
free(rgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::fadeScreen() {
|
void SystemStub_SDL::fadeScreen() {
|
||||||
_fadeOnUpdateScreen = true;
|
_fadeOnUpdateScreen = true;
|
||||||
}
|
}
|
||||||
|
@ -511,11 +573,15 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
||||||
break;
|
break;
|
||||||
case SDLK_KP_PLUS:
|
case SDLK_KP_PLUS:
|
||||||
case SDLK_PAGEUP:
|
case SDLK_PAGEUP:
|
||||||
changeGraphics(_fullscreen, _scaleFactor + 1);
|
if (_scalerType == kScalerTypeInternal || _scalerType == kScalerTypeExternal) {
|
||||||
|
changeGraphics(_fullscreen, _scaleFactor + 1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SDLK_KP_MINUS:
|
case SDLK_KP_MINUS:
|
||||||
case SDLK_PAGEDOWN:
|
case SDLK_PAGEDOWN:
|
||||||
changeGraphics(_fullscreen, _scaleFactor - 1);
|
if (_scalerType == kScalerTypeInternal || _scalerType == kScalerTypeExternal) {
|
||||||
|
changeGraphics(_fullscreen, _scaleFactor - 1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SDLK_s: {
|
case SDLK_s: {
|
||||||
char name[32];
|
char name[32];
|
||||||
|
@ -585,6 +651,16 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
||||||
case SDLK_ESCAPE:
|
case SDLK_ESCAPE:
|
||||||
_pi.escape = false;
|
_pi.escape = false;
|
||||||
break;
|
break;
|
||||||
|
case SDLK_F1:
|
||||||
|
case SDLK_F2:
|
||||||
|
case SDLK_F3:
|
||||||
|
case SDLK_F4:
|
||||||
|
case SDLK_F5:
|
||||||
|
case SDLK_F6:
|
||||||
|
case SDLK_F7:
|
||||||
|
case SDLK_F8:
|
||||||
|
changeScaler(ev.key.keysym.sym - SDLK_F1);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -717,21 +793,18 @@ void SystemStub_SDL::prepareGraphics() {
|
||||||
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
|
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
SDL_RenderSetLogicalSize(_renderer, windowW, windowH);
|
SDL_RenderSetLogicalSize(_renderer, windowW, windowH);
|
||||||
_texture = SDL_CreateTexture(_renderer, kPixelFormat, SDL_TEXTUREACCESS_STREAMING, _texW, _texH);
|
_texture = SDL_CreateTexture(_renderer, kPixelFormat, SDL_TEXTUREACCESS_STREAMING, _texW, _texH);
|
||||||
_fmt = SDL_AllocFormat(kPixelFormat);
|
|
||||||
if (_widescreen) {
|
if (_widescreen) {
|
||||||
const int w = _screenH * 16 / 9;
|
const int w = _screenH * 16 / 9;
|
||||||
const int h = _screenH;
|
const int h = _screenH;
|
||||||
_wideTexture = SDL_CreateTexture(_renderer, kPixelFormat, SDL_TEXTUREACCESS_STREAMING, w, h);
|
_wideTexture = SDL_CreateTexture(_renderer, kPixelFormat, SDL_TEXTUREACCESS_STREAMING, w, h);
|
||||||
|
clearTexture(_wideTexture, _screenH, _fmt);
|
||||||
|
|
||||||
// left and right borders
|
// left and right borders
|
||||||
_wideMargin = (w - _screenW) / 2;
|
_wideMargin = (w - _screenW) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::cleanupGraphics() {
|
void SystemStub_SDL::cleanupGraphics() {
|
||||||
if (_screenBuffer) {
|
|
||||||
free(_screenBuffer);
|
|
||||||
_screenBuffer = 0;
|
|
||||||
}
|
|
||||||
if (_texture) {
|
if (_texture) {
|
||||||
SDL_DestroyTexture(_texture);
|
SDL_DestroyTexture(_texture);
|
||||||
_texture = 0;
|
_texture = 0;
|
||||||
|
@ -748,10 +821,6 @@ void SystemStub_SDL::cleanupGraphics() {
|
||||||
SDL_DestroyWindow(_window);
|
SDL_DestroyWindow(_window);
|
||||||
_window = 0;
|
_window = 0;
|
||||||
}
|
}
|
||||||
if (_fmt) {
|
|
||||||
SDL_FreeFormat(_fmt);
|
|
||||||
_fmt = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::changeGraphics(bool fullscreen, int scaleFactor) {
|
void SystemStub_SDL::changeGraphics(bool fullscreen, int scaleFactor) {
|
||||||
|
@ -762,29 +831,53 @@ void SystemStub_SDL::changeGraphics(bool fullscreen, int scaleFactor) {
|
||||||
}
|
}
|
||||||
_fullscreen = fullscreen;
|
_fullscreen = fullscreen;
|
||||||
_scaleFactor = factor;
|
_scaleFactor = factor;
|
||||||
if (_texture) {
|
cleanupGraphics();
|
||||||
SDL_DestroyTexture(_texture);
|
|
||||||
_texture = 0;
|
|
||||||
}
|
|
||||||
if (_wideTexture) {
|
|
||||||
SDL_DestroyTexture(_wideTexture);
|
|
||||||
_wideTexture = 0;
|
|
||||||
}
|
|
||||||
if (_renderer) {
|
|
||||||
SDL_DestroyRenderer(_renderer);
|
|
||||||
_renderer = 0;
|
|
||||||
}
|
|
||||||
if (_window) {
|
|
||||||
SDL_DestroyWindow(_window);
|
|
||||||
_window = 0;
|
|
||||||
}
|
|
||||||
if (_fmt) {
|
|
||||||
SDL_FreeFormat(_fmt);
|
|
||||||
_fmt = 0;
|
|
||||||
}
|
|
||||||
prepareGraphics();
|
prepareGraphics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemStub_SDL::changeScaler(int scaler) {
|
||||||
|
ScalerParameters scalerParameters = ScalerParameters::defaults();
|
||||||
|
switch (scaler) {
|
||||||
|
case 0:
|
||||||
|
scalerParameters.type = kScalerTypePoint;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
scalerParameters.type = kScalerTypeLinear;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
scalerParameters.type = kScalerTypeInternal;
|
||||||
|
scalerParameters.scaler = &_internalScaler;
|
||||||
|
break;
|
||||||
|
#ifdef USE_STATIC_SCALER
|
||||||
|
case 3:
|
||||||
|
scalerParameters.type = kScalerTypeInternal;
|
||||||
|
scalerParameters.scaler = &scaler_nearest;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
scalerParameters.type = kScalerTypeInternal;
|
||||||
|
scalerParameters.scaler = &scaler_tv2x;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
scalerParameters.type = kScalerTypeInternal;
|
||||||
|
scalerParameters.scaler = &scaler_xbrz;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_scalerType != scalerParameters.type || scalerParameters.scaler != _scaler) {
|
||||||
|
_scalerType = scalerParameters.type;
|
||||||
|
_scaler = scalerParameters.scaler;
|
||||||
|
const int scaleFactor = CLIP(_scaleFactor, _scaler->factorMin, _scaler->factorMax);
|
||||||
|
// only recreate the window if dimensions actually changed
|
||||||
|
if (scaleFactor != _scaleFactor) {
|
||||||
|
cleanupGraphics();
|
||||||
|
_scaleFactor = scaleFactor;
|
||||||
|
prepareGraphics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::drawRect(int x, int y, int w, int h, uint8_t color) {
|
void SystemStub_SDL::drawRect(int x, int y, int w, int h, uint8_t color) {
|
||||||
const int x1 = x;
|
const int x1 = x;
|
||||||
const int y1 = y;
|
const int y1 = y;
|
||||||
|
|
58
unpack.cpp
58
unpack.cpp
|
@ -5,9 +5,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "unpack.h"
|
#include "unpack.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
struct UnpackCtx {
|
struct UnpackCtx {
|
||||||
int datasize;
|
int size;
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
uint32_t bits;
|
uint32_t bits;
|
||||||
uint8_t *dst;
|
uint8_t *dst;
|
||||||
|
@ -26,40 +27,52 @@ static bool nextBit(UnpackCtx *uc) {
|
||||||
return carry;
|
return carry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t getBits(UnpackCtx *uc, int bitsCount) {
|
static int getBits(UnpackCtx *uc, int count) {
|
||||||
uint16_t c = 0;
|
int bits = 0;
|
||||||
for (int i = 0; i < bitsCount; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
c <<= 1;
|
bits <<= 1;
|
||||||
if (nextBit(uc)) {
|
if (nextBit(uc)) {
|
||||||
c |= 1;
|
bits |= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyLiteral(UnpackCtx *uc, int bitsCount, int len) {
|
static void copyLiteral(UnpackCtx *uc, int bitsCount, int len) {
|
||||||
const int count = getBits(uc, bitsCount) + len + 1;
|
int count = getBits(uc, bitsCount) + len + 1;
|
||||||
for (int i = 0; i < count; ++i) {
|
uc->size -= count;
|
||||||
*uc->dst = (uint8_t)getBits(uc, 8);
|
if (uc->size < 0) {
|
||||||
--uc->dst;
|
count += uc->size;
|
||||||
|
uc->size = 0;
|
||||||
}
|
}
|
||||||
uc->datasize -= count;
|
for (int i = 0; i < count; ++i) {
|
||||||
|
*(uc->dst - i) = (uint8_t)getBits(uc, 8);
|
||||||
|
}
|
||||||
|
uc->dst -= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyReference(UnpackCtx *uc, int bitsCount, int count) {
|
static void copyReference(UnpackCtx *uc, int bitsCount, int count) {
|
||||||
const uint16_t offset = getBits(uc, bitsCount);
|
uc->size -= count;
|
||||||
for (int i = 0; i < count; ++i) {
|
if (uc->size < 0) {
|
||||||
*uc->dst = *(uc->dst + offset);
|
count += uc->size;
|
||||||
--uc->dst;
|
uc->size = 0;
|
||||||
}
|
}
|
||||||
uc->datasize -= count;
|
const int offset = getBits(uc, bitsCount);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
*(uc->dst - i) = *(uc->dst - i + offset);
|
||||||
|
}
|
||||||
|
uc->dst -= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool delphine_unpack(uint8_t *dst, const uint8_t *src, int len) {
|
bool delphine_unpack(uint8_t *dst, int dstSize, const uint8_t *src, int srcSize) {
|
||||||
UnpackCtx uc;
|
UnpackCtx uc;
|
||||||
uc.src = src + len - 4;
|
uc.src = src + srcSize - 4;
|
||||||
uc.datasize = READ_BE_UINT32(uc.src); uc.src -= 4;
|
uc.size = READ_BE_UINT32(uc.src); uc.src -= 4;
|
||||||
uc.dst = dst + uc.datasize - 1;
|
if (uc.size > dstSize) {
|
||||||
|
warning("Unexpected unpack size %d, buffer size %d", uc.size, dstSize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uc.dst = dst + uc.size - 1;
|
||||||
uc.crc = READ_BE_UINT32(uc.src); uc.src -= 4;
|
uc.crc = READ_BE_UINT32(uc.src); uc.src -= 4;
|
||||||
uc.bits = READ_BE_UINT32(uc.src); uc.src -= 4;
|
uc.bits = READ_BE_UINT32(uc.src); uc.src -= 4;
|
||||||
uc.crc ^= uc.bits;
|
uc.crc ^= uc.bits;
|
||||||
|
@ -87,6 +100,7 @@ bool delphine_unpack(uint8_t *dst, const uint8_t *src, int len) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (uc.datasize > 0);
|
} while (uc.size > 0);
|
||||||
|
assert(uc.size == 0);
|
||||||
return uc.crc == 0;
|
return uc.crc == 0;
|
||||||
}
|
}
|
||||||
|
|
2
unpack.h
2
unpack.h
|
@ -9,6 +9,6 @@
|
||||||
|
|
||||||
#include "intern.h"
|
#include "intern.h"
|
||||||
|
|
||||||
extern bool delphine_unpack(uint8_t *dst, const uint8_t *src, int len);
|
extern bool delphine_unpack(uint8_t *dst, int dstSize, const uint8_t *src, int srcSize);
|
||||||
|
|
||||||
#endif // UNPACK_H__
|
#endif // UNPACK_H__
|
||||||
|
|
19
video.cpp
19
video.cpp
|
@ -629,8 +629,9 @@ static void decodeLevHelper(uint8_t *dst, const uint8_t *src, int offset10, int
|
||||||
void Video::AMIGA_decodeLev(int level, int room) {
|
void Video::AMIGA_decodeLev(int level, int room) {
|
||||||
uint8_t *tmp = _res->_scratchBuffer;
|
uint8_t *tmp = _res->_scratchBuffer;
|
||||||
const int offset = READ_BE_UINT32(_res->_lev + room * 4);
|
const int offset = READ_BE_UINT32(_res->_lev + room * 4);
|
||||||
if (!delphine_unpack(tmp, _res->_lev, offset)) {
|
if (!delphine_unpack(tmp, Resource::kScratchBufferSize, _res->_lev, offset)) {
|
||||||
error("Bad CRC for level %d room %d", level, room);
|
warning("Bad CRC for level %d room %d", level, room);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
uint16_t offset10 = READ_BE_UINT16(tmp + 10);
|
uint16_t offset10 = READ_BE_UINT16(tmp + 10);
|
||||||
const uint16_t offset12 = READ_BE_UINT16(tmp + 12);
|
const uint16_t offset12 = READ_BE_UINT16(tmp + 12);
|
||||||
|
@ -900,6 +901,9 @@ void Video::PC_drawStringChar(uint8_t *dst, int pitch, int x, int y, const uint8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t _MAC_fontFrontColor;
|
||||||
|
static uint8_t _MAC_fontShadowColor;
|
||||||
|
|
||||||
void Video::MAC_drawStringChar(uint8_t *dst, int pitch, int x, int y, const uint8_t *src, uint8_t color, uint8_t chr) {
|
void Video::MAC_drawStringChar(uint8_t *dst, int pitch, int x, int y, const uint8_t *src, uint8_t color, uint8_t chr) {
|
||||||
DecodeBuffer buf;
|
DecodeBuffer buf;
|
||||||
memset(&buf, 0, sizeof(buf));
|
memset(&buf, 0, sizeof(buf));
|
||||||
|
@ -909,8 +913,8 @@ void Video::MAC_drawStringChar(uint8_t *dst, int pitch, int x, int y, const uint
|
||||||
buf.x = x * _layerScale;
|
buf.x = x * _layerScale;
|
||||||
buf.y = y * _layerScale;
|
buf.y = y * _layerScale;
|
||||||
buf.setPixel = Video::MAC_drawBufferFont;
|
buf.setPixel = Video::MAC_drawBufferFont;
|
||||||
_charFrontColor = color;
|
_MAC_fontFrontColor = color;
|
||||||
buf.dataPtr = this;
|
_MAC_fontShadowColor = _charShadowColor;
|
||||||
assert(chr >= 32);
|
assert(chr >= 32);
|
||||||
_res->MAC_decodeImageData(_res->_fnt, chr - 32, &buf);
|
_res->MAC_decodeImageData(_res->_fnt, chr - 32, &buf);
|
||||||
}
|
}
|
||||||
|
@ -1004,21 +1008,20 @@ void Video::MAC_drawBufferFont(DecodeBuffer *buf, int src_x, int src_y, int src_
|
||||||
if (y >= 0 && y < buf->h) {
|
if (y >= 0 && y < buf->h) {
|
||||||
const int x = buf->x + src_x;
|
const int x = buf->x + src_x;
|
||||||
if (x >= 0 && x < buf->w) {
|
if (x >= 0 && x < buf->w) {
|
||||||
const Video *vid = (Video *)buf->dataPtr;
|
|
||||||
const int offset = y * buf->pitch + x;
|
const int offset = y * buf->pitch + x;
|
||||||
switch (color) {
|
switch (color) {
|
||||||
case 0xC0:
|
case 0xC0:
|
||||||
buf->ptr[offset] = vid->_charShadowColor;
|
buf->ptr[offset] = _MAC_fontShadowColor;
|
||||||
break;
|
break;
|
||||||
case 0xC1:
|
case 0xC1:
|
||||||
buf->ptr[offset] = vid->_charFrontColor;
|
buf->ptr[offset] = _MAC_fontFrontColor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::MAC_fillRect(int x, int y, int w, int h, uint8_t color) {
|
void Video::fillRect(int x, int y, int w, int h, uint8_t color) {
|
||||||
uint8_t *p = _frontLayer + y * _layerScale * _w + x * _layerScale;
|
uint8_t *p = _frontLayer + y * _layerScale * _w + x * _layerScale;
|
||||||
for (int j = 0; j < h * _layerScale; ++j) {
|
for (int j = 0; j < h * _layerScale; ++j) {
|
||||||
memset(p, color, w * _layerScale);
|
memset(p, color, w * _layerScale);
|
||||||
|
|
2
video.h
2
video.h
|
@ -90,7 +90,7 @@ struct Video {
|
||||||
static void MAC_drawBuffer(DecodeBuffer *buf, int src_x, int src_y, int src_w, int src_h, uint8_t color);
|
static void MAC_drawBuffer(DecodeBuffer *buf, int src_x, int src_y, int src_w, int src_h, uint8_t color);
|
||||||
static void MAC_drawBufferMask(DecodeBuffer *buf, int src_x, int src_y, int src_w, int src_h, uint8_t color);
|
static void MAC_drawBufferMask(DecodeBuffer *buf, int src_x, int src_y, int src_w, int src_h, uint8_t color);
|
||||||
static void MAC_drawBufferFont(DecodeBuffer *buf, int src_x, int src_y, int src_w, int src_h, uint8_t color);
|
static void MAC_drawBufferFont(DecodeBuffer *buf, int src_x, int src_y, int src_w, int src_h, uint8_t color);
|
||||||
void MAC_fillRect(int x, int y, int w, int h, uint8_t color);
|
void fillRect(int x, int y, int w, int h, uint8_t color);
|
||||||
void MAC_drawSprite(int x, int y, const uint8_t *data, int frame, bool xflip, bool eraseBackground);
|
void MAC_drawSprite(int x, int y, const uint8_t *data, int frame, bool xflip, bool eraseBackground);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue