Import 0.3.0
This commit is contained in:
parent
f10e912082
commit
cb9e469636
15
Makefile
15
Makefile
|
@ -2,24 +2,21 @@
|
||||||
SDL_CFLAGS = `sdl-config --cflags`
|
SDL_CFLAGS = `sdl-config --cflags`
|
||||||
SDL_LIBS = `sdl-config --libs`
|
SDL_LIBS = `sdl-config --libs`
|
||||||
VORBIS_LIBS = -lvorbisidec
|
VORBIS_LIBS = -lvorbisidec
|
||||||
|
MODPLUG_LIBS = -lmodplug
|
||||||
ZLIB_LIBS = -lz
|
ZLIB_LIBS = -lz
|
||||||
|
|
||||||
DEFINES = -DBYPASS_PROTECTION
|
CXX := clang++
|
||||||
#DEFINES = -DBYPASS_PROTECTION -DENABLE_PASSWORD_MENU -DNDEBUG
|
CXXFLAGS := -Wall -MMD $(SDL_CFLAGS) -DUSE_ZLIB # -DUSE_MODPLUG
|
||||||
|
|
||||||
CXXFLAGS += -Wall -Wuninitialized -Wshadow -Wundef -Wreorder -Wnon-virtual-dtor -Wno-multichar
|
|
||||||
CXXFLAGS += -MMD $(SDL_CFLAGS) -DUSE_ZLIB $(DEFINES)
|
|
||||||
|
|
||||||
SRCS = collision.cpp cutscene.cpp file.cpp fs.cpp game.cpp graphics.cpp main.cpp menu.cpp \
|
SRCS = collision.cpp cutscene.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 scaler.cpp seq_player.cpp \
|
mixer.cpp mod_player.cpp ogg_player.cpp piege.cpp resource.cpp resource_aba.cpp \
|
||||||
|
scaler.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)
|
OBJS = $(SRCS:.cpp=.o)
|
||||||
DEPS = $(SRCS:.cpp=.d)
|
DEPS = $(SRCS:.cpp=.d)
|
||||||
|
|
||||||
LIBS = $(SDL_LIBS) $(VORBIS_LIBS) $(ZLIB_LIBS)
|
LIBS = $(SDL_LIBS) $(VORBIS_LIBS) $(MODPLUG_LIBS) $(ZLIB_LIBS)
|
||||||
|
|
||||||
-include Makefile.local
|
|
||||||
|
|
||||||
rs: $(OBJS)
|
rs: $(OBJS)
|
||||||
$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||||
|
|
3
README
3
README
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
REminiscence README
|
REminiscence README
|
||||||
Release version: 0.2.2 ($date)
|
Release version: 0.3.0 ($date)
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ In-game hotkeys :
|
||||||
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 - change video scaler
|
||||||
|
Alt S write screenshot as .bmp
|
||||||
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
|
||||||
|
|
|
@ -1,23 +1,12 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
void Game::col_prepareRoomState() {
|
void Game::col_prepareRoomState() {
|
||||||
memset(_col_activeCollisionSlots, 0xFF, sizeof(_col_activeCollisionSlots));
|
memset(_col_activeCollisionSlots, 0xFF, sizeof(_col_activeCollisionSlots));
|
||||||
|
|
135
cutscene.cpp
135
cutscene.cpp
|
@ -1,28 +1,19 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "cutscene.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
|
#include "util.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
#include "cutscene.h"
|
|
||||||
|
|
||||||
|
|
||||||
Cutscene::Cutscene(Resource *res, SystemStub *stub, Video *vid)
|
Cutscene::Cutscene(Resource *res, SystemStub *stub, Video *vid)
|
||||||
: _res(res), _stub(stub), _vid(vid) {
|
: _res(res), _stub(stub), _vid(vid) {
|
||||||
|
_patchedOffsetsTable = 0;
|
||||||
memset(_palBuf, 0, sizeof(_palBuf));
|
memset(_palBuf, 0, sizeof(_palBuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,12 +42,8 @@ void Cutscene::updatePalette() {
|
||||||
if (_newPal) {
|
if (_newPal) {
|
||||||
const uint8_t *p = _palBuf;
|
const uint8_t *p = _palBuf;
|
||||||
for (int i = 0; i < 32; ++i) {
|
for (int i = 0; i < 32; ++i) {
|
||||||
uint16_t color = READ_BE_UINT16(p); p += 2;
|
const uint16_t color = READ_BE_UINT16(p); p += 2;
|
||||||
uint8_t t = (color == 0) ? 0 : 3;
|
Color c = Video::AMIGA_convertColor(color);
|
||||||
Color c;
|
|
||||||
c.r = ((color & 0xF00) >> 6) | t;
|
|
||||||
c.g = ((color & 0x0F0) >> 2) | t;
|
|
||||||
c.b = ((color & 0x00F) << 2) | t;
|
|
||||||
_stub->setPaletteEntry(0xC0 + i, &c);
|
_stub->setPaletteEntry(0xC0 + i, &c);
|
||||||
}
|
}
|
||||||
_newPal = false;
|
_newPal = false;
|
||||||
|
@ -67,21 +54,36 @@ void Cutscene::setPalette() {
|
||||||
sync();
|
sync();
|
||||||
updatePalette();
|
updatePalette();
|
||||||
SWAP(_page0, _page1);
|
SWAP(_page0, _page1);
|
||||||
_stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _page0, 256);
|
_stub->copyRect(0, 0, _vid->_w, _vid->_h, _page0, 256);
|
||||||
_stub->updateScreen(0);
|
_stub->updateScreen(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cutscene::initRotationData(uint16_t a, uint16_t b, uint16_t c) {
|
#if 0
|
||||||
int16_t n1 = _sinTable[a];
|
#define SIN(a) (int16_t)(sin(a * M_PI / 180) * 256)
|
||||||
int16_t n2 = _cosTable[a];
|
#define COS(a) (int16_t)(cos(a * M_PI / 180) * 256)
|
||||||
int16_t n3 = _sinTable[c];
|
#else
|
||||||
int16_t n4 = _cosTable[c];
|
#define SIN(a) _sinTable[a]
|
||||||
int16_t n5 = _sinTable[b];
|
#define COS(a) _cosTable[a]
|
||||||
int16_t n6 = _cosTable[b];
|
#endif
|
||||||
_rotData[0] = ((n2 * n6) >> 8) - ((((n4 * n1) >> 8) * n5) >> 8);
|
|
||||||
_rotData[1] = ((n1 * n6) >> 8) + ((((n4 * n2) >> 8) * n5) >> 8);
|
/*
|
||||||
_rotData[2] = ( n3 * n1) >> 8;
|
cos(60) table: 128, math: 127
|
||||||
_rotData[3] = (-n3 * n2) >> 8;
|
cos(120) table:-127, math:-128
|
||||||
|
cos(240) table:-128, math:-127
|
||||||
|
sin(330) table: 221, math:-127
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Cutscene::setRotationTransform(uint16_t a, uint16_t b, uint16_t c) { // identity a:0 b:180 c:90
|
||||||
|
const int16_t sin_a = SIN(a);
|
||||||
|
const int16_t cos_a = COS(a);
|
||||||
|
const int16_t sin_c = SIN(c);
|
||||||
|
const int16_t cos_c = COS(c);
|
||||||
|
const int16_t sin_b = SIN(b);
|
||||||
|
const int16_t cos_b = COS(b);
|
||||||
|
_rotMat[0] /* .x1 */ = ((cos_a * cos_b) >> 8) - ((((cos_c * sin_a) >> 8) * sin_b) >> 8);
|
||||||
|
_rotMat[1] /* .y1 */ = ((sin_a * cos_b) >> 8) + ((((cos_c * cos_a) >> 8) * sin_b) >> 8);
|
||||||
|
_rotMat[2] /* .x2 */ = ( sin_c * sin_a) >> 8;
|
||||||
|
_rotMat[3] /* .y2 */ = (-sin_c * cos_a) >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Cutscene::findTextSeparators(const uint8_t *p) {
|
uint16_t Cutscene::findTextSeparators(const uint8_t *p) {
|
||||||
|
@ -159,9 +161,9 @@ void Cutscene::drawText(int16_t x, int16_t y, const uint8_t *p, uint16_t color,
|
||||||
|
|
||||||
void Cutscene::swapLayers() {
|
void Cutscene::swapLayers() {
|
||||||
if (_clearScreen == 0) {
|
if (_clearScreen == 0) {
|
||||||
memcpy(_page1, _pageC, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_page1, _pageC, _vid->_layerSize);
|
||||||
} else {
|
} else {
|
||||||
memset(_page1, 0xC0, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memset(_page1, 0xC0, _vid->_layerSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,9 +198,7 @@ void Cutscene::drawCreditsText() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*_textCurBuf++ = code;
|
*_textCurBuf++ = code;
|
||||||
_textCurBuf = _textCurBuf;
|
*_textCurBuf++ = 0xA;
|
||||||
*_textCurBuf = 0xA;
|
|
||||||
++_textCurPtr;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_creditsTextCounter -= 10; // XXX adjust
|
_creditsTextCounter -= 10; // XXX adjust
|
||||||
|
@ -216,7 +216,7 @@ void Cutscene::drawProtectionShape(uint8_t shapeNum, int16_t zoom) {
|
||||||
int16_t x = 0;
|
int16_t x = 0;
|
||||||
int16_t y = 0;
|
int16_t y = 0;
|
||||||
zoom += 512;
|
zoom += 512;
|
||||||
initRotationData(0, 180, 90);
|
setRotationTransform(0, 180, 90);
|
||||||
|
|
||||||
const uint8_t *shapeOffsetTable = _protectionShapeData + READ_BE_UINT16(_protectionShapeData + 0x02);
|
const uint8_t *shapeOffsetTable = _protectionShapeData + READ_BE_UINT16(_protectionShapeData + 0x02);
|
||||||
const uint8_t *shapeDataTable = _protectionShapeData + READ_BE_UINT16(_protectionShapeData + 0x0E);
|
const uint8_t *shapeDataTable = _protectionShapeData + READ_BE_UINT16(_protectionShapeData + 0x0E);
|
||||||
|
@ -272,7 +272,7 @@ void Cutscene::op_waitForSync() {
|
||||||
if (_textBuf == _textCurBuf) {
|
if (_textBuf == _textCurBuf) {
|
||||||
_creditsTextCounter = 20;
|
_creditsTextCounter = 20;
|
||||||
}
|
}
|
||||||
memcpy(_page1, _page0, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_page1, _page0, _vid->_layerSize);
|
||||||
drawCreditsText();
|
drawCreditsText();
|
||||||
setPalette();
|
setPalette();
|
||||||
} while (--n);
|
} while (--n);
|
||||||
|
@ -364,7 +364,7 @@ void Cutscene::op_drawShape() {
|
||||||
drawShape(primitiveVertices, x + dx, y + dy);
|
drawShape(primitiveVertices, x + dx, y + dy);
|
||||||
}
|
}
|
||||||
if (_clearScreen != 0) {
|
if (_clearScreen != 0) {
|
||||||
memcpy(_pageC, _page1, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_pageC, _page1, _vid->_layerSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,8 +609,8 @@ void Cutscene::drawShapeScaleRotate(const uint8_t *data, int16_t zoom, int16_t b
|
||||||
y = READ_BE_UINT16(data); data += 2;
|
y = READ_BE_UINT16(data); data += 2;
|
||||||
_shape_cur_x16 = _shape_ix - ix;
|
_shape_cur_x16 = _shape_ix - ix;
|
||||||
_shape_cur_y16 = _shape_iy - iy;
|
_shape_cur_y16 = _shape_iy - iy;
|
||||||
_shape_ox = _shape_cur_x = _shape_ix + ((_shape_cur_x16 * _rotData[0] + _shape_cur_y16 * _rotData[1]) >> 8);
|
_shape_ox = _shape_cur_x = _shape_ix + ((_shape_cur_x16 * _rotMat[0] + _shape_cur_y16 * _rotMat[1]) >> 8);
|
||||||
_shape_oy = _shape_cur_y = _shape_iy + ((_shape_cur_x16 * _rotData[2] + _shape_cur_y16 * _rotData[3]) >> 8);
|
_shape_oy = _shape_cur_y = _shape_iy + ((_shape_cur_x16 * _rotMat[2] + _shape_cur_y16 * _rotMat[3]) >> 8);
|
||||||
pr[0].x = 0;
|
pr[0].x = 0;
|
||||||
pr[0].y = -y;
|
pr[0].y = -y;
|
||||||
pr[1].x = -x;
|
pr[1].x = -x;
|
||||||
|
@ -655,8 +655,8 @@ void Cutscene::drawShapeScaleRotate(const uint8_t *data, int16_t zoom, int16_t b
|
||||||
pt.y = c + READ_BE_UINT16(data); data += 2;
|
pt.y = c + READ_BE_UINT16(data); data += 2;
|
||||||
_shape_cur_x16 = _shape_ix - pt.x;
|
_shape_cur_x16 = _shape_ix - pt.x;
|
||||||
_shape_cur_y16 = _shape_iy - pt.y;
|
_shape_cur_y16 = _shape_iy - pt.y;
|
||||||
_shape_cur_x = _shape_ix + ((_rotData[0] * _shape_cur_x16 + _rotData[1] * _shape_cur_y16) >> 8);
|
_shape_cur_x = _shape_ix + ((_rotMat[0] * _shape_cur_x16 + _rotMat[1] * _shape_cur_y16) >> 8);
|
||||||
_shape_cur_y = _shape_iy + ((_rotData[2] * _shape_cur_x16 + _rotData[3] * _shape_cur_y16) >> 8);
|
_shape_cur_y = _shape_iy + ((_rotMat[2] * _shape_cur_x16 + _rotMat[3] * _shape_cur_y16) >> 8);
|
||||||
if (_shape_count != 0) {
|
if (_shape_count != 0) {
|
||||||
_shape_cur_x16 = _shape_prev_x16 + (_shape_cur_x - _shape_prev_x) * zoom * 128;
|
_shape_cur_x16 = _shape_prev_x16 + (_shape_cur_x - _shape_prev_x) * zoom * 128;
|
||||||
pt.x = ((_shape_cur_x16 + 0x8000) >> 16) + _shape_ix + d;
|
pt.x = ((_shape_cur_x16 + 0x8000) >> 16) + _shape_ix + d;
|
||||||
|
@ -685,12 +685,12 @@ void Cutscene::drawShapeScaleRotate(const uint8_t *data, int16_t zoom, int16_t b
|
||||||
_shape_cur_x16 = _shape_ix - x;
|
_shape_cur_x16 = _shape_ix - x;
|
||||||
_shape_cur_y16 = _shape_iy - y;
|
_shape_cur_y16 = _shape_iy - y;
|
||||||
|
|
||||||
a = _shape_ix + ((_rotData[0] * _shape_cur_x16 + _rotData[1] * _shape_cur_y16) >> 8);
|
a = _shape_ix + ((_rotMat[0] * _shape_cur_x16 + _rotMat[1] * _shape_cur_y16) >> 8);
|
||||||
if (_shape_count == 0) {
|
if (_shape_count == 0) {
|
||||||
_shape_ox = a;
|
_shape_ox = a;
|
||||||
}
|
}
|
||||||
_shape_cur_x = shape_last_x = a;
|
_shape_cur_x = shape_last_x = a;
|
||||||
a = _shape_iy + ((_rotData[2] * _shape_cur_x16 + _rotData[3] * _shape_cur_y16) >> 8);
|
a = _shape_iy + ((_rotMat[2] * _shape_cur_x16 + _rotMat[3] * _shape_cur_y16) >> 8);
|
||||||
if (_shape_count == 0) {
|
if (_shape_count == 0) {
|
||||||
_shape_oy = a;
|
_shape_oy = a;
|
||||||
}
|
}
|
||||||
|
@ -712,10 +712,10 @@ void Cutscene::drawShapeScaleRotate(const uint8_t *data, int16_t zoom, int16_t b
|
||||||
sx = 0;
|
sx = 0;
|
||||||
_shape_cur_x16 = _shape_ix - ix;
|
_shape_cur_x16 = _shape_ix - ix;
|
||||||
_shape_cur_y16 = _shape_iy - iy;
|
_shape_cur_y16 = _shape_iy - iy;
|
||||||
a = _shape_ix + ((_rotData[0] * _shape_cur_x16 + _rotData[1] * _shape_cur_y16) >> 8);
|
a = _shape_ix + ((_rotMat[0] * _shape_cur_x16 + _rotMat[1] * _shape_cur_y16) >> 8);
|
||||||
pt2->x = a - shape_last_x;
|
pt2->x = a - shape_last_x;
|
||||||
shape_last_x = a;
|
shape_last_x = a;
|
||||||
a = _shape_iy + ((_rotData[2] * _shape_cur_x16 + _rotData[3] * _shape_cur_y16) >> 8);
|
a = _shape_iy + ((_rotMat[2] * _shape_cur_x16 + _rotMat[3] * _shape_cur_y16) >> 8);
|
||||||
pt2->y = a - shape_last_y;
|
pt2->y = a - shape_last_y;
|
||||||
shape_last_y = a;
|
shape_last_y = a;
|
||||||
++pt2;
|
++pt2;
|
||||||
|
@ -786,7 +786,7 @@ void Cutscene::op_drawShapeScaleRotate() {
|
||||||
if (shapeOffset & 0x1000) {
|
if (shapeOffset & 0x1000) {
|
||||||
r3 = fetchNextCmdWord();
|
r3 = fetchNextCmdWord();
|
||||||
}
|
}
|
||||||
initRotationData(r1, r2, r3);
|
setRotationTransform(r1, r2, r3);
|
||||||
|
|
||||||
const uint8_t *shapeOffsetTable = _polPtr + READ_BE_UINT16(_polPtr + 0x02);
|
const uint8_t *shapeOffsetTable = _polPtr + READ_BE_UINT16(_polPtr + 0x02);
|
||||||
const uint8_t *shapeDataTable = _polPtr + READ_BE_UINT16(_polPtr + 0x0E);
|
const uint8_t *shapeDataTable = _polPtr + READ_BE_UINT16(_polPtr + 0x0E);
|
||||||
|
@ -822,7 +822,7 @@ void Cutscene::op_drawCreditsText() {
|
||||||
if (_textCurBuf == _textBuf) {
|
if (_textCurBuf == _textBuf) {
|
||||||
++_creditsTextCounter;
|
++_creditsTextCounter;
|
||||||
}
|
}
|
||||||
memcpy(_page1, _page0, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_page1, _page0, _vid->_layerSize);
|
||||||
_frameDelay = 10;
|
_frameDelay = 10;
|
||||||
setPalette();
|
setPalette();
|
||||||
}
|
}
|
||||||
|
@ -842,7 +842,7 @@ void Cutscene::op_drawStringAtPos() {
|
||||||
// workaround for buggy cutscene script
|
// workaround for buggy cutscene script
|
||||||
if (_id == 0x34 && (strId & 0xFFF) == 0x45) {
|
if (_id == 0x34 && (strId & 0xFFF) == 0x45) {
|
||||||
if ((_cmdPtr - _cmdPtrBak) == 0xA) {
|
if ((_cmdPtr - _cmdPtrBak) == 0xA) {
|
||||||
_stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _page1, 256);
|
_stub->copyRect(0, 0, _vid->_w, _vid->_h, _page1, 256);
|
||||||
_stub->updateScreen(0);
|
_stub->updateScreen(0);
|
||||||
} else {
|
} else {
|
||||||
_stub->sleep(15);
|
_stub->sleep(15);
|
||||||
|
@ -965,7 +965,7 @@ void Cutscene::load(uint16_t cutName) {
|
||||||
}
|
}
|
||||||
_res->load(name, Resource::OT_CMP);
|
_res->load(name, Resource::OT_CMP);
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
_res->load(name, Resource::OT_CMD);
|
_res->load(name, Resource::OT_CMD);
|
||||||
_res->load(name, Resource::OT_POL);
|
_res->load(name, Resource::OT_POL);
|
||||||
_res->load_CINE();
|
_res->load_CINE();
|
||||||
|
@ -1019,6 +1019,31 @@ void Cutscene::play() {
|
||||||
prepare();
|
prepare();
|
||||||
uint16_t cutName = _offsetsTable[_id * 2 + 0];
|
uint16_t cutName = _offsetsTable[_id * 2 + 0];
|
||||||
uint16_t cutOff = _offsetsTable[_id * 2 + 1];
|
uint16_t cutOff = _offsetsTable[_id * 2 + 1];
|
||||||
|
if (cutName == 0xFFFF && g_options.play_disabled_cutscenes) {
|
||||||
|
switch (_id) {
|
||||||
|
case 19:
|
||||||
|
cutName = 31; // SERRURE
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
case 23:
|
||||||
|
case 24:
|
||||||
|
cutName = 12; // ASC
|
||||||
|
break;
|
||||||
|
case 30:
|
||||||
|
case 31:
|
||||||
|
cutName = 14; // METRO
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_patchedOffsetsTable) {
|
||||||
|
for (int i = 0; _patchedOffsetsTable[i] != 255; i += 3) {
|
||||||
|
if (_patchedOffsetsTable[i] == _id) {
|
||||||
|
cutName = _patchedOffsetsTable[i + 1];
|
||||||
|
cutOff = _patchedOffsetsTable[i + 2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (cutName != 0xFFFF) {
|
if (cutName != 0xFFFF) {
|
||||||
load(cutName);
|
load(cutName);
|
||||||
mainLoop(cutOff);
|
mainLoop(cutOff);
|
||||||
|
|
25
cutscene.h
25
cutscene.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CUTSCENE_H__
|
#ifndef CUTSCENE_H__
|
||||||
|
@ -36,6 +25,7 @@ struct Cutscene {
|
||||||
static const OpcodeStub _opcodeTable[];
|
static const OpcodeStub _opcodeTable[];
|
||||||
static const char *_namesTable[];
|
static const char *_namesTable[];
|
||||||
static const uint16_t _offsetsTable[];
|
static const uint16_t _offsetsTable[];
|
||||||
|
static const uint8_t _amigaDemoOffsetsTable[];
|
||||||
static const uint16_t _cosTable[];
|
static const uint16_t _cosTable[];
|
||||||
static const uint16_t _sinTable[];
|
static const uint16_t _sinTable[];
|
||||||
static const uint8_t _creditsData[];
|
static const uint8_t _creditsData[];
|
||||||
|
@ -47,6 +37,7 @@ struct Cutscene {
|
||||||
Resource *_res;
|
Resource *_res;
|
||||||
SystemStub *_stub;
|
SystemStub *_stub;
|
||||||
Video *_vid;
|
Video *_vid;
|
||||||
|
const uint8_t *_patchedOffsetsTable;
|
||||||
|
|
||||||
uint16_t _id;
|
uint16_t _id;
|
||||||
uint16_t _deathCutsceneId;
|
uint16_t _deathCutsceneId;
|
||||||
|
@ -61,7 +52,7 @@ struct Cutscene {
|
||||||
uint8_t _palBuf[0x20 * 2];
|
uint8_t _palBuf[0x20 * 2];
|
||||||
uint16_t _startOffset;
|
uint16_t _startOffset;
|
||||||
bool _creditsSequence;
|
bool _creditsSequence;
|
||||||
uint32_t _rotData[4];
|
uint32_t _rotMat[4];
|
||||||
uint8_t _primitiveColor;
|
uint8_t _primitiveColor;
|
||||||
uint8_t _clearScreen;
|
uint8_t _clearScreen;
|
||||||
Point _vertices[0x80];
|
Point _vertices[0x80];
|
||||||
|
@ -97,7 +88,7 @@ struct Cutscene {
|
||||||
void copyPalette(const uint8_t *pal, uint16_t num);
|
void copyPalette(const uint8_t *pal, uint16_t num);
|
||||||
void updatePalette();
|
void updatePalette();
|
||||||
void setPalette();
|
void setPalette();
|
||||||
void initRotationData(uint16_t a, uint16_t b, uint16_t c);
|
void setRotationTransform(uint16_t a, uint16_t b, uint16_t c);
|
||||||
uint16_t findTextSeparators(const uint8_t *p);
|
uint16_t findTextSeparators(const uint8_t *p);
|
||||||
void drawText(int16_t x, int16_t y, const uint8_t *p, uint16_t color, uint8_t *page, uint8_t n);
|
void drawText(int16_t x, int16_t y, const uint8_t *p, uint16_t color, uint8_t *page, uint8_t n);
|
||||||
void swapLayers();
|
void swapLayers();
|
||||||
|
|
26
file.cpp
26
file.cpp
|
@ -1,26 +1,16 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include "file.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
#include "util.h"
|
||||||
#ifdef USE_ZLIB
|
#ifdef USE_ZLIB
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
#endif
|
#endif
|
||||||
#include "file.h"
|
|
||||||
|
|
||||||
|
|
||||||
struct File_impl {
|
struct File_impl {
|
||||||
bool _ioErr;
|
bool _ioErr;
|
||||||
|
@ -183,7 +173,7 @@ bool File::open(const char *filename, const char *mode, const char *directory) {
|
||||||
if (!_impl) {
|
if (!_impl) {
|
||||||
_impl = new stdFile;
|
_impl = new stdFile;
|
||||||
}
|
}
|
||||||
char path[512];
|
char path[MAXPATHLEN];
|
||||||
snprintf(path, sizeof(path), "%s/%s", directory, filename);
|
snprintf(path, sizeof(path), "%s/%s", directory, filename);
|
||||||
debug(DBG_FILE, "Open file name '%s' mode '%s' path '%s'", filename, mode, path);
|
debug(DBG_FILE, "Open file name '%s' mode '%s' path '%s'", filename, mode, path);
|
||||||
return _impl->open(path, mode);
|
return _impl->open(path, mode);
|
||||||
|
|
19
file.h
19
file.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FILE_H__
|
#ifndef FILE_H__
|
||||||
|
|
23
fs.cpp
23
fs.cpp
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -21,8 +10,10 @@
|
||||||
#else
|
#else
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#endif
|
#endif
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
struct FileName {
|
struct FileName {
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -129,7 +120,7 @@ void FileSystem_impl::getPathListFromDirectory(const char *dir) {
|
||||||
if (de->d_name[0] == '.') {
|
if (de->d_name[0] == '.') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char filePath[512];
|
char filePath[MAXPATHLEN];
|
||||||
snprintf(filePath, sizeof(filePath), "%s/%s", dir, de->d_name);
|
snprintf(filePath, sizeof(filePath), "%s/%s", dir, de->d_name);
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(filePath, &st) == 0) {
|
if (stat(filePath, &st) == 0) {
|
||||||
|
|
19
fs.h
19
fs.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FS_H__
|
#ifndef FS_H__
|
||||||
|
|
234
game.cpp
234
game.cpp
|
@ -1,28 +1,17 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "systemstub.h"
|
|
||||||
#include "unpack.h"
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "seq_player.h"
|
#include "seq_player.h"
|
||||||
|
#include "systemstub.h"
|
||||||
|
#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)
|
||||||
: _cut(&_res, stub, &_vid), _menu(&_res, stub, &_vid),
|
: _cut(&_res, stub, &_vid), _menu(&_res, stub, &_vid),
|
||||||
|
@ -32,41 +21,38 @@ Game::Game(SystemStub *stub, FileSystem *fs, const char *savePath, int level, Re
|
||||||
_inp_demo = 0;
|
_inp_demo = 0;
|
||||||
_inp_record = false;
|
_inp_record = false;
|
||||||
_inp_replay = false;
|
_inp_replay = false;
|
||||||
_skillLevel = 1;
|
_skillLevel = _menu._skill = 1;
|
||||||
_currentLevel = level;
|
_currentLevel = _menu._level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::run() {
|
void Game::run() {
|
||||||
_stub->init(g_caption, Video::GAMESCREEN_W, Video::GAMESCREEN_H);
|
|
||||||
|
|
||||||
_randSeed = time(0);
|
_randSeed = time(0);
|
||||||
|
|
||||||
|
_res.init();
|
||||||
_res.load_TEXT();
|
_res.load_TEXT();
|
||||||
|
|
||||||
switch (_res._type) {
|
switch (_res._type) {
|
||||||
case kResourceTypeAmiga:
|
case kResourceTypeAmiga:
|
||||||
_res.load("FONT8", Resource::OT_FNT, "SPR");
|
_res.load("FONT8", Resource::OT_FNT, "SPR");
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
_res.load("FB_TXT", Resource::OT_FNT);
|
_res.load("FB_TXT", Resource::OT_FNT);
|
||||||
_res._hasSeqData = _fs->exists("INTRO.SEQ");
|
_res._hasSeqData = _fs->exists("INTRO.SEQ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BYPASS_PROTECTION
|
if (!g_options.bypass_protection) {
|
||||||
while (!handleProtectionScreen());
|
while (!handleProtectionScreen());
|
||||||
if (_stub->_pi.quit) {
|
if (_stub->_pi.quit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
|
||||||
_mix.init();
|
_mix.init();
|
||||||
|
_mix._mod._isAmiga = _res.isAmiga();
|
||||||
|
|
||||||
playCutscene(0x40);
|
playCutscene(0x40);
|
||||||
playCutscene(0x0D);
|
playCutscene(0x0D);
|
||||||
if (!_cut._interrupted && _res._type == kResourceTypePC) {
|
|
||||||
playCutscene(0x4A);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (_res._type) {
|
switch (_res._type) {
|
||||||
case kResourceTypeAmiga:
|
case kResourceTypeAmiga:
|
||||||
|
@ -74,7 +60,7 @@ void Game::run() {
|
||||||
_res.load("ICON", Resource::OT_ICN, "SPR");
|
_res.load("ICON", Resource::OT_ICN, "SPR");
|
||||||
_res.load("PERSO", Resource::OT_SPM);
|
_res.load("PERSO", Resource::OT_SPM);
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
_res.load("GLOBAL", Resource::OT_ICN);
|
_res.load("GLOBAL", Resource::OT_ICN);
|
||||||
_res.load("GLOBAL", Resource::OT_SPC);
|
_res.load("GLOBAL", Resource::OT_SPC);
|
||||||
_res.load("PERSO", Resource::OT_SPR);
|
_res.load("PERSO", Resource::OT_SPR);
|
||||||
|
@ -83,12 +69,20 @@ void Game::run() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_res.isAmiga()) {
|
||||||
|
displayTitleScreenAmiga();
|
||||||
|
_stub->setScreenSize(Video::GAMESCREEN_W, Video::GAMESCREEN_H);
|
||||||
|
}
|
||||||
|
|
||||||
while (!_stub->_pi.quit) {
|
while (!_stub->_pi.quit) {
|
||||||
if (_res._type == kResourceTypePC) {
|
if (_res.isDOS()) {
|
||||||
_mix.playMusic(1);
|
_mix.playMusic(1);
|
||||||
if (!_menu.handleTitleScreen(_skillLevel, _currentLevel)) {
|
_menu.handleTitleScreen();
|
||||||
|
if (_menu._selectedOption == Menu::MENU_OPTION_ITEM_QUIT) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
_skillLevel = _menu._skill;
|
||||||
|
_currentLevel = _menu._level;
|
||||||
_mix.stopMusic();
|
_mix.stopMusic();
|
||||||
}
|
}
|
||||||
if (_currentLevel == 7) {
|
if (_currentLevel == 7) {
|
||||||
|
@ -105,6 +99,7 @@ void Game::run() {
|
||||||
loadLevelData();
|
loadLevelData();
|
||||||
resetGameState();
|
resetGameState();
|
||||||
_endLoop = false;
|
_endLoop = false;
|
||||||
|
_frameTimestamp = _stub->getTimeStamp();
|
||||||
while (!_stub->_pi.quit && !_endLoop) {
|
while (!_stub->_pi.quit && !_endLoop) {
|
||||||
mainLoop();
|
mainLoop();
|
||||||
}
|
}
|
||||||
|
@ -112,9 +107,45 @@ void Game::run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_res.free_TEXT();
|
_res.free_TEXT();
|
||||||
|
|
||||||
_mix.free();
|
_mix.free();
|
||||||
_stub->destroy();
|
_res.fini();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::displayTitleScreenAmiga() {
|
||||||
|
static const char *FILENAME = "present.cmp";
|
||||||
|
_res.load_CMP_menu(FILENAME, _res._memBuf);
|
||||||
|
static const int kW = 320;
|
||||||
|
static const int kH = 224;
|
||||||
|
uint8_t *buf = (uint8_t *)malloc(kW * kH);
|
||||||
|
if (!buf) {
|
||||||
|
error("Failed to allocate screen buffer w=%d h=%d", kW, kH);
|
||||||
|
}
|
||||||
|
_vid.AMIGA_decodeCmp(_res._memBuf + 6, buf);
|
||||||
|
static const int kAmigaColors[] = {
|
||||||
|
0x000, 0x123, 0x012, 0x134, 0x433, 0x453, 0x046, 0x245,
|
||||||
|
0x751, 0x455, 0x665, 0x268, 0x961, 0x478, 0x677, 0x786,
|
||||||
|
0x17B, 0x788, 0xB84, 0xC92, 0x49C, 0xF00, 0x9A8, 0x9AA,
|
||||||
|
0xCA7, 0xEA3, 0x8BD, 0xBBB, 0xEC7, 0xBCD, 0xDDB, 0xEED
|
||||||
|
};
|
||||||
|
for (int i = 0; i < 32; ++i) {
|
||||||
|
Color c = Video::AMIGA_convertColor(kAmigaColors[i]);
|
||||||
|
_stub->setPaletteEntry(i, &c);
|
||||||
|
}
|
||||||
|
_stub->setScreenSize(kW, kH);
|
||||||
|
_stub->copyRect(0, 0, kW, kH, buf, kW);
|
||||||
|
_stub->updateScreen(0);
|
||||||
|
free(buf);
|
||||||
|
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() {
|
||||||
|
@ -166,7 +197,7 @@ void Game::mainLoop() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy(_vid._frontLayer, _vid._backLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_vid._frontLayer, _vid._backLayer, _vid._layerSize);
|
||||||
pge_getInput();
|
pge_getInput();
|
||||||
pge_prepare();
|
pge_prepare();
|
||||||
col_prepareRoomState();
|
col_prepareRoomState();
|
||||||
|
@ -221,14 +252,14 @@ void Game::mainLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::updateTiming() {
|
void Game::updateTiming() {
|
||||||
static uint32_t tstamp = 0;
|
static const int frameHz = 30;
|
||||||
int32_t delay = _stub->getTimeStamp() - tstamp;
|
int32_t delay = _stub->getTimeStamp() - _frameTimestamp;
|
||||||
int32_t pause = (_stub->_pi.dbgMask & PlayerInput::DF_FASTMODE) ? 20 : 30;
|
int32_t pause = (_stub->_pi.dbgMask & PlayerInput::DF_FASTMODE) ? 20 : (1000 / frameHz);
|
||||||
pause -= delay;
|
pause -= delay;
|
||||||
if (pause > 0) {
|
if (pause > 0) {
|
||||||
_stub->sleep(pause);
|
_stub->sleep(pause);
|
||||||
}
|
}
|
||||||
tstamp = _stub->getTimeStamp();
|
_frameTimestamp = _stub->getTimeStamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::playCutscene(int id) {
|
void Game::playCutscene(int id) {
|
||||||
|
@ -292,13 +323,15 @@ void Game::playCutscene(int id) {
|
||||||
_mix.playMusic(Cutscene::_musicTable[_cut._id]);
|
_mix.playMusic(Cutscene::_musicTable[_cut._id]);
|
||||||
}
|
}
|
||||||
_cut.play();
|
_cut.play();
|
||||||
|
if (id == 0xD && !_cut._interrupted && _res.isDOS()) {
|
||||||
|
_cut._id = 0x4A;
|
||||||
|
_cut.play();
|
||||||
|
}
|
||||||
if (id == 0x3D) {
|
if (id == 0x3D) {
|
||||||
_cut.startCredits();
|
_cut.startCredits();
|
||||||
}
|
}
|
||||||
if (_cut._interrupted || id != 0x0D) {
|
|
||||||
_mix.stopMusic();
|
_mix.stopMusic();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Game::playCutsceneSeq(const char *name) {
|
bool Game::playCutsceneSeq(const char *name) {
|
||||||
|
@ -348,7 +381,8 @@ void Game::inp_handleSpecialKeys() {
|
||||||
} else {
|
} else {
|
||||||
if (_inp_demo->open(demoFile, "zwb", _savePath)) {
|
if (_inp_demo->open(demoFile, "zwb", _savePath)) {
|
||||||
debug(DBG_INFO, "Recording input keys");
|
debug(DBG_INFO, "Recording input keys");
|
||||||
_inp_demo->writeUint32BE('FBDM');
|
static const uint32_t TAG_FBDM = 0x4642444D;
|
||||||
|
_inp_demo->writeUint32BE(TAG_FBDM);
|
||||||
_inp_demo->writeUint16BE(0);
|
_inp_demo->writeUint16BE(0);
|
||||||
_inp_demo->writeUint32BE(_randSeed);
|
_inp_demo->writeUint32BE(_randSeed);
|
||||||
record = true;
|
record = true;
|
||||||
|
@ -395,7 +429,7 @@ void Game::showFinalScore() {
|
||||||
strcpy(buf, _menu._passwords[7][_skillLevel]);
|
strcpy(buf, _menu._passwords[7][_skillLevel]);
|
||||||
_vid.drawString(buf, (256 - strlen(buf) * 8) / 2, 16, 0xE7);
|
_vid.drawString(buf, (256 - strlen(buf) * 8) / 2, 16, 0xE7);
|
||||||
while (!_stub->_pi.quit) {
|
while (!_stub->_pi.quit) {
|
||||||
_stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _vid._frontLayer, 256);
|
_stub->copyRect(0, 0, _vid._w, _vid._h, _vid._frontLayer, 256);
|
||||||
_stub->updateScreen(0);
|
_stub->updateScreen(0);
|
||||||
_stub->processEvents();
|
_stub->processEvents();
|
||||||
if (_stub->_pi.enter) {
|
if (_stub->_pi.enter) {
|
||||||
|
@ -407,7 +441,7 @@ void Game::showFinalScore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Game::handleConfigPanel() {
|
bool Game::handleConfigPanel() {
|
||||||
if (_res._type == kResourceTypeAmiga) {
|
if (_res.isAmiga()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const int x = 7;
|
const int x = 7;
|
||||||
|
@ -499,6 +533,10 @@ bool Game::handleConfigPanel() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (_stub->_pi.escape) {
|
||||||
|
_stub->_pi.escape = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_vid.fullRefresh();
|
_vid.fullRefresh();
|
||||||
return (current == MENU_ITEM_ABORT);
|
return (current == MENU_ITEM_ABORT);
|
||||||
|
@ -512,7 +550,7 @@ bool Game::handleContinueAbort() {
|
||||||
uint8_t color_inc = 0xFF;
|
uint8_t color_inc = 0xFF;
|
||||||
Color col;
|
Color col;
|
||||||
_stub->getPaletteEntry(0xE4, &col);
|
_stub->getPaletteEntry(0xE4, &col);
|
||||||
memcpy(_vid._tempLayer, _vid._frontLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_vid._tempLayer, _vid._frontLayer, _vid._layerSize);
|
||||||
while (timeout >= 0 && !_stub->_pi.quit) {
|
while (timeout >= 0 && !_stub->_pi.quit) {
|
||||||
const char *str;
|
const char *str;
|
||||||
str = _res.getMenuString(LocaleData::LI_01_CONTINUE_OR_ABORT);
|
str = _res.getMenuString(LocaleData::LI_01_CONTINUE_OR_ABORT);
|
||||||
|
@ -545,26 +583,28 @@ bool Game::handleContinueAbort() {
|
||||||
_stub->_pi.enter = false;
|
_stub->_pi.enter = false;
|
||||||
return (current_color == 0);
|
return (current_color == 0);
|
||||||
}
|
}
|
||||||
_stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _vid._frontLayer, 256);
|
_stub->copyRect(0, 0, _vid._w, _vid._h, _vid._frontLayer, 256);
|
||||||
_stub->updateScreen(0);
|
_stub->updateScreen(0);
|
||||||
if (col.b >= 0x3D) {
|
static const int COLOR_STEP = 8;
|
||||||
|
static const int COLOR_MIN = 16;
|
||||||
|
static const int COLOR_MAX = 256 - 16;
|
||||||
|
if (col.b >= COLOR_MAX) {
|
||||||
color_inc = 0;
|
color_inc = 0;
|
||||||
}
|
} else if (col.b < COLOR_MIN) {
|
||||||
if (col.b < 2) {
|
|
||||||
color_inc = 0xFF;
|
color_inc = 0xFF;
|
||||||
}
|
}
|
||||||
if (color_inc == 0xFF) {
|
if (color_inc == 0xFF) {
|
||||||
col.b += 2;
|
col.b += COLOR_STEP;
|
||||||
col.g += 2;
|
col.g += COLOR_STEP;
|
||||||
} else {
|
} else {
|
||||||
col.b -= 2;
|
col.b -= COLOR_STEP;
|
||||||
col.g -= 2;
|
col.g -= COLOR_STEP;
|
||||||
}
|
}
|
||||||
_stub->setPaletteEntry(0xE4, &col);
|
_stub->setPaletteEntry(0xE4, &col);
|
||||||
_stub->processEvents();
|
_stub->processEvents();
|
||||||
_stub->sleep(100);
|
_stub->sleep(100);
|
||||||
--timeout;
|
--timeout;
|
||||||
memcpy(_vid._frontLayer, _vid._tempLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_vid._frontLayer, _vid._tempLayer, _vid._layerSize);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -584,7 +624,7 @@ bool Game::handleProtectionScreen() {
|
||||||
int shapeNum = getRandomNumber() % 30;
|
int shapeNum = getRandomNumber() % 30;
|
||||||
for (int16_t zoom = 2000; zoom != 0; zoom -= 100) {
|
for (int16_t zoom = 2000; zoom != 0; zoom -= 100) {
|
||||||
_cut.drawProtectionShape(shapeNum, zoom);
|
_cut.drawProtectionShape(shapeNum, zoom);
|
||||||
_stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _vid._tempLayer, 256);
|
_stub->copyRect(0, 0, _vid._w, _vid._h, _vid._tempLayer, 256);
|
||||||
_stub->updateScreen(0);
|
_stub->updateScreen(0);
|
||||||
_stub->sleep(30);
|
_stub->sleep(30);
|
||||||
}
|
}
|
||||||
|
@ -595,7 +635,7 @@ bool Game::handleProtectionScreen() {
|
||||||
int len = 0;
|
int len = 0;
|
||||||
do {
|
do {
|
||||||
codeText[len] = '\0';
|
codeText[len] = '\0';
|
||||||
memcpy(_vid._frontLayer, _vid._tempLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_vid._frontLayer, _vid._tempLayer, _vid._layerSize);
|
||||||
_menu.drawString("PROTECTION", 2, 11, 5);
|
_menu.drawString("PROTECTION", 2, 11, 5);
|
||||||
char buf[20];
|
char buf[20];
|
||||||
snprintf(buf, sizeof(buf), "CODE %d : %s", codeNum + 1, codeText);
|
snprintf(buf, sizeof(buf), "CODE %d : %s", codeNum + 1, codeText);
|
||||||
|
@ -654,7 +694,7 @@ void Game::printLevelCode() {
|
||||||
if (_printLevelCodeCounter != 0) {
|
if (_printLevelCodeCounter != 0) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
snprintf(buf, sizeof(buf), "CODE: %s", _menu._passwords[_currentLevel][_skillLevel]);
|
snprintf(buf, sizeof(buf), "CODE: %s", _menu._passwords[_currentLevel][_skillLevel]);
|
||||||
_vid.drawString(buf, (Video::GAMESCREEN_W - strlen(buf) * 8) / 2, 16, 0xE7);
|
_vid.drawString(buf, (_vid._w - strlen(buf) * 8) / 2, 16, 0xE7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -678,7 +718,7 @@ void Game::drawLevelTexts() {
|
||||||
uint8_t icon_num = obj - 1;
|
uint8_t icon_num = obj - 1;
|
||||||
drawIcon(icon_num, 80, 8, 0xA);
|
drawIcon(icon_num, 80, 8, 0xA);
|
||||||
uint8_t txt_num = pge->init_PGE->text_num;
|
uint8_t txt_num = pge->init_PGE->text_num;
|
||||||
const char *str = (const char *)_res._tbn + READ_LE_UINT16(_res._tbn + txt_num * 2);
|
const char *str = (const char *)_res.getTextString(txt_num);
|
||||||
_vid.drawString(str, (176 - strlen(str) * 8) / 2, 26, 0xE6);
|
_vid.drawString(str, (176 - strlen(str) * 8) / 2, 26, 0xE6);
|
||||||
if (icon_num == 2) {
|
if (icon_num == 2) {
|
||||||
printSaveStateCompleted();
|
printSaveStateCompleted();
|
||||||
|
@ -695,7 +735,7 @@ void Game::drawStoryTexts() {
|
||||||
if (_textToDisplay != 0xFFFF) {
|
if (_textToDisplay != 0xFFFF) {
|
||||||
uint16_t text_col_mask = 0xE8;
|
uint16_t text_col_mask = 0xE8;
|
||||||
const uint8_t *str = _res.getGameString(_textToDisplay);
|
const uint8_t *str = _res.getGameString(_textToDisplay);
|
||||||
memcpy(_vid._tempLayer, _vid._frontLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_vid._tempLayer, _vid._frontLayer, _vid._layerSize);
|
||||||
int textSpeechSegment = 0;
|
int textSpeechSegment = 0;
|
||||||
while (!_stub->_pi.quit) {
|
while (!_stub->_pi.quit) {
|
||||||
drawIcon(_currentInventoryIconNum, 80, 8, 0xA);
|
drawIcon(_currentInventoryIconNum, 80, 8, 0xA);
|
||||||
|
@ -735,7 +775,7 @@ void Game::drawStoryTexts() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++str;
|
++str;
|
||||||
memcpy(_vid._frontLayer, _vid._tempLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_vid._frontLayer, _vid._tempLayer, _vid._layerSize);
|
||||||
}
|
}
|
||||||
_textToDisplay = 0xFFFF;
|
_textToDisplay = 0xFFFF;
|
||||||
}
|
}
|
||||||
|
@ -811,7 +851,7 @@ void Game::prepareAnimsHelper(LivePGE *pge, int16_t dx, int16_t dy) {
|
||||||
w = ((dataPtr[2] >> 7) + 1) * 16;
|
w = ((dataPtr[2] >> 7) + 1) * 16;
|
||||||
h = dataPtr[2] & 0x7F;
|
h = dataPtr[2] & 0x7F;
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
w = dataPtr[2];
|
w = dataPtr[2];
|
||||||
h = dataPtr[3];
|
h = dataPtr[3];
|
||||||
dataPtr += 4;
|
dataPtr += 4;
|
||||||
|
@ -885,7 +925,7 @@ void Game::drawAnimBuffer(uint8_t stateNum, AnimBufferState *state) {
|
||||||
_vid.AMIGA_decodeSpm(state->dataPtr, _res._memBuf);
|
_vid.AMIGA_decodeSpm(state->dataPtr, _res._memBuf);
|
||||||
drawCharacter(_res._memBuf, state->x, state->y, state->h, state->w, pge->flags);
|
drawCharacter(_res._memBuf, state->x, state->y, state->h, state->w, pge->flags);
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
if (!(state->dataPtr[-2] & 0x80)) {
|
if (!(state->dataPtr[-2] & 0x80)) {
|
||||||
decodeCharacterFrame(state->dataPtr, _res._memBuf);
|
decodeCharacterFrame(state->dataPtr, _res._memBuf);
|
||||||
drawCharacter(_res._memBuf, state->x, state->y, state->h, state->w, pge->flags);
|
drawCharacter(_res._memBuf, state->x, state->y, state->h, state->w, pge->flags);
|
||||||
|
@ -923,7 +963,7 @@ void Game::drawObject(const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t flag
|
||||||
count = dataPtr[8];
|
count = dataPtr[8];
|
||||||
dataPtr += 9;
|
dataPtr += 9;
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
count = dataPtr[5];
|
count = dataPtr[5];
|
||||||
dataPtr += 6;
|
dataPtr += 6;
|
||||||
break;
|
break;
|
||||||
|
@ -956,13 +996,9 @@ void Game::drawObjectFrame(const uint8_t *bankDataPtr, const uint8_t *dataPtr, i
|
||||||
|
|
||||||
switch (_res._type) {
|
switch (_res._type) {
|
||||||
case kResourceTypeAmiga:
|
case kResourceTypeAmiga:
|
||||||
if (sprite_w == 24) {
|
|
||||||
// TODO: fix p24xN
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_vid.AMIGA_decodeSpc(src, sprite_w, sprite_h, _res._memBuf);
|
_vid.AMIGA_decodeSpc(src, sprite_w, sprite_h, _res._memBuf);
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
_vid.PC_decodeSpc(src, sprite_w, sprite_h, _res._memBuf);
|
_vid.PC_decodeSpc(src, sprite_w, sprite_h, _res._memBuf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1197,10 +1233,10 @@ int Game::loadMonsterSprites(LivePGE *pge) {
|
||||||
_curMonsterFrame = mList[0];
|
_curMonsterFrame = mList[0];
|
||||||
if (_curMonsterNum != mList[1]) {
|
if (_curMonsterNum != mList[1]) {
|
||||||
_curMonsterNum = mList[1];
|
_curMonsterNum = mList[1];
|
||||||
if (_res._type == kResourceTypeAmiga) {
|
if (_res.isAmiga()) {
|
||||||
_res.load(_monsterNames[1][_curMonsterNum], Resource::OT_SPM);
|
_res.load(_monsterNames[1][_curMonsterNum], Resource::OT_SPM);
|
||||||
static const uint8_t tab[4] = { 0, 8, 0, 8 };
|
static const uint8_t tab[4] = { 0, 8, 0, 8 };
|
||||||
const int offset = _vid._mapPalSlot2 * 16 + tab[_curMonsterNum];
|
const int offset = _vid._mapPalSlot3 * 16 + tab[_curMonsterNum];
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
_vid.setPaletteColorBE(0x50 + i, offset + i);
|
_vid.setPaletteColorBE(0x50 + i, offset + i);
|
||||||
}
|
}
|
||||||
|
@ -1220,15 +1256,23 @@ void Game::loadLevelMap() {
|
||||||
switch (_res._type) {
|
switch (_res._type) {
|
||||||
case kResourceTypeAmiga:
|
case kResourceTypeAmiga:
|
||||||
if (_currentLevel == 1) {
|
if (_currentLevel == 1) {
|
||||||
static const uint8_t tab[64] = {
|
int num = 0;
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0,
|
switch (_currentRoom) {
|
||||||
0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0,
|
case 14:
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
case 19:
|
||||||
0, 0, 0, 0, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
|
case 52:
|
||||||
};
|
case 53:
|
||||||
const int num = tab[_currentRoom];
|
num = 1;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
case 24:
|
||||||
|
case 27:
|
||||||
|
case 56:
|
||||||
|
num = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (num != 0 && _res._levNum != num) {
|
if (num != 0 && _res._levNum != num) {
|
||||||
char name[8];
|
char name[9];
|
||||||
snprintf(name, sizeof(name), "level2_%d", num);
|
snprintf(name, sizeof(name), "level2_%d", num);
|
||||||
_res.load(name, Resource::OT_LEV);
|
_res.load(name, Resource::OT_LEV);
|
||||||
_res._levNum = num;
|
_res._levNum = num;
|
||||||
|
@ -1236,8 +1280,12 @@ void Game::loadLevelMap() {
|
||||||
}
|
}
|
||||||
_vid.AMIGA_decodeLev(_currentLevel, _currentRoom);
|
_vid.AMIGA_decodeLev(_currentLevel, _currentRoom);
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
|
if (_res._map) {
|
||||||
_vid.PC_decodeMap(_currentLevel, _currentRoom);
|
_vid.PC_decodeMap(_currentLevel, _currentRoom);
|
||||||
|
} else if (_res._lev) {
|
||||||
|
_vid.PC_decodeLev(_currentLevel, _currentRoom);
|
||||||
|
}
|
||||||
_vid.PC_setLevelPalettes();
|
_vid.PC_setLevelPalettes();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1248,9 +1296,8 @@ void Game::loadLevelData() {
|
||||||
const Level *lvl = &_gameLevels[_currentLevel];
|
const Level *lvl = &_gameLevels[_currentLevel];
|
||||||
switch (_res._type) {
|
switch (_res._type) {
|
||||||
case kResourceTypeAmiga:
|
case kResourceTypeAmiga:
|
||||||
if (_fs->exists("demo.lev")) { // demo data files
|
if (_res._isDemo) {
|
||||||
Cutscene::_namesTable[1] = "HOLOCUBE";
|
_cut._patchedOffsetsTable = Cutscene::_amigaDemoOffsetsTable;
|
||||||
Cutscene::_namesTable[4] = "CHUTE2";
|
|
||||||
static const char *fname1 = "demo";
|
static const char *fname1 = "demo";
|
||||||
static const char *fname2 = "demof";
|
static const char *fname2 = "demof";
|
||||||
_res.load(fname1, Resource::OT_MBK);
|
_res.load(fname1, Resource::OT_MBK);
|
||||||
|
@ -1301,12 +1348,20 @@ void Game::loadLevelData() {
|
||||||
_res.load(lvl->nameAmiga, Resource::OT_SGD);
|
_res.load(lvl->nameAmiga, Resource::OT_SGD);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
_res.load(lvl->name, Resource::OT_MBK);
|
_res.load(lvl->name, Resource::OT_MBK);
|
||||||
_res.load(lvl->name, Resource::OT_CT);
|
_res.load(lvl->name, Resource::OT_CT);
|
||||||
_res.load(lvl->name, Resource::OT_PAL);
|
_res.load(lvl->name, Resource::OT_PAL);
|
||||||
_res.load(lvl->name, Resource::OT_RP);
|
_res.load(lvl->name, Resource::OT_RP);
|
||||||
|
if (_res._isDemo || g_options.use_tiledata) { // use .BNQ/.LEV/(.SGD) instead of .MAP (PC demo)
|
||||||
|
if (_currentLevel == 0) {
|
||||||
|
_res.load(lvl->name, Resource::OT_SGD);
|
||||||
|
}
|
||||||
|
_res.load(lvl->name, Resource::OT_LEV);
|
||||||
|
_res.load(lvl->name, Resource::OT_BNQ);
|
||||||
|
} else {
|
||||||
_res.load(lvl->name, Resource::OT_MAP);
|
_res.load(lvl->name, Resource::OT_MAP);
|
||||||
|
}
|
||||||
_res.load(lvl->name2, Resource::OT_PGE);
|
_res.load(lvl->name2, Resource::OT_PGE);
|
||||||
_res.load(lvl->name2, Resource::OT_OBJ);
|
_res.load(lvl->name2, Resource::OT_OBJ);
|
||||||
_res.load(lvl->name2, Resource::OT_ANI);
|
_res.load(lvl->name2, Resource::OT_ANI);
|
||||||
|
@ -1315,6 +1370,9 @@ void Game::loadLevelData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_cut._id = lvl->cutscene_id;
|
_cut._id = lvl->cutscene_id;
|
||||||
|
if (_res._isDemo && _currentLevel == 5) { // PC demo does not include TELEPORT.*
|
||||||
|
_cut._id = 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
_curMonsterNum = 0xFFFF;
|
_curMonsterNum = 0xFFFF;
|
||||||
_curMonsterFrame = 0;
|
_curMonsterFrame = 0;
|
||||||
|
@ -1377,7 +1435,7 @@ void Game::drawIcon(uint8_t iconNum, int16_t x, int16_t y, uint8_t colMask) {
|
||||||
_vid.AMIGA_decodeIcn(_res._icn, iconNum, buf);
|
_vid.AMIGA_decodeIcn(_res._icn, iconNum, buf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
_vid.PC_decodeIcn(_res._icn, iconNum, buf);
|
_vid.PC_decodeIcn(_res._icn, iconNum, buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1392,7 +1450,7 @@ void Game::playSound(uint8_t sfxId, uint8_t softVol) {
|
||||||
MixerChunk mc;
|
MixerChunk mc;
|
||||||
mc.data = sfx->data;
|
mc.data = sfx->data;
|
||||||
mc.len = sfx->len;
|
mc.len = sfx->len;
|
||||||
const int freq = _res._type == kResourceTypeAmiga ? 3546897 / 650 : 6000;
|
const int freq = _res.isAmiga() ? 3546897 / 650 : 6000;
|
||||||
_mix.play(&mc, freq, Mixer::MAX_VOLUME >> softVol);
|
_mix.play(&mc, freq, Mixer::MAX_VOLUME >> softVol);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1476,7 +1534,7 @@ void Game::handleInventory() {
|
||||||
drawIcon(76, icon_x_pos, 157, 0xA);
|
drawIcon(76, icon_x_pos, 157, 0xA);
|
||||||
selected_pge = items[item_it].live_pge;
|
selected_pge = items[item_it].live_pge;
|
||||||
uint8_t txt_num = items[item_it].init_pge->text_num;
|
uint8_t txt_num = items[item_it].init_pge->text_num;
|
||||||
const char *str = (const char *)_res._tbn + READ_LE_UINT16(_res._tbn + txt_num * 2);
|
const char *str = (const char *)_res.getTextString(txt_num);
|
||||||
_vid.drawString(str, (256 - strlen(str) * 8) / 2, 189, 0xED);
|
_vid.drawString(str, (256 - strlen(str) * 8) / 2, 189, 0xED);
|
||||||
if (items[item_it].init_pge->init_flags & 4) {
|
if (items[item_it].init_pge->init_flags & 4) {
|
||||||
char buf[10];
|
char buf[10];
|
||||||
|
@ -1593,6 +1651,8 @@ void Game::makeGameStateName(uint8_t slot, char *buf) {
|
||||||
sprintf(buf, "rs-level%d-%02d.state", _currentLevel + 1, slot);
|
sprintf(buf, "rs-level%d-%02d.state", _currentLevel + 1, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const uint32_t TAG_FBSV = 0x46425356;
|
||||||
|
|
||||||
bool Game::saveGameState(uint8_t slot) {
|
bool Game::saveGameState(uint8_t slot) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
char stateFile[20];
|
char stateFile[20];
|
||||||
|
@ -1602,7 +1662,7 @@ bool Game::saveGameState(uint8_t slot) {
|
||||||
warning("Unable to save state file '%s'", stateFile);
|
warning("Unable to save state file '%s'", stateFile);
|
||||||
} else {
|
} else {
|
||||||
// header
|
// header
|
||||||
f.writeUint32BE('FBSV');
|
f.writeUint32BE(TAG_FBSV);
|
||||||
f.writeUint16BE(2);
|
f.writeUint16BE(2);
|
||||||
char buf[32];
|
char buf[32];
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
|
@ -1629,7 +1689,7 @@ bool Game::loadGameState(uint8_t slot) {
|
||||||
warning("Unable to open state file '%s'", stateFile);
|
warning("Unable to open state file '%s'", stateFile);
|
||||||
} else {
|
} else {
|
||||||
uint32_t id = f.readUint32BE();
|
uint32_t id = f.readUint32BE();
|
||||||
if (id != 'FBSV') {
|
if (id != TAG_FBSV) {
|
||||||
warning("Bad save state format");
|
warning("Bad save state format");
|
||||||
} else {
|
} else {
|
||||||
uint16_t ver = f.readUint16BE();
|
uint16_t ver = f.readUint16BE();
|
||||||
|
|
21
game.h
21
game.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GAME_H__
|
#ifndef GAME_H__
|
||||||
|
@ -94,10 +83,12 @@ struct Game {
|
||||||
uint16_t _deathCutsceneCounter;
|
uint16_t _deathCutsceneCounter;
|
||||||
bool _saveStateCompleted;
|
bool _saveStateCompleted;
|
||||||
bool _endLoop;
|
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, ResourceType ver, Language lang);
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
void displayTitleScreenAmiga();
|
||||||
void resetGameState();
|
void resetGameState();
|
||||||
void mainLoop();
|
void mainLoop();
|
||||||
void updateTiming();
|
void updateTiming();
|
||||||
|
|
21
graphics.cpp
21
graphics.cpp
|
@ -1,22 +1,11 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
void Graphics::setClippingRect(int16_t rx, int16_t ry, int16_t rw, int16_t rh) {
|
void Graphics::setClippingRect(int16_t rx, int16_t ry, int16_t rw, int16_t rh) {
|
||||||
debug(DBG_VIDEO, "Graphics::setClippingRect(%d, %d, %d, %d)", rx, ry, rw, rh);
|
debug(DBG_VIDEO, "Graphics::setClippingRect(%d, %d, %d, %d)", rx, ry, rw, rh);
|
||||||
|
|
19
graphics.h
19
graphics.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GRAPHICS_H__
|
#ifndef GRAPHICS_H__
|
||||||
|
|
45
intern.h
45
intern.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef INTERN_H__
|
#ifndef INTERN_H__
|
||||||
|
@ -24,22 +13,19 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "util.h"
|
#ifndef ABS
|
||||||
|
|
||||||
#define ABS(x) ((x)<0?-(x):(x))
|
#define ABS(x) ((x)<0?-(x):(x))
|
||||||
|
#endif
|
||||||
|
#ifndef MAX
|
||||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
#define MAX(x,y) ((x)>(y)?(x):(y))
|
||||||
|
#endif
|
||||||
|
#ifndef MIN
|
||||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
#define MIN(x,y) ((x)<(y)?(x):(y))
|
||||||
|
#endif
|
||||||
#ifndef ARRAYSIZE
|
#ifndef ARRAYSIZE
|
||||||
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
|
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
inline void SWAP_UINT16(uint16_t *ptr) {
|
|
||||||
const uint8_t hi = *ptr >> 8;
|
|
||||||
const uint8_t lo = *ptr & 255;
|
|
||||||
*ptr = (lo << 8) | hi;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint16_t READ_BE_UINT16(const void *ptr) {
|
inline uint16_t READ_BE_UINT16(const void *ptr) {
|
||||||
const uint8_t *b = (const uint8_t *)ptr;
|
const uint8_t *b = (const uint8_t *)ptr;
|
||||||
return (b[0] << 8) | b[1];
|
return (b[0] << 8) | b[1];
|
||||||
|
@ -77,7 +63,15 @@ enum Language {
|
||||||
|
|
||||||
enum ResourceType {
|
enum ResourceType {
|
||||||
kResourceTypeAmiga,
|
kResourceTypeAmiga,
|
||||||
kResourceTypePC
|
kResourceTypeDOS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Options {
|
||||||
|
bool bypass_protection;
|
||||||
|
bool play_disabled_cutscenes;
|
||||||
|
bool enable_password_menu;
|
||||||
|
bool fade_out_palette;
|
||||||
|
bool use_tiledata;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Color {
|
struct Color {
|
||||||
|
@ -219,6 +213,7 @@ struct SoundFx {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern Options g_options;
|
||||||
extern const char *g_caption;
|
extern const char *g_caption;
|
||||||
|
|
||||||
#endif // INTERN_H__
|
#endif // INTERN_H__
|
||||||
|
|
19
locale.cpp
19
locale.cpp
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "locale.h"
|
#include "locale.h"
|
||||||
|
|
19
locale.h
19
locale.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LOCALE_H__
|
#ifndef LOCALE_H__
|
||||||
|
|
99
main.cpp
99
main.cpp
|
@ -1,33 +1,28 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
#include "scaler.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
static const char *USAGE =
|
static const char *USAGE =
|
||||||
"REminiscence - Flashback Interpreter\n"
|
"REminiscence - Flashback Interpreter\n"
|
||||||
"Usage: %s [OPTIONS]...\n"
|
"Usage: %s [OPTIONS]...\n"
|
||||||
" --datapath=PATH Path to data files (default 'DATA')\n"
|
" --datapath=PATH Path to data files (default 'DATA')\n"
|
||||||
" --savepath=PATH Path to save files (default '.')\n"
|
" --savepath=PATH Path to save files (default '.')\n"
|
||||||
" --levelnum=NUM Starting level (default '0')";
|
" --levelnum=NUM Start level (default '0')\n"
|
||||||
|
" --fullscreen Start fullscreen\n"
|
||||||
|
" --scaler=INDEX Graphics scaler\n"
|
||||||
|
;
|
||||||
|
|
||||||
static int detectVersion(FileSystem *fs) {
|
static int detectVersion(FileSystem *fs) {
|
||||||
static const struct {
|
static const struct {
|
||||||
|
@ -35,9 +30,11 @@ static int detectVersion(FileSystem *fs) {
|
||||||
int type;
|
int type;
|
||||||
const char *name;
|
const char *name;
|
||||||
} table[] = {
|
} table[] = {
|
||||||
{ "LEVEL1.MAP", kResourceTypePC, "PC" },
|
{ "DEMO_UK.ABA", kResourceTypeDOS, "DOS (Demo)" },
|
||||||
|
{ "INTRO.SEQ", kResourceTypeDOS, "DOS CD" },
|
||||||
|
{ "LEVEL1.MAP", kResourceTypeDOS, "DOS" },
|
||||||
{ "LEVEL1.LEV", kResourceTypeAmiga, "Amiga" },
|
{ "LEVEL1.LEV", kResourceTypeAmiga, "Amiga" },
|
||||||
{ "DEMO.LEV", kResourceTypeAmiga, "Amiga" },
|
{ "DEMO.LEV", kResourceTypeAmiga, "Amiga (Demo)" },
|
||||||
{ 0, -1 }
|
{ 0, -1 }
|
||||||
};
|
};
|
||||||
for (int i = 0; table[i].filename; ++i) {
|
for (int i = 0; table[i].filename; ++i) {
|
||||||
|
@ -74,13 +71,65 @@ static Language detectLanguage(FileSystem *fs) {
|
||||||
return LANG_EN;
|
return LANG_EN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Options g_options;
|
||||||
const char *g_caption = "REminiscence";
|
const char *g_caption = "REminiscence";
|
||||||
|
|
||||||
|
static void initOptions() {
|
||||||
|
// defaults
|
||||||
|
g_options.bypass_protection = true;
|
||||||
|
g_options.play_disabled_cutscenes = false;
|
||||||
|
g_options.enable_password_menu = false;
|
||||||
|
g_options.fade_out_palette = true;
|
||||||
|
// read configuration file
|
||||||
|
struct {
|
||||||
|
const char *name;
|
||||||
|
bool *value;
|
||||||
|
} opts[] = {
|
||||||
|
{ "bypass_protection", &g_options.bypass_protection },
|
||||||
|
{ "play_disabled_cutscenes", &g_options.play_disabled_cutscenes },
|
||||||
|
{ "enable_password_menu", &g_options.enable_password_menu },
|
||||||
|
{ "fade_out_palette", &g_options.fade_out_palette },
|
||||||
|
{ "use_tiledata", &g_options.use_tiledata },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
static const char *filename = "rs.cfg";
|
||||||
|
FILE *fp = fopen(filename, "rb");
|
||||||
|
if (fp) {
|
||||||
|
char buf[256];
|
||||||
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
|
if (buf[0] == '#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const char *p = strchr(buf, '=');
|
||||||
|
if (p) {
|
||||||
|
++p;
|
||||||
|
while (*p && isspace(*p)) {
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
if (*p) {
|
||||||
|
const bool value = (*p == 't' || *p == 'T' || *p == '1');
|
||||||
|
for (int i = 0; opts[i].name; ++i) {
|
||||||
|
if (strncmp(buf, opts[i].name, strlen(opts[i].name)) == 0) {
|
||||||
|
*opts[i].value = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int DEFAULT_SCALER = SCALER_SCALE_3X;
|
||||||
|
|
||||||
#undef main
|
#undef main
|
||||||
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;
|
||||||
|
int scaler = DEFAULT_SCALER;
|
||||||
|
bool fullscreen = false;
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
// data path as the only command line argument
|
// data path as the only command line argument
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -93,6 +142,8 @@ int main(int argc, char *argv[]) {
|
||||||
{ "datapath", required_argument, 0, 1 },
|
{ "datapath", required_argument, 0, 1 },
|
||||||
{ "savepath", required_argument, 0, 2 },
|
{ "savepath", required_argument, 0, 2 },
|
||||||
{ "levelnum", required_argument, 0, 3 },
|
{ "levelnum", required_argument, 0, 3 },
|
||||||
|
{ "fullscreen", no_argument, 0, 4 },
|
||||||
|
{ "scaler", required_argument, 0, 5 },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
int index;
|
int index;
|
||||||
|
@ -110,11 +161,21 @@ int main(int argc, char *argv[]) {
|
||||||
case 3:
|
case 3:
|
||||||
levelNum = atoi(optarg);
|
levelNum = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
fullscreen = true;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
scaler = atoi(optarg);
|
||||||
|
if (scaler < 0 || scaler >= NUM_SCALERS) {
|
||||||
|
scaler = DEFAULT_SCALER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf(USAGE, argv[0]);
|
printf(USAGE, argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initOptions();
|
||||||
g_debugMask = DBG_INFO; // DBG_CUT | DBG_VIDEO | DBG_RES | DBG_MENU | DBG_PGE | DBG_GAME | DBG_UNPACK | DBG_COL | DBG_MOD | DBG_SFX | DBG_FILE;
|
g_debugMask = DBG_INFO; // DBG_CUT | DBG_VIDEO | DBG_RES | DBG_MENU | DBG_PGE | DBG_GAME | DBG_UNPACK | DBG_COL | DBG_MOD | DBG_SFX | DBG_FILE;
|
||||||
FileSystem fs(dataPath);
|
FileSystem fs(dataPath);
|
||||||
const int version = detectVersion(&fs);
|
const int version = detectVersion(&fs);
|
||||||
|
@ -125,8 +186,10 @@ int main(int argc, char *argv[]) {
|
||||||
Language language = detectLanguage(&fs);
|
Language language = detectLanguage(&fs);
|
||||||
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);
|
||||||
|
stub->init(g_caption, Video::GAMESCREEN_W, Video::GAMESCREEN_H, scaler, fullscreen);
|
||||||
g->run();
|
g->run();
|
||||||
delete g;
|
delete g;
|
||||||
|
stub->destroy();
|
||||||
delete stub;
|
delete stub;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
218
menu.cpp
218
menu.cpp
|
@ -1,29 +1,20 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
#include "menu.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
|
#include "util.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
#include "menu.h"
|
|
||||||
|
|
||||||
|
|
||||||
Menu::Menu(Resource *res, SystemStub *stub, Video *vid)
|
Menu::Menu(Resource *res, SystemStub *stub, Video *vid)
|
||||||
: _res(res), _stub(stub), _vid(vid) {
|
: _res(res), _stub(stub), _vid(vid) {
|
||||||
|
_skill = 1;
|
||||||
|
_level = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::drawString(const char *str, int16_t y, int16_t x, uint8_t color) {
|
void Menu::drawString(const char *str, int16_t y, int16_t x, uint8_t color) {
|
||||||
|
@ -73,13 +64,11 @@ void Menu::drawString(const char *str, int16_t y, int16_t x, uint8_t color) {
|
||||||
|
|
||||||
void Menu::drawString2(const char *str, int16_t y, int16_t x) {
|
void Menu::drawString2(const char *str, int16_t y, int16_t x) {
|
||||||
debug(DBG_MENU, "Menu::drawString2()");
|
debug(DBG_MENU, "Menu::drawString2()");
|
||||||
int len = 0;
|
int i = 0;
|
||||||
while (*str) {
|
for (; str[i]; ++i) {
|
||||||
_vid->PC_drawChar((uint8_t)*str, y, x + len);
|
_vid->PC_drawChar((uint8_t)str[i], y, x + i);
|
||||||
++str;
|
|
||||||
++len;
|
|
||||||
}
|
}
|
||||||
_vid->markBlockAsDirty(x * 8, y * 8, len * 8, 8);
|
_vid->markBlockAsDirty(x * 8, y * 8, i * 8, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::loadPicture(const char *prefix) {
|
void Menu::loadPicture(const char *prefix) {
|
||||||
|
@ -99,22 +88,20 @@ void Menu::loadPicture(const char *prefix) {
|
||||||
void Menu::handleInfoScreen() {
|
void Menu::handleInfoScreen() {
|
||||||
debug(DBG_MENU, "Menu::handleInfoScreen()");
|
debug(DBG_MENU, "Menu::handleInfoScreen()");
|
||||||
_vid->fadeOut();
|
_vid->fadeOut();
|
||||||
switch (_res->_lang) {
|
if (_res->_lang == LANG_FR) {
|
||||||
case LANG_FR:
|
|
||||||
loadPicture("instru_f");
|
loadPicture("instru_f");
|
||||||
break;
|
} else {
|
||||||
case LANG_EN:
|
|
||||||
case LANG_DE:
|
|
||||||
case LANG_SP:
|
|
||||||
case LANG_IT:
|
|
||||||
loadPicture("instru_e");
|
loadPicture("instru_e");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
_vid->fullRefresh();
|
_vid->fullRefresh();
|
||||||
_vid->updateScreen();
|
_vid->updateScreen();
|
||||||
do {
|
do {
|
||||||
_stub->sleep(EVENTS_DELAY);
|
_stub->sleep(EVENTS_DELAY);
|
||||||
_stub->processEvents();
|
_stub->processEvents();
|
||||||
|
if (_stub->_pi.escape) {
|
||||||
|
_stub->_pi.escape = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (_stub->_pi.enter) {
|
if (_stub->_pi.enter) {
|
||||||
_stub->_pi.enter = false;
|
_stub->_pi.enter = false;
|
||||||
break;
|
break;
|
||||||
|
@ -122,18 +109,22 @@ void Menu::handleInfoScreen() {
|
||||||
} while (!_stub->_pi.quit);
|
} while (!_stub->_pi.quit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::handleSkillScreen(uint8_t &new_skill) {
|
void Menu::handleSkillScreen() {
|
||||||
debug(DBG_MENU, "Menu::handleSkillScreen()");
|
debug(DBG_MENU, "Menu::handleSkillScreen()");
|
||||||
static const uint8_t option_colors[3][3] = { { 2, 3, 3 }, { 3, 2, 3}, { 3, 3, 2 } };
|
static const uint8_t colors[3][3] = {
|
||||||
|
{ 2, 3, 3 }, // easy
|
||||||
|
{ 3, 2, 3 }, // normal
|
||||||
|
{ 3, 3, 2 } // expert
|
||||||
|
};
|
||||||
_vid->fadeOut();
|
_vid->fadeOut();
|
||||||
loadPicture("menu3");
|
loadPicture("menu3");
|
||||||
_vid->fullRefresh();
|
_vid->fullRefresh();
|
||||||
drawString(_res->getMenuString(LocaleData::LI_12_SKILL_LEVEL), 12, 4, 3);
|
drawString(_res->getMenuString(LocaleData::LI_12_SKILL_LEVEL), 12, 4, 3);
|
||||||
int skill_level = new_skill;
|
int skill_level = _skill;
|
||||||
do {
|
do {
|
||||||
drawString(_res->getMenuString(LocaleData::LI_13_EASY), 15, 14, option_colors[skill_level][0]);
|
drawString(_res->getMenuString(LocaleData::LI_13_EASY), 15, 14, colors[skill_level][0]);
|
||||||
drawString(_res->getMenuString(LocaleData::LI_14_NORMAL), 17, 14, option_colors[skill_level][1]);
|
drawString(_res->getMenuString(LocaleData::LI_14_NORMAL), 17, 14, colors[skill_level][1]);
|
||||||
drawString(_res->getMenuString(LocaleData::LI_15_EXPERT), 19, 14, option_colors[skill_level][2]);
|
drawString(_res->getMenuString(LocaleData::LI_15_EXPERT), 19, 14, colors[skill_level][2]);
|
||||||
|
|
||||||
_vid->updateScreen();
|
_vid->updateScreen();
|
||||||
_stub->sleep(EVENTS_DELAY);
|
_stub->sleep(EVENTS_DELAY);
|
||||||
|
@ -155,16 +146,20 @@ void Menu::handleSkillScreen(uint8_t &new_skill) {
|
||||||
skill_level = 0;
|
skill_level = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_stub->_pi.escape) {
|
||||||
|
_stub->_pi.escape = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (_stub->_pi.enter) {
|
if (_stub->_pi.enter) {
|
||||||
_stub->_pi.enter = false;
|
_stub->_pi.enter = false;
|
||||||
new_skill = skill_level;
|
_skill = skill_level;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} while (!_stub->_pi.quit);
|
} while (!_stub->_pi.quit);
|
||||||
new_skill = 1;
|
_skill = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Menu::handlePasswordScreen(uint8_t &new_skill, uint8_t &new_level) {
|
bool Menu::handlePasswordScreen() {
|
||||||
debug(DBG_MENU, "Menu::handlePasswordScreen()");
|
debug(DBG_MENU, "Menu::handlePasswordScreen()");
|
||||||
_vid->fadeOut();
|
_vid->fadeOut();
|
||||||
_vid->_charShadowColor = _charVar1;
|
_vid->_charShadowColor = _charVar1;
|
||||||
|
@ -206,14 +201,18 @@ bool Menu::handlePasswordScreen(uint8_t &new_skill, uint8_t &new_level) {
|
||||||
--len;
|
--len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_stub->_pi.escape) {
|
||||||
|
_stub->_pi.escape = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (_stub->_pi.enter) {
|
if (_stub->_pi.enter) {
|
||||||
_stub->_pi.enter = false;
|
_stub->_pi.enter = false;
|
||||||
password[len] = '\0';
|
password[len] = '\0';
|
||||||
for (int level = 0; level < 8; ++level) {
|
for (int level = 0; level < 8; ++level) {
|
||||||
for (int skill = 0; skill < 3; ++skill) {
|
for (int skill = 0; skill < 3; ++skill) {
|
||||||
if (strcmp(_passwords[level][skill], password) == 0) {
|
if (strcmp(_passwords[level][skill], password) == 0) {
|
||||||
new_level = level;
|
_level = level;
|
||||||
new_skill = skill;
|
_skill = skill;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,13 +223,13 @@ bool Menu::handlePasswordScreen(uint8_t &new_skill, uint8_t &new_level) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Menu::handleLevelScreen(uint8_t &new_skill, uint8_t &new_level) {
|
bool Menu::handleLevelScreen() {
|
||||||
debug(DBG_MENU, "Menu::handleLevelScreen()");
|
debug(DBG_MENU, "Menu::handleLevelScreen()");
|
||||||
_vid->fadeOut();
|
_vid->fadeOut();
|
||||||
loadPicture("menu2");
|
loadPicture("menu2");
|
||||||
_vid->fullRefresh();
|
_vid->fullRefresh();
|
||||||
uint8_t currentSkill = new_skill;
|
int currentSkill = _skill;
|
||||||
uint8_t currentLevel = new_level;
|
int currentLevel = _level;
|
||||||
do {
|
do {
|
||||||
static const char *levelTitles[] = {
|
static const char *levelTitles[] = {
|
||||||
"Titan / The Jungle",
|
"Titan / The Jungle",
|
||||||
|
@ -287,56 +286,77 @@ bool Menu::handleLevelScreen(uint8_t &new_skill, uint8_t &new_level) {
|
||||||
currentSkill = 0;
|
currentSkill = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_stub->_pi.escape) {
|
||||||
|
_stub->_pi.escape = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (_stub->_pi.enter) {
|
if (_stub->_pi.enter) {
|
||||||
_stub->_pi.enter = false;
|
_stub->_pi.enter = false;
|
||||||
new_skill = currentSkill;
|
_skill = currentSkill;
|
||||||
new_level = currentLevel;
|
_level = currentLevel;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} while (!_stub->_pi.quit);
|
} while (!_stub->_pi.quit);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Menu::handleTitleScreen(uint8_t &new_skill, uint8_t &new_level) {
|
void Menu::handleTitleScreen() {
|
||||||
debug(DBG_MENU, "Menu::handleTitleScreen()");
|
debug(DBG_MENU, "Menu::handleTitleScreen()");
|
||||||
bool quit_loop = false;
|
|
||||||
int menu_entry = 0;
|
|
||||||
bool reinit_screen = true;
|
|
||||||
bool continue_game = true;
|
|
||||||
_charVar1 = 0;
|
_charVar1 = 0;
|
||||||
_charVar2 = 0;
|
_charVar2 = 0;
|
||||||
_charVar3 = 0;
|
_charVar3 = 0;
|
||||||
_charVar4 = 0;
|
_charVar4 = 0;
|
||||||
_charVar5 = 0;
|
_charVar5 = 0;
|
||||||
static const struct {
|
|
||||||
int str;
|
static const int MAX_MENU_ITEMS = 5;
|
||||||
int opt;
|
Item menuItems[MAX_MENU_ITEMS];
|
||||||
} menu_items[] = {
|
int menuItemsCount = 0;
|
||||||
{ LocaleData::LI_07_START, MENU_OPTION_ITEM_START },
|
|
||||||
#ifdef ENABLE_PASSWORD_MENU
|
menuItems[menuItemsCount].str = LocaleData::LI_07_START;
|
||||||
{ LocaleData::LI_08_SKILL, MENU_OPTION_ITEM_SKILL },
|
menuItems[menuItemsCount].opt = MENU_OPTION_ITEM_START;
|
||||||
{ LocaleData::LI_09_PASSWORD, MENU_OPTION_ITEM_PASSWORD },
|
++menuItemsCount;
|
||||||
#else
|
if (g_options.enable_password_menu) {
|
||||||
{ LocaleData::LI_06_LEVEL, MENU_OPTION_ITEM_LEVEL },
|
menuItems[menuItemsCount].str = LocaleData::LI_08_SKILL;
|
||||||
#endif
|
menuItems[menuItemsCount].opt = MENU_OPTION_ITEM_SKILL;
|
||||||
{ LocaleData::LI_10_INFO, MENU_OPTION_ITEM_INFO },
|
++menuItemsCount;
|
||||||
{ LocaleData::LI_11_QUIT, MENU_OPTION_ITEM_QUIT }
|
menuItems[menuItemsCount].str = LocaleData::LI_09_PASSWORD;
|
||||||
};
|
menuItems[menuItemsCount].opt = MENU_OPTION_ITEM_PASSWORD;
|
||||||
static const int menu_items_count = ARRAYSIZE(menu_items);
|
++menuItemsCount;
|
||||||
while (!quit_loop) {
|
} else {
|
||||||
if (reinit_screen) {
|
menuItems[menuItemsCount].str = LocaleData::LI_06_LEVEL;
|
||||||
|
menuItems[menuItemsCount].opt = MENU_OPTION_ITEM_LEVEL;
|
||||||
|
++menuItemsCount;
|
||||||
|
}
|
||||||
|
menuItems[menuItemsCount].str = LocaleData::LI_10_INFO;
|
||||||
|
menuItems[menuItemsCount].opt = MENU_OPTION_ITEM_INFO;
|
||||||
|
++menuItemsCount;
|
||||||
|
menuItems[menuItemsCount].str = LocaleData::LI_11_QUIT;
|
||||||
|
menuItems[menuItemsCount].opt = MENU_OPTION_ITEM_QUIT;
|
||||||
|
++menuItemsCount;
|
||||||
|
|
||||||
|
_selectedOption = -1;
|
||||||
|
_currentScreen = -1;
|
||||||
|
_nextScreen = SCREEN_TITLE;
|
||||||
|
|
||||||
|
bool quitLoop = false;
|
||||||
|
int currentEntry = 0;
|
||||||
|
|
||||||
|
while (!quitLoop) {
|
||||||
|
if (_nextScreen == SCREEN_TITLE) {
|
||||||
_vid->fadeOut();
|
_vid->fadeOut();
|
||||||
loadPicture("menu1");
|
loadPicture("menu1");
|
||||||
_vid->fullRefresh();
|
_vid->fullRefresh();
|
||||||
_charVar3 = 1;
|
_charVar3 = 1;
|
||||||
_charVar4 = 2;
|
_charVar4 = 2;
|
||||||
menu_entry = 0;
|
currentEntry = 0;
|
||||||
reinit_screen = false;
|
_currentScreen = _nextScreen;
|
||||||
|
_nextScreen = -1;
|
||||||
}
|
}
|
||||||
int selected_menu_entry = -1;
|
int selectedItem = -1;
|
||||||
const int y_start = 26 - menu_items_count * 2;
|
const int yPos = 26 - menuItemsCount * 2;
|
||||||
for (int i = 0; i < menu_items_count; ++i) {
|
for (int i = 0; i < menuItemsCount; ++i) {
|
||||||
drawString(_res->getMenuString(menu_items[i].str), y_start + i * 2, 20, (i == menu_entry) ? 2 : 3);
|
drawString(_res->getMenuString(menuItems[i].str), yPos + i * 2, 20, (i == currentEntry) ? 2 : 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
_vid->updateScreen();
|
_vid->updateScreen();
|
||||||
|
@ -345,63 +365,55 @@ bool Menu::handleTitleScreen(uint8_t &new_skill, uint8_t &new_level) {
|
||||||
|
|
||||||
if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
|
if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
|
||||||
_stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
|
_stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
|
||||||
if (menu_entry != 0) {
|
if (currentEntry != 0) {
|
||||||
--menu_entry;
|
--currentEntry;
|
||||||
} else {
|
} else {
|
||||||
menu_entry = menu_items_count - 1;
|
currentEntry = menuItemsCount - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
|
if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
|
||||||
_stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
|
_stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
|
||||||
if (menu_entry != menu_items_count - 1) {
|
if (currentEntry != menuItemsCount - 1) {
|
||||||
++menu_entry;
|
++currentEntry;
|
||||||
} else {
|
} else {
|
||||||
menu_entry = 0;
|
currentEntry = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_stub->_pi.enter) {
|
if (_stub->_pi.enter) {
|
||||||
_stub->_pi.enter = false;
|
_stub->_pi.enter = false;
|
||||||
selected_menu_entry = menu_entry;
|
selectedItem = currentEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected_menu_entry != -1) {
|
if (selectedItem != -1) {
|
||||||
switch (menu_items[selected_menu_entry].opt) {
|
_selectedOption = menuItems[selectedItem].opt;
|
||||||
|
switch (_selectedOption) {
|
||||||
case MENU_OPTION_ITEM_START:
|
case MENU_OPTION_ITEM_START:
|
||||||
quit_loop = true;
|
quitLoop = true;
|
||||||
break;
|
break;
|
||||||
case MENU_OPTION_ITEM_SKILL:
|
case MENU_OPTION_ITEM_SKILL:
|
||||||
handleSkillScreen(new_skill);
|
_currentScreen = SCREEN_SKILL;
|
||||||
reinit_screen = true;
|
handleSkillScreen();
|
||||||
break;
|
break;
|
||||||
case MENU_OPTION_ITEM_PASSWORD:
|
case MENU_OPTION_ITEM_PASSWORD:
|
||||||
if (handlePasswordScreen(new_skill, new_level)) {
|
_currentScreen = SCREEN_PASSWORD;
|
||||||
quit_loop = true;
|
quitLoop = handlePasswordScreen();
|
||||||
} else {
|
|
||||||
reinit_screen = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MENU_OPTION_ITEM_LEVEL:
|
case MENU_OPTION_ITEM_LEVEL:
|
||||||
if (handleLevelScreen(new_skill, new_level)) {
|
_currentScreen = SCREEN_LEVEL;
|
||||||
quit_loop = true;
|
quitLoop = handleLevelScreen();
|
||||||
} else {
|
|
||||||
reinit_screen = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MENU_OPTION_ITEM_INFO:
|
case MENU_OPTION_ITEM_INFO:
|
||||||
|
_currentScreen = SCREEN_INFO;
|
||||||
handleInfoScreen();
|
handleInfoScreen();
|
||||||
reinit_screen = true;
|
|
||||||
break;
|
break;
|
||||||
case MENU_OPTION_ITEM_QUIT:
|
case MENU_OPTION_ITEM_QUIT:
|
||||||
continue_game = false;
|
quitLoop = true;
|
||||||
quit_loop = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
_nextScreen = SCREEN_TITLE;
|
||||||
}
|
}
|
||||||
if (_stub->_pi.quit) {
|
if (_stub->_pi.quit) {
|
||||||
continue_game = false;
|
|
||||||
quit_loop = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return continue_game;
|
|
||||||
}
|
}
|
||||||
|
|
48
menu.h
48
menu.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MENU_H__
|
#ifndef MENU_H__
|
||||||
|
@ -33,18 +22,36 @@ struct Menu {
|
||||||
MENU_OPTION_ITEM_INFO,
|
MENU_OPTION_ITEM_INFO,
|
||||||
MENU_OPTION_ITEM_QUIT
|
MENU_OPTION_ITEM_QUIT
|
||||||
};
|
};
|
||||||
|
enum {
|
||||||
|
SCREEN_TITLE,
|
||||||
|
SCREEN_SKILL,
|
||||||
|
SCREEN_PASSWORD,
|
||||||
|
SCREEN_LEVEL,
|
||||||
|
SCREEN_INFO
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
EVENTS_DELAY = 80
|
EVENTS_DELAY = 80
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Item {
|
||||||
|
int str;
|
||||||
|
int opt;
|
||||||
|
};
|
||||||
|
|
||||||
static const char *_passwords[8][3];
|
static const char *_passwords[8][3];
|
||||||
|
|
||||||
Resource *_res;
|
Resource *_res;
|
||||||
SystemStub *_stub;
|
SystemStub *_stub;
|
||||||
Video *_vid;
|
Video *_vid;
|
||||||
|
|
||||||
const char **_textOptions;
|
int _currentScreen;
|
||||||
|
int _nextScreen;
|
||||||
|
int _selectedOption;
|
||||||
|
|
||||||
|
int _skill;
|
||||||
|
int _level;
|
||||||
|
|
||||||
uint8_t _charVar1;
|
uint8_t _charVar1;
|
||||||
uint8_t _charVar2;
|
uint8_t _charVar2;
|
||||||
uint8_t _charVar3;
|
uint8_t _charVar3;
|
||||||
|
@ -56,11 +63,12 @@ struct Menu {
|
||||||
void drawString(const char *str, int16_t y, int16_t x, uint8_t color);
|
void drawString(const char *str, int16_t y, int16_t x, uint8_t color);
|
||||||
void drawString2(const char *str, int16_t y, int16_t x);
|
void drawString2(const char *str, int16_t y, int16_t x);
|
||||||
void loadPicture(const char *prefix);
|
void loadPicture(const char *prefix);
|
||||||
|
|
||||||
void handleInfoScreen();
|
void handleInfoScreen();
|
||||||
void handleSkillScreen(uint8_t &new_skill);
|
void handleSkillScreen();
|
||||||
bool handlePasswordScreen(uint8_t &new_skill, uint8_t &new_level);
|
bool handlePasswordScreen();
|
||||||
bool handleLevelScreen(uint8_t &new_skill, uint8_t &new_level);
|
bool handleLevelScreen();
|
||||||
bool handleTitleScreen(uint8_t &new_skill, uint8_t &new_level);
|
void handleTitleScreen();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MENU_H__
|
#endif // MENU_H__
|
||||||
|
|
38
mixer.cpp
38
mixer.cpp
|
@ -1,23 +1,12 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mixer.h"
|
#include "mixer.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
Mixer::Mixer(FileSystem *fs, SystemStub *stub)
|
Mixer::Mixer(FileSystem *fs, SystemStub *stub)
|
||||||
: _stub(stub), _musicType(MT_NONE), _mod(this, fs), _ogg(this, fs), _sfx(this) {
|
: _stub(stub), _musicType(MT_NONE), _mod(this, fs), _ogg(this, fs), _sfx(this) {
|
||||||
|
@ -144,7 +133,17 @@ void Mixer::stopMusic() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mixer::mix(int8_t *buf, int len) {
|
static void nr(const int8_t *in, int len, int8_t *out) {
|
||||||
|
static int prev = 0;
|
||||||
|
for (int i = 0; i < len; ++i) {
|
||||||
|
const int vnr = in[i] >> 1;
|
||||||
|
out[i] = vnr + prev;
|
||||||
|
prev = vnr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mixer::mix(int8_t *out, int len) {
|
||||||
|
int8_t buf[len];
|
||||||
memset(buf, 0, len);
|
memset(buf, 0, len);
|
||||||
if (_premixHook) {
|
if (_premixHook) {
|
||||||
if (!_premixHook(_premixHookData, buf, len)) {
|
if (!_premixHook(_premixHookData, buf, len)) {
|
||||||
|
@ -160,12 +159,13 @@ void Mixer::mix(int8_t *buf, int len) {
|
||||||
ch->active = false;
|
ch->active = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int out = resampleLinear(&ch->chunk, ch->chunkPos, ch->chunkInc, FRAC_BITS);
|
const int sample = ch->chunk.getPCM(ch->chunkPos >> FRAC_BITS);
|
||||||
addclamp(buf[pos], out * ch->volume / Mixer::MAX_VOLUME);
|
addclamp(buf[pos], sample * ch->volume / Mixer::MAX_VOLUME);
|
||||||
ch->chunkPos += ch->chunkInc;
|
ch->chunkPos += ch->chunkInc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
nr(buf, len, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mixer::addclamp(int8_t& a, int b) {
|
void Mixer::addclamp(int8_t& a, int b) {
|
||||||
|
|
28
mixer.h
28
mixer.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MIXER_H__
|
#ifndef MIXER_H__
|
||||||
|
@ -96,13 +85,4 @@ struct Mixer {
|
||||||
static void mixCallback(void *param, int8_t *buf, int len);
|
static void mixCallback(void *param, int8_t *buf, int len);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
|
||||||
int resampleLinear(T *sample, int pos, int step, int fracBits) {
|
|
||||||
const int inputPos = pos >> fracBits;
|
|
||||||
const int inputFrac = pos & ((1 << fracBits) - 1);
|
|
||||||
int out = sample->getPCM(inputPos);
|
|
||||||
out += (sample->getPCM(inputPos + 1) - out) * inputFrac >> fracBits;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MIXER_H__
|
#endif // MIXER_H__
|
||||||
|
|
304
mod_player.cpp
304
mod_player.cpp
|
@ -1,33 +1,168 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "mixer.h"
|
#include "mixer.h"
|
||||||
#include "mod_player.h"
|
#include "mod_player.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#ifdef USE_MODPLUG
|
||||||
|
#include <libmodplug/modplug.h>
|
||||||
|
|
||||||
ModPlayer::ModPlayer(Mixer *mixer, FileSystem *fs)
|
struct ModPlayer_impl {
|
||||||
: _playing(false), _mix(mixer), _fs(fs) {
|
|
||||||
|
ModPlugFile *_mf;
|
||||||
|
ModPlug_Settings _settings;
|
||||||
|
bool _repeatIntro;
|
||||||
|
|
||||||
|
ModPlayer_impl()
|
||||||
|
: _mf(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(const int rate) {
|
||||||
|
memset(&_settings, 0, sizeof(_settings));
|
||||||
|
ModPlug_GetSettings(&_settings);
|
||||||
|
_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION;
|
||||||
|
_settings.mChannels = 1;
|
||||||
|
_settings.mBits = 8;
|
||||||
|
_settings.mFrequency = rate;
|
||||||
|
_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
|
||||||
|
ModPlug_SetSettings(&_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load(File *f) {
|
||||||
|
const uint32_t size = f->size();
|
||||||
|
uint8_t *data = (uint8_t *)malloc(size);
|
||||||
|
if (data) {
|
||||||
|
f->read(data, size);
|
||||||
|
_mf = ModPlug_Load(data, size);
|
||||||
|
}
|
||||||
|
return _mf != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unload() {
|
||||||
|
if (_mf) {
|
||||||
|
ModPlug_Unload(_mf);
|
||||||
|
_mf = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mix(int8_t *buf, int len) {
|
||||||
|
memset(buf, 0, len);
|
||||||
|
if (_mf) {
|
||||||
|
const int order = ModPlug_GetCurrentOrder(_mf);
|
||||||
|
if (order == 3 && _repeatIntro) {
|
||||||
|
ModPlug_SeekOrder(_mf, 1);
|
||||||
|
_repeatIntro = false;
|
||||||
|
}
|
||||||
|
const int count = ModPlug_Read(_mf, buf, len);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
buf[i] ^= 0x80;
|
||||||
|
}
|
||||||
|
return count > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
struct ModPlayer_impl {
|
||||||
|
enum {
|
||||||
|
NUM_SAMPLES = 31,
|
||||||
|
NUM_TRACKS = 4,
|
||||||
|
NUM_PATTERNS = 128,
|
||||||
|
FRAC_BITS = 12,
|
||||||
|
PAULA_FREQ = 3546897
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SampleInfo {
|
||||||
|
char name[23];
|
||||||
|
uint16_t len;
|
||||||
|
uint8_t fineTune;
|
||||||
|
uint8_t volume;
|
||||||
|
uint16_t repeatPos;
|
||||||
|
uint16_t repeatLen;
|
||||||
|
int8_t *data;
|
||||||
|
|
||||||
|
int8_t getPCM(int offset) const {
|
||||||
|
if (offset < 0) {
|
||||||
|
offset = 0;
|
||||||
|
} else if (offset >= (int)len) {
|
||||||
|
offset = len - 1;
|
||||||
|
}
|
||||||
|
return data[offset];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ModuleInfo {
|
||||||
|
char songName[21];
|
||||||
|
SampleInfo samples[NUM_SAMPLES];
|
||||||
|
uint8_t numPatterns;
|
||||||
|
uint8_t patternOrderTable[NUM_PATTERNS];
|
||||||
|
uint8_t *patternsTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Track {
|
||||||
|
SampleInfo *sample;
|
||||||
|
uint8_t volume;
|
||||||
|
int pos;
|
||||||
|
int freq;
|
||||||
|
uint16_t period;
|
||||||
|
uint16_t periodIndex;
|
||||||
|
uint16_t effectData;
|
||||||
|
int vibratoSpeed;
|
||||||
|
int vibratoAmp;
|
||||||
|
int vibratoPos;
|
||||||
|
int portamento;
|
||||||
|
int portamentoSpeed;
|
||||||
|
int retriggerCounter;
|
||||||
|
int delayCounter;
|
||||||
|
int cutCounter;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool _playing;
|
||||||
|
int _mixingRate;
|
||||||
|
ModuleInfo _modInfo;
|
||||||
|
uint8_t _currentPatternOrder;
|
||||||
|
uint8_t _currentPatternPos;
|
||||||
|
uint8_t _currentTick;
|
||||||
|
uint8_t _songSpeed;
|
||||||
|
uint8_t _songTempo;
|
||||||
|
int _patternDelay;
|
||||||
|
int _patternLoopPos;
|
||||||
|
int _patternLoopCount;
|
||||||
|
int _samplesLeft;
|
||||||
|
bool _repeatIntro;
|
||||||
|
Track _tracks[NUM_TRACKS];
|
||||||
|
|
||||||
|
ModPlayer_impl();
|
||||||
|
|
||||||
|
void init(const int rate);
|
||||||
|
uint16_t findPeriod(uint16_t period, uint8_t fineTune) const;
|
||||||
|
bool load(File *f);
|
||||||
|
void unload();
|
||||||
|
void handleNote(int trackNum, uint32_t noteData);
|
||||||
|
void handleTick();
|
||||||
|
void applyVolumeSlide(int trackNum, int amount);
|
||||||
|
void applyVibrato(int trackNum);
|
||||||
|
void applyPortamento(int trackNum);
|
||||||
|
void handleEffect(int trackNum, bool tick);
|
||||||
|
void mixSamples(int8_t *buf, int len);
|
||||||
|
bool mix(int8_t *buf, int len);
|
||||||
|
};
|
||||||
|
|
||||||
|
ModPlayer_impl::ModPlayer_impl()
|
||||||
|
: _playing(false) {
|
||||||
memset(&_modInfo, 0, sizeof(_modInfo));
|
memset(&_modInfo, 0, sizeof(_modInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ModPlayer::findPeriod(uint16_t period, uint8_t fineTune) const {
|
uint16_t ModPlayer_impl::findPeriod(uint16_t period, uint8_t fineTune) const {
|
||||||
for (int p = 0; p < 36; ++p) {
|
for (int p = 0; p < 36; ++p) {
|
||||||
if (_periodTable[p] == period) {
|
if (ModPlayer::_periodTable[p] == period) {
|
||||||
return fineTune * 36 + p;
|
return fineTune * 36 + p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +170,11 @@ uint16_t ModPlayer::findPeriod(uint16_t period, uint8_t fineTune) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPlayer::load(File *f) {
|
void ModPlayer_impl::init(const int rate) {
|
||||||
|
_mixingRate = rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModPlayer_impl::load(File *f) {
|
||||||
f->read(_modInfo.songName, 20);
|
f->read(_modInfo.songName, 20);
|
||||||
_modInfo.songName[20] = 0;
|
_modInfo.songName[20] = 0;
|
||||||
debug(DBG_MOD, "songName = '%s'", _modInfo.songName);
|
debug(DBG_MOD, "songName = '%s'", _modInfo.songName);
|
||||||
|
@ -80,32 +219,7 @@ void ModPlayer::load(File *f) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void ModPlayer::unload() {
|
|
||||||
if (_modInfo.songName[0]) {
|
|
||||||
free(_modInfo.patternsTable);
|
|
||||||
for (int s = 0; s < NUM_SAMPLES; ++s) {
|
|
||||||
free(_modInfo.samples[s].data);
|
|
||||||
}
|
|
||||||
memset(&_modInfo, 0, sizeof(_modInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModPlayer::play(uint8_t num) {
|
|
||||||
if (!_playing && num < _modulesFilesCount) {
|
|
||||||
File f;
|
|
||||||
bool found = false;
|
|
||||||
for (uint8_t i = 0; i < ARRAYSIZE(_modulesFiles[num]); ++i) {
|
|
||||||
if (f.open(_modulesFiles[num][i], "rb", _fs)) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
warning("Can't find music file %d", num);
|
|
||||||
} else {
|
|
||||||
load(&f);
|
|
||||||
_currentPatternOrder = 0;
|
_currentPatternOrder = 0;
|
||||||
_currentPatternPos = 0;
|
_currentPatternPos = 0;
|
||||||
_currentTick = 0;
|
_currentTick = 0;
|
||||||
|
@ -115,24 +229,25 @@ void ModPlayer::play(uint8_t num) {
|
||||||
_patternLoopPos = 0;
|
_patternLoopPos = 0;
|
||||||
_patternLoopCount = -1;
|
_patternLoopCount = -1;
|
||||||
_samplesLeft = 0;
|
_samplesLeft = 0;
|
||||||
_songNum = num;
|
_repeatIntro = false;
|
||||||
_introSongHack = false;
|
|
||||||
memset(_tracks, 0, sizeof(_tracks));
|
memset(_tracks, 0, sizeof(_tracks));
|
||||||
_mix->setPremixHook(mixCallback, this);
|
|
||||||
_playing = true;
|
_playing = true;
|
||||||
}
|
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPlayer::stop() {
|
void ModPlayer_impl::unload() {
|
||||||
if (_playing) {
|
if (_modInfo.songName[0]) {
|
||||||
_mix->setPremixHook(0, 0);
|
free(_modInfo.patternsTable);
|
||||||
|
for (int s = 0; s < NUM_SAMPLES; ++s) {
|
||||||
|
free(_modInfo.samples[s].data);
|
||||||
|
}
|
||||||
|
memset(&_modInfo, 0, sizeof(_modInfo));
|
||||||
|
}
|
||||||
_playing = false;
|
_playing = false;
|
||||||
}
|
|
||||||
unload();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPlayer::handleNote(int trackNum, uint32_t noteData) {
|
void ModPlayer_impl::handleNote(int trackNum, uint32_t noteData) {
|
||||||
Track *tk = &_tracks[trackNum];
|
Track *tk = &_tracks[trackNum];
|
||||||
uint16_t sampleNum = ((noteData >> 24) & 0xF0) | ((noteData >> 12) & 0xF);
|
uint16_t sampleNum = ((noteData >> 24) & 0xF0) | ((noteData >> 12) & 0xF);
|
||||||
uint16_t samplePeriod = (noteData >> 16) & 0xFFF;
|
uint16_t samplePeriod = (noteData >> 16) & 0xFFF;
|
||||||
|
@ -146,10 +261,10 @@ void ModPlayer::handleNote(int trackNum, uint32_t noteData) {
|
||||||
if (samplePeriod != 0) {
|
if (samplePeriod != 0) {
|
||||||
tk->periodIndex = findPeriod(samplePeriod, tk->sample->fineTune);
|
tk->periodIndex = findPeriod(samplePeriod, tk->sample->fineTune);
|
||||||
if ((effectData >> 8) != 0x3 && (effectData >> 8) != 0x5) {
|
if ((effectData >> 8) != 0x3 && (effectData >> 8) != 0x5) {
|
||||||
tk->period = _periodTable[tk->periodIndex];
|
tk->period = ModPlayer::_periodTable[tk->periodIndex];
|
||||||
tk->freq = PAULA_FREQ / tk->period;
|
tk->freq = PAULA_FREQ / tk->period;
|
||||||
} else {
|
} else {
|
||||||
tk->portamento = _periodTable[tk->periodIndex];
|
tk->portamento = ModPlayer::_periodTable[tk->periodIndex];
|
||||||
}
|
}
|
||||||
tk->vibratoAmp = 0;
|
tk->vibratoAmp = 0;
|
||||||
tk->vibratoSpeed = 0;
|
tk->vibratoSpeed = 0;
|
||||||
|
@ -158,7 +273,7 @@ void ModPlayer::handleNote(int trackNum, uint32_t noteData) {
|
||||||
tk->effectData = effectData;
|
tk->effectData = effectData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPlayer::applyVolumeSlide(int trackNum, int amount) {
|
void ModPlayer_impl::applyVolumeSlide(int trackNum, int amount) {
|
||||||
debug(DBG_MOD, "ModPlayer::applyVolumeSlide(%d, %d)", trackNum, amount);
|
debug(DBG_MOD, "ModPlayer::applyVolumeSlide(%d, %d)", trackNum, amount);
|
||||||
Track *tk = &_tracks[trackNum];
|
Track *tk = &_tracks[trackNum];
|
||||||
int vol = tk->volume + amount;
|
int vol = tk->volume + amount;
|
||||||
|
@ -170,10 +285,16 @@ void ModPlayer::applyVolumeSlide(int trackNum, int amount) {
|
||||||
tk->volume = vol;
|
tk->volume = vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPlayer::applyVibrato(int trackNum) {
|
void ModPlayer_impl::applyVibrato(int trackNum) {
|
||||||
|
static const int8_t sineWaveTable[] = {
|
||||||
|
0, 24, 49, 74, 97, 120, -115, -95, -76, -59, -44, -32, -21, -12, -6, -3,
|
||||||
|
-1, -3, -6, -12, -21, -32, -44, -59, -76, -95, -115, 120, 97, 74, 49, 24,
|
||||||
|
0, -24, -49, -74, -97, -120, 115, 95, 76, 59, 44, 32, 21, 12, 6, 3,
|
||||||
|
1, 3, 6, 12, 21, 32, 44, 59, 76, 95, 115, -120, -97, -74, -49, -24
|
||||||
|
};
|
||||||
debug(DBG_MOD, "ModPlayer::applyVibrato(%d)", trackNum);
|
debug(DBG_MOD, "ModPlayer::applyVibrato(%d)", trackNum);
|
||||||
Track *tk = &_tracks[trackNum];
|
Track *tk = &_tracks[trackNum];
|
||||||
int vib = tk->vibratoAmp * _sineWaveTable[tk->vibratoPos] / 128;
|
int vib = tk->vibratoAmp * sineWaveTable[tk->vibratoPos] / 128;
|
||||||
if (tk->period + vib != 0) {
|
if (tk->period + vib != 0) {
|
||||||
tk->freq = PAULA_FREQ / (tk->period + vib);
|
tk->freq = PAULA_FREQ / (tk->period + vib);
|
||||||
}
|
}
|
||||||
|
@ -183,7 +304,7 @@ void ModPlayer::applyVibrato(int trackNum) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPlayer::applyPortamento(int trackNum) {
|
void ModPlayer_impl::applyPortamento(int trackNum) {
|
||||||
debug(DBG_MOD, "ModPlayer::applyPortamento(%d)", trackNum);
|
debug(DBG_MOD, "ModPlayer::applyPortamento(%d)", trackNum);
|
||||||
Track *tk = &_tracks[trackNum];
|
Track *tk = &_tracks[trackNum];
|
||||||
if (tk->period < tk->portamento) {
|
if (tk->period < tk->portamento) {
|
||||||
|
@ -196,7 +317,7 @@ void ModPlayer::applyPortamento(int trackNum) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPlayer::handleEffect(int trackNum, bool tick) {
|
void ModPlayer_impl::handleEffect(int trackNum, bool tick) {
|
||||||
Track *tk = &_tracks[trackNum];
|
Track *tk = &_tracks[trackNum];
|
||||||
uint8_t effectNum = tk->effectData >> 8;
|
uint8_t effectNum = tk->effectData >> 8;
|
||||||
uint8_t effectXY = tk->effectData & 0xFF;
|
uint8_t effectXY = tk->effectData & 0xFF;
|
||||||
|
@ -209,10 +330,10 @@ void ModPlayer::handleEffect(int trackNum, bool tick) {
|
||||||
uint16_t period = tk->period;
|
uint16_t period = tk->period;
|
||||||
switch (_currentTick & 3) {
|
switch (_currentTick & 3) {
|
||||||
case 1:
|
case 1:
|
||||||
period = _periodTable[tk->periodIndex + effectX];
|
period = ModPlayer::_periodTable[tk->periodIndex + effectX];
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
period = _periodTable[tk->periodIndex + effectY];
|
period = ModPlayer::_periodTable[tk->periodIndex + effectY];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tk->freq = PAULA_FREQ / period;
|
tk->freq = PAULA_FREQ / period;
|
||||||
|
@ -411,7 +532,7 @@ void ModPlayer::handleEffect(int trackNum, bool tick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPlayer::handleTick() {
|
void ModPlayer_impl::handleTick() {
|
||||||
if (!_playing) {
|
if (!_playing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -436,9 +557,9 @@ void ModPlayer::handleTick() {
|
||||||
// On the amiga version, the introduction cutscene is shorter than the PC version ;
|
// On the amiga version, the introduction cutscene is shorter than the PC version ;
|
||||||
// so the music module doesn't synchronize at all with the PC datafiles, here we
|
// so the music module doesn't synchronize at all with the PC datafiles, here we
|
||||||
// add a hack to let the music play longer
|
// add a hack to let the music play longer
|
||||||
if (_songNum == 0 && _currentPatternOrder == 3 && !_introSongHack) {
|
if (_currentPatternOrder == 3 && _repeatIntro) {
|
||||||
_currentPatternOrder = 1;
|
_currentPatternOrder = 1;
|
||||||
_introSongHack = true;
|
_repeatIntro = false;
|
||||||
// warning("Introduction module synchronization hack");
|
// warning("Introduction module synchronization hack");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -456,7 +577,7 @@ void ModPlayer::handleTick() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModPlayer::mixSamples(int8_t *buf, int samplesLen) {
|
void ModPlayer_impl::mixSamples(int8_t *buf, int samplesLen) {
|
||||||
for (int i = 0; i < NUM_TRACKS; ++i) {
|
for (int i = 0; i < NUM_TRACKS; ++i) {
|
||||||
Track *tk = &_tracks[i];
|
Track *tk = &_tracks[i];
|
||||||
if (tk->sample != 0 && tk->delayCounter == 0) {
|
if (tk->sample != 0 && tk->delayCounter == 0) {
|
||||||
|
@ -465,7 +586,7 @@ void ModPlayer::mixSamples(int8_t *buf, int samplesLen) {
|
||||||
int len = si->len << FRAC_BITS;
|
int len = si->len << FRAC_BITS;
|
||||||
int loopLen = si->repeatLen << FRAC_BITS;
|
int loopLen = si->repeatLen << FRAC_BITS;
|
||||||
int loopPos = si->repeatPos << FRAC_BITS;
|
int loopPos = si->repeatPos << FRAC_BITS;
|
||||||
int deltaPos = (tk->freq << FRAC_BITS) / _mix->getSampleRate();
|
int deltaPos = (tk->freq << FRAC_BITS) / _mixingRate;
|
||||||
int curLen = samplesLen;
|
int curLen = samplesLen;
|
||||||
int pos = tk->pos;
|
int pos = tk->pos;
|
||||||
while (curLen != 0) {
|
while (curLen != 0) {
|
||||||
|
@ -485,7 +606,7 @@ void ModPlayer::mixSamples(int8_t *buf, int samplesLen) {
|
||||||
curLen = 0;
|
curLen = 0;
|
||||||
}
|
}
|
||||||
while (count--) {
|
while (count--) {
|
||||||
int out = resampleLinear(si, pos, deltaPos, FRAC_BITS);
|
const int out = si->getPCM(pos >> FRAC_BITS);
|
||||||
Mixer::addclamp(*mixbuf++, out * tk->volume / 64);
|
Mixer::addclamp(*mixbuf++, out * tk->volume / 64);
|
||||||
pos += deltaPos;
|
pos += deltaPos;
|
||||||
}
|
}
|
||||||
|
@ -495,10 +616,10 @@ void ModPlayer::mixSamples(int8_t *buf, int samplesLen) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModPlayer::mix(int8_t *buf, int len) {
|
bool ModPlayer_impl::mix(int8_t *buf, int len) {
|
||||||
if (_playing) {
|
if (_playing) {
|
||||||
memset(buf, 0, len);
|
memset(buf, 0, len);
|
||||||
const int samplesPerTick = _mix->getSampleRate() / (50 * _songTempo / 125);
|
const int samplesPerTick = _mixingRate / (50 * _songTempo / 125);
|
||||||
while (len != 0) {
|
while (len != 0) {
|
||||||
if (_samplesLeft == 0) {
|
if (_samplesLeft == 0) {
|
||||||
handleTick();
|
handleTick();
|
||||||
|
@ -516,7 +637,42 @@ bool ModPlayer::mix(int8_t *buf, int len) {
|
||||||
}
|
}
|
||||||
return _playing;
|
return _playing;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ModPlayer::ModPlayer(Mixer *mixer, FileSystem *fs)
|
||||||
|
: _playing(false), _mix(mixer), _fs(fs) {
|
||||||
|
_impl = new ModPlayer_impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModPlayer::~ModPlayer() {
|
||||||
|
delete _impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModPlayer::play(int num) {
|
||||||
|
if (num < _modulesFilesCount) {
|
||||||
|
File f;
|
||||||
|
for (uint8_t i = 0; i < ARRAYSIZE(_modulesFiles[num]); ++i) {
|
||||||
|
if (f.open(_modulesFiles[num][i], "rb", _fs)) {
|
||||||
|
_impl->init(_mix->getSampleRate());
|
||||||
|
if (_impl->load(&f)) {
|
||||||
|
_impl->_repeatIntro = (num == 0) && !_isAmiga;
|
||||||
|
_mix->setPremixHook(mixCallback, _impl);
|
||||||
|
_playing = true;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModPlayer::stop() {
|
||||||
|
if (_playing) {
|
||||||
|
_mix->setPremixHook(0, 0);
|
||||||
|
_impl->unload();
|
||||||
|
_playing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ModPlayer::mixCallback(void *param, int8_t *buf, int len) {
|
bool ModPlayer::mixCallback(void *param, int8_t *buf, int len) {
|
||||||
return ((ModPlayer *)param)->mix(buf, len);
|
return ((ModPlayer_impl *)param)->mix(buf, len);
|
||||||
}
|
}
|
||||||
|
|
103
mod_player.h
103
mod_player.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MOD_PLAYER_H__
|
#ifndef MOD_PLAYER_H__
|
||||||
|
@ -20,101 +9,27 @@
|
||||||
|
|
||||||
#include "intern.h"
|
#include "intern.h"
|
||||||
|
|
||||||
struct File;
|
|
||||||
struct FileSystem;
|
struct FileSystem;
|
||||||
struct Mixer;
|
struct Mixer;
|
||||||
|
struct ModPlayer_impl;
|
||||||
|
|
||||||
struct ModPlayer {
|
struct ModPlayer {
|
||||||
enum {
|
|
||||||
NUM_SAMPLES = 31,
|
|
||||||
NUM_TRACKS = 4,
|
|
||||||
NUM_PATTERNS = 128,
|
|
||||||
FRAC_BITS = 12,
|
|
||||||
PAULA_FREQ = 3546897
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SampleInfo {
|
|
||||||
char name[23];
|
|
||||||
uint16_t len;
|
|
||||||
uint8_t fineTune;
|
|
||||||
uint8_t volume;
|
|
||||||
uint16_t repeatPos;
|
|
||||||
uint16_t repeatLen;
|
|
||||||
int8_t *data;
|
|
||||||
|
|
||||||
int8_t getPCM(int offset) const {
|
|
||||||
if (offset < 0) {
|
|
||||||
offset = 0;
|
|
||||||
} else if (offset >= (int)len) {
|
|
||||||
offset = len - 1;
|
|
||||||
}
|
|
||||||
return data[offset];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModuleInfo {
|
|
||||||
char songName[21];
|
|
||||||
SampleInfo samples[NUM_SAMPLES];
|
|
||||||
uint8_t numPatterns;
|
|
||||||
uint8_t patternOrderTable[NUM_PATTERNS];
|
|
||||||
uint8_t *patternsTable;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Track {
|
|
||||||
SampleInfo *sample;
|
|
||||||
uint8_t volume;
|
|
||||||
int pos;
|
|
||||||
int freq;
|
|
||||||
uint16_t period;
|
|
||||||
uint16_t periodIndex;
|
|
||||||
uint16_t effectData;
|
|
||||||
int vibratoSpeed;
|
|
||||||
int vibratoAmp;
|
|
||||||
int vibratoPos;
|
|
||||||
int portamento;
|
|
||||||
int portamentoSpeed;
|
|
||||||
int retriggerCounter;
|
|
||||||
int delayCounter;
|
|
||||||
int cutCounter;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int8_t _sineWaveTable[];
|
|
||||||
static const uint16_t _periodTable[];
|
static const uint16_t _periodTable[];
|
||||||
static const char *_modulesFiles[][2];
|
static const char *_modulesFiles[][2];
|
||||||
static const int _modulesFilesCount;
|
static const int _modulesFilesCount;
|
||||||
|
|
||||||
ModuleInfo _modInfo;
|
bool _isAmiga;
|
||||||
uint8_t _currentPatternOrder;
|
|
||||||
uint8_t _currentPatternPos;
|
|
||||||
uint8_t _currentTick;
|
|
||||||
uint8_t _songSpeed;
|
|
||||||
uint8_t _songTempo;
|
|
||||||
int _patternDelay;
|
|
||||||
int _patternLoopPos;
|
|
||||||
int _patternLoopCount;
|
|
||||||
int _samplesLeft;
|
|
||||||
uint8_t _songNum;
|
|
||||||
bool _introSongHack;
|
|
||||||
bool _playing;
|
bool _playing;
|
||||||
Track _tracks[NUM_TRACKS];
|
|
||||||
Mixer *_mix;
|
Mixer *_mix;
|
||||||
FileSystem *_fs;
|
FileSystem *_fs;
|
||||||
|
ModPlayer_impl *_impl;
|
||||||
|
|
||||||
ModPlayer(Mixer *mixer, FileSystem *fs);
|
ModPlayer(Mixer *mixer, FileSystem *fs);
|
||||||
|
~ModPlayer();
|
||||||
|
|
||||||
uint16_t findPeriod(uint16_t period, uint8_t fineTune) const;
|
void play(int num);
|
||||||
void load(File *f);
|
|
||||||
void unload();
|
|
||||||
void play(uint8_t num);
|
|
||||||
void stop();
|
void stop();
|
||||||
void handleNote(int trackNum, uint32_t noteData);
|
|
||||||
void handleTick();
|
|
||||||
void applyVolumeSlide(int trackNum, int amount);
|
|
||||||
void applyVibrato(int trackNum);
|
|
||||||
void applyPortamento(int trackNum);
|
|
||||||
void handleEffect(int trackNum, bool tick);
|
|
||||||
void mixSamples(int8_t *buf, int len);
|
|
||||||
bool mix(int8_t *buf, int len);
|
|
||||||
|
|
||||||
static bool mixCallback(void *param, int8_t *buf, int len);
|
static bool mixCallback(void *param, int8_t *buf, int len);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_TREMOR
|
#ifdef USE_TREMOR
|
||||||
|
|
19
ogg_player.h
19
ogg_player.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef OGG_PLAYER_H__
|
#ifndef OGG_PLAYER_H__
|
||||||
|
|
50
piege.cpp
50
piege.cpp
|
@ -1,25 +1,14 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cutscene.h"
|
#include "cutscene.h"
|
||||||
|
#include "game.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
#include "game.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
void Game::pge_resetGroups() {
|
void Game::pge_resetGroups() {
|
||||||
memset(_pge_groupsTable, 0, sizeof(_pge_groupsTable));
|
memset(_pge_groupsTable, 0, sizeof(_pge_groupsTable));
|
||||||
|
@ -133,7 +122,7 @@ void Game::pge_process(LivePGE *pge) {
|
||||||
pge_setupNextAnimFrame(pge, le);
|
pge_setupNextAnimFrame(pge, le);
|
||||||
}
|
}
|
||||||
const uint8_t *anim_data = _res.getAniData(pge->obj_type);
|
const uint8_t *anim_data = _res.getAniData(pge->obj_type);
|
||||||
if (READ_LE_UINT16(anim_data) <= pge->anim_seq) {
|
if (_res._readUint16(anim_data) <= pge->anim_seq) {
|
||||||
InitPGE *init_pge = pge->init_PGE;
|
InitPGE *init_pge = pge->init_PGE;
|
||||||
assert(init_pge->obj_node_number < _res._numObjectNodes);
|
assert(init_pge->obj_node_number < _res._numObjectNodes);
|
||||||
ObjectNode *on = _res._objectNodesMap[init_pge->obj_node_number];
|
ObjectNode *on = _res._objectNodesMap[init_pge->obj_node_number];
|
||||||
|
@ -200,7 +189,7 @@ void Game::pge_setupNextAnimFrame(LivePGE *pge, GroupPGE *le) {
|
||||||
|
|
||||||
set_anim:
|
set_anim:
|
||||||
const uint8_t *anim_data = _res.getAniData(pge->obj_type);
|
const uint8_t *anim_data = _res.getAniData(pge->obj_type);
|
||||||
uint8_t _dh = READ_LE_UINT16(anim_data);
|
uint8_t _dh = _res._readUint16(anim_data);
|
||||||
uint8_t _dl = pge->anim_seq;
|
uint8_t _dl = pge->anim_seq;
|
||||||
const uint8_t *anim_frame = anim_data + 6 + _dl * 4;
|
const uint8_t *anim_frame = anim_data + 6 + _dl * 4;
|
||||||
while (_dh > _dl) {
|
while (_dh > _dl) {
|
||||||
|
@ -239,12 +228,12 @@ void Game::pge_playAnimSound(LivePGE *pge, uint16_t arg2) {
|
||||||
void Game::pge_setupAnim(LivePGE *pge) {
|
void Game::pge_setupAnim(LivePGE *pge) {
|
||||||
debug(DBG_PGE, "Game::pge_setupAnim() pgeNum=%d", pge - &_pgeLive[0]);
|
debug(DBG_PGE, "Game::pge_setupAnim() pgeNum=%d", pge - &_pgeLive[0]);
|
||||||
const uint8_t *anim_data = _res.getAniData(pge->obj_type);
|
const uint8_t *anim_data = _res.getAniData(pge->obj_type);
|
||||||
if (READ_LE_UINT16(anim_data) < pge->anim_seq) {
|
if (_res._readUint16(anim_data) < pge->anim_seq) {
|
||||||
pge->anim_seq = 0;
|
pge->anim_seq = 0;
|
||||||
}
|
}
|
||||||
const uint8_t *anim_frame = anim_data + 6 + pge->anim_seq * 4;
|
const uint8_t *anim_frame = anim_data + 6 + pge->anim_seq * 4;
|
||||||
if (READ_LE_UINT16(anim_frame) != 0xFFFF) {
|
if (_res._readUint16(anim_frame) != 0xFFFF) {
|
||||||
uint16_t fl = READ_LE_UINT16(anim_frame);
|
uint16_t fl = _res._readUint16(anim_frame);
|
||||||
if (pge->flags & 1) {
|
if (pge->flags & 1) {
|
||||||
fl ^= 0x8000;
|
fl ^= 0x8000;
|
||||||
pge->pos_x -= (int8_t)anim_frame[2];
|
pge->pos_x -= (int8_t)anim_frame[2];
|
||||||
|
@ -257,10 +246,10 @@ void Game::pge_setupAnim(LivePGE *pge) {
|
||||||
pge->flags |= 2;
|
pge->flags |= 2;
|
||||||
}
|
}
|
||||||
pge->flags &= ~8;
|
pge->flags &= ~8;
|
||||||
if (READ_LE_UINT16(anim_data + 4) & 0xFFFF) {
|
if (_res._readUint16(anim_data + 4) & 0xFFFF) {
|
||||||
pge->flags |= 8;
|
pge->flags |= 8;
|
||||||
}
|
}
|
||||||
pge->anim_number = READ_LE_UINT16(anim_frame) & 0x7FFF;
|
pge->anim_number = _res._readUint16(anim_frame) & 0x7FFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,12 +360,12 @@ void Game::pge_prepare() {
|
||||||
|
|
||||||
void Game::pge_setupDefaultAnim(LivePGE *pge) {
|
void Game::pge_setupDefaultAnim(LivePGE *pge) {
|
||||||
const uint8_t *anim_data = _res.getAniData(pge->obj_type);
|
const uint8_t *anim_data = _res.getAniData(pge->obj_type);
|
||||||
if (pge->anim_seq < READ_LE_UINT16(anim_data)) {
|
if (pge->anim_seq < _res._readUint16(anim_data)) {
|
||||||
pge->anim_seq = 0;
|
pge->anim_seq = 0;
|
||||||
}
|
}
|
||||||
const uint8_t *anim_frame = anim_data + 6 + pge->anim_seq * 4;
|
const uint8_t *anim_frame = anim_data + 6 + pge->anim_seq * 4;
|
||||||
if (READ_LE_UINT16(anim_frame) != 0xFFFF) {
|
if (_res._readUint16(anim_frame) != 0xFFFF) {
|
||||||
uint16_t f = READ_LE_UINT16(anim_data);
|
uint16_t f = _res._readUint16(anim_data);
|
||||||
if (pge->flags & 1) {
|
if (pge->flags & 1) {
|
||||||
f ^= 0x8000;
|
f ^= 0x8000;
|
||||||
}
|
}
|
||||||
|
@ -385,10 +374,10 @@ void Game::pge_setupDefaultAnim(LivePGE *pge) {
|
||||||
pge->flags |= 2;
|
pge->flags |= 2;
|
||||||
}
|
}
|
||||||
pge->flags &= ~8;
|
pge->flags &= ~8;
|
||||||
if (READ_LE_UINT16(anim_data + 4) & 0xFFFF) {
|
if (_res._readUint16(anim_data + 4) & 0xFFFF) {
|
||||||
pge->flags |= 8;
|
pge->flags |= 8;
|
||||||
}
|
}
|
||||||
pge->anim_number = READ_LE_UINT16(anim_frame) & 0x7FFF;
|
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=%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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1277,7 +1266,8 @@ int Game::pge_op_setPiegeDefaultAnim(ObjectOpcodeArgs *args) {
|
||||||
int16_t r = args->pge->init_PGE->counter_values[args->a];
|
int16_t r = args->pge->init_PGE->counter_values[args->a];
|
||||||
args->pge->room_location = r;
|
args->pge->room_location = r;
|
||||||
if (r == 1) {
|
if (r == 1) {
|
||||||
warning("setting _loadMap to true");
|
// this happens after death tower, on earth, when Conrad passes
|
||||||
|
// by the first policeman who's about to shoot him in the back
|
||||||
_loadMap = true;
|
_loadMap = true;
|
||||||
}
|
}
|
||||||
pge_setupDefaultAnim(args->pge);
|
pge_setupDefaultAnim(args->pge);
|
||||||
|
|
347
resource.cpp
347
resource.cpp
|
@ -1,31 +1,25 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "unpack.h"
|
#include "fs.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
#include "unpack.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
Resource::Resource(FileSystem *fs, ResourceType ver, Language lang) {
|
Resource::Resource(FileSystem *fs, ResourceType ver, Language lang) {
|
||||||
memset(this, 0, sizeof(Resource));
|
memset(this, 0, sizeof(Resource));
|
||||||
|
_fs = fs;
|
||||||
_type = ver;
|
_type = ver;
|
||||||
_lang = lang;
|
_lang = lang;
|
||||||
_fs = fs;
|
_isDemo = false;
|
||||||
_memBuf = (uint8_t *)malloc(256 * 224);
|
_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) {
|
if (!_memBuf) {
|
||||||
error("Unable to allocate temporary memory buffer");
|
error("Unable to allocate temporary memory buffer");
|
||||||
}
|
}
|
||||||
|
@ -56,6 +50,25 @@ Resource::~Resource() {
|
||||||
}
|
}
|
||||||
free(_sfxList);
|
free(_sfxList);
|
||||||
free(_bankData);
|
free(_bankData);
|
||||||
|
delete _aba;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resource::init() {
|
||||||
|
switch (_type) {
|
||||||
|
case kResourceTypeAmiga:
|
||||||
|
_isDemo = _fs->exists("demo.lev");
|
||||||
|
break;
|
||||||
|
case kResourceTypeDOS:
|
||||||
|
if (_fs->exists(ResourceAba::FILENAME)) {
|
||||||
|
_aba = new ResourceAba(_fs);
|
||||||
|
_aba->readEntries();
|
||||||
|
_isDemo = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resource::fini() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::clearLevelRes() {
|
void Resource::clearLevelRes() {
|
||||||
|
@ -66,6 +79,7 @@ void Resource::clearLevelRes() {
|
||||||
free(_lev); _lev = 0;
|
free(_lev); _lev = 0;
|
||||||
_levNum = -1;
|
_levNum = -1;
|
||||||
free(_sgd); _sgd = 0;
|
free(_sgd); _sgd = 0;
|
||||||
|
free(_bnq); _bnq = 0;
|
||||||
free(_ani); _ani = 0;
|
free(_ani); _ani = 0;
|
||||||
free_OBJ();
|
free_OBJ();
|
||||||
}
|
}
|
||||||
|
@ -119,7 +133,7 @@ void Resource::load_FIB(const char *fileName) {
|
||||||
error("I/O error when reading '%s'", _entryName);
|
error("I/O error when reading '%s'", _entryName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error("Can't open '%s'", _entryName);
|
error("Cannot open '%s'", _entryName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,45 +160,86 @@ void Resource::load_SPL_demo() {
|
||||||
|
|
||||||
void Resource::load_MAP_menu(const char *fileName, uint8_t *dstPtr) {
|
void Resource::load_MAP_menu(const char *fileName, uint8_t *dstPtr) {
|
||||||
debug(DBG_RES, "Resource::load_MAP_menu('%s')", fileName);
|
debug(DBG_RES, "Resource::load_MAP_menu('%s')", fileName);
|
||||||
|
static const int kMenuMapSize = 0x3800 * 4;
|
||||||
snprintf(_entryName, sizeof(_entryName), "%s.MAP", fileName);
|
snprintf(_entryName, sizeof(_entryName), "%s.MAP", fileName);
|
||||||
File f;
|
File f;
|
||||||
if (f.open(_entryName, "rb", _fs)) {
|
if (f.open(_entryName, "rb", _fs)) {
|
||||||
if (f.size() != 0x3800 * 4) {
|
if (f.read(dstPtr, kMenuMapSize) != kMenuMapSize) {
|
||||||
error("Wrong file size for '%s', %d", _entryName, f.size());
|
error("Failed to read '%s'", _entryName);
|
||||||
}
|
}
|
||||||
f.read(dstPtr, 0x3800 * 4);
|
|
||||||
if (f.ioErr()) {
|
if (f.ioErr()) {
|
||||||
error("I/O error when reading '%s'", _entryName);
|
error("I/O error when reading '%s'", _entryName);
|
||||||
}
|
}
|
||||||
} else {
|
return;
|
||||||
error("Can't open '%s'", _entryName);
|
} else if (_aba) {
|
||||||
|
uint32_t size = 0;
|
||||||
|
uint8_t *dat = _aba->loadEntry(_entryName, &size);
|
||||||
|
if (dat) {
|
||||||
|
if (size != kMenuMapSize) {
|
||||||
|
error("Unexpected size %d for '%s'", size, _entryName);
|
||||||
}
|
}
|
||||||
|
memcpy(dstPtr, dat, size);
|
||||||
|
free(dat);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("Cannot load '%s'", _entryName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::load_PAL_menu(const char *fileName, uint8_t *dstPtr) {
|
void Resource::load_PAL_menu(const char *fileName, uint8_t *dstPtr) {
|
||||||
debug(DBG_RES, "Resource::load_PAL_menu('%s')", fileName);
|
debug(DBG_RES, "Resource::load_PAL_menu('%s')", fileName);
|
||||||
|
static const int kMenuPalSize = 768;
|
||||||
snprintf(_entryName, sizeof(_entryName), "%s.PAL", fileName);
|
snprintf(_entryName, sizeof(_entryName), "%s.PAL", fileName);
|
||||||
File f;
|
File f;
|
||||||
if (f.open(_entryName, "rb", _fs)) {
|
if (f.open(_entryName, "rb", _fs)) {
|
||||||
if (f.size() != 768) {
|
if (f.read(dstPtr, kMenuPalSize) != kMenuPalSize) {
|
||||||
error("Wrong file size for '%s', %d", _entryName, f.size());
|
error("Failed to read '%s'", _entryName);
|
||||||
}
|
}
|
||||||
f.read(dstPtr, 768);
|
|
||||||
if (f.ioErr()) {
|
if (f.ioErr()) {
|
||||||
error("I/O error when reading '%s'", _entryName);
|
error("I/O error when reading '%s'", _entryName);
|
||||||
}
|
}
|
||||||
} else {
|
return;
|
||||||
error("Can't open '%s'", _entryName);
|
} else if (_aba) {
|
||||||
|
uint32_t size = 0;
|
||||||
|
uint8_t *dat = _aba->loadEntry(_entryName, &size);
|
||||||
|
if (dat) {
|
||||||
|
if (size != kMenuPalSize) {
|
||||||
|
error("Unexpected size %d for '%s'", size, _entryName);
|
||||||
}
|
}
|
||||||
|
memcpy(dstPtr, dat, size);
|
||||||
|
free(dat);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("Cannot load '%s'", _entryName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resource::load_CMP_menu(const char *fileName, uint8_t *dstPtr) {
|
||||||
|
File f;
|
||||||
|
if (f.open(fileName, "rb", _fs)) {
|
||||||
|
const uint32_t size = f.readUint32BE();
|
||||||
|
uint8_t *tmp = (uint8_t *)malloc(size);
|
||||||
|
if (!tmp) {
|
||||||
|
error("Failed to allocate CMP temporary buffer");
|
||||||
|
}
|
||||||
|
f.read(tmp, size);
|
||||||
|
if (!delphine_unpack(dstPtr, tmp, size)) {
|
||||||
|
error("Bad CRC for %s", fileName);
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
error("Cannot load '%s'", fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::load_SPR_OFF(const char *fileName, uint8_t *sprData) {
|
void Resource::load_SPR_OFF(const char *fileName, uint8_t *sprData) {
|
||||||
debug(DBG_RES, "Resource::load_SPR_OFF('%s')", fileName);
|
debug(DBG_RES, "Resource::load_SPR_OFF('%s')", fileName);
|
||||||
snprintf(_entryName, sizeof(_entryName), "%s.OFF", fileName);
|
snprintf(_entryName, sizeof(_entryName), "%s.OFF", fileName);
|
||||||
|
uint8_t *offData = 0;
|
||||||
File f;
|
File f;
|
||||||
if (f.open(_entryName, "rb", _fs)) {
|
if (f.open(_entryName, "rb", _fs)) {
|
||||||
int len = f.size();
|
const int len = f.size();
|
||||||
uint8_t *offData = (uint8_t *)malloc(len);
|
offData = (uint8_t *)malloc(len);
|
||||||
if (!offData) {
|
if (!offData) {
|
||||||
error("Unable to allocate sprite offsets");
|
error("Unable to allocate sprite offsets");
|
||||||
}
|
}
|
||||||
|
@ -192,6 +247,10 @@ void Resource::load_SPR_OFF(const char *fileName, uint8_t *sprData) {
|
||||||
if (f.ioErr()) {
|
if (f.ioErr()) {
|
||||||
error("I/O error when reading '%s'", _entryName);
|
error("I/O error when reading '%s'", _entryName);
|
||||||
}
|
}
|
||||||
|
} else if (_aba) {
|
||||||
|
offData = _aba->loadEntry(_entryName);
|
||||||
|
}
|
||||||
|
if (offData) {
|
||||||
const uint8_t *p = offData;
|
const uint8_t *p = offData;
|
||||||
uint16_t pos;
|
uint16_t pos;
|
||||||
while ((pos = READ_LE_UINT16(p)) != 0xFFFF) {
|
while ((pos = READ_LE_UINT16(p)) != 0xFFFF) {
|
||||||
|
@ -205,9 +264,9 @@ void Resource::load_SPR_OFF(const char *fileName, uint8_t *sprData) {
|
||||||
p += 6;
|
p += 6;
|
||||||
}
|
}
|
||||||
free(offData);
|
free(offData);
|
||||||
} else {
|
return;
|
||||||
error("Can't open '%s'", _entryName);
|
|
||||||
}
|
}
|
||||||
|
error("Cannot load '%s'", _entryName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::load_CINE() {
|
void Resource::load_CINE() {
|
||||||
|
@ -243,8 +302,11 @@ void Resource::load_CINE() {
|
||||||
if (f.ioErr()) {
|
if (f.ioErr()) {
|
||||||
error("I/O error when reading '%s'", _entryName);
|
error("I/O error when reading '%s'", _entryName);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (_aba) {
|
||||||
error("Can't open '%s'", _entryName);
|
_cine_off = _aba->loadEntry(_entryName);
|
||||||
|
}
|
||||||
|
if (!_cine_off) {
|
||||||
|
error("Cannot load '%s'", _entryName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_cine_txt == 0) {
|
if (_cine_txt == 0) {
|
||||||
|
@ -260,8 +322,11 @@ void Resource::load_CINE() {
|
||||||
if (f.ioErr()) {
|
if (f.ioErr()) {
|
||||||
error("I/O error when reading '%s'", _entryName);
|
error("I/O error when reading '%s'", _entryName);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (_aba) {
|
||||||
error("Can't open '%s'", _entryName);
|
_cine_txt = _aba->loadEntry(_entryName);
|
||||||
|
}
|
||||||
|
if (!_cine_txt) {
|
||||||
|
error("Cannot load '%s'", _entryName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,6 +523,10 @@ void Resource::load(const char *objName, int objType, const char *ext) {
|
||||||
snprintf(_entryName, sizeof(_entryName), "%s.SGD", objName);
|
snprintf(_entryName, sizeof(_entryName), "%s.SGD", objName);
|
||||||
loadStub = &Resource::load_SGD;
|
loadStub = &Resource::load_SGD;
|
||||||
break;
|
break;
|
||||||
|
case OT_BNQ:
|
||||||
|
snprintf(_entryName, sizeof(_entryName), "%s.BNQ", objName);
|
||||||
|
loadStub = &Resource::load_BNQ;
|
||||||
|
break;
|
||||||
case OT_SPM:
|
case OT_SPM:
|
||||||
snprintf(_entryName, sizeof(_entryName), "%s.SPM", objName);
|
snprintf(_entryName, sizeof(_entryName), "%s.SPM", objName);
|
||||||
loadStub = &Resource::load_SPM;
|
loadStub = &Resource::load_SPM;
|
||||||
|
@ -477,7 +546,70 @@ void Resource::load(const char *objName, int objType, const char *ext) {
|
||||||
error("I/O error when reading '%s'", _entryName);
|
error("I/O error when reading '%s'", _entryName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error("Can't open '%s'", _entryName);
|
if (_aba) {
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t *dat = _aba->loadEntry(_entryName, &size);
|
||||||
|
if (dat) {
|
||||||
|
switch (objType) {
|
||||||
|
case OT_MBK:
|
||||||
|
_mbk = dat;
|
||||||
|
break;
|
||||||
|
case OT_PGE:
|
||||||
|
decodePGE(dat, size);
|
||||||
|
break;
|
||||||
|
case OT_PAL:
|
||||||
|
_pal = dat;
|
||||||
|
break;
|
||||||
|
case OT_CT:
|
||||||
|
if (!delphine_unpack((uint8_t *)_ctData, dat, size)) {
|
||||||
|
error("Bad CRC for '%s'", _entryName);
|
||||||
|
}
|
||||||
|
free(dat);
|
||||||
|
break;
|
||||||
|
case OT_SPC:
|
||||||
|
_spc = dat;
|
||||||
|
_numSpc = READ_BE_UINT16(_spc) / 2;
|
||||||
|
break;
|
||||||
|
case OT_RP:
|
||||||
|
if (size != 0x4A) {
|
||||||
|
error("Unexpected size %d for '%s'", size, _entryName);
|
||||||
|
}
|
||||||
|
memcpy(_rp, dat, size);
|
||||||
|
free(dat);
|
||||||
|
break;
|
||||||
|
case OT_ICN:
|
||||||
|
_icn = dat;
|
||||||
|
break;
|
||||||
|
case OT_FNT:
|
||||||
|
_fnt = dat;
|
||||||
|
break;
|
||||||
|
case OT_OBJ:
|
||||||
|
_numObjectNodes = READ_LE_UINT16(dat);
|
||||||
|
assert(_numObjectNodes == 230);
|
||||||
|
decodeOBJ(dat + 2, size - 2);
|
||||||
|
break;
|
||||||
|
case OT_ANI:
|
||||||
|
_ani = dat;
|
||||||
|
break;
|
||||||
|
case OT_TBN:
|
||||||
|
_tbn = dat;
|
||||||
|
break;
|
||||||
|
case OT_CMD:
|
||||||
|
_cmd = dat;
|
||||||
|
break;
|
||||||
|
case OT_POL:
|
||||||
|
_pol = dat;
|
||||||
|
break;
|
||||||
|
case OT_BNQ:
|
||||||
|
_bnq = dat;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Cannot load '%s' type %d", _entryName, objType);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("Cannot open '%s'", _entryName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,7 +834,7 @@ void Resource::decodeOBJ(const uint8_t *tmp, int size) {
|
||||||
int tmpOffset = 0;
|
int tmpOffset = 0;
|
||||||
_numObjectNodes = 230;
|
_numObjectNodes = 230;
|
||||||
for (int i = 0; i < _numObjectNodes; ++i) {
|
for (int i = 0; i < _numObjectNodes; ++i) {
|
||||||
offsets[i] = READ_BE_UINT32(tmp + tmpOffset); tmpOffset += 4;
|
offsets[i] = _readUint32(tmp + tmpOffset); tmpOffset += 4;
|
||||||
}
|
}
|
||||||
offsets[_numObjectNodes] = size;
|
offsets[_numObjectNodes] = size;
|
||||||
int numObjectsCount = 0;
|
int numObjectsCount = 0;
|
||||||
|
@ -724,23 +856,23 @@ void Resource::decodeOBJ(const uint8_t *tmp, int size) {
|
||||||
error("Unable to allocate ObjectNode num=%d", i);
|
error("Unable to allocate ObjectNode num=%d", i);
|
||||||
}
|
}
|
||||||
const uint8_t *objData = tmp + offsets[i];
|
const uint8_t *objData = tmp + offsets[i];
|
||||||
on->last_obj_number = READ_BE_UINT16(objData); objData += 2;
|
on->last_obj_number = _readUint16(objData); objData += 2;
|
||||||
on->num_objects = objectsCount[iObj];
|
on->num_objects = objectsCount[iObj];
|
||||||
on->objects = (Object *)malloc(sizeof(Object) * on->num_objects);
|
on->objects = (Object *)malloc(sizeof(Object) * on->num_objects);
|
||||||
for (int j = 0; j < on->num_objects; ++j) {
|
for (int j = 0; j < on->num_objects; ++j) {
|
||||||
Object *obj = &on->objects[j];
|
Object *obj = &on->objects[j];
|
||||||
obj->type = READ_BE_UINT16(objData); objData += 2;
|
obj->type = _readUint16(objData); objData += 2;
|
||||||
obj->dx = *objData++;
|
obj->dx = *objData++;
|
||||||
obj->dy = *objData++;
|
obj->dy = *objData++;
|
||||||
obj->init_obj_type = READ_BE_UINT16(objData); objData += 2;
|
obj->init_obj_type = _readUint16(objData); objData += 2;
|
||||||
obj->opcode2 = *objData++;
|
obj->opcode2 = *objData++;
|
||||||
obj->opcode1 = *objData++;
|
obj->opcode1 = *objData++;
|
||||||
obj->flags = *objData++;
|
obj->flags = *objData++;
|
||||||
obj->opcode3 = *objData++;
|
obj->opcode3 = *objData++;
|
||||||
obj->init_obj_number = READ_BE_UINT16(objData); objData += 2;
|
obj->init_obj_number = _readUint16(objData); objData += 2;
|
||||||
obj->opcode_arg1 = READ_BE_UINT16(objData); objData += 2;
|
obj->opcode_arg1 = _readUint16(objData); objData += 2;
|
||||||
obj->opcode_arg2 = READ_BE_UINT16(objData); objData += 2;
|
obj->opcode_arg2 = _readUint16(objData); objData += 2;
|
||||||
obj->opcode_arg3 = READ_BE_UINT16(objData); objData += 2;
|
obj->opcode_arg3 = _readUint16(objData); objData += 2;
|
||||||
debug(DBG_RES, "obj_node=%d obj=%d op1=0x%X op2=0x%X op3=0x%X", i, j, obj->opcode2, obj->opcode1, obj->opcode3);
|
debug(DBG_RES, "obj_node=%d obj=%d op1=0x%X op2=0x%X op3=0x%X", i, j, obj->opcode2, obj->opcode1, obj->opcode3);
|
||||||
}
|
}
|
||||||
++iObj;
|
++iObj;
|
||||||
|
@ -753,13 +885,20 @@ void Resource::decodeOBJ(const uint8_t *tmp, int size) {
|
||||||
|
|
||||||
void Resource::load_PGE(File *f) {
|
void Resource::load_PGE(File *f) {
|
||||||
debug(DBG_RES, "Resource::load_PGE()");
|
debug(DBG_RES, "Resource::load_PGE()");
|
||||||
int len = f->size() - 2;
|
|
||||||
_pgeNum = f->readUint16LE();
|
|
||||||
if (_type == kResourceTypeAmiga) {
|
if (_type == kResourceTypeAmiga) {
|
||||||
SWAP_UINT16(&_pgeNum);
|
const int size = f->size();
|
||||||
|
uint8_t *tmp = (uint8_t *)malloc(size);
|
||||||
|
if (!tmp) {
|
||||||
|
error("Unable to allocate PGE temporary buffer");
|
||||||
}
|
}
|
||||||
|
f->read(tmp, size);
|
||||||
|
decodePGE(tmp, size);
|
||||||
|
free(tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_pgeNum = f->readUint16LE();
|
||||||
memset(_pgeInit, 0, sizeof(_pgeInit));
|
memset(_pgeInit, 0, sizeof(_pgeInit));
|
||||||
debug(DBG_RES, "len=%d _pgeNum=%d", len, _pgeNum);
|
debug(DBG_RES, "_pgeNum=%d", _pgeNum);
|
||||||
for (uint16_t i = 0; i < _pgeNum; ++i) {
|
for (uint16_t i = 0; i < _pgeNum; ++i) {
|
||||||
InitPGE *pge = &_pgeInit[i];
|
InitPGE *pge = &_pgeInit[i];
|
||||||
pge->type = f->readUint16LE();
|
pge->type = f->readUint16LE();
|
||||||
|
@ -784,56 +923,46 @@ void Resource::load_PGE(File *f) {
|
||||||
f->readByte();
|
f->readByte();
|
||||||
pge->text_num = f->readUint16LE();
|
pge->text_num = f->readUint16LE();
|
||||||
}
|
}
|
||||||
if (_type == kResourceTypeAmiga) {
|
}
|
||||||
|
|
||||||
|
void Resource::decodePGE(const uint8_t *p, int size) {
|
||||||
|
_pgeNum = _readUint16(p); p += 2;
|
||||||
|
memset(_pgeInit, 0, sizeof(_pgeInit));
|
||||||
|
debug(DBG_RES, "len=%d _pgeNum=%d", size, _pgeNum);
|
||||||
for (uint16_t i = 0; i < _pgeNum; ++i) {
|
for (uint16_t i = 0; i < _pgeNum; ++i) {
|
||||||
InitPGE *pge = &_pgeInit[i];
|
InitPGE *pge = &_pgeInit[i];
|
||||||
SWAP_UINT16((uint16_t *)&pge->type);
|
pge->type = _readUint16(p); p += 2;
|
||||||
SWAP_UINT16((uint16_t *)&pge->pos_x);
|
pge->pos_x = _readUint16(p); p += 2;
|
||||||
SWAP_UINT16((uint16_t *)&pge->pos_y);
|
pge->pos_y = _readUint16(p); p += 2;
|
||||||
SWAP_UINT16((uint16_t *)&pge->obj_node_number);
|
pge->obj_node_number = _readUint16(p); p += 2;
|
||||||
SWAP_UINT16((uint16_t *)&pge->life);
|
pge->life = _readUint16(p); p += 2;
|
||||||
for (int lc = 0; lc < 4; ++lc) {
|
for (int lc = 0; lc < 4; ++lc) {
|
||||||
SWAP_UINT16((uint16_t *)&pge->counter_values[lc]);
|
pge->counter_values[lc] = _readUint16(p); p += 2;
|
||||||
}
|
|
||||||
SWAP_UINT16((uint16_t *)&pge->text_num);
|
|
||||||
}
|
}
|
||||||
|
pge->object_type = *p++;
|
||||||
|
pge->init_room = *p++;
|
||||||
|
pge->room_location = *p++;
|
||||||
|
pge->init_flags = *p++;
|
||||||
|
pge->colliding_icon_num = *p++;
|
||||||
|
pge->icon_num = *p++;
|
||||||
|
pge->object_id = *p++;
|
||||||
|
pge->skill = *p++;
|
||||||
|
pge->mirror_x = *p++;
|
||||||
|
pge->flags = *p++;
|
||||||
|
pge->unk1C = *p++;
|
||||||
|
++p;
|
||||||
|
pge->text_num = _readUint16(p); p += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::load_ANI(File *f) {
|
void Resource::load_ANI(File *f) {
|
||||||
debug(DBG_RES, "Resource::load_ANI()");
|
debug(DBG_RES, "Resource::load_ANI()");
|
||||||
int size = f->size() - 2;
|
const int size = f->size();
|
||||||
_ani = (uint8_t *)malloc(size);
|
_ani = (uint8_t *)malloc(size);
|
||||||
if (!_ani) {
|
if (!_ani) {
|
||||||
error("Unable to allocate ANI buffer");
|
error("Unable to allocate ANI buffer");
|
||||||
} else {
|
} else {
|
||||||
uint16_t count = f->readUint16LE();
|
|
||||||
f->read(_ani, size);
|
f->read(_ani, size);
|
||||||
if (_type == kResourceTypeAmiga) {
|
|
||||||
const uint8_t *end = _ani + size;
|
|
||||||
SWAP_UINT16(&count);
|
|
||||||
// byte-swap animation data
|
|
||||||
for (uint16_t i = 0; i < count; ++i) {
|
|
||||||
uint8_t *p = _ani + READ_BE_UINT16(_ani + 2 * i);
|
|
||||||
// byte-swap offset
|
|
||||||
SWAP<uint8_t>(_ani[2 * i], _ani[2 * i + 1]);
|
|
||||||
if (p >= end) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const int frames = READ_BE_UINT16(p);
|
|
||||||
if (p[0] != 0) {
|
|
||||||
// byte-swap only once
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// byte-swap anim count
|
|
||||||
SWAP<uint8_t>(p[0], p[1]);
|
|
||||||
debug(DBG_RES, "ani=%d frames=%d", i, frames);
|
|
||||||
for (int j = 0; j < frames; ++j) {
|
|
||||||
// byte-swap next frame
|
|
||||||
SWAP<uint8_t>(p[6 + j * 4], p[6 + j * 4 + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,13 +975,6 @@ void Resource::load_TBN(File *f) {
|
||||||
} else {
|
} else {
|
||||||
f->read(_tbn, len);
|
f->read(_tbn, len);
|
||||||
}
|
}
|
||||||
if (_type == kResourceTypeAmiga) {
|
|
||||||
const int firstOffset = READ_BE_UINT16(_tbn);
|
|
||||||
for (int i = 0; i < firstOffset; i += 2) {
|
|
||||||
// byte-swap offset
|
|
||||||
SWAP<uint8_t>(_tbn[i], _tbn[i + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::load_CMD(File *pf) {
|
void Resource::load_CMD(File *pf) {
|
||||||
|
@ -1011,6 +1133,17 @@ void Resource::load_LEV(File *f) {
|
||||||
|
|
||||||
void Resource::load_SGD(File *f) {
|
void Resource::load_SGD(File *f) {
|
||||||
const int len = f->size();
|
const int len = f->size();
|
||||||
|
if (_type == kResourceTypeDOS) {
|
||||||
|
_sgd = (uint8_t *)malloc(len);
|
||||||
|
if (!_sgd) {
|
||||||
|
error("Unable to allocate SGD buffer");
|
||||||
|
} else {
|
||||||
|
f->read(_sgd, len);
|
||||||
|
// first byte == number of entries, clear to fix up 32 bits offset
|
||||||
|
_sgd[0] = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
f->seek(len - 4);
|
f->seek(len - 4);
|
||||||
int size = f->readUint32BE();
|
int size = f->readUint32BE();
|
||||||
f->seek(0);
|
f->seek(0);
|
||||||
|
@ -1029,6 +1162,16 @@ void Resource::load_SGD(File *f) {
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Resource::load_BNQ(File *f) {
|
||||||
|
const int len = f->size();
|
||||||
|
_bnq = (uint8_t *)malloc(len);
|
||||||
|
if (!_bnq) {
|
||||||
|
error("Unable to allocate BNQ buffer");
|
||||||
|
} else {
|
||||||
|
f->read(_bnq, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Resource::load_SPM(File *f) {
|
void Resource::load_SPM(File *f) {
|
||||||
static const int kPersoDatSize = 178647;
|
static const int kPersoDatSize = 178647;
|
||||||
const int len = f->size();
|
const int len = f->size();
|
||||||
|
@ -1072,19 +1215,23 @@ void Resource::clearBankData() {
|
||||||
|
|
||||||
int Resource::getBankDataSize(uint16_t num) {
|
int Resource::getBankDataSize(uint16_t num) {
|
||||||
int len = READ_BE_UINT16(_mbk + num * 6 + 4);
|
int len = READ_BE_UINT16(_mbk + num * 6 + 4);
|
||||||
int size = 0;
|
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case kResourceTypeAmiga:
|
case kResourceTypeAmiga:
|
||||||
if (len & 0x8000) {
|
if (len & 0x8000) {
|
||||||
len = -(int16_t)len;
|
len = -(int16_t)len;
|
||||||
}
|
}
|
||||||
size = len * 32;
|
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
size = (len & 0x7FFF) * 32;
|
if (len & 0x8000) {
|
||||||
|
if (_mbk == _bnq) { // demo .bnq use signed int
|
||||||
|
len = -(int16_t)len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return size;
|
len &= 0x7FFF;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return len * 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *Resource::findBankData(uint16_t num) {
|
uint8_t *Resource::findBankData(uint16_t num) {
|
||||||
|
@ -1099,7 +1246,7 @@ uint8_t *Resource::findBankData(uint16_t num) {
|
||||||
uint8_t *Resource::loadBankData(uint16_t num) {
|
uint8_t *Resource::loadBankData(uint16_t num) {
|
||||||
const uint8_t *ptr = _mbk + num * 6;
|
const uint8_t *ptr = _mbk + num * 6;
|
||||||
int dataOffset = READ_BE_UINT32(ptr);
|
int dataOffset = READ_BE_UINT32(ptr);
|
||||||
if (_type == kResourceTypePC) {
|
if (_type == kResourceTypeDOS) {
|
||||||
// first byte of the data buffer corresponds
|
// first byte of the data buffer corresponds
|
||||||
// to the total count of entries
|
// to the total count of entries
|
||||||
dataOffset &= 0xFFFF;
|
dataOffset &= 0xFFFF;
|
||||||
|
|
45
resource.h
45
resource.h
|
@ -1,24 +1,14 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RESOURCE_H__
|
#ifndef RESOURCE_H__
|
||||||
#define RESOURCE_H__
|
#define RESOURCE_H__
|
||||||
|
|
||||||
#include "intern.h"
|
#include "intern.h"
|
||||||
|
#include "resource_aba.h"
|
||||||
|
|
||||||
struct File;
|
struct File;
|
||||||
struct FileSystem;
|
struct FileSystem;
|
||||||
|
@ -93,11 +83,13 @@ struct Resource {
|
||||||
OT_SPL,
|
OT_SPL,
|
||||||
OT_LEV,
|
OT_LEV,
|
||||||
OT_SGD,
|
OT_SGD,
|
||||||
|
OT_BNQ,
|
||||||
OT_SPM
|
OT_SPM
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NUM_SFXS = 66,
|
NUM_SFXS = 66,
|
||||||
|
NUM_BANK_BUFFERS = 50,
|
||||||
NUM_SPRITES = 1287
|
NUM_SPRITES = 1287
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,6 +100,10 @@ struct Resource {
|
||||||
FileSystem *_fs;
|
FileSystem *_fs;
|
||||||
ResourceType _type;
|
ResourceType _type;
|
||||||
Language _lang;
|
Language _lang;
|
||||||
|
bool _isDemo;
|
||||||
|
ResourceAba *_aba;
|
||||||
|
uint16_t (*_readUint16)(const void *);
|
||||||
|
uint32_t (*_readUint32)(const void *);
|
||||||
bool _hasSeqData;
|
bool _hasSeqData;
|
||||||
char _entryName[32];
|
char _entryName[32];
|
||||||
uint8_t *_fnt;
|
uint8_t *_fnt;
|
||||||
|
@ -131,6 +127,7 @@ struct Resource {
|
||||||
uint8_t *_lev;
|
uint8_t *_lev;
|
||||||
int _levNum;
|
int _levNum;
|
||||||
uint8_t *_sgd;
|
uint8_t *_sgd;
|
||||||
|
uint8_t *_bnq;
|
||||||
uint16_t _numObjectNodes;
|
uint16_t _numObjectNodes;
|
||||||
ObjectNode *_objectNodesMap[255];
|
ObjectNode *_objectNodesMap[255];
|
||||||
uint8_t *_memBuf;
|
uint8_t *_memBuf;
|
||||||
|
@ -147,17 +144,24 @@ struct Resource {
|
||||||
uint8_t *_bankData;
|
uint8_t *_bankData;
|
||||||
uint8_t *_bankDataHead;
|
uint8_t *_bankDataHead;
|
||||||
uint8_t *_bankDataTail;
|
uint8_t *_bankDataTail;
|
||||||
BankSlot _bankBuffers[50];
|
BankSlot _bankBuffers[NUM_BANK_BUFFERS];
|
||||||
int _bankBuffersCount;
|
int _bankBuffersCount;
|
||||||
|
|
||||||
Resource(FileSystem *fs, ResourceType type, Language lang);
|
Resource(FileSystem *fs, ResourceType type, Language lang);
|
||||||
~Resource();
|
~Resource();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void fini();
|
||||||
|
|
||||||
|
bool isDOS() const { return _type == kResourceTypeDOS; }
|
||||||
|
bool isAmiga() const { return _type == kResourceTypeAmiga; }
|
||||||
|
|
||||||
void clearLevelRes();
|
void clearLevelRes();
|
||||||
void load_FIB(const char *fileName);
|
void load_FIB(const char *fileName);
|
||||||
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_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 load_TEXT();
|
void load_TEXT();
|
||||||
|
@ -178,6 +182,7 @@ struct Resource {
|
||||||
void load_OBC(File *pf);
|
void load_OBC(File *pf);
|
||||||
void decodeOBJ(const uint8_t *, int);
|
void decodeOBJ(const uint8_t *, int);
|
||||||
void load_PGE(File *pf);
|
void load_PGE(File *pf);
|
||||||
|
void decodePGE(const uint8_t *, int);
|
||||||
void load_ANI(File *pf);
|
void load_ANI(File *pf);
|
||||||
void load_TBN(File *pf);
|
void load_TBN(File *pf);
|
||||||
void load_CMD(File *pf);
|
void load_CMD(File *pf);
|
||||||
|
@ -187,10 +192,14 @@ struct Resource {
|
||||||
void load_SPL(File *pf);
|
void load_SPL(File *pf);
|
||||||
void load_LEV(File *pf);
|
void load_LEV(File *pf);
|
||||||
void load_SGD(File *pf);
|
void load_SGD(File *pf);
|
||||||
|
void load_BNQ(File *pf);
|
||||||
void load_SPM(File *f);
|
void load_SPM(File *f);
|
||||||
const uint8_t *getAniData(int num) const {
|
const uint8_t *getAniData(int num) const {
|
||||||
const int offset = READ_LE_UINT16(_ani + num * 2);
|
const int offset = _readUint16(_ani + 2 + num * 2);
|
||||||
return _ani + offset;
|
return _ani + 2 + offset;
|
||||||
|
}
|
||||||
|
const uint8_t *getTextString(int num) {
|
||||||
|
return _tbn + _readUint16(_tbn + num * 2);
|
||||||
}
|
}
|
||||||
const uint8_t *getGameString(int num) {
|
const uint8_t *getGameString(int num) {
|
||||||
return _stringsTable + READ_LE_UINT16(_stringsTable + num * 2);
|
return _stringsTable + READ_LE_UINT16(_stringsTable + num * 2);
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
|
||||||
|
#include "resource_aba.h"
|
||||||
|
#include "unpack.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
const char *ResourceAba::FILENAME = "DEMO_UK.ABA";
|
||||||
|
|
||||||
|
ResourceAba::ResourceAba(FileSystem *fs)
|
||||||
|
: _fs(fs) {
|
||||||
|
_entries = 0;
|
||||||
|
_entriesCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceAba::~ResourceAba() {
|
||||||
|
free(_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceAba::readEntries() {
|
||||||
|
if (_f.open(FILENAME, "rb", _fs)) {
|
||||||
|
_entriesCount = _f.readUint16BE();
|
||||||
|
_entries = (ResourceAbaEntry *)calloc(_entriesCount, sizeof(ResourceAbaEntry));
|
||||||
|
if (!_entries) {
|
||||||
|
error("Failed to allocate %d _entries", _entriesCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int entrySize = _f.readUint16BE();
|
||||||
|
assert(entrySize == 30);
|
||||||
|
uint32_t nextOffset = 0;
|
||||||
|
for (int i = 0; i < _entriesCount; ++i) {
|
||||||
|
_f.read(_entries[i].name, sizeof(_entries[i].name));
|
||||||
|
_entries[i].offset = _f.readUint32BE();
|
||||||
|
_entries[i].compressedSize = _f.readUint32BE();
|
||||||
|
_entries[i].size = _f.readUint32BE();
|
||||||
|
const uint32_t tag = _f.readUint32BE();
|
||||||
|
assert(tag == TAG);
|
||||||
|
debug(DBG_RES, "'%s' offset 0x%X size %d/%d", _entries[i].name, _entries[i].offset, _entries[i].compressedSize, _entries[i].size);
|
||||||
|
if (i != 0) {
|
||||||
|
assert(nextOffset == _entries[i].offset);
|
||||||
|
}
|
||||||
|
nextOffset = _entries[i].offset + _entries[i].compressedSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ResourceAbaEntry *ResourceAba::findEntry(const char *name) const {
|
||||||
|
for (int i = 0; i < _entriesCount; ++i) {
|
||||||
|
if (strcasecmp(_entries[i].name, name) == 0) {
|
||||||
|
return &_entries[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *ResourceAba::loadEntry(const char *name, uint32_t *size) {
|
||||||
|
uint8_t *dst = 0;
|
||||||
|
const ResourceAbaEntry *e = findEntry(name);
|
||||||
|
if (e) {
|
||||||
|
if (size) {
|
||||||
|
*size = e->size;
|
||||||
|
}
|
||||||
|
uint8_t *tmp = (uint8_t *)malloc(e->compressedSize);
|
||||||
|
if (!tmp) {
|
||||||
|
error("Failed to allocate %d bytes", e->compressedSize);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_f.seek(e->offset);
|
||||||
|
_f.read(tmp, e->compressedSize);
|
||||||
|
if (e->compressedSize == e->size) {
|
||||||
|
dst = tmp;
|
||||||
|
} else {
|
||||||
|
dst = (uint8_t *)malloc(e->size);
|
||||||
|
if (!dst) {
|
||||||
|
error("Failed to allocate %d bytes", e->size);
|
||||||
|
free(tmp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const bool ret = delphine_unpack(dst, tmp, e->compressedSize);
|
||||||
|
if (!ret) {
|
||||||
|
error("Bad CRC for '%s'", name);
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
#ifndef RESOURCE_ABA_H__
|
||||||
|
#define RESOURCE_ABA_H__
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
struct FileSystem;
|
||||||
|
|
||||||
|
struct ResourceAbaEntry {
|
||||||
|
char name[14];
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t compressedSize;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResourceAba {
|
||||||
|
|
||||||
|
static const char *FILENAME;
|
||||||
|
static const int TAG = 0x442E4D2E;
|
||||||
|
|
||||||
|
FileSystem *_fs;
|
||||||
|
File _f;
|
||||||
|
ResourceAbaEntry *_entries;
|
||||||
|
int _entriesCount;
|
||||||
|
|
||||||
|
ResourceAba(FileSystem *fs);
|
||||||
|
~ResourceAba();
|
||||||
|
|
||||||
|
void readEntries();
|
||||||
|
const ResourceAbaEntry *findEntry(const char *name) const;
|
||||||
|
uint8_t *loadEntry(const char *name, uint32_t *size = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RESOURCE_ABA_H__
|
|
@ -0,0 +1,14 @@
|
||||||
|
# display copy protection shapes
|
||||||
|
bypass_protection=true
|
||||||
|
|
||||||
|
# enable playback of 'asc', 'metro' and 'serrure' cutscenes
|
||||||
|
play_disabled_cutscenes=false
|
||||||
|
|
||||||
|
# use original password level selection menu screen
|
||||||
|
enable_password_menu=false
|
||||||
|
|
||||||
|
# fade palette to black for screen transition (use blending if false)
|
||||||
|
fade_out_palette=true
|
||||||
|
|
||||||
|
# use .BNQ & .LEV datafiles (tile based rendering) for backgrounds (instead of .MAP)
|
||||||
|
use_tiledata=false
|
21
scaler.cpp
21
scaler.cpp
|
@ -1,22 +1,11 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "scaler.h"
|
#include "scaler.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
static void point1x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
|
static void point1x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
|
||||||
dstPitch >>= 1;
|
dstPitch >>= 1;
|
||||||
|
|
19
scaler.h
19
scaler.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SCALER_H__
|
#ifndef SCALER_H__
|
||||||
|
|
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
@ -20,7 +9,7 @@
|
||||||
#include "mixer.h"
|
#include "mixer.h"
|
||||||
#include "seq_player.h"
|
#include "seq_player.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
bool SeqDemuxer::open(File *f) {
|
bool SeqDemuxer::open(File *f) {
|
||||||
_f = f;
|
_f = f;
|
||||||
|
|
19
seq_player.h
19
seq_player.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SEQ_PLAYER_H__
|
#ifndef SEQ_PLAYER_H__
|
||||||
|
|
|
@ -1,23 +1,12 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mixer.h"
|
#include "mixer.h"
|
||||||
#include "sfx_player.h"
|
#include "sfx_player.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
SfxPlayer::SfxPlayer(Mixer *mixer)
|
SfxPlayer::SfxPlayer(Mixer *mixer)
|
||||||
: _mod(0), _playing(false), _mix(mixer) {
|
: _mod(0), _playing(false), _mix(mixer) {
|
||||||
|
@ -137,7 +126,7 @@ void SfxPlayer::mixSamples(int8_t *buf, int samplesLen) {
|
||||||
curLen = 0;
|
curLen = 0;
|
||||||
}
|
}
|
||||||
while (count--) {
|
while (count--) {
|
||||||
int out = resampleLinear(si, pos, deltaPos, FRAC_BITS);
|
const int out = si->getPCM(pos >> FRAC_BITS);
|
||||||
Mixer::addclamp(*mixbuf++, out * si->vol / 64);
|
Mixer::addclamp(*mixbuf++, out * si->vol / 64);
|
||||||
pos += deltaPos;
|
pos += deltaPos;
|
||||||
}
|
}
|
||||||
|
|
19
sfx_player.h
19
sfx_player.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SFX_PLAYER_H__
|
#ifndef SFX_PLAYER_H__
|
||||||
|
|
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
@ -72,7 +61,10 @@ const char *Cutscene::_namesTable[] = {
|
||||||
"LOGOS",
|
"LOGOS",
|
||||||
"OVER",
|
"OVER",
|
||||||
"SCORE",
|
"SCORE",
|
||||||
"INTRO2"
|
"INTRO2",
|
||||||
|
"SERRURE",
|
||||||
|
"HOLOCUBE",
|
||||||
|
"CHUTE2"
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint16_t Cutscene::_offsetsTable[] = {
|
const uint16_t Cutscene::_offsetsTable[] = {
|
||||||
|
@ -94,6 +86,12 @@ const uint16_t Cutscene::_offsetsTable[] = {
|
||||||
0xFFFF, 0x0000
|
0xFFFF, 0x0000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uint8_t Cutscene::_amigaDemoOffsetsTable[] = {
|
||||||
|
1, 32, 0, /* HOLOCUBE */
|
||||||
|
6, 33, 0, /* CHUTE2 */
|
||||||
|
255
|
||||||
|
};
|
||||||
|
|
||||||
const uint16_t Cutscene::_cosTable[] = {
|
const uint16_t Cutscene::_cosTable[] = {
|
||||||
0x0100, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FE, 0x00FE,
|
0x0100, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FE, 0x00FE,
|
||||||
0x00FD, 0x00FC, 0x00FC, 0x00FB, 0x00FA, 0x00F9, 0x00F8, 0x00F7,
|
0x00FD, 0x00FC, 0x00FC, 0x00FB, 0x00FA, 0x00F9, 0x00F8, 0x00F7,
|
||||||
|
@ -2545,13 +2543,6 @@ const uint8_t Video::_palSlot0xF[] = {
|
||||||
0xA7, 0xAF, 0xA7, 0xB3, 0xBF, 0xBB, 0xBF, 0xCF, 0xCF, 0xCF, 0x00, 0x33, 0x00, 0x17, 0x0F, 0x1F
|
0xA7, 0xAF, 0xA7, 0xB3, 0xBF, 0xBB, 0xBF, 0xCF, 0xCF, 0xCF, 0x00, 0x33, 0x00, 0x17, 0x0F, 0x1F
|
||||||
};
|
};
|
||||||
|
|
||||||
const int8_t ModPlayer::_sineWaveTable[] = {
|
|
||||||
0, 24, 49, 74, 97, 120, -115, -95, -76, -59, -44, -32, -21, -12, -6, -3,
|
|
||||||
-1, -3, -6, -12, -21, -32, -44, -59, -76, -95, -115, 120, 97, 74, 49, 24,
|
|
||||||
0, -24, -49, -74, -97, -120, 115, 95, 76, 59, 44, 32, 21, 12, 6, 3,
|
|
||||||
1, 3, 6, 12, 21, 32, 44, 59, 76, 95, 115, -120, -97, -74, -49, -24
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint16_t ModPlayer::_periodTable[] = {
|
const uint16_t ModPlayer::_periodTable[] = {
|
||||||
856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453, // C-1 to B-1 Finetune 0
|
856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453, // C-1 to B-1 Finetune 0
|
||||||
428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, // C-2 to B-2 Finetune 0
|
428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, // C-2 to B-2 Finetune 0
|
||||||
|
|
22
systemstub.h
22
systemstub.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SYSTEMSTUB_H__
|
#ifndef SYSTEMSTUB_H__
|
||||||
|
@ -62,9 +51,10 @@ struct SystemStub {
|
||||||
|
|
||||||
virtual ~SystemStub() {}
|
virtual ~SystemStub() {}
|
||||||
|
|
||||||
virtual void init(const char *title, int w, int h) = 0;
|
virtual void init(const char *title, int w, int h, int scaler, bool fullscreen) = 0;
|
||||||
virtual void destroy() = 0;
|
virtual void destroy() = 0;
|
||||||
|
|
||||||
|
virtual void setScreenSize(int w, int h) = 0;
|
||||||
virtual void setPalette(const uint8_t *pal, int n) = 0;
|
virtual void setPalette(const uint8_t *pal, int n) = 0;
|
||||||
virtual void setPaletteEntry(int i, const Color *c) = 0;
|
virtual void setPaletteEntry(int i, const Color *c) = 0;
|
||||||
virtual void getPaletteEntry(int i, Color *c) = 0;
|
virtual void getPaletteEntry(int i, Color *c) = 0;
|
||||||
|
|
|
@ -1,24 +1,13 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include "scaler.h"
|
#include "scaler.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
struct SystemStub_SDL : SystemStub {
|
struct SystemStub_SDL : SystemStub {
|
||||||
enum {
|
enum {
|
||||||
|
@ -41,10 +30,12 @@ struct SystemStub_SDL : SystemStub {
|
||||||
bool _fadeOnUpdateScreen;
|
bool _fadeOnUpdateScreen;
|
||||||
void (*_audioCbProc)(void *, int8_t *, int);
|
void (*_audioCbProc)(void *, int8_t *, int);
|
||||||
void *_audioCbData;
|
void *_audioCbData;
|
||||||
|
int _screenshot;
|
||||||
|
|
||||||
virtual ~SystemStub_SDL() {}
|
virtual ~SystemStub_SDL() {}
|
||||||
virtual void init(const char *title, int w, int h);
|
virtual void init(const char *title, int w, int h, int scaler, bool fullscreen);
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
virtual void setScreenSize(int w, int h);
|
||||||
virtual void setPalette(const uint8_t *pal, int n);
|
virtual void setPalette(const uint8_t *pal, int n);
|
||||||
virtual void setPaletteEntry(int i, const Color *c);
|
virtual void setPaletteEntry(int i, const Color *c);
|
||||||
virtual void getPaletteEntry(int i, Color *c);
|
virtual void getPaletteEntry(int i, Color *c);
|
||||||
|
@ -62,8 +53,6 @@ struct SystemStub_SDL : SystemStub {
|
||||||
virtual void unlockAudio();
|
virtual void unlockAudio();
|
||||||
|
|
||||||
void processEvent(const SDL_Event &ev, bool &paused);
|
void processEvent(const SDL_Event &ev, bool &paused);
|
||||||
void updateScreen_GL(int shakeOffset);
|
|
||||||
void updateScreen_SW(int shakeOffset);
|
|
||||||
void prepareGfxMode();
|
void prepareGfxMode();
|
||||||
void cleanupGfxMode();
|
void cleanupGfxMode();
|
||||||
void switchGfxMode(bool fullscreen, uint8_t scaler);
|
void switchGfxMode(bool fullscreen, uint8_t scaler);
|
||||||
|
@ -76,30 +65,23 @@ SystemStub *SystemStub_SDL_create() {
|
||||||
return new SystemStub_SDL();
|
return new SystemStub_SDL();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::init(const char *title, int w, int h) {
|
void SystemStub_SDL::init(const char *title, int w, int h, int scaler, bool fullscreen) {
|
||||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
|
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
|
||||||
SDL_ShowCursor(SDL_DISABLE);
|
SDL_ShowCursor(SDL_DISABLE);
|
||||||
SDL_WM_SetCaption(title, NULL);
|
SDL_WM_SetCaption(title, NULL);
|
||||||
memset(&_pi, 0, sizeof(_pi));
|
memset(&_pi, 0, sizeof(_pi));
|
||||||
_screenW = w;
|
_screenBuffer = 0;
|
||||||
_screenH = h;
|
|
||||||
// allocate some extra bytes for the scaling routines
|
|
||||||
const int screenBufferSize = (w + 2) * (h + 2) * sizeof(uint16_t);
|
|
||||||
_screenBuffer = (uint16_t *)malloc(screenBufferSize);
|
|
||||||
if (!_screenBuffer) {
|
|
||||||
error("SystemStub_SDL::init() Unable to allocate offscreen buffer");
|
|
||||||
}
|
|
||||||
memset(_screenBuffer, 0, screenBufferSize);
|
|
||||||
_fadeScreenBuffer = 0;
|
_fadeScreenBuffer = 0;
|
||||||
_fadeOnUpdateScreen = false;
|
_fadeOnUpdateScreen = false;
|
||||||
_fullscreen = false;
|
_fullscreen = fullscreen;
|
||||||
_currentScaler = SCALER_SCALE_3X;
|
_currentScaler = scaler;
|
||||||
memset(_pal, 0, sizeof(_pal));
|
memset(_pal, 0, sizeof(_pal));
|
||||||
prepareGfxMode();
|
setScreenSize(w, h);
|
||||||
_joystick = NULL;
|
_joystick = NULL;
|
||||||
if (SDL_NumJoysticks() > 0) {
|
if (SDL_NumJoysticks() > 0) {
|
||||||
_joystick = SDL_JoystickOpen(0);
|
_joystick = SDL_JoystickOpen(0);
|
||||||
}
|
}
|
||||||
|
_screenshot = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::destroy() {
|
void SystemStub_SDL::destroy() {
|
||||||
|
@ -110,6 +92,25 @@ void SystemStub_SDL::destroy() {
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemStub_SDL::setScreenSize(int w, int h) {
|
||||||
|
if (_screenW == w && _screenH == h) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free(_screenBuffer);
|
||||||
|
_screenBuffer = 0;
|
||||||
|
free(_fadeScreenBuffer);
|
||||||
|
_fadeScreenBuffer = 0;
|
||||||
|
// allocate some extra bytes for the scaling routines
|
||||||
|
const int screenBufferSize = (w + 2) * (h + 2) * sizeof(uint16_t);
|
||||||
|
_screenBuffer = (uint16_t *)calloc(1, screenBufferSize);
|
||||||
|
if (!_screenBuffer) {
|
||||||
|
error("SystemStub_SDL::setScreenSize() Unable to allocate offscreen buffer, w=%d, h=%d", w, h);
|
||||||
|
}
|
||||||
|
_screenW = w;
|
||||||
|
_screenH = h;
|
||||||
|
prepareGfxMode();
|
||||||
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::setPalette(const uint8_t *pal, int n) {
|
void SystemStub_SDL::setPalette(const uint8_t *pal, int n) {
|
||||||
assert(n <= 256);
|
assert(n <= 256);
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
|
@ -121,17 +122,11 @@ void SystemStub_SDL::setPalette(const uint8_t *pal, int n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::setPaletteEntry(int i, const Color *c) {
|
void SystemStub_SDL::setPaletteEntry(int i, const Color *c) {
|
||||||
uint8_t r = (c->r << 2) | (c->r & 3);
|
_pal[i] = SDL_MapRGB(_screenSurface->format, c->r, c->g, c->b);
|
||||||
uint8_t g = (c->g << 2) | (c->g & 3);
|
|
||||||
uint8_t b = (c->b << 2) | (c->b & 3);
|
|
||||||
_pal[i] = SDL_MapRGB(_screenSurface->format, r, g, b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::getPaletteEntry(int i, Color *c) {
|
void SystemStub_SDL::getPaletteEntry(int i, Color *c) {
|
||||||
SDL_GetRGB(_pal[i], _screenSurface->format, &c->r, &c->g, &c->b);
|
SDL_GetRGB(_pal[i], _screenSurface->format, &c->r, &c->g, &c->b);
|
||||||
c->r >>= 2;
|
|
||||||
c->g >>= 2;
|
|
||||||
c->b >>= 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::setOverscanColor(int i) {
|
void SystemStub_SDL::setOverscanColor(int i) {
|
||||||
|
@ -278,8 +273,8 @@ void SystemStub_SDL::updateScreen(int shakeOffset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::processEvents() {
|
void SystemStub_SDL::processEvents() {
|
||||||
while (true) {
|
|
||||||
bool paused = false;
|
bool paused = false;
|
||||||
|
while (true) {
|
||||||
SDL_Event ev;
|
SDL_Event ev;
|
||||||
while (SDL_PollEvent(&ev)) {
|
while (SDL_PollEvent(&ev)) {
|
||||||
processEvent(ev, paused);
|
processEvent(ev, paused);
|
||||||
|
@ -431,6 +426,12 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
||||||
if (_currentScaler > 0) {
|
if (_currentScaler > 0) {
|
||||||
switchGfxMode(_fullscreen, s);
|
switchGfxMode(_fullscreen, s);
|
||||||
}
|
}
|
||||||
|
} else if (ev.key.keysym.sym == SDLK_s) {
|
||||||
|
char name[32];
|
||||||
|
snprintf(name, sizeof(name), "screenshot-%03d.bmp", _screenshot);
|
||||||
|
SDL_SaveBMP(_screenSurface, name);
|
||||||
|
++_screenshot;
|
||||||
|
debug(DBG_INFO, "Written '%s'", name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (ev.key.keysym.mod & KMOD_CTRL) {
|
} else if (ev.key.keysym.mod & KMOD_CTRL) {
|
||||||
|
|
19
unpack.cpp
19
unpack.cpp
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "unpack.h"
|
#include "unpack.h"
|
||||||
|
|
19
unpack.h
19
unpack.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UNPACK_H__
|
#ifndef UNPACK_H__
|
||||||
|
|
19
util.cpp
19
util.cpp
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
19
util.h
19
util.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UTIL_H__
|
#ifndef UTIL_H__
|
||||||
|
|
329
video.cpp
329
video.cpp
|
@ -1,38 +1,25 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
#include "unpack.h"
|
#include "unpack.h"
|
||||||
|
#include "util.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
|
|
||||||
|
|
||||||
Video::Video(Resource *res, SystemStub *stub)
|
Video::Video(Resource *res, SystemStub *stub)
|
||||||
: _res(res), _stub(stub) {
|
: _res(res), _stub(stub) {
|
||||||
_frontLayer = (uint8_t *)malloc(GAMESCREEN_W * GAMESCREEN_H);
|
_w = GAMESCREEN_W;
|
||||||
memset(_frontLayer, 0, GAMESCREEN_W * GAMESCREEN_H);
|
_h = GAMESCREEN_H;
|
||||||
_backLayer = (uint8_t *)malloc(GAMESCREEN_W * GAMESCREEN_H);
|
_layerSize = _w * _h;
|
||||||
memset(_backLayer, 0, GAMESCREEN_W * GAMESCREEN_H);
|
_frontLayer = (uint8_t *)calloc(1, _layerSize);
|
||||||
_tempLayer = (uint8_t *)malloc(GAMESCREEN_W * GAMESCREEN_H);
|
_backLayer = (uint8_t *)calloc(1,_layerSize);
|
||||||
memset(_tempLayer, 0, GAMESCREEN_W * GAMESCREEN_H);
|
_tempLayer = (uint8_t *)calloc(1, _layerSize);
|
||||||
_tempLayer2 = (uint8_t *)malloc(GAMESCREEN_W * GAMESCREEN_H);
|
_tempLayer2 = (uint8_t *)calloc(1, _layerSize);
|
||||||
memset(_tempLayer2, 0, GAMESCREEN_W * GAMESCREEN_H);
|
_screenBlocks = (uint8_t *)calloc(1, (_w / SCREENBLOCK_W) * (_h / SCREENBLOCK_H));
|
||||||
_screenBlocks = (uint8_t *)malloc((GAMESCREEN_W / SCREENBLOCK_W) * (GAMESCREEN_H / SCREENBLOCK_H));
|
|
||||||
memset(_screenBlocks, 0, (GAMESCREEN_W / SCREENBLOCK_W) * (GAMESCREEN_H / SCREENBLOCK_H));
|
|
||||||
_fullRefresh = true;
|
_fullRefresh = true;
|
||||||
_shakeOffset = 0;
|
_shakeOffset = 0;
|
||||||
_charFrontColor = 0;
|
_charFrontColor = 0;
|
||||||
|
@ -50,15 +37,15 @@ Video::~Video() {
|
||||||
|
|
||||||
void Video::markBlockAsDirty(int16_t x, int16_t y, uint16_t w, uint16_t h) {
|
void Video::markBlockAsDirty(int16_t x, int16_t y, uint16_t w, uint16_t h) {
|
||||||
debug(DBG_VIDEO, "Video::markBlockAsDirty(%d, %d, %d, %d)", x, y, w, h);
|
debug(DBG_VIDEO, "Video::markBlockAsDirty(%d, %d, %d, %d)", x, y, w, h);
|
||||||
assert(x >= 0 && x + w <= GAMESCREEN_W && y >= 0 && y + h <= GAMESCREEN_H);
|
assert(x >= 0 && x + w <= _w && y >= 0 && y + h <= _h);
|
||||||
int bx1 = x / SCREENBLOCK_W;
|
int bx1 = x / SCREENBLOCK_W;
|
||||||
int by1 = y / SCREENBLOCK_H;
|
int by1 = y / SCREENBLOCK_H;
|
||||||
int bx2 = (x + w - 1) / SCREENBLOCK_W;
|
int bx2 = (x + w - 1) / SCREENBLOCK_W;
|
||||||
int by2 = (y + h - 1) / SCREENBLOCK_H;
|
int by2 = (y + h - 1) / SCREENBLOCK_H;
|
||||||
assert(bx2 < GAMESCREEN_W / SCREENBLOCK_W && by2 < GAMESCREEN_H / SCREENBLOCK_H);
|
assert(bx2 < _w / SCREENBLOCK_W && by2 < _h / SCREENBLOCK_H);
|
||||||
for (; by1 <= by2; ++by1) {
|
for (; by1 <= by2; ++by1) {
|
||||||
for (int i = bx1; i <= bx2; ++i) {
|
for (int i = bx1; i <= bx2; ++i) {
|
||||||
_screenBlocks[by1 * (GAMESCREEN_W / SCREENBLOCK_W) + i] = 2;
|
_screenBlocks[by1 * (_w / SCREENBLOCK_W) + i] = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,16 +54,16 @@ void Video::updateScreen() {
|
||||||
debug(DBG_VIDEO, "Video::updateScreen()");
|
debug(DBG_VIDEO, "Video::updateScreen()");
|
||||||
// _fullRefresh = true;
|
// _fullRefresh = true;
|
||||||
if (_fullRefresh) {
|
if (_fullRefresh) {
|
||||||
_stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _frontLayer, 256);
|
_stub->copyRect(0, 0, _w, _h, _frontLayer, 256);
|
||||||
_stub->updateScreen(_shakeOffset);
|
_stub->updateScreen(_shakeOffset);
|
||||||
_fullRefresh = false;
|
_fullRefresh = false;
|
||||||
} else {
|
} else {
|
||||||
int i, j;
|
int i, j;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
uint8_t *p = _screenBlocks;
|
uint8_t *p = _screenBlocks;
|
||||||
for (j = 0; j < GAMESCREEN_H / SCREENBLOCK_H; ++j) {
|
for (j = 0; j < _h / SCREENBLOCK_H; ++j) {
|
||||||
uint16_t nh = 0;
|
uint16_t nh = 0;
|
||||||
for (i = 0; i < GAMESCREEN_W / SCREENBLOCK_W; ++i) {
|
for (i = 0; i < _w / SCREENBLOCK_W; ++i) {
|
||||||
if (p[i] != 0) {
|
if (p[i] != 0) {
|
||||||
--p[i];
|
--p[i];
|
||||||
++nh;
|
++nh;
|
||||||
|
@ -92,7 +79,7 @@ void Video::updateScreen() {
|
||||||
_stub->copyRect(x, j * SCREENBLOCK_H, nh * SCREENBLOCK_W, SCREENBLOCK_H, _frontLayer, 256);
|
_stub->copyRect(x, j * SCREENBLOCK_H, nh * SCREENBLOCK_W, SCREENBLOCK_H, _frontLayer, 256);
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
p += GAMESCREEN_W / SCREENBLOCK_W;
|
p += _w / SCREENBLOCK_W;
|
||||||
}
|
}
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
_stub->updateScreen(_shakeOffset);
|
_stub->updateScreen(_shakeOffset);
|
||||||
|
@ -107,13 +94,16 @@ void Video::updateScreen() {
|
||||||
void Video::fullRefresh() {
|
void Video::fullRefresh() {
|
||||||
debug(DBG_VIDEO, "Video::fullRefresh()");
|
debug(DBG_VIDEO, "Video::fullRefresh()");
|
||||||
_fullRefresh = true;
|
_fullRefresh = true;
|
||||||
memset(_screenBlocks, 0, (GAMESCREEN_W / SCREENBLOCK_W) * (GAMESCREEN_H / SCREENBLOCK_H));
|
memset(_screenBlocks, 0, (_w / SCREENBLOCK_W) * (_h / SCREENBLOCK_H));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::fadeOut() {
|
void Video::fadeOut() {
|
||||||
debug(DBG_VIDEO, "Video::fadeOut()");
|
debug(DBG_VIDEO, "Video::fadeOut()");
|
||||||
|
if (g_options.fade_out_palette) {
|
||||||
|
fadeOutPalette();
|
||||||
|
} else {
|
||||||
_stub->fadeScreen();
|
_stub->fadeScreen();
|
||||||
// fadeOutPalette();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::fadeOutPalette() {
|
void Video::fadeOutPalette() {
|
||||||
|
@ -134,15 +124,7 @@ void Video::fadeOutPalette() {
|
||||||
|
|
||||||
void Video::setPaletteColorBE(int num, int offset) {
|
void Video::setPaletteColorBE(int num, int offset) {
|
||||||
const int color = READ_BE_UINT16(_res->_pal + offset * 2);
|
const int color = READ_BE_UINT16(_res->_pal + offset * 2);
|
||||||
Color c;
|
Color c = AMIGA_convertColor(color, true);
|
||||||
c.r = (color & 0x00F) << 2;
|
|
||||||
c.g = (color & 0x0F0) >> 2;
|
|
||||||
c.b = (color & 0xF00) >> 6;
|
|
||||||
if (color != 0) {
|
|
||||||
c.r |= 3;
|
|
||||||
c.g |= 3;
|
|
||||||
c.b |= 3;
|
|
||||||
}
|
|
||||||
_stub->setPaletteEntry(num, &c);
|
_stub->setPaletteEntry(num, &c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,15 +133,7 @@ void Video::setPaletteSlotBE(int palSlot, int palNum) {
|
||||||
const uint8_t *p = _res->_pal + palNum * 0x20;
|
const uint8_t *p = _res->_pal + palNum * 0x20;
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
const int color = READ_BE_UINT16(p); p += 2;
|
const int color = READ_BE_UINT16(p); p += 2;
|
||||||
Color c;
|
Color c = AMIGA_convertColor(color, true);
|
||||||
c.r = (color & 0x00F) << 2;
|
|
||||||
c.g = (color & 0x0F0) >> 2;
|
|
||||||
c.b = (color & 0xF00) >> 6;
|
|
||||||
if (color != 0) {
|
|
||||||
c.r |= 3;
|
|
||||||
c.g |= 3;
|
|
||||||
c.b |= 3;
|
|
||||||
}
|
|
||||||
_stub->setPaletteEntry(palSlot * 0x10 + i, &c);
|
_stub->setPaletteEntry(palSlot * 0x10 + i, &c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,10 +142,7 @@ void Video::setPaletteSlotLE(int palSlot, const uint8_t *palData) {
|
||||||
debug(DBG_VIDEO, "Video::setPaletteSlotLE()");
|
debug(DBG_VIDEO, "Video::setPaletteSlotLE()");
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
uint16_t color = READ_LE_UINT16(palData); palData += 2;
|
uint16_t color = READ_LE_UINT16(palData); palData += 2;
|
||||||
Color c;
|
Color c = AMIGA_convertColor(color);
|
||||||
c.b = (color & 0x00F) << 2;
|
|
||||||
c.g = (color & 0x0F0) >> 2;
|
|
||||||
c.r = (color & 0xF00) >> 6;
|
|
||||||
_stub->setPaletteEntry(palSlot * 0x10 + i, &c);
|
_stub->setPaletteEntry(palSlot * 0x10 + i, &c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,13 +157,22 @@ void Video::setPalette0xF() {
|
||||||
const uint8_t *p = _palSlot0xF;
|
const uint8_t *p = _palSlot0xF;
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
Color c;
|
Color c;
|
||||||
c.r = *p++ >> 2;
|
c.r = *p++;
|
||||||
c.g = *p++ >> 2;
|
c.g = *p++;
|
||||||
c.b = *p++ >> 2;
|
c.b = *p++;
|
||||||
_stub->setPaletteEntry(0xF0 + i, &c);
|
_stub->setPaletteEntry(0xF0 + i, &c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Video::PC_decodeLev(int level, int room) {
|
||||||
|
uint8_t *tmp = _res->_mbk;
|
||||||
|
_res->_mbk = _res->_bnq;
|
||||||
|
_res->clearBankData();
|
||||||
|
AMIGA_decodeLev(level, room);
|
||||||
|
_res->_mbk = tmp;
|
||||||
|
_res->clearBankData();
|
||||||
|
}
|
||||||
|
|
||||||
static void PC_decodeMapHelper(int sz, const uint8_t *src, uint8_t *dst) {
|
static void PC_decodeMapHelper(int sz, const uint8_t *src, uint8_t *dst) {
|
||||||
const uint8_t *end = src + sz;
|
const uint8_t *end = src + sz;
|
||||||
while (src < end) {
|
while (src < end) {
|
||||||
|
@ -248,7 +228,7 @@ void Video::PC_decodeMap(int level, int room) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy(_backLayer, _frontLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memcpy(_backLayer, _frontLayer, _layerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::PC_setLevelPalettes() {
|
void Video::PC_setLevelPalettes() {
|
||||||
|
@ -294,14 +274,15 @@ void Video::PC_decodeSpc(const uint8_t *src, int w, int h, uint8_t *dst) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AMIGA_blit3pNxN(uint8_t *dst, int pitch, int w, int h, const uint8_t *src) {
|
static void AMIGA_planar16(uint8_t *dst, int w, int h, int depth, const uint8_t *src) {
|
||||||
|
const int pitch = w * 16;
|
||||||
const int planarSize = w * 2 * h;
|
const int planarSize = w * 2 * h;
|
||||||
for (int y = 0; y < h; ++y) {
|
for (int y = 0; y < h; ++y) {
|
||||||
for (int x = 0; x < w; ++x) {
|
for (int x = 0; x < w; ++x) {
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
int color = 0;
|
int color = 0;
|
||||||
const int mask = 1 << (15 - i);
|
const int mask = 1 << (15 - i);
|
||||||
for (int bit = 0; bit < 3; ++bit) {
|
for (int bit = 0; bit < depth; ++bit) {
|
||||||
if (READ_BE_UINT16(src + bit * planarSize) & mask) {
|
if (READ_BE_UINT16(src + bit * planarSize) & mask) {
|
||||||
color |= 1 << bit;
|
color |= 1 << bit;
|
||||||
}
|
}
|
||||||
|
@ -314,26 +295,7 @@ static void AMIGA_blit3pNxN(uint8_t *dst, int pitch, int w, int h, const uint8_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AMIGA_blit4p16xN(uint8_t *dst, int w, int h, const uint8_t *src) {
|
static void AMIGA_planar8(uint8_t *dst, int w, int h, const uint8_t *src) {
|
||||||
const int planarSize = w * 2 * h;
|
|
||||||
assert(w == 1);
|
|
||||||
for (int y = 0; y < h; ++y) {
|
|
||||||
for (int i = 0; i < 16; ++i) {
|
|
||||||
int color = 0;
|
|
||||||
const int mask = 1 << (15 - i);
|
|
||||||
for (int bit = 0; bit < 4; ++bit) {
|
|
||||||
if (READ_BE_UINT16(src + bit * planarSize) & mask) {
|
|
||||||
color |= 1 << bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dst[i] = color;
|
|
||||||
}
|
|
||||||
src += 2;
|
|
||||||
dst += 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void AMIGA_blit4p8xN(uint8_t *dst, int w, int h, const uint8_t *src) {
|
|
||||||
assert(w == 8);
|
assert(w == 8);
|
||||||
for (int y = 0; y < h; ++y) {
|
for (int y = 0; y < h; ++y) {
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
@ -351,27 +313,7 @@ static void AMIGA_blit4p8xN(uint8_t *dst, int w, int h, const uint8_t *src) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AMIGA_blit4pNxN(uint8_t *dst, int w, int h, const uint8_t *src) {
|
static void AMIGA_planar_mask(uint8_t *dst, int x0, int y0, int w, int h, uint8_t *src, uint8_t *mask, int size) {
|
||||||
const int planarSize = w / 8 * h;
|
|
||||||
for (int y = 0; y < h; ++y) {
|
|
||||||
for (int x = 0; x < w / 8; ++x) {
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
|
||||||
int color = 0;
|
|
||||||
const int mask = 1 << (7 - i);
|
|
||||||
for (int bit = 0; bit < 4; ++bit) {
|
|
||||||
if (src[bit * planarSize] & mask) {
|
|
||||||
color |= 1 << bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dst[x * 8 + i] = color;
|
|
||||||
}
|
|
||||||
++src;
|
|
||||||
}
|
|
||||||
dst += w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void AMIGA_blit4pNxN_mask(uint8_t *dst, int x0, int y0, int w, int h, uint8_t *src, uint8_t *mask, int size) {
|
|
||||||
dst += y0 * 256 + x0;
|
dst += y0 * 256 + x0;
|
||||||
for (int y = 0; y < h; ++y) {
|
for (int y = 0; y < h; ++y) {
|
||||||
for (int x = 0; x < w * 2; ++x) {
|
for (int x = 0; x < w * 2; ++x) {
|
||||||
|
@ -398,7 +340,7 @@ static void AMIGA_blit4pNxN_mask(uint8_t *dst, int x0, int y0, int w, int h, uin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AMIGA_decodeRLE(uint8_t *dst, const uint8_t *src) {
|
static void AMIGA_decodeRle(uint8_t *dst, const uint8_t *src) {
|
||||||
int code = READ_BE_UINT16(src) & 0x7FFF; src += 2;
|
int code = READ_BE_UINT16(src) & 0x7FFF; src += 2;
|
||||||
const uint8_t *end = src + code;
|
const uint8_t *end = src + code;
|
||||||
do {
|
do {
|
||||||
|
@ -417,7 +359,30 @@ static void AMIGA_decodeRLE(uint8_t *dst, const uint8_t *src) {
|
||||||
assert(src == end);
|
assert(src == end);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AMIGA_decodeSgd(uint8_t *dst, const uint8_t *src, const uint8_t *data) {
|
static void PC_drawTileMask(uint8_t *dst, int x0, int y0, int w, int h, uint8_t *m, uint8_t *p, int size) {
|
||||||
|
assert(size == (w * 2 * h));
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for (int x = 0; x < w; ++x) {
|
||||||
|
const int bits = READ_BE_UINT16(m); m += 2;
|
||||||
|
for (int bit = 0; bit < 8; ++bit) {
|
||||||
|
const int j = y0 + y;
|
||||||
|
const int i = x0 + 2 * (x * 8 + bit);
|
||||||
|
if (i >= 0 && i < Video::GAMESCREEN_W && j >= 0 && j < Video::GAMESCREEN_H) {
|
||||||
|
const uint8_t color = *p;
|
||||||
|
if (bits & (1 << (15 - (bit * 2)))) {
|
||||||
|
dst[j * Video::GAMESCREEN_W + i] = color >> 4;
|
||||||
|
}
|
||||||
|
if (bits & (1 << (15 - (bit * 2 + 1)))) {
|
||||||
|
dst[j * Video::GAMESCREEN_W + i + 1] = color & 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decodeSgd(uint8_t *dst, const uint8_t *src, const uint8_t *data, const bool isAmiga) {
|
||||||
int num = -1;
|
int num = -1;
|
||||||
uint8_t buf[256 * 32];
|
uint8_t buf[256 * 32];
|
||||||
int count = READ_BE_UINT16(src) - 1; src += 2;
|
int count = READ_BE_UINT16(src) - 1; src += 2;
|
||||||
|
@ -427,7 +392,7 @@ static void AMIGA_decodeSgd(uint8_t *dst, const uint8_t *src, const uint8_t *dat
|
||||||
int d1 = READ_BE_UINT16(src); src += 2;
|
int d1 = READ_BE_UINT16(src); src += 2;
|
||||||
if (d2 != 0xFFFF) {
|
if (d2 != 0xFFFF) {
|
||||||
d2 &= ~(1 << 15);
|
d2 &= ~(1 << 15);
|
||||||
const int offset = READ_BE_UINT32(data + d2 * 4);
|
const int32_t offset = READ_BE_UINT32(data + d2 * 4);
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
const uint8_t *ptr = data - offset;
|
const uint8_t *ptr = data - offset;
|
||||||
const int size = READ_BE_UINT16(ptr); ptr += 2;
|
const int size = READ_BE_UINT16(ptr); ptr += 2;
|
||||||
|
@ -441,18 +406,22 @@ static void AMIGA_decodeSgd(uint8_t *dst, const uint8_t *src, const uint8_t *dat
|
||||||
num = d2;
|
num = d2;
|
||||||
const int size = READ_BE_UINT16(data + offset) & 0x7FFF;
|
const int size = READ_BE_UINT16(data + offset) & 0x7FFF;
|
||||||
assert(size <= (int)sizeof(buf));
|
assert(size <= (int)sizeof(buf));
|
||||||
AMIGA_decodeRLE(buf, data + offset);
|
AMIGA_decodeRle(buf, data + offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const int w = (buf[0] + 1) >> 1;
|
const int w = (buf[0] + 1) >> 1;
|
||||||
const int h = buf[1] + 1;
|
const int h = buf[1] + 1;
|
||||||
const int planarSize = READ_BE_UINT16(buf + 2);
|
const int planarSize = READ_BE_UINT16(buf + 2);
|
||||||
AMIGA_blit4pNxN_mask(dst, (int16_t)d0, (int16_t)d1, w, h, buf + 4, buf + 4 + planarSize, planarSize);
|
if (isAmiga) {
|
||||||
|
AMIGA_planar_mask(dst, (int16_t)d0, (int16_t)d1, w, h, buf + 4, buf + 4 + planarSize, planarSize);
|
||||||
|
} else {
|
||||||
|
PC_drawTileMask(dst, (int16_t)d0, (int16_t)d1, w, h, buf + 4, buf + 4 + planarSize, planarSize);
|
||||||
|
}
|
||||||
} while (--count >= 0);
|
} while (--count >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t *AMIGA_mirrorY(const uint8_t *a2) {
|
static const uint8_t *AMIGA_mirrorTileY(const uint8_t *a2) {
|
||||||
static uint8_t buf[32];
|
static uint8_t buf[32];
|
||||||
|
|
||||||
a2 += 24;
|
a2 += 24;
|
||||||
|
@ -465,7 +434,7 @@ static const uint8_t *AMIGA_mirrorY(const uint8_t *a2) {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t *AMIGA_mirrorX(const uint8_t *a2) {
|
static const uint8_t *AMIGA_mirrorTileX(const uint8_t *a2) {
|
||||||
static uint8_t buf[32];
|
static uint8_t buf[32];
|
||||||
|
|
||||||
for (int i = 0; i < 32; ++i) {
|
for (int i = 0; i < 32; ++i) {
|
||||||
|
@ -480,7 +449,13 @@ static const uint8_t *AMIGA_mirrorX(const uint8_t *a2) {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AMIGA_blit4p8x8(uint8_t *dst, int pitch, const uint8_t *src, int pal, int colorKey = -1) {
|
static void AMIGA_drawTile(uint8_t *dst, int pitch, const uint8_t *src, int pal, const bool xflip, const bool yflip, int colorKey) {
|
||||||
|
if (yflip) {
|
||||||
|
src = AMIGA_mirrorTileY(src);
|
||||||
|
}
|
||||||
|
if (xflip) {
|
||||||
|
src = AMIGA_mirrorTileX(src);
|
||||||
|
}
|
||||||
for (int y = 0; y < 8; ++y) {
|
for (int y = 0; y < 8; ++y) {
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
const int mask = 1 << (7 - i);
|
const int mask = 1 << (7 - i);
|
||||||
|
@ -499,26 +474,53 @@ static void AMIGA_blit4p8x8(uint8_t *dst, int pitch, const uint8_t *src, int pal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AMIGA_decodeLevHelper(uint8_t *dst, const uint8_t *src, int offset10, int offset12, const uint8_t *a5, bool sgdBuf) {
|
static void PC_drawTile(uint8_t *dst, const uint8_t *src, int mask, const bool xflip, const bool yflip, int colorKey) {
|
||||||
|
int pitch = Video::GAMESCREEN_W;
|
||||||
|
if (yflip) {
|
||||||
|
dst += 7 * pitch;
|
||||||
|
pitch = -pitch;
|
||||||
|
}
|
||||||
|
int inc = 1;
|
||||||
|
if (xflip) {
|
||||||
|
dst += 7;
|
||||||
|
inc = -inc;
|
||||||
|
}
|
||||||
|
for (int y = 0; y < 8; ++y) {
|
||||||
|
for (int i = 0; i < 8; i += 2) {
|
||||||
|
int color = *src >> 4;
|
||||||
|
if (color != colorKey) {
|
||||||
|
dst[inc * i] = mask | color;
|
||||||
|
}
|
||||||
|
color = *src & 15;
|
||||||
|
if (color != colorKey) {
|
||||||
|
dst[inc * (i + 1)] = mask | color;
|
||||||
|
}
|
||||||
|
++src;
|
||||||
|
}
|
||||||
|
dst += pitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decodeLevHelper(uint8_t *dst, const uint8_t *src, int offset10, int offset12, const uint8_t *a5, bool sgdBuf, bool isPC) {
|
||||||
if (offset10 != 0) {
|
if (offset10 != 0) {
|
||||||
const uint8_t *a0 = src + offset10;
|
const uint8_t *a0 = src + offset10;
|
||||||
for (int y = 0; y < 224; y += 8) {
|
for (int y = 0; y < 224; y += 8) {
|
||||||
for (int x = 0; x < 256; x += 8) {
|
for (int x = 0; x < 256; x += 8) {
|
||||||
const int d3 = READ_BE_UINT16(a0); a0 += 2;
|
const int d3 = isPC ? READ_LE_UINT16(a0) : READ_BE_UINT16(a0); a0 += 2;
|
||||||
const int d0 = d3 & 0x7FF;
|
const int d0 = d3 & 0x7FF;
|
||||||
if (d0 != 0) {
|
if (d0 != 0) {
|
||||||
const uint8_t *a2 = a5 + d0 * 32;
|
const uint8_t *a2 = a5 + d0 * 32;
|
||||||
if ((d3 & (1 << 12)) != 0) {
|
const bool yflip = (d3 & (1 << 12)) != 0;
|
||||||
a2 = AMIGA_mirrorY(a2);
|
const bool xflip = (d3 & (1 << 11)) != 0;
|
||||||
}
|
|
||||||
if ((d3 & (1 << 11)) != 0) {
|
|
||||||
a2 = AMIGA_mirrorX(a2);
|
|
||||||
}
|
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
if ((d3 < (1 << 15)) == 0) {
|
if ((d3 < (1 << 15)) == 0) {
|
||||||
mask = 0x80;
|
mask = 0x80;
|
||||||
}
|
}
|
||||||
AMIGA_blit4p8x8(dst + y * 256 + x, 256, a2, mask);
|
if (isPC) {
|
||||||
|
PC_drawTile(dst + y * 256 + x, a2, mask, xflip, yflip, -1);
|
||||||
|
} else {
|
||||||
|
AMIGA_drawTile(dst + y * 256 + x, 256, a2, mask, xflip, yflip, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,26 +529,26 @@ static void AMIGA_decodeLevHelper(uint8_t *dst, const uint8_t *src, int offset10
|
||||||
const uint8_t *a0 = src + offset12;
|
const uint8_t *a0 = src + offset12;
|
||||||
for (int y = 0; y < 224; y += 8) {
|
for (int y = 0; y < 224; y += 8) {
|
||||||
for (int x = 0; x < 256; x += 8) {
|
for (int x = 0; x < 256; x += 8) {
|
||||||
int d3 = READ_BE_UINT16(a0); a0 += 2;
|
const int d3 = isPC ? READ_LE_UINT16(a0) : READ_BE_UINT16(a0); a0 += 2;
|
||||||
int d0 = d3 & 0x7FF;
|
int d0 = d3 & 0x7FF;
|
||||||
if (d0 != 0 && sgdBuf) {
|
if (d0 != 0 && sgdBuf) {
|
||||||
d0 -= 896;
|
d0 -= 896;
|
||||||
}
|
}
|
||||||
if (d0 != 0) {
|
if (d0 != 0) {
|
||||||
const uint8_t *a2 = a5 + d0 * 32;
|
const uint8_t *a2 = a5 + d0 * 32;
|
||||||
if ((d3 & (1 << 12)) != 0) {
|
const bool yflip = (d3 & (1 << 12)) != 0;
|
||||||
a2 = AMIGA_mirrorY(a2);
|
const bool xflip = (d3 & (1 << 11)) != 0;
|
||||||
}
|
|
||||||
if ((d3 & (1 << 11)) != 0) {
|
|
||||||
a2 = AMIGA_mirrorX(a2);
|
|
||||||
}
|
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
if ((d3 & 0x6000) != 0 && sgdBuf) {
|
if ((d3 & 0x6000) != 0 && sgdBuf) {
|
||||||
mask = 0x10;
|
mask = 0x10;
|
||||||
} else if ((d3 < (1 << 15)) == 0) {
|
} else if ((d3 < (1 << 15)) == 0) {
|
||||||
mask = 0x80;
|
mask = 0x80;
|
||||||
}
|
}
|
||||||
AMIGA_blit4p8x8(dst + y * 256 + x, 256, a2, mask, 0);
|
if (isPC) {
|
||||||
|
PC_drawTile(dst + y * 256 + x, a2, mask, xflip, yflip, 0);
|
||||||
|
} else {
|
||||||
|
AMIGA_drawTile(dst + y * 256 + x, 256, a2, mask, xflip, yflip, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -584,49 +586,52 @@ void Video::AMIGA_decodeLev(int level, int room) {
|
||||||
}
|
}
|
||||||
const int d3 = *a1++;
|
const int d3 = *a1++;
|
||||||
if (d3 == 255) {
|
if (d3 == 255) {
|
||||||
assert(sz + d1 < kTempMbkSize * 32);
|
assert(sz + d1 <= kTempMbkSize * 32);
|
||||||
memcpy(buf + sz, a6, d1);
|
memcpy(buf + sz, a6, d1);
|
||||||
sz += d1;
|
sz += d1;
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < d3 + 1; ++i) {
|
for (int i = 0; i < d3 + 1; ++i) {
|
||||||
const int d4 = *a1++;
|
const int d4 = *a1++;
|
||||||
assert(sz + 32 < kTempMbkSize * 32);
|
assert(sz + 32 <= kTempMbkSize * 32);
|
||||||
memcpy(buf + sz, a6 + d4 * 32, 32);
|
memcpy(buf + sz, a6 + d4 * 32, 32);
|
||||||
sz += 32;
|
sz += 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memset(_frontLayer, 0, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
memset(_frontLayer, 0, _layerSize);
|
||||||
if (tmp[1] != 0) {
|
if (tmp[1] != 0) {
|
||||||
assert(_res->_sgd);
|
assert(_res->_sgd);
|
||||||
AMIGA_decodeSgd(_frontLayer, tmp + offset10, _res->_sgd);
|
decodeSgd(_frontLayer, tmp + offset10, _res->_sgd, _res->isAmiga());
|
||||||
offset10 = 0;
|
offset10 = 0;
|
||||||
}
|
}
|
||||||
AMIGA_decodeLevHelper(_frontLayer, tmp, offset10, offset12, buf, tmp[1] != 0);
|
decodeLevHelper(_frontLayer, tmp, offset10, offset12, buf, tmp[1] != 0, _res->isDOS());
|
||||||
memcpy(_backLayer, _frontLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
|
free(buf);
|
||||||
uint16_t num[4];
|
memcpy(_backLayer, _frontLayer, _layerSize);
|
||||||
for (int i = 0; i < 4; ++i) {
|
_mapPalSlot1 = READ_BE_UINT16(tmp + 2);
|
||||||
num[i] = READ_BE_UINT16(tmp + 2 + i * 2);
|
_mapPalSlot2 = READ_BE_UINT16(tmp + 4);
|
||||||
|
_mapPalSlot3 = READ_BE_UINT16(tmp + 6);
|
||||||
|
_mapPalSlot4 = READ_BE_UINT16(tmp + 8);
|
||||||
|
if (_res->isDOS()) {
|
||||||
|
// done in ::PC_setLevelPalettes
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
_mapPalSlot1 = num[1];
|
setPaletteSlotBE(0x0, _mapPalSlot1);
|
||||||
_mapPalSlot2 = num[2];
|
|
||||||
setPaletteSlotBE(0x0, num[0]);
|
|
||||||
for (int i = 1; i < 5; ++i) {
|
for (int i = 1; i < 5; ++i) {
|
||||||
setPaletteSlotBE(i, _mapPalSlot2);
|
setPaletteSlotBE(i, _mapPalSlot3);
|
||||||
}
|
}
|
||||||
setPaletteSlotBE(0x6, _mapPalSlot2);
|
setPaletteSlotBE(0x6, _mapPalSlot3);
|
||||||
setPaletteSlotBE(0x8, num[0]);
|
setPaletteSlotBE(0x8, _mapPalSlot1);
|
||||||
setPaletteSlotBE(0xA, _mapPalSlot2);
|
setPaletteSlotBE(0xA, _mapPalSlot3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::AMIGA_decodeSpm(const uint8_t *src, uint8_t *dst) {
|
void Video::AMIGA_decodeSpm(const uint8_t *src, uint8_t *dst) {
|
||||||
uint8_t buf[256 * 32];
|
uint8_t buf[256 * 32];
|
||||||
const int size = READ_BE_UINT16(src + 3) & 0x7FFF;
|
const int size = READ_BE_UINT16(src + 3) & 0x7FFF;
|
||||||
assert(size <= (int)sizeof(buf));
|
assert(size <= (int)sizeof(buf));
|
||||||
AMIGA_decodeRLE(buf, src + 3);
|
AMIGA_decodeRle(buf, src + 3);
|
||||||
const int w = (src[2] >> 7) + 1;
|
const int w = (src[2] >> 7) + 1;
|
||||||
const int h = src[2] & 0x7F;
|
const int h = src[2] & 0x7F;
|
||||||
AMIGA_blit3pNxN(dst, w * 16, w, h, buf);
|
AMIGA_planar16(dst, w, h, 3, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::AMIGA_decodeIcn(const uint8_t *src, int num, uint8_t *dst) {
|
void Video::AMIGA_decodeIcn(const uint8_t *src, int num, uint8_t *dst) {
|
||||||
|
@ -638,20 +643,28 @@ void Video::AMIGA_decodeIcn(const uint8_t *src, int num, uint8_t *dst) {
|
||||||
}
|
}
|
||||||
const int h = 1 + *src++;
|
const int h = 1 + *src++;
|
||||||
const int w = 1 + *src++;
|
const int w = 1 + *src++;
|
||||||
AMIGA_blit4p16xN(dst, w, h, src + 4);
|
AMIGA_planar16(dst, w, h, 4, src + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::AMIGA_decodeSpc(const uint8_t *src, int w, int h, uint8_t *dst) {
|
void Video::AMIGA_decodeSpc(const uint8_t *src, int w, int h, uint8_t *dst) {
|
||||||
switch (w) {
|
switch (w) {
|
||||||
case 8:
|
case 8:
|
||||||
AMIGA_blit4p8xN(dst, w, h, src);
|
AMIGA_planar8(dst, w, h, src);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
case 32:
|
||||||
|
AMIGA_planar16(dst, w / 16, h, 4, src);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
AMIGA_blit4pNxN(dst, w, h, src);
|
warning("AMIGA_decodeSpc w=%d unimplemented", w);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Video::AMIGA_decodeCmp(const uint8_t *src, uint8_t *dst) {
|
||||||
|
AMIGA_planar16(dst, 20, 224, 5, src);
|
||||||
|
}
|
||||||
|
|
||||||
void Video::drawSpriteSub1(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask) {
|
void Video::drawSpriteSub1(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask) {
|
||||||
debug(DBG_VIDEO, "Video::drawSpriteSub1(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
|
debug(DBG_VIDEO, "Video::drawSpriteSub1(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
|
||||||
while (h--) {
|
while (h--) {
|
||||||
|
@ -811,7 +824,7 @@ const char *Video::drawString(const char *str, int16_t x, int16_t y, uint8_t col
|
||||||
case kResourceTypeAmiga:
|
case kResourceTypeAmiga:
|
||||||
drawCharFunc = &Video::AMIGA_drawStringChar;
|
drawCharFunc = &Video::AMIGA_drawStringChar;
|
||||||
break;
|
break;
|
||||||
case kResourceTypePC:
|
case kResourceTypeDOS:
|
||||||
drawCharFunc = &Video::PC_drawStringChar;
|
drawCharFunc = &Video::PC_drawStringChar;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -829,3 +842,17 @@ const char *Video::drawString(const char *str, int16_t x, int16_t y, uint8_t col
|
||||||
markBlockAsDirty(x, y, len * 8, 8);
|
markBlockAsDirty(x, y, len * 8, 8);
|
||||||
return str - 1;
|
return str - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color Video::AMIGA_convertColor(const uint16_t color, bool bgr) { // 4bits to 8bits
|
||||||
|
int r = (color & 0xF00) >> 8;
|
||||||
|
int g = (color & 0xF0) >> 4;
|
||||||
|
int b = color & 0xF;
|
||||||
|
if (bgr) {
|
||||||
|
SWAP(r, b);
|
||||||
|
}
|
||||||
|
Color c;
|
||||||
|
c.r = (r << 4) | r;
|
||||||
|
c.g = (g << 4) | g;
|
||||||
|
c.b = (b << 4) | b;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
24
video.h
24
video.h
|
@ -1,18 +1,7 @@
|
||||||
/* REminiscence - Flashback interpreter
|
|
||||||
* Copyright (C) 2005-2015 Gregory Montoir
|
/*
|
||||||
*
|
* REminiscence - Flashback interpreter
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* Copyright (C) 2005-2015 Gregory Montoir (cyx@users.sourceforge.net)
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VIDEO_H__
|
#ifndef VIDEO_H__
|
||||||
|
@ -41,6 +30,8 @@ struct Video {
|
||||||
Resource *_res;
|
Resource *_res;
|
||||||
SystemStub *_stub;
|
SystemStub *_stub;
|
||||||
|
|
||||||
|
int _w, _h;
|
||||||
|
int _layerSize;
|
||||||
uint8_t *_frontLayer;
|
uint8_t *_frontLayer;
|
||||||
uint8_t *_backLayer;
|
uint8_t *_backLayer;
|
||||||
uint8_t *_tempLayer;
|
uint8_t *_tempLayer;
|
||||||
|
@ -67,6 +58,7 @@ struct Video {
|
||||||
void setPaletteSlotLE(int palSlot, const uint8_t *palData);
|
void setPaletteSlotLE(int palSlot, const uint8_t *palData);
|
||||||
void setTextPalette();
|
void setTextPalette();
|
||||||
void setPalette0xF();
|
void setPalette0xF();
|
||||||
|
void PC_decodeLev(int level, int room);
|
||||||
void PC_decodeMap(int level, int room);
|
void PC_decodeMap(int level, int room);
|
||||||
void PC_setLevelPalettes();
|
void PC_setLevelPalettes();
|
||||||
void PC_decodeIcn(const uint8_t *src, int num, uint8_t *dst);
|
void PC_decodeIcn(const uint8_t *src, int num, uint8_t *dst);
|
||||||
|
@ -75,6 +67,7 @@ struct Video {
|
||||||
void AMIGA_decodeSpm(const uint8_t *src, uint8_t *dst);
|
void AMIGA_decodeSpm(const uint8_t *src, uint8_t *dst);
|
||||||
void AMIGA_decodeIcn(const uint8_t *src, int num, uint8_t *dst);
|
void AMIGA_decodeIcn(const uint8_t *src, int num, uint8_t *dst);
|
||||||
void AMIGA_decodeSpc(const uint8_t *src, int w, int h, uint8_t *dst);
|
void AMIGA_decodeSpc(const uint8_t *src, int w, int h, uint8_t *dst);
|
||||||
|
void AMIGA_decodeCmp(const uint8_t *src, uint8_t *dst);
|
||||||
void drawSpriteSub1(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
|
void drawSpriteSub1(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
|
||||||
void drawSpriteSub2(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
|
void drawSpriteSub2(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
|
||||||
void drawSpriteSub3(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
|
void drawSpriteSub3(const uint8_t *src, uint8_t *dst, int pitch, int h, int w, uint8_t colMask);
|
||||||
|
@ -85,6 +78,7 @@ struct Video {
|
||||||
void PC_drawStringChar(uint8_t *dst, int pitch, const uint8_t *src, uint8_t color, uint8_t chr);
|
void PC_drawStringChar(uint8_t *dst, int pitch, const uint8_t *src, uint8_t color, uint8_t chr);
|
||||||
void AMIGA_drawStringChar(uint8_t *dst, int pitch, const uint8_t *src, uint8_t color, uint8_t chr);
|
void AMIGA_drawStringChar(uint8_t *dst, int pitch, const uint8_t *src, uint8_t color, uint8_t chr);
|
||||||
const char *drawString(const char *str, int16_t x, int16_t y, uint8_t col);
|
const char *drawString(const char *str, int16_t x, int16_t y, uint8_t col);
|
||||||
|
static Color AMIGA_convertColor(const uint16_t color, bool bgr = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VIDEO_H__
|
#endif // VIDEO_H__
|
||||||
|
|
Loading…
Reference in New Issue