Import 0.3.2
This commit is contained in:
parent
577fec920a
commit
5addfc699a
|
@ -1,6 +1,6 @@
|
|||
|
||||
REminiscence README
|
||||
Release version: 0.3.1
|
||||
Release version: 0.3.2
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -23,8 +23,6 @@ Data Files:
|
|||
-----------
|
||||
|
||||
You will need the original files of the PC (DOS or CD) or Amiga release.
|
||||
If you have a version distributed by SSI, you'll have to rename the files
|
||||
and drop the 'ssi' suffix (ie. logosssi.cmd -> logos.cmd).
|
||||
|
||||
To hear background music during polygonal cutscenes with the PC version,
|
||||
you'll need to copy the .mod files of the Amiga version :
|
||||
|
@ -83,8 +81,6 @@ In-game hotkeys :
|
|||
Ctrl S save game state
|
||||
Ctrl L load game state
|
||||
Ctrl + and - change game state slot
|
||||
Ctrl R toggle input keys record
|
||||
Ctrl P toggle input keys replay
|
||||
|
||||
Debug hotkeys :
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ void Game::col_clearState() {
|
|||
}
|
||||
|
||||
void Game::col_preparePiegeState(LivePGE *pge) {
|
||||
debug(DBG_COL, "Game::col_preparePiegeState() pge_num=%d", pge - &_pgeLive[0]);
|
||||
debug(DBG_COL, "Game::col_preparePiegeState() pge_num=%ld", pge - &_pgeLive[0]);
|
||||
CollisionSlot *ct_slot1, *ct_slot2;
|
||||
if (pge->init_PGE->unk1C == 0) {
|
||||
pge->collision_slot = 0xFF;
|
||||
|
|
|
@ -31,6 +31,7 @@ struct Cutscene {
|
|||
static const char *_namesTable[];
|
||||
static const uint16_t _offsetsTable[];
|
||||
static const uint8_t _amigaDemoOffsetsTable[];
|
||||
static const uint8_t _ssiOffsetsTable[];
|
||||
static const uint16_t _cosTable[];
|
||||
static const uint16_t _sinTable[];
|
||||
static const uint8_t _creditsDataDOS[];
|
||||
|
|
185
game.cpp
185
game.cpp
|
@ -13,31 +13,47 @@
|
|||
#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, int demo, ResourceType ver, Language lang)
|
||||
: _cut(&_res, stub, &_vid), _menu(&_res, stub, &_vid),
|
||||
_mix(fs, stub), _res(fs, ver, lang), _seq(stub, &_mix), _vid(&_res, stub),
|
||||
_stub(stub), _fs(fs), _savePath(savePath) {
|
||||
_stateSlot = 1;
|
||||
_inp_demo = 0;
|
||||
_inp_record = false;
|
||||
_inp_replay = false;
|
||||
_inp_demPos = 0;
|
||||
_skillLevel = _menu._skill = 1;
|
||||
_currentLevel = _menu._level = level;
|
||||
_demoBin = demo;
|
||||
}
|
||||
|
||||
void Game::run() {
|
||||
_randSeed = time(0);
|
||||
|
||||
if (_demoBin != -1) {
|
||||
if (_demoBin < (int)ARRAYSIZE(_demoInputs)) {
|
||||
const char *fn = _demoInputs[_demoBin].name;
|
||||
debug(DBG_INFO, "Loading inputs from '%s'", fn);
|
||||
_res.load_DEM(fn);
|
||||
}
|
||||
if (_res._demLen == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_res.init();
|
||||
_res.load_TEXT();
|
||||
|
||||
switch (_res._type) {
|
||||
case kResourceTypeAmiga:
|
||||
_res.load("FONT8", Resource::OT_FNT, "SPR");
|
||||
if (_res._isDemo) {
|
||||
_cut._patchedOffsetsTable = Cutscene::_amigaDemoOffsetsTable;
|
||||
}
|
||||
break;
|
||||
case kResourceTypeDOS:
|
||||
_res.load("FB_TXT", Resource::OT_FNT);
|
||||
_res._hasSeqData = _fs->exists("INTRO.SEQ");
|
||||
if (_fs->exists("logosssi.cmd")) {
|
||||
_cut._patchedOffsetsTable = Cutscene::_ssiOffsetsTable;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -51,8 +67,10 @@ void Game::run() {
|
|||
_mix.init();
|
||||
_mix._mod._isAmiga = _res.isAmiga();
|
||||
|
||||
playCutscene(0x40);
|
||||
playCutscene(0x0D);
|
||||
if (_demoBin == -1) {
|
||||
playCutscene(0x40);
|
||||
playCutscene(0x0D);
|
||||
}
|
||||
|
||||
switch (_res._type) {
|
||||
case kResourceTypeAmiga:
|
||||
|
@ -70,25 +88,30 @@ void Game::run() {
|
|||
}
|
||||
|
||||
while (!_stub->_pi.quit) {
|
||||
switch (_res._type) {
|
||||
case kResourceTypeDOS:
|
||||
_mix.playMusic(1);
|
||||
_menu.handleTitleScreen();
|
||||
if (_menu._selectedOption == Menu::MENU_OPTION_ITEM_QUIT || _stub->_pi.quit) {
|
||||
_stub->_pi.quit = true;
|
||||
if (_demoBin != -1) {
|
||||
_currentLevel = _demoInputs[_demoBin].level;
|
||||
_randSeed = 0;
|
||||
} else {
|
||||
switch (_res._type) {
|
||||
case kResourceTypeDOS:
|
||||
_mix.playMusic(1);
|
||||
_menu.handleTitleScreen();
|
||||
if (_menu._selectedOption == Menu::MENU_OPTION_ITEM_QUIT || _stub->_pi.quit) {
|
||||
_stub->_pi.quit = true;
|
||||
break;
|
||||
}
|
||||
_skillLevel = _menu._skill;
|
||||
_currentLevel = _menu._level;
|
||||
_mix.stopMusic();
|
||||
break;
|
||||
case kResourceTypeAmiga:
|
||||
displayTitleScreenAmiga();
|
||||
_stub->setScreenSize(Video::GAMESCREEN_W, Video::GAMESCREEN_H);
|
||||
break;
|
||||
}
|
||||
if (_stub->_pi.quit) {
|
||||
break;
|
||||
}
|
||||
_skillLevel = _menu._skill;
|
||||
_currentLevel = _menu._level;
|
||||
_mix.stopMusic();
|
||||
break;
|
||||
case kResourceTypeAmiga:
|
||||
displayTitleScreenAmiga();
|
||||
_stub->setScreenSize(Video::GAMESCREEN_W, Video::GAMESCREEN_H);
|
||||
break;
|
||||
}
|
||||
if (_stub->_pi.quit) {
|
||||
break;
|
||||
}
|
||||
if (_currentLevel == 7) {
|
||||
_vid.fadeOut();
|
||||
|
@ -107,6 +130,10 @@ void Game::run() {
|
|||
_frameTimestamp = _stub->getTimeStamp();
|
||||
while (!_stub->_pi.quit && !_endLoop) {
|
||||
mainLoop();
|
||||
if (_demoBin != -1 && _inp_demPos >= _res._demLen) {
|
||||
debug(DBG_INFO, "End of demo");
|
||||
_stub->_pi.quit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -370,52 +397,6 @@ void Game::inp_handleSpecialKeys() {
|
|||
}
|
||||
_stub->_pi.stateSlot = 0;
|
||||
}
|
||||
if (_stub->_pi.inpRecord || _stub->_pi.inpReplay) {
|
||||
bool replay = false;
|
||||
bool record = false;
|
||||
char demoFile[20];
|
||||
makeGameDemoName(demoFile);
|
||||
if (_inp_demo) {
|
||||
_inp_demo->close();
|
||||
delete _inp_demo;
|
||||
}
|
||||
_inp_demo = new File;
|
||||
if (_stub->_pi.inpRecord) {
|
||||
if (_inp_record) {
|
||||
debug(DBG_INFO, "Stop recording input keys");
|
||||
} else {
|
||||
if (_inp_demo->open(demoFile, "zwb", _savePath)) {
|
||||
debug(DBG_INFO, "Recording input keys");
|
||||
static const uint32_t TAG_FBDM = 0x4642444D;
|
||||
_inp_demo->writeUint32BE(TAG_FBDM);
|
||||
_inp_demo->writeUint16BE(0);
|
||||
_inp_demo->writeUint32BE(_randSeed);
|
||||
record = true;
|
||||
} else {
|
||||
warning("Unable to save demo file '%s'", demoFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_stub->_pi.inpReplay) {
|
||||
if (_inp_replay) {
|
||||
debug(DBG_INFO, "Stop replaying input keys");
|
||||
} else {
|
||||
if (_inp_demo->open(demoFile, "zrb", _savePath)) {
|
||||
debug(DBG_INFO, "Replaying input keys");
|
||||
_inp_demo->readUint32BE();
|
||||
_inp_demo->readUint16BE();
|
||||
_randSeed = _inp_demo->readUint32BE();
|
||||
replay = true;
|
||||
} else {
|
||||
warning("Unable to open demo file '%s'", demoFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
_inp_record = record;
|
||||
_inp_replay = replay;
|
||||
_stub->_pi.inpReplay = false;
|
||||
_stub->_pi.inpRecord = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::drawCurrentInventoryItem() {
|
||||
|
@ -838,7 +819,7 @@ void Game::prepareAnims() {
|
|||
}
|
||||
|
||||
void Game::prepareAnimsHelper(LivePGE *pge, int16_t dx, int16_t dy) {
|
||||
debug(DBG_GAME, "Game::prepareAnimsHelper() dx=0x%X dy=0x%X pge_num=%d pge->flags=0x%X pge->anim_number=0x%X", dx, dy, pge - &_pgeLive[0], pge->flags, pge->anim_number);
|
||||
debug(DBG_GAME, "Game::prepareAnimsHelper() dx=0x%X dy=0x%X pge_num=%ld pge->flags=0x%X pge->anim_number=0x%X", dx, dy, pge - &_pgeLive[0], pge->flags, pge->anim_number);
|
||||
if (!(pge->flags & 8)) {
|
||||
if (pge->index != 0 && loadMonsterSprites(pge) == 0) {
|
||||
return;
|
||||
|
@ -980,7 +961,7 @@ void Game::drawObject(const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t flag
|
|||
}
|
||||
|
||||
void Game::drawObjectFrame(const uint8_t *bankDataPtr, const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t flags) {
|
||||
debug(DBG_GAME, "Game::drawObjectFrame(0x%X, %d, %d, 0x%X)", dataPtr, x, y, flags);
|
||||
debug(DBG_GAME, "Game::drawObjectFrame(%p, %d, %d, 0x%X)", dataPtr, x, y, flags);
|
||||
const uint8_t *src = bankDataPtr + dataPtr[0] * 32;
|
||||
|
||||
int16_t sprite_y = y + dataPtr[2];
|
||||
|
@ -1111,8 +1092,7 @@ void Game::decodeCharacterFrame(const uint8_t *dataPtr, uint8_t *dstPtr) {
|
|||
}
|
||||
|
||||
void Game::drawCharacter(const uint8_t *dataPtr, int16_t pos_x, int16_t pos_y, uint8_t a, uint8_t b, uint8_t flags) {
|
||||
debug(DBG_GAME, "Game::drawCharacter(0x%X, %d, %d, 0x%X, 0x%X, 0x%X)", dataPtr, pos_x, pos_y, a, b, flags);
|
||||
|
||||
debug(DBG_GAME, "Game::drawCharacter(%p, %d, %d, 0x%X, 0x%X, 0x%X)", dataPtr, pos_x, pos_y, a, b, flags);
|
||||
bool var16 = false; // sprite_mirror_y
|
||||
if (b & 0x40) {
|
||||
b &= 0xBF;
|
||||
|
@ -1197,7 +1177,7 @@ void Game::drawCharacter(const uint8_t *dataPtr, int16_t pos_x, int16_t pos_y, u
|
|||
uint32_t dst_offset = 256 * pos_y + pos_x;
|
||||
uint8_t sprite_col_mask = ((flags & 0x60) == 0x60) ? 0x50 : 0x40;
|
||||
|
||||
debug(DBG_GAME, "dst_offset=0x%X src_offset=0x%X", dst_offset, src - dataPtr);
|
||||
debug(DBG_GAME, "dst_offset=0x%X src_offset=%ld", dst_offset, src - dataPtr);
|
||||
|
||||
if (!(flags & 2)) {
|
||||
if (var16) {
|
||||
|
@ -1302,7 +1282,6 @@ void Game::loadLevelData() {
|
|||
switch (_res._type) {
|
||||
case kResourceTypeAmiga:
|
||||
if (_res._isDemo) {
|
||||
_cut._patchedOffsetsTable = Cutscene::_amigaDemoOffsetsTable;
|
||||
static const char *fname1 = "demo";
|
||||
static const char *fname2 = "demof";
|
||||
_res.load(fname1, Resource::OT_MBK);
|
||||
|
@ -1397,6 +1376,17 @@ void Game::loadLevelData() {
|
|||
pge_loadForCurrentLevel(n);
|
||||
}
|
||||
|
||||
if (_demoBin != -1) {
|
||||
_cut._id = -1;
|
||||
if (_demoInputs[_demoBin].room != 255) {
|
||||
_pgeLive[0].room_location = _demoInputs[_demoBin].room;
|
||||
_pgeLive[0].pos_x = _demoInputs[_demoBin].x;
|
||||
_pgeLive[0].pos_y = _demoInputs[_demoBin].y;
|
||||
} else {
|
||||
_inp_demPos = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < _res._pgeNum; ++i) {
|
||||
if (_res._pgeInit[i].skill <= _skillLevel) {
|
||||
LivePGE *pge = &_pgeLive[i];
|
||||
|
@ -1466,7 +1456,7 @@ void Game::playSound(uint8_t sfxId, uint8_t softVol) {
|
|||
|
||||
uint16_t Game::getRandomNumber() {
|
||||
uint32_t n = _randSeed * 2;
|
||||
if (_randSeed > n) {
|
||||
if (((int32_t)_randSeed) >= 0) {
|
||||
n ^= 0x1D872B41;
|
||||
}
|
||||
_randSeed = n;
|
||||
|
@ -1614,44 +1604,17 @@ void Game::handleInventory() {
|
|||
}
|
||||
|
||||
void Game::inp_update() {
|
||||
if (_inp_replay && _inp_demo) {
|
||||
uint8_t keymask = _inp_demo->readByte();
|
||||
if (_inp_demo->ioErr()) {
|
||||
_inp_replay = false;
|
||||
} else {
|
||||
_stub->_pi.dirMask = keymask & 0xF;
|
||||
_stub->_pi.enter = (keymask & 0x10) != 0;
|
||||
_stub->_pi.space = (keymask & 0x20) != 0;
|
||||
_stub->_pi.shift = (keymask & 0x40) != 0;
|
||||
_stub->_pi.quit = (keymask & 0x80) != 0;
|
||||
}
|
||||
}
|
||||
_stub->processEvents();
|
||||
if (_inp_record && _inp_demo) {
|
||||
uint8_t keymask = _stub->_pi.dirMask;
|
||||
if (_stub->_pi.enter) {
|
||||
keymask |= 0x10;
|
||||
}
|
||||
if (_stub->_pi.space) {
|
||||
keymask |= 0x20;
|
||||
}
|
||||
if (_stub->_pi.shift) {
|
||||
keymask |= 0x40;
|
||||
}
|
||||
if (_stub->_pi.quit) {
|
||||
keymask |= 0x80;
|
||||
}
|
||||
_inp_demo->writeByte(keymask);
|
||||
if (_inp_demo->ioErr()) {
|
||||
_inp_record = false;
|
||||
}
|
||||
if (_inp_demPos < _res._demLen) {
|
||||
const int keymask = _res._dem[_inp_demPos++];
|
||||
_stub->_pi.dirMask = keymask & 0xF;
|
||||
_stub->_pi.enter = (keymask & 0x10) != 0;
|
||||
_stub->_pi.space = (keymask & 0x20) != 0;
|
||||
_stub->_pi.shift = (keymask & 0x40) != 0;
|
||||
_stub->_pi.backspace = (keymask & 0x80) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::makeGameDemoName(char *buf) {
|
||||
sprintf(buf, "rs-level%d.demo", _currentLevel + 1);
|
||||
}
|
||||
|
||||
void Game::makeGameStateName(uint8_t slot, char *buf) {
|
||||
sprintf(buf, "rs-level%d-%02d.state", _currentLevel + 1, slot);
|
||||
}
|
||||
|
@ -1856,7 +1819,7 @@ void Game::loadState(File *f) {
|
|||
}
|
||||
|
||||
void AnimBuffers::addState(uint8_t stateNum, int16_t x, int16_t y, const uint8_t *dataPtr, LivePGE *pge, uint8_t w, uint8_t h) {
|
||||
debug(DBG_GAME, "AnimBuffers::addState() stateNum=%d x=%d y=%d dataPtr=0x%X pge=0x%X", stateNum, x, y, dataPtr, pge);
|
||||
debug(DBG_GAME, "AnimBuffers::addState() stateNum=%d x=%d y=%d dataPtr=%p pge=%p", stateNum, x, y, dataPtr, pge);
|
||||
assert(stateNum < 4);
|
||||
AnimBufferState *state = _states[stateNum];
|
||||
state->x = x;
|
||||
|
|
9
game.h
9
game.h
|
@ -32,6 +32,7 @@ struct Game {
|
|||
CT_LEFT_ROOM = 0xC0
|
||||
};
|
||||
|
||||
static const Demo _demoInputs[3];
|
||||
static const Level _gameLevels[];
|
||||
static const uint16_t _scoreTable[];
|
||||
static const uint8_t _monsterListLevel1[];
|
||||
|
@ -63,6 +64,7 @@ struct Game {
|
|||
const char **_textsTable;
|
||||
uint8_t _currentLevel;
|
||||
uint8_t _skillLevel;
|
||||
int _demoBin;
|
||||
uint32_t _score;
|
||||
uint8_t _currentRoom;
|
||||
uint8_t _currentIcon;
|
||||
|
@ -85,7 +87,7 @@ struct Game {
|
|||
bool _endLoop;
|
||||
uint32_t _frameTimestamp;
|
||||
|
||||
Game(SystemStub *, FileSystem *, const char *savePath, int level, ResourceType ver, Language lang);
|
||||
Game(SystemStub *, FileSystem *, const char *savePath, int level, int demo, ResourceType ver, Language lang);
|
||||
|
||||
void run();
|
||||
void displayTitleScreenAmiga();
|
||||
|
@ -351,9 +353,7 @@ struct Game {
|
|||
// input
|
||||
uint8_t _inp_lastKeysHit;
|
||||
uint8_t _inp_lastKeysHitLeftRight;
|
||||
bool _inp_replay;
|
||||
bool _inp_record;
|
||||
File *_inp_demo;
|
||||
int _inp_demPos;
|
||||
|
||||
void inp_handleSpecialKeys();
|
||||
void inp_update();
|
||||
|
@ -363,7 +363,6 @@ struct Game {
|
|||
uint8_t _stateSlot;
|
||||
bool _validSaveState;
|
||||
|
||||
void makeGameDemoName(char *buf);
|
||||
void makeGameStateName(uint8_t slot, char *buf);
|
||||
bool saveGameState(uint8_t slot);
|
||||
bool loadGameState(uint8_t slot);
|
||||
|
|
7
intern.h
7
intern.h
|
@ -106,6 +106,13 @@ struct Point {
|
|||
int16_t y;
|
||||
};
|
||||
|
||||
struct Demo {
|
||||
const char *name;
|
||||
int level;
|
||||
int room;
|
||||
int x, y;
|
||||
};
|
||||
|
||||
struct Level {
|
||||
const char *name;
|
||||
const char *name2;
|
||||
|
|
7
main.cpp
7
main.cpp
|
@ -134,6 +134,7 @@ int main(int argc, char *argv[]) {
|
|||
int scaler = DEFAULT_SCALER;
|
||||
bool fullscreen = false;
|
||||
int forcedLanguage = -1;
|
||||
int demoNum = -1;
|
||||
if (argc == 2) {
|
||||
// data path as the only command line argument
|
||||
struct stat st;
|
||||
|
@ -149,6 +150,7 @@ int main(int argc, char *argv[]) {
|
|||
{ "fullscreen", no_argument, 0, 4 },
|
||||
{ "scaler", required_argument, 0, 5 },
|
||||
{ "language", required_argument, 0, 6 },
|
||||
{ "playdemo", required_argument, 0, 7 },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
int index;
|
||||
|
@ -195,6 +197,9 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
demoNum = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
printf(USAGE, argv[0]);
|
||||
return 0;
|
||||
|
@ -210,7 +215,7 @@ 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);
|
||||
Game *g = new Game(stub, &fs, savePath, levelNum, demoNum, (ResourceType)version, language);
|
||||
stub->init(g_caption, Video::GAMESCREEN_W, Video::GAMESCREEN_H, scaler, fullscreen);
|
||||
g->run();
|
||||
delete g;
|
||||
|
|
10
piege.cpp
10
piege.cpp
|
@ -113,7 +113,7 @@ void Game::pge_loadForCurrentLevel(uint16_t idx) {
|
|||
}
|
||||
|
||||
void Game::pge_process(LivePGE *pge) {
|
||||
debug(DBG_PGE, "Game::pge_process() pge_num=%d", pge - &_pgeLive[0]);
|
||||
debug(DBG_PGE, "Game::pge_process() pge_num=%ld", pge - &_pgeLive[0]);
|
||||
_pge_playAnimSound = true;
|
||||
_pge_currentPiegeFacingDir = (pge->flags & 1) != 0;
|
||||
_pge_currentPiegeRoom = pge->room_location;
|
||||
|
@ -226,7 +226,7 @@ void Game::pge_playAnimSound(LivePGE *pge, uint16_t arg2) {
|
|||
}
|
||||
|
||||
void Game::pge_setupAnim(LivePGE *pge) {
|
||||
debug(DBG_PGE, "Game::pge_setupAnim() pgeNum=%d", pge - &_pgeLive[0]);
|
||||
debug(DBG_PGE, "Game::pge_setupAnim() pgeNum=%ld", pge - &_pgeLive[0]);
|
||||
const uint8_t *anim_data = _res.getAniData(pge->obj_type);
|
||||
if (_res._readUint16(anim_data) < pge->anim_seq) {
|
||||
pge->anim_seq = 0;
|
||||
|
@ -254,7 +254,7 @@ void Game::pge_setupAnim(LivePGE *pge) {
|
|||
}
|
||||
|
||||
int Game::pge_execute(LivePGE *live_pge, InitPGE *init_pge, const Object *obj) {
|
||||
debug(DBG_PGE, "Game::pge_execute() pge_num=%d op1=0x%X op2=0x%X op3=0x%X", live_pge - &_pgeLive[0], obj->opcode1, obj->opcode2, obj->opcode3);
|
||||
debug(DBG_PGE, "Game::pge_execute() pge_num=%ld op1=0x%X op2=0x%X op3=0x%X", live_pge - &_pgeLive[0], obj->opcode1, obj->opcode2, obj->opcode3);
|
||||
pge_OpcodeProc op;
|
||||
ObjectOpcodeArgs args;
|
||||
if (obj->opcode1) {
|
||||
|
@ -378,7 +378,7 @@ void Game::pge_setupDefaultAnim(LivePGE *pge) {
|
|||
pge->flags |= 8;
|
||||
}
|
||||
pge->anim_number = _res._readUint16(anim_frame) & 0x7FFF;
|
||||
debug(DBG_PGE, "Game::pge_setupDefaultAnim() pgeNum=%d pge->flags=0x%X pge->anim_number=0x%X pge->anim_seq=0x%X", pge - &_pgeLive[0], pge->flags, pge->anim_number, pge->anim_seq);
|
||||
debug(DBG_PGE, "Game::pge_setupDefaultAnim() pgeNum=%ld pge->flags=0x%X pge->anim_number=0x%X pge->anim_seq=0x%X", pge - &_pgeLive[0], pge->flags, pge->anim_number, pge->anim_seq);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,7 +464,7 @@ void Game::pge_setupOtherPieges(LivePGE *pge, InitPGE *init_pge) {
|
|||
}
|
||||
|
||||
void Game::pge_addToCurrentRoomList(LivePGE *pge, uint8_t room) {
|
||||
debug(DBG_PGE, "Game::pge_addToCurrentRoomList() pgeNum=%d room=%d", pge - &_pgeLive[0], room);
|
||||
debug(DBG_PGE, "Game::pge_addToCurrentRoomList() pgeNum=%ld room=%d", pge - &_pgeLive[0], room);
|
||||
if (room != pge->room_location) {
|
||||
LivePGE *cur_pge = _pge_liveTable1[room];
|
||||
LivePGE *prev_pge = 0;
|
||||
|
|
13
resource.cpp
13
resource.cpp
|
@ -84,6 +84,19 @@ void Resource::clearLevelRes() {
|
|||
free_OBJ();
|
||||
}
|
||||
|
||||
void Resource::load_DEM(const char *filename) {
|
||||
free(_dem); _dem = 0;
|
||||
_demLen = 0;
|
||||
File f;
|
||||
if (f.open(filename, "rb", _fs)) {
|
||||
_demLen = f.size();
|
||||
_dem = (uint8_t *)malloc(_demLen);
|
||||
if (_dem) {
|
||||
f.read(_dem, _demLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Resource::load_FIB(const char *fileName) {
|
||||
debug(DBG_RES, "Resource::load_FIB('%s')", fileName);
|
||||
static const uint8_t fibonacciTable[] = {
|
||||
|
|
|
@ -148,6 +148,8 @@ struct Resource {
|
|||
uint8_t *_bankDataTail;
|
||||
BankSlot _bankBuffers[NUM_BANK_BUFFERS];
|
||||
int _bankBuffersCount;
|
||||
uint8_t *_dem;
|
||||
int _demLen;
|
||||
|
||||
Resource(FileSystem *fs, ResourceType type, Language lang);
|
||||
~Resource();
|
||||
|
@ -159,6 +161,7 @@ struct Resource {
|
|||
bool isAmiga() const { return _type == kResourceTypeAmiga; }
|
||||
|
||||
void clearLevelRes();
|
||||
void load_DEM(const char *filename);
|
||||
void load_FIB(const char *fileName);
|
||||
void load_SPL_demo();
|
||||
void load_MAP_menu(const char *fileName, uint8_t *dstPtr);
|
||||
|
|
|
@ -64,7 +64,8 @@ const char *Cutscene::_namesTable[] = {
|
|||
"INTRO2",
|
||||
"SERRURE",
|
||||
"HOLOCUBE",
|
||||
"CHUTE2"
|
||||
"CHUTE2",
|
||||
"LOGOSSSI",
|
||||
};
|
||||
|
||||
const uint16_t Cutscene::_offsetsTable[] = {
|
||||
|
@ -92,6 +93,11 @@ const uint8_t Cutscene::_amigaDemoOffsetsTable[] = {
|
|||
255
|
||||
};
|
||||
|
||||
const uint8_t Cutscene::_ssiOffsetsTable[] = {
|
||||
64, 34, 0, /* LOGOSSSI */
|
||||
255
|
||||
};
|
||||
|
||||
const uint16_t Cutscene::_cosTable[] = {
|
||||
0x0100, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FE, 0x00FE,
|
||||
0x00FD, 0x00FC, 0x00FC, 0x00FB, 0x00FA, 0x00F9, 0x00F8, 0x00F7,
|
||||
|
@ -830,6 +836,12 @@ const Cutscene::Text Cutscene::_frTextsTable[] = {
|
|||
{ -1, 0 }
|
||||
};
|
||||
|
||||
const Demo Game::_demoInputs[] = {
|
||||
{ "demo1.bin", 0, 0x33, 0x60, 0x46 },
|
||||
{ "demo51.bin", 5, 0x00, 0x60, 0xD6 },
|
||||
{ "demo3.bin" , 2, 0xFF, 0x00, 0x00 }
|
||||
};
|
||||
|
||||
const Level Game::_gameLevels[] = {
|
||||
{ "level1", "level1", "level1", 0x00, 1, 3 },
|
||||
{ "level2", "level2", "level2", 0x2F, 1, 4 },
|
||||
|
|
|
@ -35,9 +35,6 @@ struct PlayerInput {
|
|||
bool load;
|
||||
int stateSlot;
|
||||
|
||||
bool inpRecord;
|
||||
bool inpReplay;
|
||||
|
||||
bool mirrorMode;
|
||||
|
||||
uint8_t dbgMask;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "util.h"
|
||||
|
||||
static const int kAudioHz = 22050;
|
||||
|
||||
static const int kJoystickIndex = 0;
|
||||
static const int kJoystickCommitValue = 3200;
|
||||
|
||||
struct SystemStub_SDL : SystemStub {
|
||||
|
@ -17,6 +19,7 @@ struct SystemStub_SDL : SystemStub {
|
|||
SDL_Window *_window;
|
||||
SDL_Renderer *_renderer;
|
||||
SDL_Texture *_texture;
|
||||
SDL_GameController *_controller;
|
||||
#else
|
||||
SDL_Surface *_surface;
|
||||
#endif
|
||||
|
@ -83,15 +86,34 @@ void SystemStub_SDL::init(const char *title, int w, int h, int scaler, bool full
|
|||
memset(_pal, 0, sizeof(_pal));
|
||||
_screenW = _screenH = 0;
|
||||
setScreenSize(w, h);
|
||||
_joystick = NULL;
|
||||
_joystick = 0;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
_controller = 0;
|
||||
if (SDL_NumJoysticks() > 0) {
|
||||
_joystick = SDL_JoystickOpen(0);
|
||||
SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
|
||||
if (SDL_IsGameController(kJoystickIndex)) {
|
||||
_controller = SDL_GameControllerOpen(kJoystickIndex);
|
||||
}
|
||||
if (!_controller) {
|
||||
_joystick = SDL_JoystickOpen(kJoystickIndex);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (SDL_NumJoysticks() > 0) {
|
||||
_joystick = SDL_JoystickOpen(kJoystickIndex);
|
||||
}
|
||||
#endif
|
||||
_screenshot = 1;
|
||||
}
|
||||
|
||||
void SystemStub_SDL::destroy() {
|
||||
cleanupGraphics();
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (_controller) {
|
||||
SDL_GameControllerClose(_controller);
|
||||
_controller = 0;
|
||||
}
|
||||
#endif
|
||||
if (_joystick) {
|
||||
SDL_JoystickClose(_joystick);
|
||||
_joystick = 0;
|
||||
|
@ -141,7 +163,7 @@ void SystemStub_SDL::setOverscanColor(int i) {
|
|||
}
|
||||
|
||||
void SystemStub_SDL::copyRect(int x, int y, int w, int h, const uint8_t *buf, int pitch) {
|
||||
if (_numBlitRects >= ARRAYSIZE(_blitRects)) {
|
||||
if (_numBlitRects >= (int)ARRAYSIZE(_blitRects)) {
|
||||
warning("SystemStub_SDL::copyRect() Too many blit rects, you may experience graphical glitches");
|
||||
} else {
|
||||
// extend the dirty region by 1 pixel for scalers accessing 'outer' pixels
|
||||
|
@ -201,13 +223,16 @@ void SystemStub_SDL::copyRect(int x, int y, int w, int h, const uint8_t *buf, in
|
|||
}
|
||||
|
||||
void SystemStub_SDL::fadeScreen() {
|
||||
const int fadeScreenBufferSize = _screenH * _screenW * sizeof(uint16_t);
|
||||
const int bufferSize = _screenH * _screenW * sizeof(uint16_t);
|
||||
if (!_fadeScreenBuffer) {
|
||||
_fadeScreenBuffer = (uint16_t *)malloc(fadeScreenBufferSize);
|
||||
assert(_fadeScreenBuffer);
|
||||
_fadeScreenBuffer = (uint16_t *)malloc(bufferSize);
|
||||
if (!_fadeScreenBuffer) {
|
||||
warning("SystemStub_SDL::fadeScreen() Unable to allocate buffer size %d", bufferSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_fadeOnUpdateScreen = true;
|
||||
memcpy(_fadeScreenBuffer, _screenBuffer + _screenW + 1, fadeScreenBufferSize);
|
||||
memcpy(_fadeScreenBuffer, _screenBuffer + _screenW + 1, bufferSize);
|
||||
}
|
||||
|
||||
static uint16_t blendPixel16(uint16_t colorSrc, uint16_t colorDst, uint32_t mask, int step) {
|
||||
|
@ -219,9 +244,23 @@ static uint16_t blendPixel16(uint16_t colorSrc, uint16_t colorDst, uint32_t mask
|
|||
|
||||
void SystemStub_SDL::updateScreen(int shakeOffset) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
// _fadeOnUpdateScreen
|
||||
SDL_UpdateTexture(_texture, 0, _screenBuffer + _screenW + 1, _screenW * sizeof(uint16_t));
|
||||
SDL_RenderClear(_renderer);
|
||||
if (_fadeOnUpdateScreen) {
|
||||
SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_Rect r;
|
||||
r.x = r.y = 0;
|
||||
SDL_GetRendererOutputSize(_renderer, &r.w, &r.h);
|
||||
for (int i = 1; i <= 16; ++i) {
|
||||
SDL_SetRenderDrawColor(_renderer, 0, 0, 0, 256 - i * 16);
|
||||
SDL_RenderCopy(_renderer, _texture, 0, 0);
|
||||
SDL_RenderFillRect(_renderer, &r);
|
||||
SDL_RenderPresent(_renderer);
|
||||
SDL_Delay(30);
|
||||
}
|
||||
_fadeOnUpdateScreen = false;
|
||||
return;
|
||||
}
|
||||
if (shakeOffset != 0) {
|
||||
SDL_Rect r;
|
||||
r.x = 0;
|
||||
|
@ -375,41 +414,111 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
|||
}
|
||||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
if (_joystick) {
|
||||
switch (ev.jbutton.button) {
|
||||
case 0:
|
||||
_pi.space = true;
|
||||
break;
|
||||
case 1:
|
||||
_pi.shift = true;
|
||||
break;
|
||||
case 2:
|
||||
_pi.enter = true;
|
||||
break;
|
||||
case 3:
|
||||
_pi.backspace = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_JOYBUTTONUP:
|
||||
if (_joystick) {
|
||||
const bool pressed = (ev.jbutton.state == SDL_PRESSED);
|
||||
switch (ev.jbutton.button) {
|
||||
case 0:
|
||||
_pi.space = false;
|
||||
_pi.space = pressed;
|
||||
break;
|
||||
case 1:
|
||||
_pi.shift = false;
|
||||
_pi.shift = pressed;
|
||||
break;
|
||||
case 2:
|
||||
_pi.enter = false;
|
||||
_pi.enter = pressed;
|
||||
break;
|
||||
case 3:
|
||||
_pi.backspace = false;
|
||||
_pi.backspace = pressed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
if (_controller) {
|
||||
switch (ev.caxis.axis) {
|
||||
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX:
|
||||
if (ev.caxis.value < -kJoystickCommitValue) {
|
||||
_pi.dirMask |= PlayerInput::DIR_LEFT;
|
||||
} else {
|
||||
_pi.dirMask &= ~PlayerInput::DIR_LEFT;
|
||||
}
|
||||
if (ev.caxis.value > kJoystickCommitValue) {
|
||||
_pi.dirMask |= PlayerInput::DIR_RIGHT;
|
||||
} else {
|
||||
_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY:
|
||||
if (ev.caxis.value < -kJoystickCommitValue) {
|
||||
_pi.dirMask |= PlayerInput::DIR_UP;
|
||||
} else {
|
||||
_pi.dirMask &= ~PlayerInput::DIR_UP;
|
||||
}
|
||||
if (ev.caxis.value > kJoystickCommitValue) {
|
||||
_pi.dirMask |= PlayerInput::DIR_DOWN;
|
||||
} else {
|
||||
_pi.dirMask &= ~PlayerInput::DIR_DOWN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
if (_controller) {
|
||||
const bool pressed = (ev.cbutton.state == SDL_PRESSED);
|
||||
switch (ev.cbutton.button) {
|
||||
case SDL_CONTROLLER_BUTTON_A:
|
||||
_pi.enter = pressed;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_B:
|
||||
_pi.space = pressed;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_X:
|
||||
_pi.shift = pressed;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_Y:
|
||||
_pi.backspace = pressed;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_BACK:
|
||||
case SDL_CONTROLLER_BUTTON_START:
|
||||
_pi.escape = pressed;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_UP:
|
||||
if (pressed) {
|
||||
_pi.dirMask |= PlayerInput::DIR_UP;
|
||||
} else {
|
||||
_pi.dirMask &= ~PlayerInput::DIR_UP;
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
|
||||
if (pressed) {
|
||||
_pi.dirMask |= PlayerInput::DIR_DOWN;
|
||||
} else {
|
||||
_pi.dirMask &= ~PlayerInput::DIR_DOWN;
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
|
||||
if (pressed) {
|
||||
_pi.dirMask |= PlayerInput::DIR_LEFT;
|
||||
} else {
|
||||
_pi.dirMask &= ~PlayerInput::DIR_LEFT;
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
|
||||
if (pressed) {
|
||||
_pi.dirMask |= PlayerInput::DIR_RIGHT;
|
||||
} else {
|
||||
_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SDL_KEYUP:
|
||||
switch (ev.key.keysym.sym) {
|
||||
case SDLK_LEFT:
|
||||
|
@ -484,10 +593,6 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
|||
_pi.stateSlot = 1;
|
||||
} else if (ev.key.keysym.sym == SDLK_KP_MINUS || ev.key.keysym.sym == SDLK_PAGEDOWN) {
|
||||
_pi.stateSlot = -1;
|
||||
} else if (ev.key.keysym.sym == SDLK_r) {
|
||||
_pi.inpRecord = true;
|
||||
} else if (ev.key.keysym.sym == SDLK_p) {
|
||||
_pi.inpReplay = true;
|
||||
}
|
||||
}
|
||||
_pi.lastChar = ev.key.keysym.sym;
|
||||
|
|
6
util.h
6
util.h
|
@ -27,8 +27,8 @@ enum {
|
|||
|
||||
extern uint16_t g_debugMask;
|
||||
|
||||
extern void debug(uint16_t cm, const char *msg, ...);
|
||||
extern void error(const char *msg, ...);
|
||||
extern void warning(const char *msg, ...);
|
||||
extern void debug(uint16_t cm, const char *msg, ...); // __attribute__((__format__(__printf__, 2, 3)))
|
||||
extern void error(const char *msg, ...); // __attribute__((__format__(__printf__, 1, 2)))
|
||||
extern void warning(const char *msg, ...); // __attribute__((__format__(__printf__, 1, 2)))
|
||||
|
||||
#endif // UTIL_H__
|
||||
|
|
Loading…
Reference in New Issue