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
|
||||
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 \
|
||||
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 \
|
||||
sfx_player.cpp staticres.cpp systemstub_sdl.cpp unpack.cpp util.cpp video.cpp
|
||||
|
||||
OBJS = $(SRCS:.cpp=.o)
|
||||
DEPS = $(SRCS:.cpp=.d)
|
||||
SCALERS := scalers/scaler_nearest.cpp scalers/scaler_tv2x.cpp scalers/scaler_xbrz.cpp scalers/xbrz/xbrz.cpp
|
||||
|
||||
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)
|
||||
|
||||
|
|
11
README.txt
11
README.txt
|
@ -1,6 +1,6 @@
|
|||
|
||||
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 '.')
|
||||
--levelnum=NUM Level to start from (default '0')
|
||||
--fullscreen Fullscreen display
|
||||
--widescreen 16:9 display
|
||||
--widescreen=MODE 16:9 display
|
||||
--scaler=NAME@X Graphics scaler (default 'scale@3')
|
||||
--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
|
||||
'--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 :
|
||||
|
||||
Arrow Keys move Conrad
|
||||
|
@ -60,11 +64,12 @@ In-game hotkeys :
|
|||
Escape display the options
|
||||
Backspace display the inventory
|
||||
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
|
||||
Ctrl S save game state
|
||||
Ctrl L load game state
|
||||
Ctrl + and - change game state slot
|
||||
Function Keys change game screen scaler
|
||||
|
||||
Debug hotkeys :
|
||||
|
||||
|
|
25
cutscene.cpp
25
cutscene.cpp
|
@ -938,7 +938,12 @@ void Cutscene::op_handleKeys() {
|
|||
_cmdPtr = getCommandData();
|
||||
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() {
|
||||
|
@ -951,7 +956,7 @@ uint16_t Cutscene::fetchNextCmdWord() {
|
|||
return i;
|
||||
}
|
||||
|
||||
void Cutscene::mainLoop(uint16_t offset) {
|
||||
void Cutscene::mainLoop(uint16_t num) {
|
||||
_frameDelay = 5;
|
||||
_tstamp = _stub->getTimeStamp();
|
||||
|
||||
|
@ -963,14 +968,20 @@ void Cutscene::mainLoop(uint16_t offset) {
|
|||
_newPal = false;
|
||||
_hasAlphaColor = false;
|
||||
const uint8_t *p = getCommandData();
|
||||
if (offset != 0) {
|
||||
offset = READ_BE_UINT16(p + (offset + 1) * 2);
|
||||
int offset = 0;
|
||||
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;
|
||||
_cmdPtr = _cmdPtrBak = p + _startOffset + offset;
|
||||
_cmdPtr = _cmdPtrBak = p + _baseOffset + offset;
|
||||
_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) {
|
||||
uint8_t op = fetchNextCmdByte();
|
||||
|
|
|
@ -71,7 +71,7 @@ struct Cutscene {
|
|||
uint8_t _frameDelay;
|
||||
bool _newPal;
|
||||
uint8_t _palBuf[0x20 * 2];
|
||||
uint16_t _startOffset;
|
||||
uint16_t _baseOffset;
|
||||
bool _creditsSequence;
|
||||
uint32_t _rotMat[4];
|
||||
uint8_t _primitiveColor;
|
||||
|
@ -139,7 +139,7 @@ struct Cutscene {
|
|||
|
||||
uint8_t fetchNextCmdByte();
|
||||
uint16_t fetchNextCmdWord();
|
||||
void mainLoop(uint16_t offset);
|
||||
void mainLoop(uint16_t num);
|
||||
bool load(uint16_t cutName);
|
||||
void unload();
|
||||
void prepare();
|
||||
|
|
102
game.cpp
102
game.cpp
|
@ -14,7 +14,7 @@
|
|||
#include "unpack.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),
|
||||
_mix(fs, stub), _res(fs, ver, lang), _seq(stub, &_mix), _vid(&_res, stub),
|
||||
_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;
|
||||
_currentLevel = _menu._level = level;
|
||||
_demoBin = -1;
|
||||
_widescreenMode = widescreenMode;
|
||||
}
|
||||
|
||||
void Game::run() {
|
||||
|
@ -63,6 +64,12 @@ void Game::run() {
|
|||
_mix.init();
|
||||
_mix._mod._isAmiga = _res.isAmiga();
|
||||
|
||||
if (_res.isMac()) {
|
||||
displayTitleScreenMac(Menu::kMacTitleScreen_MacPlay);
|
||||
if (!_stub->_pi.quit) {
|
||||
displayTitleScreenMac(Menu::kMacTitleScreen_Presage);
|
||||
}
|
||||
}
|
||||
playCutscene(0x40);
|
||||
playCutscene(0x0D);
|
||||
|
||||
|
@ -86,7 +93,7 @@ void Game::run() {
|
|||
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) {
|
||||
if (presentMenu) {
|
||||
_mix.playMusic(1);
|
||||
|
@ -121,7 +128,7 @@ void Game::run() {
|
|||
_stub->setScreenSize(Video::GAMESCREEN_W, Video::GAMESCREEN_H);
|
||||
break;
|
||||
case kResourceTypeMac:
|
||||
// TODO:
|
||||
displayTitleScreenMac(Menu::kMacTitleScreen_Flashback);
|
||||
break;
|
||||
}
|
||||
if (_stub->_pi.quit) {
|
||||
|
@ -172,10 +179,10 @@ void Game::run() {
|
|||
|
||||
void Game::displayTitleScreenAmiga() {
|
||||
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 kH = 224;
|
||||
uint8_t *buf = (uint8_t *)calloc(kW * kH, 1);
|
||||
uint8_t *buf = (uint8_t *)calloc(1, kW * kH);
|
||||
if (!buf) {
|
||||
error("Failed to allocate screen buffer w=%d h=%d", kW, kH);
|
||||
}
|
||||
|
@ -190,13 +197,13 @@ void Game::displayTitleScreenAmiga() {
|
|||
_stub->setPaletteEntry(i, &c);
|
||||
}
|
||||
_stub->setScreenSize(kW, kH);
|
||||
// fill with black
|
||||
_stub->copyRect(0, 0, kW, kH, buf, kW);
|
||||
_stub->updateScreen(0);
|
||||
_vid.AMIGA_decodeCmp(_res._scratchBuffer + 6, buf);
|
||||
free(buf);
|
||||
int h = 0;
|
||||
while (1) {
|
||||
if (h < kH / 2) {
|
||||
if (h <= kH / 2) {
|
||||
const int y = kH / 2 - h;
|
||||
_stub->copyRect(0, y, kW, h * 2, buf, kW);
|
||||
_stub->updateScreen(0);
|
||||
|
@ -212,6 +219,72 @@ void Game::displayTitleScreenAmiga() {
|
|||
}
|
||||
_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() {
|
||||
|
@ -496,8 +569,12 @@ bool Game::handleConfigPanel() {
|
|||
|
||||
switch (_res._type) {
|
||||
case kResourceTypeAmiga:
|
||||
// TODO
|
||||
return true;
|
||||
for (int i = 0; i < h; ++i) {
|
||||
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:
|
||||
// top-left rounded corner
|
||||
_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 + w), Video::CHAR_H * (y + i), _res._fnt, _vid._charFrontColor, 0x87);
|
||||
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;
|
||||
|
@ -1523,7 +1600,7 @@ void Game::loadLevelMap() {
|
|||
_vid.AMIGA_decodeLev(_currentLevel, _currentRoom);
|
||||
break;
|
||||
case kResourceTypeDOS:
|
||||
if (_stub->hasWidescreen()) { // draw adjacent rooms
|
||||
if (_stub->hasWidescreen() && _widescreenMode == kWidescreenAdjacentRooms) {
|
||||
const int leftRoom = _res._ctData[CT_LEFT_ROOM + _currentRoom];
|
||||
if (leftRoom > 0 && hasLevelMap(_currentLevel, leftRoom)) {
|
||||
_vid.PC_decodeMap(_currentLevel, leftRoom);
|
||||
|
@ -1540,6 +1617,9 @@ void Game::loadLevelMap() {
|
|||
}
|
||||
}
|
||||
_vid.PC_decodeMap(_currentLevel, _currentRoom);
|
||||
if (_stub->hasWidescreen() && _widescreenMode == kWidescreenMirrorRoom) {
|
||||
_stub->copyRectMirrorBorders(Video::GAMESCREEN_W, Video::GAMESCREEN_H, _vid._backLayer);
|
||||
}
|
||||
break;
|
||||
case kResourceTypeMac:
|
||||
_vid.MAC_decodeMap(_currentLevel, _currentRoom);
|
||||
|
|
4
game.h
4
game.h
|
@ -86,11 +86,13 @@ struct Game {
|
|||
bool _saveStateCompleted;
|
||||
bool _endLoop;
|
||||
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 displayTitleScreenAmiga();
|
||||
void displayTitleScreenMac(int num);
|
||||
void resetGameState();
|
||||
void mainLoop();
|
||||
void updateTiming();
|
||||
|
|
6
intern.h
6
intern.h
|
@ -100,6 +100,12 @@ enum Skill {
|
|||
kSkillExpert,
|
||||
};
|
||||
|
||||
enum WidescreenMode {
|
||||
kWidescreenNone,
|
||||
kWidescreenAdjacentRooms,
|
||||
kWidescreenMirrorRoom,
|
||||
};
|
||||
|
||||
struct Options {
|
||||
bool bypass_protection;
|
||||
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"
|
||||
" --levelnum=NUM Start to level, bypass introduction\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"
|
||||
" --language=LANG Language (fr,en,de,sp,it,jp)\n"
|
||||
;
|
||||
|
@ -74,6 +74,7 @@ static Language detectLanguage(FileSystem *fs) {
|
|||
return table[i].language;
|
||||
}
|
||||
}
|
||||
warning("Unable to detect language, defaults to English");
|
||||
return LANG_EN;
|
||||
}
|
||||
|
||||
|
@ -126,12 +127,17 @@ static void initOptions() {
|
|||
}
|
||||
if (*p) {
|
||||
const bool value = (*p == 't' || *p == 'T' || *p == '1');
|
||||
bool foundOption = false;
|
||||
for (int i = 0; opts[i].name; ++i) {
|
||||
if (strncmp(buf, opts[i].name, strlen(opts[i].name)) == 0) {
|
||||
*opts[i].value = value;
|
||||
foundOption = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundOption) {
|
||||
warning("Unhandled option '%s', ignoring", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,10 +149,16 @@ static void parseScaler(char *name, ScalerParameters *scalerParameters) {
|
|||
struct {
|
||||
const char *name;
|
||||
int type;
|
||||
const Scaler *scaler;
|
||||
} scalers[] = {
|
||||
{ "point", kScalerTypePoint },
|
||||
{ "linear", kScalerTypeLinear },
|
||||
{ "scale", kScalerTypeInternal },
|
||||
{ "point", kScalerTypePoint, 0 },
|
||||
{ "linear", kScalerTypeLinear, 0 },
|
||||
{ "scale", kScalerTypeInternal, &_internalScaler },
|
||||
#ifdef USE_STATIC_SCALER
|
||||
{ "nearest", kScalerTypeInternal, &scaler_nearest },
|
||||
{ "tv2x", kScalerTypeInternal, &scaler_tv2x },
|
||||
{ "xbrz", kScalerTypeInternal, &scaler_xbrz },
|
||||
#endif
|
||||
{ 0, -1 }
|
||||
};
|
||||
bool found = false;
|
||||
|
@ -157,6 +169,7 @@ static void parseScaler(char *name, ScalerParameters *scalerParameters) {
|
|||
for (int i = 0; scalers[i].name; ++i) {
|
||||
if (strcmp(scalers[i].name, name) == 0) {
|
||||
scalerParameters->type = (ScalerType)scalers[i].type;
|
||||
scalerParameters->scaler = scalers[i].scaler;
|
||||
found = true;
|
||||
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[]) {
|
||||
const char *dataPath = "DATA";
|
||||
const char *savePath = ".";
|
||||
int levelNum = 0;
|
||||
bool fullscreen = false;
|
||||
bool widescreen = false;
|
||||
WidescreenMode widescreen = kWidescreenNone;
|
||||
ScalerParameters scalerParameters = ScalerParameters::defaults();
|
||||
int forcedLanguage = -1;
|
||||
if (argc == 2) {
|
||||
|
@ -202,7 +233,7 @@ int main(int argc, char *argv[]) {
|
|||
{ "fullscreen", no_argument, 0, 4 },
|
||||
{ "scaler", required_argument, 0, 5 },
|
||||
{ "language", required_argument, 0, 6 },
|
||||
{ "widescreen", no_argument, 0, 7 },
|
||||
{ "widescreen", required_argument, 0, 7 },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
int index;
|
||||
|
@ -248,7 +279,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
break;
|
||||
case 7:
|
||||
widescreen = true;
|
||||
widescreen = parseWidescreen(optarg);
|
||||
break;
|
||||
default:
|
||||
printf(USAGE, argv[0]);
|
||||
|
@ -265,8 +296,8 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
const Language language = (forcedLanguage == -1) ? detectLanguage(&fs) : (Language)forcedLanguage;
|
||||
SystemStub *stub = SystemStub_SDL_create();
|
||||
Game *g = new Game(stub, &fs, savePath, levelNum, (ResourceType)version, language);
|
||||
stub->init(g_caption, g->_vid._w, g->_vid._h, fullscreen, widescreen, &scalerParameters);
|
||||
Game *g = new Game(stub, &fs, savePath, levelNum, (ResourceType)version, language, widescreen);
|
||||
stub->init(g_caption, g->_vid._w, g->_vid._h, fullscreen, widescreen != kWidescreenNone, &scalerParameters);
|
||||
g->run();
|
||||
delete g;
|
||||
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 len = 0;
|
||||
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:
|
||||
for (; str[len]; ++len) {
|
||||
_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) {
|
||||
_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;
|
||||
}
|
||||
_vid->markBlockAsDirty(x * w, y * h, len * w, h);
|
||||
|
|
8
menu.h
8
menu.h
|
@ -30,6 +30,14 @@ struct Menu {
|
|||
SCREEN_LEVEL,
|
||||
SCREEN_INFO
|
||||
};
|
||||
enum {
|
||||
kMacTitleScreen_MacPlay = 1,
|
||||
kMacTitleScreen_Presage = 2,
|
||||
kMacTitleScreen_Flashback = 3,
|
||||
kMacTitleScreen_LeftEye = 4,
|
||||
kMacTitleScreen_RightEye = 5,
|
||||
kMacTitleScreen_Controls = 6
|
||||
};
|
||||
|
||||
enum {
|
||||
EVENTS_DELAY = 80
|
||||
|
|
28
resource.cpp
28
resource.cpp
|
@ -21,7 +21,7 @@ Resource::Resource(FileSystem *fs, ResourceType ver, Language lang) {
|
|||
_mac = 0;
|
||||
_readUint16 = (_type == kResourceTypeDOS) ? READ_LE_UINT16 : READ_BE_UINT16;
|
||||
_readUint32 = (_type == kResourceTypeDOS) ? READ_LE_UINT32 : READ_BE_UINT32;
|
||||
_scratchBuffer = (uint8_t *)malloc(320 * 224 + 1024);
|
||||
_scratchBuffer = (uint8_t *)malloc(kScratchBufferSize);
|
||||
if (!_scratchBuffer) {
|
||||
error("Unable to allocate temporary memory buffer");
|
||||
}
|
||||
|
@ -36,9 +36,9 @@ Resource::Resource(FileSystem *fs, ResourceType ver, Language lang) {
|
|||
|
||||
Resource::~Resource() {
|
||||
clearLevelRes();
|
||||
MAC_unloadLevelData();
|
||||
free(_fnt);
|
||||
free(_icn); _icn = 0;
|
||||
_icnLen = 0;
|
||||
free(_icn);
|
||||
free(_tab);
|
||||
free(_spc);
|
||||
free(_spr1);
|
||||
|
@ -268,7 +268,7 @@ void Resource::load_PAL_menu(const char *fileName, uint8_t *dstPtr) {
|
|||
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;
|
||||
if (f.open(fileName, "rb", _fs)) {
|
||||
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");
|
||||
}
|
||||
f.read(tmp, size);
|
||||
if (!delphine_unpack(dstPtr, tmp, size)) {
|
||||
if (!delphine_unpack(_scratchBuffer, kScratchBufferSize, tmp, size)) {
|
||||
error("Bad CRC for %s", fileName);
|
||||
}
|
||||
free(tmp);
|
||||
|
@ -668,7 +668,7 @@ void Resource::load(const char *objName, int objType, const char *ext) {
|
|||
_pal = dat;
|
||||
break;
|
||||
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);
|
||||
}
|
||||
free(dat);
|
||||
|
@ -736,7 +736,7 @@ void Resource::load_CT(File *pf) {
|
|||
error("Unable to allocate CT buffer");
|
||||
} else {
|
||||
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");
|
||||
}
|
||||
free(tmp);
|
||||
|
@ -936,7 +936,7 @@ void Resource::load_OBC(File *f) {
|
|||
}
|
||||
f->seek(4);
|
||||
f->read(packedData, packedSize);
|
||||
if (!delphine_unpack(tmp, packedData, packedSize)) {
|
||||
if (!delphine_unpack(tmp, unpackedSize, packedData, packedSize)) {
|
||||
error("Bad CRC for compressed object data");
|
||||
}
|
||||
free(packedData);
|
||||
|
@ -1153,7 +1153,7 @@ void Resource::load_CMP(File *pf) {
|
|||
}
|
||||
if (data[0].packedSize == data[0].size) {
|
||||
memcpy(_pol, tmp + data[0].offset, data[0].packedSize);
|
||||
} else if (!delphine_unpack(_pol, tmp + data[0].offset, data[0].packedSize)) {
|
||||
} else if (!delphine_unpack(_pol, data[0].size, tmp + data[0].offset, data[0].packedSize)) {
|
||||
error("Bad CRC for cutscene polygon data");
|
||||
}
|
||||
_cmd = (uint8_t *)malloc(data[1].size);
|
||||
|
@ -1162,7 +1162,7 @@ void Resource::load_CMP(File *pf) {
|
|||
}
|
||||
if (data[1].packedSize == data[1].size) {
|
||||
memcpy(_cmd, tmp + data[1].offset, data[1].packedSize);
|
||||
} else if (!delphine_unpack(_cmd, tmp + data[1].offset, data[1].packedSize)) {
|
||||
} else if (!delphine_unpack(_cmd, data[1].size, tmp + data[1].offset, data[1].packedSize)) {
|
||||
error("Bad CRC for cutscene command data");
|
||||
}
|
||||
free(tmp);
|
||||
|
@ -1278,7 +1278,7 @@ void Resource::load_SGD(File *f) {
|
|||
if (!_sgd) {
|
||||
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");
|
||||
}
|
||||
free(tmp);
|
||||
|
@ -1310,12 +1310,12 @@ void Resource::load_SPM(File *f) {
|
|||
if (!_spr1) {
|
||||
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");
|
||||
}
|
||||
} else {
|
||||
assert(size <= sizeof(_sprm));
|
||||
if (!delphine_unpack(_sprm, tmp, len)) {
|
||||
if (!delphine_unpack(_sprm, sizeof(_sprm), tmp, len)) {
|
||||
error("Bad CRC for SPM data");
|
||||
}
|
||||
}
|
||||
|
@ -1391,7 +1391,7 @@ uint8_t *Resource::loadBankData(uint16_t num) {
|
|||
} else {
|
||||
assert(dataOffset > 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,7 +112,8 @@ struct Resource {
|
|||
|
||||
enum {
|
||||
kPaulaFreq = 3546897,
|
||||
kClutSize = 1024
|
||||
kClutSize = 1024,
|
||||
kScratchBufferSize = 320 * 224 + 1024
|
||||
};
|
||||
|
||||
static const uint16_t _voicesOffsetsTable[];
|
||||
|
@ -187,6 +188,7 @@ struct Resource {
|
|||
|
||||
bool isDOS() const { return _type == kResourceTypeDOS; }
|
||||
bool isAmiga() const { return _type == kResourceTypeAmiga; }
|
||||
bool isMac() const { return _type == kResourceTypeMac; }
|
||||
|
||||
bool fileExists(const char *filename);
|
||||
|
||||
|
@ -196,7 +198,7 @@ struct Resource {
|
|||
void load_SPL_demo();
|
||||
void load_MAP_menu(const char *fileName, uint8_t *dstPtr);
|
||||
void load_PAL_menu(const char *fileName, uint8_t *dstPtr);
|
||||
void load_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_CINE();
|
||||
void free_CINE();
|
||||
|
|
|
@ -74,7 +74,7 @@ uint8_t *ResourceAba::loadEntry(const char *name, uint32_t *size) {
|
|||
free(tmp);
|
||||
return 0;
|
||||
}
|
||||
const bool ret = delphine_unpack(dst, tmp, e->compressedSize);
|
||||
const bool ret = delphine_unpack(dst, e->size, tmp, e->compressedSize);
|
||||
if (!ret) {
|
||||
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
|
||||
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
|
||||
|
||||
# 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);
|
||||
|
||||
#ifdef USE_STATIC_SCALER
|
||||
extern const Scaler scaler_nearest;
|
||||
extern const Scaler scaler_tv2x;
|
||||
extern const Scaler scaler_xbrz;
|
||||
#endif
|
||||
|
||||
#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 copyRectLeftBorder(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 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 copyRectLeftBorder(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 updateScreen(int shakeOffset);
|
||||
virtual void processEvents();
|
||||
|
@ -82,6 +83,7 @@ struct SystemStub_SDL : SystemStub {
|
|||
void prepareGraphics();
|
||||
void cleanupGraphics();
|
||||
void changeGraphics(bool fullscreen, int scaleFactor);
|
||||
void changeScaler(int scaler);
|
||||
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;
|
||||
_renderer = 0;
|
||||
_texture = 0;
|
||||
_fmt = 0;
|
||||
_fmt = SDL_AllocFormat(kPixelFormat);
|
||||
_screenBuffer = 0;
|
||||
_fadeOnUpdateScreen = false;
|
||||
_fullscreen = fullscreen;
|
||||
_scalerType = scalerParameters->type;
|
||||
_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(_darkPalette, 0, sizeof(_darkPalette));
|
||||
_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() {
|
||||
cleanupGraphics();
|
||||
if (_screenBuffer) {
|
||||
free(_screenBuffer);
|
||||
_screenBuffer = 0;
|
||||
}
|
||||
if (_fmt) {
|
||||
SDL_FreeFormat(_fmt);
|
||||
_fmt = 0;
|
||||
}
|
||||
if (_controller) {
|
||||
SDL_GameControllerClose(_controller);
|
||||
_controller = 0;
|
||||
|
@ -147,6 +157,10 @@ void SystemStub_SDL::setScreenSize(int w, int h) {
|
|||
return;
|
||||
}
|
||||
cleanupGraphics();
|
||||
if (_screenBuffer) {
|
||||
free(_screenBuffer);
|
||||
_screenBuffer = 0;
|
||||
}
|
||||
const int screenBufferSize = w * h * sizeof(uint32_t);
|
||||
_screenBuffer = (uint32_t *)calloc(1, screenBufferSize);
|
||||
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) {
|
||||
assert(w >= _wideMargin);
|
||||
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]];
|
||||
}
|
||||
} 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;
|
||||
SDL_Rect r;
|
||||
|
@ -263,7 +293,10 @@ void SystemStub_SDL::copyRectRightBorder(int w, int h, const uint8_t *buf) {
|
|||
rgb[i] = _darkPalette[buf[i]];
|
||||
}
|
||||
} 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;
|
||||
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() {
|
||||
_fadeOnUpdateScreen = true;
|
||||
}
|
||||
|
@ -511,11 +573,15 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
|||
break;
|
||||
case SDLK_KP_PLUS:
|
||||
case SDLK_PAGEUP:
|
||||
changeGraphics(_fullscreen, _scaleFactor + 1);
|
||||
if (_scalerType == kScalerTypeInternal || _scalerType == kScalerTypeExternal) {
|
||||
changeGraphics(_fullscreen, _scaleFactor + 1);
|
||||
}
|
||||
break;
|
||||
case SDLK_KP_MINUS:
|
||||
case SDLK_PAGEDOWN:
|
||||
changeGraphics(_fullscreen, _scaleFactor - 1);
|
||||
if (_scalerType == kScalerTypeInternal || _scalerType == kScalerTypeExternal) {
|
||||
changeGraphics(_fullscreen, _scaleFactor - 1);
|
||||
}
|
||||
break;
|
||||
case SDLK_s: {
|
||||
char name[32];
|
||||
|
@ -585,6 +651,16 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
|||
case SDLK_ESCAPE:
|
||||
_pi.escape = false;
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -717,21 +793,18 @@ void SystemStub_SDL::prepareGraphics() {
|
|||
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
|
||||
SDL_RenderSetLogicalSize(_renderer, windowW, windowH);
|
||||
_texture = SDL_CreateTexture(_renderer, kPixelFormat, SDL_TEXTUREACCESS_STREAMING, _texW, _texH);
|
||||
_fmt = SDL_AllocFormat(kPixelFormat);
|
||||
if (_widescreen) {
|
||||
const int w = _screenH * 16 / 9;
|
||||
const int h = _screenH;
|
||||
_wideTexture = SDL_CreateTexture(_renderer, kPixelFormat, SDL_TEXTUREACCESS_STREAMING, w, h);
|
||||
clearTexture(_wideTexture, _screenH, _fmt);
|
||||
|
||||
// left and right borders
|
||||
_wideMargin = (w - _screenW) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
void SystemStub_SDL::cleanupGraphics() {
|
||||
if (_screenBuffer) {
|
||||
free(_screenBuffer);
|
||||
_screenBuffer = 0;
|
||||
}
|
||||
if (_texture) {
|
||||
SDL_DestroyTexture(_texture);
|
||||
_texture = 0;
|
||||
|
@ -748,10 +821,6 @@ void SystemStub_SDL::cleanupGraphics() {
|
|||
SDL_DestroyWindow(_window);
|
||||
_window = 0;
|
||||
}
|
||||
if (_fmt) {
|
||||
SDL_FreeFormat(_fmt);
|
||||
_fmt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SystemStub_SDL::changeGraphics(bool fullscreen, int scaleFactor) {
|
||||
|
@ -762,29 +831,53 @@ void SystemStub_SDL::changeGraphics(bool fullscreen, int scaleFactor) {
|
|||
}
|
||||
_fullscreen = fullscreen;
|
||||
_scaleFactor = factor;
|
||||
if (_texture) {
|
||||
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;
|
||||
}
|
||||
cleanupGraphics();
|
||||
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) {
|
||||
const int x1 = x;
|
||||
const int y1 = y;
|
||||
|
|
58
unpack.cpp
58
unpack.cpp
|
@ -5,9 +5,10 @@
|
|||
*/
|
||||
|
||||
#include "unpack.h"
|
||||
#include "util.h"
|
||||
|
||||
struct UnpackCtx {
|
||||
int datasize;
|
||||
int size;
|
||||
uint32_t crc;
|
||||
uint32_t bits;
|
||||
uint8_t *dst;
|
||||
|
@ -26,40 +27,52 @@ static bool nextBit(UnpackCtx *uc) {
|
|||
return carry;
|
||||
}
|
||||
|
||||
static uint16_t getBits(UnpackCtx *uc, int bitsCount) {
|
||||
uint16_t c = 0;
|
||||
for (int i = 0; i < bitsCount; ++i) {
|
||||
c <<= 1;
|
||||
static int getBits(UnpackCtx *uc, int count) {
|
||||
int bits = 0;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
bits <<= 1;
|
||||
if (nextBit(uc)) {
|
||||
c |= 1;
|
||||
bits |= 1;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
return bits;
|
||||
}
|
||||
|
||||
static void copyLiteral(UnpackCtx *uc, int bitsCount, int len) {
|
||||
const int count = getBits(uc, bitsCount) + len + 1;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
*uc->dst = (uint8_t)getBits(uc, 8);
|
||||
--uc->dst;
|
||||
int count = getBits(uc, bitsCount) + len + 1;
|
||||
uc->size -= count;
|
||||
if (uc->size < 0) {
|
||||
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) {
|
||||
const uint16_t offset = getBits(uc, bitsCount);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
*uc->dst = *(uc->dst + offset);
|
||||
--uc->dst;
|
||||
uc->size -= count;
|
||||
if (uc->size < 0) {
|
||||
count += uc->size;
|
||||
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;
|
||||
uc.src = src + len - 4;
|
||||
uc.datasize = READ_BE_UINT32(uc.src); uc.src -= 4;
|
||||
uc.dst = dst + uc.datasize - 1;
|
||||
uc.src = src + srcSize - 4;
|
||||
uc.size = READ_BE_UINT32(uc.src); uc.src -= 4;
|
||||
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.bits = READ_BE_UINT32(uc.src); uc.src -= 4;
|
||||
uc.crc ^= uc.bits;
|
||||
|
@ -87,6 +100,7 @@ bool delphine_unpack(uint8_t *dst, const uint8_t *src, int len) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
} while (uc.datasize > 0);
|
||||
} while (uc.size > 0);
|
||||
assert(uc.size == 0);
|
||||
return uc.crc == 0;
|
||||
}
|
||||
|
|
2
unpack.h
2
unpack.h
|
@ -9,6 +9,6 @@
|
|||
|
||||
#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__
|
||||
|
|
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) {
|
||||
uint8_t *tmp = _res->_scratchBuffer;
|
||||
const int offset = READ_BE_UINT32(_res->_lev + room * 4);
|
||||
if (!delphine_unpack(tmp, _res->_lev, offset)) {
|
||||
error("Bad CRC for level %d room %d", level, room);
|
||||
if (!delphine_unpack(tmp, Resource::kScratchBufferSize, _res->_lev, offset)) {
|
||||
warning("Bad CRC for level %d room %d", level, room);
|
||||
return;
|
||||
}
|
||||
uint16_t offset10 = READ_BE_UINT16(tmp + 10);
|
||||
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) {
|
||||
DecodeBuffer 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.y = y * _layerScale;
|
||||
buf.setPixel = Video::MAC_drawBufferFont;
|
||||
_charFrontColor = color;
|
||||
buf.dataPtr = this;
|
||||
_MAC_fontFrontColor = color;
|
||||
_MAC_fontShadowColor = _charShadowColor;
|
||||
assert(chr >= 32);
|
||||
_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) {
|
||||
const int x = buf->x + src_x;
|
||||
if (x >= 0 && x < buf->w) {
|
||||
const Video *vid = (Video *)buf->dataPtr;
|
||||
const int offset = y * buf->pitch + x;
|
||||
switch (color) {
|
||||
case 0xC0:
|
||||
buf->ptr[offset] = vid->_charShadowColor;
|
||||
buf->ptr[offset] = _MAC_fontShadowColor;
|
||||
break;
|
||||
case 0xC1:
|
||||
buf->ptr[offset] = vid->_charFrontColor;
|
||||
buf->ptr[offset] = _MAC_fontFrontColor;
|
||||
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;
|
||||
for (int j = 0; j < h * _layerScale; ++j) {
|
||||
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_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);
|
||||
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);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue