Import 0.3.6

This commit is contained in:
Gregory Montoir 2018-01-15 00:00:00 +08:00
parent e2f30e28a0
commit e8f6b94ef8
14 changed files with 114 additions and 76 deletions

View File

@ -1,6 +1,6 @@
REminiscence README
Release version: 0.3.5
Release version: 0.3.6
-------------------------------------------------------------------------------

View File

@ -13,7 +13,7 @@
#include "unpack.h"
#include "util.h"
Game::Game(SystemStub *stub, FileSystem *fs, const char *savePath, int level, int demo, ResourceType ver, Language lang)
Game::Game(SystemStub *stub, FileSystem *fs, const char *savePath, int level, 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) {
@ -21,23 +21,12 @@ Game::Game(SystemStub *stub, FileSystem *fs, const char *savePath, int level, in
_inp_demPos = 0;
_skillLevel = _menu._skill = 1;
_currentLevel = _menu._level = level;
_demoBin = demo;
_demoBin = -1;
}
void Game::run() {
_randSeed = time(0);
if (_demoBin != -1) {
if (_demoBin < 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();
@ -69,10 +58,8 @@ void Game::run() {
_mix.init();
_mix._mod._isAmiga = _res.isAmiga();
if (_demoBin == -1) {
playCutscene(0x40);
playCutscene(0x0D);
}
playCutscene(0x40);
playCutscene(0x0D);
switch (_res._type) {
case kResourceTypeAmiga:
@ -90,10 +77,7 @@ void Game::run() {
}
while (!_stub->_pi.quit) {
if (_demoBin != -1) {
_currentLevel = _demoInputs[_demoBin].level;
_randSeed = 0;
} else if (_res._isDemo) {
if (_res._isDemo) {
// do not present title screen and menus
} else {
_mix.playMusic(1);
@ -104,6 +88,21 @@ void Game::run() {
_stub->_pi.quit = true;
break;
}
if (_menu._selectedOption == Menu::MENU_OPTION_ITEM_DEMO) {
_demoBin = (_demoBin + 1) % ARRAYSIZE(_demoInputs);
const char *fn = _demoInputs[_demoBin].name;
debug(DBG_DEMO, "Loading inputs from '%s'", fn);
_res.load_DEM(fn);
if (_res._demLen == 0) {
continue;
}
_skillLevel = 1;
_currentLevel = _demoInputs[_demoBin].level;
_randSeed = 0;
_mix.stopMusic();
break;
}
_demoBin = -1;
_skillLevel = _menu._skill;
_currentLevel = _menu._level;
_mix.stopMusic();
@ -135,10 +134,17 @@ void Game::run() {
while (!_stub->_pi.quit && !_endLoop) {
mainLoop();
if (_demoBin != -1 && _inp_demPos >= _res._demLen) {
debug(DBG_INFO, "End of demo");
_stub->_pi.quit = true;
debug(DBG_DEMO, "End of demo");
// exit level
_demoBin = -1;
_endLoop = true;
}
}
// flush inputs
_stub->_pi.dirMask = 0;
_stub->_pi.enter = false;
_stub->_pi.space = false;
_stub->_pi.shift = false;
}
}
@ -149,7 +155,7 @@ void Game::run() {
void Game::displayTitleScreenAmiga() {
static const char *FILENAME = "present.cmp";
_res.load_CMP_menu(FILENAME, _res._memBuf);
_res.load_CMP_menu(FILENAME, _res._scratchBuffer);
static const int kW = 320;
static const int kH = 224;
uint8_t *buf = (uint8_t *)calloc(kW * kH, 1);
@ -169,7 +175,7 @@ void Game::displayTitleScreenAmiga() {
_stub->setScreenSize(kW, kH);
_stub->copyRect(0, 0, kW, kH, buf, kW);
_stub->updateScreen(0);
_vid.AMIGA_decodeCmp(_res._memBuf + 6, buf);
_vid.AMIGA_decodeCmp(_res._scratchBuffer + 6, buf);
free(buf);
for (int h = 0; h < kH / 2; h += 2) {
const int y = kH / 2 - h;
@ -261,7 +267,7 @@ void Game::mainLoop() {
return;
}
if (_loadMap) {
if (_currentRoom == 0xFF) {
if (_currentRoom == 0xFF || !hasLevelMap(_currentLevel, _pgeLive[0].room_location)) {
_cut._id = 6;
_deathCutsceneCounter = 1;
} else {
@ -288,7 +294,7 @@ void Game::mainLoop() {
}
if (_stub->_pi.escape) {
_stub->_pi.escape = false;
if (handleConfigPanel()) {
if (_demoBin != -1 || handleConfigPanel()) {
_endLoop = true;
return;
}
@ -382,7 +388,7 @@ void Game::playCutscene(int id) {
bool Game::playCutsceneSeq(const char *name) {
File f;
if (f.open(name, "rb", _fs)) {
_seq.setBackBuffer(_res._memBuf);
_seq.setBackBuffer(_res._scratchBuffer);
_seq.play(&f);
_vid.fullRefresh();
return true;
@ -967,13 +973,13 @@ void Game::drawAnimBuffer(uint8_t stateNum, AnimBufferState *state) {
}
switch (_res._type) {
case kResourceTypeAmiga:
_vid.AMIGA_decodeSpm(state->dataPtr, _res._memBuf);
drawCharacter(_res._memBuf, state->x, state->y, state->h, state->w, pge->flags);
_vid.AMIGA_decodeSpm(state->dataPtr, _res._scratchBuffer);
drawCharacter(_res._scratchBuffer, state->x, state->y, state->h, state->w, pge->flags);
break;
case kResourceTypeDOS:
if (!(state->dataPtr[-2] & 0x80)) {
decodeCharacterFrame(state->dataPtr, _res._memBuf);
drawCharacter(_res._memBuf, state->x, state->y, state->h, state->w, pge->flags);
decodeCharacterFrame(state->dataPtr, _res._scratchBuffer);
drawCharacter(_res._scratchBuffer, state->x, state->y, state->h, state->w, pge->flags);
} else {
drawCharacter(state->dataPtr, state->x, state->y, state->h, state->w, pge->flags);
}
@ -1041,14 +1047,14 @@ void Game::drawObjectFrame(const uint8_t *bankDataPtr, const uint8_t *dataPtr, i
switch (_res._type) {
case kResourceTypeAmiga:
_vid.AMIGA_decodeSpc(src, sprite_w, sprite_h, _res._memBuf);
_vid.AMIGA_decodeSpc(src, sprite_w, sprite_h, _res._scratchBuffer);
break;
case kResourceTypeDOS:
_vid.PC_decodeSpc(src, sprite_w, sprite_h, _res._memBuf);
_vid.PC_decodeSpc(src, sprite_w, sprite_h, _res._scratchBuffer);
break;
}
src = _res._memBuf;
src = _res._scratchBuffer;
bool sprite_mirror_x = false;
int16_t sprite_clipped_w;
if (sprite_x >= 0) {
@ -1294,6 +1300,15 @@ int Game::loadMonsterSprites(LivePGE *pge) {
return 0xFFFF;
}
bool Game::hasLevelMap(int level, int room) const {
if (_res._map) {
return READ_LE_UINT32(_res._map + room * 6) != 0;
} else if (_res._lev) {
return READ_BE_UINT32(_res._lev + room * 4) != 0;
}
return false;
}
void Game::loadLevelMap() {
debug(DBG_GAME, "Game::loadLevelMap() room=%d", _currentRoom);
_currentIcon = 0xFF;
@ -1441,6 +1456,7 @@ void Game::loadLevelData() {
_pgeLive[0].room_location = _demoInputs[_demoBin].room;
_pgeLive[0].pos_x = _demoInputs[_demoBin].x;
_pgeLive[0].pos_y = _demoInputs[_demoBin].y;
_inp_demPos = 0;
} else {
_inp_demPos = 1;
}
@ -1669,7 +1685,7 @@ void Game::handleInventory() {
void Game::inp_update() {
_stub->processEvents();
if (_inp_demPos < _res._demLen) {
if (_demoBin != -1 && _inp_demPos < _res._demLen) {
const int keymask = _res._dem[_inp_demPos++];
_stub->_pi.dirMask = keymask & 0xF;
_stub->_pi.enter = (keymask & 0x10) != 0;

3
game.h
View File

@ -87,7 +87,7 @@ struct Game {
bool _endLoop;
uint32_t _frameTimestamp;
Game(SystemStub *, FileSystem *, const char *savePath, int level, int demo, ResourceType ver, Language lang);
Game(SystemStub *, FileSystem *, const char *savePath, int level, ResourceType ver, Language lang);
void run();
void displayTitleScreenAmiga();
@ -96,6 +96,7 @@ struct Game {
void updateTiming();
void playCutscene(int id = -1);
bool playCutsceneSeq(const char *name);
bool hasLevelMap(int level, int room) const;
void loadLevelMap();
void loadLevelData();
void drawIcon(uint8_t iconNum, int16_t x, int16_t y, uint8_t colMask);

View File

@ -174,7 +174,6 @@ int main(int argc, char *argv[]) {
bool fullscreen = false;
ScalerParameters scalerParameters = ScalerParameters::defaults();
int forcedLanguage = -1;
int demoNum = -1;
if (argc == 2) {
// data path as the only command line argument
struct stat st;
@ -190,7 +189,6 @@ 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;
@ -235,9 +233,6 @@ int main(int argc, char *argv[]) {
}
}
break;
case 7:
demoNum = atoi(optarg);
break;
default:
printf(USAGE, argv[0]);
return 0;
@ -253,7 +248,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, demoNum, (ResourceType)version, language);
Game *g = new Game(stub, &fs, savePath, levelNum, (ResourceType)version, language);
stub->init(g_caption, Video::GAMESCREEN_W, Video::GAMESCREEN_H, fullscreen, &scalerParameters);
g->run();
delete g;

View File

@ -73,16 +73,16 @@ void Menu::drawString2(const char *str, int16_t y, int16_t x) {
void Menu::loadPicture(const char *prefix) {
debug(DBG_MENU, "Menu::loadPicture('%s')", prefix);
_res->load_MAP_menu(prefix, _res->_memBuf);
_res->load_MAP_menu(prefix, _res->_scratchBuffer);
for (int i = 0; i < 4; ++i) {
for (int y = 0; y < 224; ++y) {
for (int x = 0; x < 64; ++x) {
_vid->_frontLayer[i + x * 4 + 256 * y] = _res->_memBuf[0x3800 * i + x + 64 * y];
_vid->_frontLayer[i + x * 4 + 256 * y] = _res->_scratchBuffer[0x3800 * i + x + 64 * y];
}
}
}
_res->load_PAL_menu(prefix, _res->_memBuf);
_stub->setPalette(_res->_memBuf, 256);
_res->load_PAL_menu(prefix, _res->_scratchBuffer);
_stub->setPalette(_res->_scratchBuffer, 256);
}
void Menu::handleInfoScreen() {
@ -309,7 +309,7 @@ void Menu::handleTitleScreen() {
_charVar4 = 0;
_charVar5 = 0;
static const int MAX_MENU_ITEMS = 5;
static const int MAX_MENU_ITEMS = 6;
Item menuItems[MAX_MENU_ITEMS];
int menuItemsCount = 0;
@ -331,6 +331,9 @@ void Menu::handleTitleScreen() {
menuItems[menuItemsCount].str = LocaleData::LI_10_INFO;
menuItems[menuItemsCount].opt = MENU_OPTION_ITEM_INFO;
++menuItemsCount;
menuItems[menuItemsCount].str = LocaleData::LI_23_DEMO;
menuItems[menuItemsCount].opt = MENU_OPTION_ITEM_DEMO;
++menuItemsCount;
menuItems[menuItemsCount].str = LocaleData::LI_11_QUIT;
menuItems[menuItemsCount].opt = MENU_OPTION_ITEM_QUIT;
++menuItemsCount;
@ -406,6 +409,9 @@ void Menu::handleTitleScreen() {
_currentScreen = SCREEN_INFO;
handleInfoScreen();
break;
case MENU_OPTION_ITEM_DEMO:
quitLoop = true;
break;
case MENU_OPTION_ITEM_QUIT:
quitLoop = true;
break;

1
menu.h
View File

@ -20,6 +20,7 @@ struct Menu {
MENU_OPTION_ITEM_PASSWORD,
MENU_OPTION_ITEM_LEVEL,
MENU_OPTION_ITEM_INFO,
MENU_OPTION_ITEM_DEMO,
MENU_OPTION_ITEM_QUIT
};
enum {

View File

@ -30,6 +30,7 @@ struct ModPlayer_impl {
_settings.mBits = 16;
_settings.mFrequency = rate;
_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
_settings.mLoopCount = -1;
ModPlug_SetSettings(&_settings);
}
@ -58,7 +59,15 @@ struct ModPlayer_impl {
_repeatIntro = false;
}
const int count = ModPlug_Read(_mf, buf, len * sizeof(int16_t));
return count > 0;
// setting mLoopCount to non-zero does not trigger any looping in
// my test and ModPlug_Read returns 0.
// looking at the libmodplug-0.8.8 tarball, it seems the variable
// m_nRepeatCount is commented in sndmix.cpp. Not sure how if this
// is a known bug, we workaround it here.
if (count == 0) {
ModPlug_SeekOrder(_mf, 0);
}
return true;
}
return false;
}
@ -570,7 +579,8 @@ void ModPlayer_impl::handleTick() {
}
if (_currentPatternOrder == _modInfo.numPatterns) {
debug(DBG_MOD, "ModPlayer::handleEffect() _currentPatternOrder == _modInfo.numPatterns");
_playing = false;
// _playing = false;
_currentPatternOrder = 0;
}
}

View File

@ -193,7 +193,7 @@ set_anim:
uint8_t _dl = pge->anim_seq;
const uint8_t *anim_frame = anim_data + 6 + _dl * 4;
while (_dh > _dl) {
if (READ_LE_UINT16(anim_frame) != 0xFFFF) {
if (_res._readUint16(anim_frame) != 0xFFFF) {
if (_pge_currentPiegeFacingDir) {
pge->pos_x -= (int8_t)anim_frame[2];
} else {

View File

@ -19,8 +19,8 @@ Resource::Resource(FileSystem *fs, ResourceType ver, Language lang) {
_aba = 0;
_readUint16 = (_type == kResourceTypeDOS) ? READ_LE_UINT16 : READ_BE_UINT16;
_readUint32 = (_type == kResourceTypeDOS) ? READ_LE_UINT32 : READ_BE_UINT32;
_memBuf = (uint8_t *)malloc(320 * 224 + 1024);
if (!_memBuf) {
_scratchBuffer = (uint8_t *)malloc(320 * 224 + 1024);
if (!_scratchBuffer) {
error("Unable to allocate temporary memory buffer");
}
static const int kBankDataSize = 0x7000;
@ -40,7 +40,7 @@ Resource::~Resource() {
free(_tab);
free(_spc);
free(_spr1);
free(_memBuf);
free(_scratchBuffer);
free(_cmd);
free(_pol);
free(_cine_off);

View File

@ -37,6 +37,7 @@ struct LocaleData {
LI_20_LOAD_GAME,
LI_21_SAVE_GAME,
LI_22_SAVE_SLOT,
LI_23_DEMO,
LI_NUM
};
@ -144,7 +145,7 @@ struct Resource {
uint8_t *_bnq;
uint16_t _numObjectNodes;
ObjectNode *_objectNodesMap[255];
uint8_t *_memBuf;
uint8_t *_scratchBuffer;
SoundFx *_sfxList;
uint8_t _numSfx;
uint8_t *_cmd;

View File

@ -2261,7 +2261,7 @@ const uint8_t LocaleData::_stringsTableJP[] = {
0x0a, 0x61, 0x7a, 0x73, 0x20, 0x7d, 0x73, 0x6a, 0xcf, 0x92, 0x00
};
const char *LocaleData::_textsTableFR[] = {
const char *LocaleData::_textsTableFR[LocaleData::LI_NUM] = {
"CONTINUER OU ABANDONNER ?",
"TEMPS",
"CONTINUER",
@ -2283,10 +2283,11 @@ const char *LocaleData::_textsTableFR[] = {
"ABANDONNER",
"CHARGER",
"SAUVEGARDER",
"PARTIE"
"PARTIE",
"DEMO"
};
const char *LocaleData::_textsTableEN[] = {
const char *LocaleData::_textsTableEN[LocaleData::LI_NUM] = {
"CONTINUE OR ABORT THIS GAME ?",
"TIME",
"CONTINUE",
@ -2308,10 +2309,11 @@ const char *LocaleData::_textsTableEN[] = {
"ABORT GAME",
"LOAD GAME",
"SAVE GAME",
"SLOT"
"SLOT",
"DEMO"
};
const char *LocaleData::_textsTableDE[] = {
const char *LocaleData::_textsTableDE[LocaleData::LI_NUM] = {
"WEITERSPIELEN ODER ABBRECHEN ?",
"ZEIT : ",
"WEITERSPIELEN",
@ -2333,10 +2335,11 @@ const char *LocaleData::_textsTableDE[] = {
"SPIEL ABBRECHEN",
"LADEN",
"SPEICHERN",
"SPIEL"
"SPIEL",
"DEMO"
};
const char *LocaleData::_textsTableSP[] = {
const char *LocaleData::_textsTableSP[LocaleData::LI_NUM] = {
"CONTINUAR O TERMINAR JUEGO ?",
"TIEMPO",
"SEGUIR",
@ -2358,10 +2361,11 @@ const char *LocaleData::_textsTableSP[] = {
"PARAR JUEGO",
"CARGAR DATOS",
"GUARDAR DATOS",
"JUEGO"
"JUEGO",
"DEMO"
};
const char *LocaleData::_textsTableIT[] = {
const char *LocaleData::_textsTableIT[LocaleData::LI_NUM] = {
"CONTINUA O ABBANDONA GIOCO",
"TEMPO",
"CONTINUA",
@ -2383,7 +2387,8 @@ const char *LocaleData::_textsTableIT[] = {
"ESCI DAL GIOCO",
"CARICA IL GIOCO",
"SALVA IL GIOCO",
"SLOT"
"SLOT",
"DEMO"
};
const uint8_t LocaleData::_level1TbnJP[] = {

View File

@ -611,6 +611,8 @@ void SystemStub_SDL::prepareGraphics() {
int flags = 0;
if (_fullscreen) {
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
} else {
flags |= SDL_WINDOW_RESIZABLE;
}
_window = SDL_CreateWindow(_caption, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowW, windowH, flags);
SDL_Surface *icon = SDL_LoadBMP(kIconBmp);

3
util.h
View File

@ -22,7 +22,8 @@ enum {
DBG_CUT = 1 << 9,
DBG_MOD = 1 << 10,
DBG_SFX = 1 << 11,
DBG_FILE = 1 << 12
DBG_FILE = 1 << 12,
DBG_DEMO = 1 << 13
};
extern uint16_t g_debugMask;

View File

@ -188,7 +188,7 @@ void Video::PC_decodeLev(int level, int room) {
_res->clearBankData();
}
static void PC_decodeMapHelper(int sz, const uint8_t *src, uint8_t *dst) {
static void PC_decodeMapPlane(int sz, const uint8_t *src, uint8_t *dst) {
const uint8_t *end = src + sz;
while (src < end) {
int16_t code = (int8_t)*src++;
@ -212,6 +212,7 @@ void Video::PC_decodeMap(int level, int room) {
if (off == 0) {
error("Invalid room %d", room);
}
// int size = READ_LE_UINT16(_res->_map + room * 6 + 4);
bool packed = true;
if (off < 0) {
off = -off;
@ -226,19 +227,18 @@ void Video::PC_decodeMap(int level, int room) {
// workaround for wrong palette colors (fire)
_mapPalSlot4 = 5;
}
static const int kPlaneSize = 256 * 224 / 4;
if (packed) {
uint8_t *vid = _frontLayer;
for (int i = 0; i < 4; ++i) {
const int sz = READ_LE_UINT16(p); p += 2;
PC_decodeMapHelper(sz, p, _res->_memBuf); p += sz;
memcpy(vid, _res->_memBuf, 256 * 56);
vid += 256 * 56;
PC_decodeMapPlane(sz, p, _res->_scratchBuffer); p += sz;
memcpy(_frontLayer + i * kPlaneSize, _res->_scratchBuffer, kPlaneSize);
}
} else {
for (int i = 0; i < 4; ++i) {
for (int y = 0; y < 224; ++y) {
for (int x = 0; x < 64; ++x) {
_frontLayer[i + x * 4 + 256 * y] = p[256 * 56 * i + x + 64 * y];
_frontLayer[i + x * 4 + 256 * y] = p[kPlaneSize * i + x + 64 * y];
}
}
}
@ -601,7 +601,7 @@ 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->_memBuf;
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);
@ -835,8 +835,8 @@ void Video::PC_drawChar(uint8_t c, int16_t y, int16_t x, bool forceDefaultFont)
void Video::AMIGA_drawStringChar(uint8_t *dst, int pitch, const uint8_t *src, uint8_t color, uint8_t chr) {
assert(chr >= 32);
AMIGA_decodeIcn(src, chr - 32, _res->_memBuf);
src = _res->_memBuf;
AMIGA_decodeIcn(src, chr - 32, _res->_scratchBuffer);
src = _res->_scratchBuffer;
for (int y = 0; y < 8; ++y) {
for (int x = 0; x < 8; ++x) {
if (src[x] != 0) {