Import 0.3.4
This commit is contained in:
parent
1cd2866af7
commit
31757e48dc
7
Makefile
7
Makefile
|
@ -2,21 +2,22 @@
|
||||||
SDL_CFLAGS := `sdl2-config --cflags`
|
SDL_CFLAGS := `sdl2-config --cflags`
|
||||||
SDL_LIBS := `sdl2-config --libs`
|
SDL_LIBS := `sdl2-config --libs`
|
||||||
|
|
||||||
|
DL_LIBS := -ldl
|
||||||
MODPLUG_LIBS := -lmodplug
|
MODPLUG_LIBS := -lmodplug
|
||||||
TREMOR_LIBS := -lvorbisidec -logg
|
TREMOR_LIBS := -lvorbisidec -logg
|
||||||
ZLIB_LIBS := -lz
|
ZLIB_LIBS := -lz
|
||||||
|
|
||||||
CXXFLAGS += -Wall -MMD $(SDL_CFLAGS) -DUSE_MODPLUG -DUSE_TREMOR -DUSE_ZLIB
|
CXXFLAGS += -Wall -MMD $(SDL_CFLAGS) -DUSE_MODPLUG -DUSE_TREMOR -DUSE_ZLIB
|
||||||
|
|
||||||
SRCS = collision.cpp cutscene.cpp file.cpp fs.cpp game.cpp graphics.cpp main.cpp menu.cpp \
|
SRCS = collision.cpp cutscene.cpp dynlib.cpp file.cpp fs.cpp game.cpp graphics.cpp main.cpp menu.cpp \
|
||||||
mixer.cpp mod_player.cpp ogg_player.cpp piege.cpp resource.cpp resource_aba.cpp \
|
mixer.cpp mod_player.cpp ogg_player.cpp piege.cpp resource.cpp resource_aba.cpp \
|
||||||
scaler.cpp seq_player.cpp \
|
scaler.cpp screenshot.cpp seq_player.cpp \
|
||||||
sfx_player.cpp staticres.cpp systemstub_sdl.cpp unpack.cpp util.cpp video.cpp
|
sfx_player.cpp staticres.cpp systemstub_sdl.cpp unpack.cpp util.cpp video.cpp
|
||||||
|
|
||||||
OBJS = $(SRCS:.cpp=.o)
|
OBJS = $(SRCS:.cpp=.o)
|
||||||
DEPS = $(SRCS:.cpp=.d)
|
DEPS = $(SRCS:.cpp=.d)
|
||||||
|
|
||||||
LIBS = $(SDL_LIBS) $(MODPLUG_LIBS) $(TREMOR_LIBS) $(ZLIB_LIBS)
|
LIBS = $(SDL_LIBS) $(DL_LIBS) $(MODPLUG_LIBS) $(TREMOR_LIBS) $(ZLIB_LIBS)
|
||||||
|
|
||||||
rs: $(OBJS)
|
rs: $(OBJS)
|
||||||
$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
REminiscence README
|
REminiscence README
|
||||||
Release version: 0.3.3
|
Release version: 0.3.4
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ directory. These paths can be changed using command line switches :
|
||||||
--savepath=PATH Path to save files (default '.')
|
--savepath=PATH Path to save files (default '.')
|
||||||
--levelnum=NUM Level to start from (default '0')
|
--levelnum=NUM Level to start from (default '0')
|
||||||
--fullscreen Fullscreen display
|
--fullscreen Fullscreen display
|
||||||
--scaler=INDEX Graphics scaler
|
--scaler=NAME@X Graphics scaler (default 'scale@3')
|
||||||
--language=LANG Language (fr,en,de,sp,it)
|
--language=LANG Language (fr,en,de,sp,it)
|
||||||
|
|
||||||
In-game hotkeys :
|
In-game hotkeys :
|
||||||
|
@ -56,7 +56,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
|
Alt S write screenshot as .tga
|
||||||
Ctrl S save game state
|
Ctrl S save game state
|
||||||
Ctrl L load game state
|
Ctrl L load game state
|
||||||
Ctrl + and - change game state slot
|
Ctrl + and - change game state slot
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include "dynlib.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
struct DynLib_impl {
|
||||||
|
HINSTANCE _dl;
|
||||||
|
DynLib_impl(const char *name) {
|
||||||
|
char dllname[MAXPATHLEN];
|
||||||
|
snprintf(dllname, sizeof(dllname), "%s.dll", name);
|
||||||
|
_dl = LoadLibrary(dllname);
|
||||||
|
}
|
||||||
|
~DynLib_impl() {
|
||||||
|
if (_dl) {
|
||||||
|
FreeLibrary(_dl);
|
||||||
|
_dl = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void *getSymbol(const char *name) {
|
||||||
|
return (void *)GetProcAddress(_dl, name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct DynLib_impl {
|
||||||
|
void *_dl;
|
||||||
|
DynLib_impl(const char *name) {
|
||||||
|
char soname[MAXPATHLEN];
|
||||||
|
snprintf(soname, sizeof(soname), "%s.so", name);
|
||||||
|
_dl = dlopen(soname, RTLD_LAZY);
|
||||||
|
}
|
||||||
|
~DynLib_impl() {
|
||||||
|
if (_dl) {
|
||||||
|
dlclose(_dl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void *getSymbol(const char *name) {
|
||||||
|
return dlsym(_dl, name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DynLib::DynLib(const char *name) {
|
||||||
|
_impl = new DynLib_impl(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
DynLib::~DynLib() {
|
||||||
|
delete _impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *DynLib::getSymbol(const char *name) {
|
||||||
|
return _impl->getSymbol(name);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
#ifndef DYNLIB_H__
|
||||||
|
#define DYNLIB_H__
|
||||||
|
|
||||||
|
struct DynLib_impl;
|
||||||
|
|
||||||
|
struct DynLib {
|
||||||
|
DynLib_impl *_impl;
|
||||||
|
|
||||||
|
DynLib(const char *name);
|
||||||
|
~DynLib();
|
||||||
|
|
||||||
|
void *getSymbol(const char *name);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DYNLIB_H__
|
22
file.cpp
22
file.cpp
|
@ -25,7 +25,7 @@ struct File_impl {
|
||||||
virtual uint32_t size() = 0;
|
virtual uint32_t size() = 0;
|
||||||
virtual void seek(int32_t off) = 0;
|
virtual void seek(int32_t off) = 0;
|
||||||
virtual uint32_t read(void *ptr, uint32_t len) = 0;
|
virtual uint32_t read(void *ptr, uint32_t len) = 0;
|
||||||
virtual uint32_t write(void *ptr, uint32_t len) = 0;
|
virtual uint32_t write(const void *ptr, uint32_t len) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StdioFile : File_impl {
|
struct StdioFile : File_impl {
|
||||||
|
@ -67,7 +67,7 @@ struct StdioFile : File_impl {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint32_t write(void *ptr, uint32_t len) {
|
uint32_t write(const void *ptr, uint32_t len) {
|
||||||
if (_fp) {
|
if (_fp) {
|
||||||
uint32_t r = fwrite(ptr, 1, len, _fp);
|
uint32_t r = fwrite(ptr, 1, len, _fp);
|
||||||
if (r != len) {
|
if (r != len) {
|
||||||
|
@ -119,7 +119,7 @@ struct GzipFile : File_impl {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint32_t write(void *ptr, uint32_t len) {
|
uint32_t write(const void *ptr, uint32_t len) {
|
||||||
if (_fp) {
|
if (_fp) {
|
||||||
uint32_t r = gzwrite(_fp, ptr, len);
|
uint32_t r = gzwrite(_fp, ptr, len);
|
||||||
if (r != len) {
|
if (r != len) {
|
||||||
|
@ -136,8 +136,9 @@ struct GzipFile : File_impl {
|
||||||
struct AssetFile: File_impl {
|
struct AssetFile: File_impl {
|
||||||
SDL_RWops *_rw;
|
SDL_RWops *_rw;
|
||||||
AssetFile() : _rw(0) {}
|
AssetFile() : _rw(0) {}
|
||||||
bool open(const char *path, const char *mode) {
|
bool prefixedOpen(const char *prefix, const char *name) {
|
||||||
_ioErr = false;
|
char path[MAXPATHLEN];
|
||||||
|
snprintf(path, sizeof(path), "%s%s", prefix, name);
|
||||||
_rw = SDL_RWFromFile(path, "rb");
|
_rw = SDL_RWFromFile(path, "rb");
|
||||||
if (!_rw) {
|
if (!_rw) {
|
||||||
// try uppercase
|
// try uppercase
|
||||||
|
@ -146,6 +147,9 @@ struct AssetFile: File_impl {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; path[i] && i < MAXPATHLEN - 1; ++i) {
|
for (; path[i] && i < MAXPATHLEN - 1; ++i) {
|
||||||
fixedPath[i] = path[i];
|
fixedPath[i] = path[i];
|
||||||
|
if (i < strlen(prefix)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (fixedPath[i] >= 'a' && fixedPath[i] <= 'z') {
|
if (fixedPath[i] >= 'a' && fixedPath[i] <= 'z') {
|
||||||
fixedPath[i] += 'A' - 'a';
|
fixedPath[i] += 'A' - 'a';
|
||||||
}
|
}
|
||||||
|
@ -156,6 +160,10 @@ struct AssetFile: File_impl {
|
||||||
}
|
}
|
||||||
return _rw != 0;
|
return _rw != 0;
|
||||||
}
|
}
|
||||||
|
bool open(const char *path, const char *mode) {
|
||||||
|
_ioErr = false;
|
||||||
|
return prefixedOpen("", path) || prefixedOpen("/sdcard/flashback/", path);
|
||||||
|
}
|
||||||
void close() {
|
void close() {
|
||||||
if (_rw) {
|
if (_rw) {
|
||||||
SDL_RWclose(_rw);
|
SDL_RWclose(_rw);
|
||||||
|
@ -182,7 +190,7 @@ struct AssetFile: File_impl {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint32_t write(void *ptr, uint32_t len) {
|
uint32_t write(const void *ptr, uint32_t len) {
|
||||||
_ioErr = true;
|
_ioErr = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -308,7 +316,7 @@ uint32_t File::readUint32BE() {
|
||||||
return (hi << 16) | lo;
|
return (hi << 16) | lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t File::write(void *ptr, uint32_t len) {
|
uint32_t File::write(const void *ptr, uint32_t len) {
|
||||||
return _impl->write(ptr, len);
|
return _impl->write(ptr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
file.h
2
file.h
|
@ -30,7 +30,7 @@ struct File {
|
||||||
uint32_t readUint32LE();
|
uint32_t readUint32LE();
|
||||||
uint16_t readUint16BE();
|
uint16_t readUint16BE();
|
||||||
uint32_t readUint32BE();
|
uint32_t readUint32BE();
|
||||||
uint32_t write(void *ptr, uint32_t size);
|
uint32_t write(const void *ptr, uint32_t size);
|
||||||
void writeByte(uint8_t b);
|
void writeByte(uint8_t b);
|
||||||
void writeUint16BE(uint16_t n);
|
void writeUint16BE(uint16_t n);
|
||||||
void writeUint32BE(uint32_t n);
|
void writeUint32BE(uint32_t n);
|
||||||
|
|
8
game.cpp
8
game.cpp
|
@ -695,8 +695,12 @@ void Game::printLevelCode() {
|
||||||
if (_printLevelCodeCounter != 0) {
|
if (_printLevelCodeCounter != 0) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
const char *code = Menu::_passwords[_currentLevel][_skillLevel];
|
const char *code = Menu::_passwords[_currentLevel][_skillLevel];
|
||||||
if (_res.isAmiga() && _res._lang == LANG_FR) {
|
if (_res.isAmiga()) {
|
||||||
code = Menu::_passwordsFrAmiga[_skillLevel * 7 + _currentLevel];
|
if (_res._lang == LANG_FR) {
|
||||||
|
code = Menu::_passwordsFrAmiga[_skillLevel * 7 + _currentLevel];
|
||||||
|
} else {
|
||||||
|
code = Menu::_passwordsEnAmiga[_skillLevel * 7 + _currentLevel];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
snprintf(buf, sizeof(buf), "CODE: %s", code);
|
snprintf(buf, sizeof(buf), "CODE: %s", code);
|
||||||
_vid.drawString(buf, (_vid._w - strlen(buf) * 8) / 2, 16, 0xE7);
|
_vid.drawString(buf, (_vid._w - strlen(buf) * 8) / 2, 16, 0xE7);
|
||||||
|
|
49
main.cpp
49
main.cpp
|
@ -22,7 +22,7 @@ static const char *USAGE =
|
||||||
" --savepath=PATH Path to save files (default '.')\n"
|
" --savepath=PATH Path to save files (default '.')\n"
|
||||||
" --levelnum=NUM Start to level, bypass introduction\n"
|
" --levelnum=NUM Start to level, bypass introduction\n"
|
||||||
" --fullscreen Fullscreen display\n"
|
" --fullscreen Fullscreen display\n"
|
||||||
" --scaler=INDEX Graphics scaler\n"
|
" --scaler=NAME@X Graphics scaler (default 'scale@3')\n"
|
||||||
" --language=LANG Language (fr,en,de,sp,it)\n"
|
" --language=LANG Language (fr,en,de,sp,it)\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -127,14 +127,50 @@ static void initOptions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int DEFAULT_SCALER = SCALER_SCALE_3X;
|
static void parseScaler(char *name, ScalerParameters *scalerParameters) {
|
||||||
|
struct {
|
||||||
|
const char *name;
|
||||||
|
int type;
|
||||||
|
} scalers[] = {
|
||||||
|
{ "point", kScalerTypePoint },
|
||||||
|
{ "linear", kScalerTypeLinear },
|
||||||
|
{ "scale", kScalerTypeInternal },
|
||||||
|
{ 0, -1 }
|
||||||
|
};
|
||||||
|
bool found = false;
|
||||||
|
char *sep = strchr(name, '@');
|
||||||
|
if (sep) {
|
||||||
|
*sep = 0;
|
||||||
|
}
|
||||||
|
for (int i = 0; scalers[i].name; ++i) {
|
||||||
|
if (strcmp(scalers[i].name, name) == 0) {
|
||||||
|
scalerParameters->type = (ScalerType)scalers[i].type;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
char libname[32];
|
||||||
|
snprintf(libname, sizeof(libname), "scaler_%s", name);
|
||||||
|
const Scaler *scaler = findScaler(libname);
|
||||||
|
if (scaler) {
|
||||||
|
scalerParameters->type = kScalerTypeExternal;
|
||||||
|
scalerParameters->scaler = scaler;
|
||||||
|
} else {
|
||||||
|
warning("Scaler '%s' not found, using default", libname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sep) {
|
||||||
|
scalerParameters->factor = atoi(sep + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
bool fullscreen = false;
|
||||||
|
ScalerParameters scalerParameters = ScalerParameters::defaults();
|
||||||
int forcedLanguage = -1;
|
int forcedLanguage = -1;
|
||||||
int demoNum = -1;
|
int demoNum = -1;
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
|
@ -174,10 +210,7 @@ int main(int argc, char *argv[]) {
|
||||||
fullscreen = true;
|
fullscreen = true;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
scaler = atoi(optarg);
|
parseScaler(optarg, &scalerParameters);
|
||||||
if (scaler < 0 || scaler >= NUM_SCALERS) {
|
|
||||||
scaler = DEFAULT_SCALER;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 6: {
|
case 6: {
|
||||||
static const struct {
|
static const struct {
|
||||||
|
@ -218,7 +251,7 @@ int main(int argc, char *argv[]) {
|
||||||
const Language language = (forcedLanguage == -1) ? detectLanguage(&fs) : (Language)forcedLanguage;
|
const Language language = (forcedLanguage == -1) ? detectLanguage(&fs) : (Language)forcedLanguage;
|
||||||
SystemStub *stub = SystemStub_SDL_create();
|
SystemStub *stub = SystemStub_SDL_create();
|
||||||
Game *g = new Game(stub, &fs, savePath, levelNum, demoNum, (ResourceType)version, language);
|
Game *g = new Game(stub, &fs, savePath, levelNum, demoNum, (ResourceType)version, language);
|
||||||
stub->init(g_caption, Video::GAMESCREEN_W, Video::GAMESCREEN_H, scaler, fullscreen);
|
stub->init(g_caption, Video::GAMESCREEN_W, Video::GAMESCREEN_H, fullscreen, &scalerParameters);
|
||||||
g->run();
|
g->run();
|
||||||
delete g;
|
delete g;
|
||||||
stub->destroy();
|
stub->destroy();
|
||||||
|
|
1
menu.h
1
menu.h
|
@ -41,6 +41,7 @@ struct Menu {
|
||||||
|
|
||||||
static const char *_passwords[8][3];
|
static const char *_passwords[8][3];
|
||||||
static const char *_passwordsFrAmiga[];
|
static const char *_passwordsFrAmiga[];
|
||||||
|
static const char *_passwordsEnAmiga[];
|
||||||
|
|
||||||
Resource *_res;
|
Resource *_res;
|
||||||
SystemStub *_stub;
|
SystemStub *_stub;
|
||||||
|
|
2
rs.cfg
2
rs.cfg
|
@ -8,7 +8,7 @@ play_disabled_cutscenes=false
|
||||||
enable_password_menu=false
|
enable_password_menu=false
|
||||||
|
|
||||||
# fade palette to black for screen transition (use blending if false)
|
# fade palette to black for screen transition (use blending if false)
|
||||||
fade_out_palette=true
|
fade_out_palette=false
|
||||||
|
|
||||||
# use .BNQ & .LEV datafiles (tile based rendering) for backgrounds (instead of .MAP)
|
# use .BNQ & .LEV datafiles (tile based rendering) for backgrounds (instead of .MAP)
|
||||||
use_tiledata=false
|
use_tiledata=false
|
||||||
|
|
179
scaler.cpp
179
scaler.cpp
|
@ -5,79 +5,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "scaler.h"
|
#include "scaler.h"
|
||||||
|
#include "dynlib.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static void point1x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
|
static void scale2x(uint32_t *dst, int dstPitch, const uint32_t *src, int srcPitch, int w, int h) {
|
||||||
dstPitch >>= 1;
|
|
||||||
while (h--) {
|
|
||||||
memcpy(dst, src, w * 2);
|
|
||||||
dst += dstPitch;
|
|
||||||
src += srcPitch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void point2x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
|
|
||||||
dstPitch >>= 1;
|
|
||||||
const int dstPitch2 = dstPitch * 2;
|
const int dstPitch2 = dstPitch * 2;
|
||||||
while (h--) {
|
for (int y = 0; y < h; ++y) {
|
||||||
uint16_t *p = dst;
|
uint32_t *p = dst;
|
||||||
for (int i = 0; i < w; ++i, p += 2) {
|
for (int x = 0; x < w; ++x, p += 2) {
|
||||||
const uint16_t c = *(src + i);
|
const uint32_t E = *(src + x);
|
||||||
for (int j = 0; j < 2; ++j) {
|
const uint32_t B = (y == 0) ? E : *(src + x - srcPitch);
|
||||||
*(p + j) = *(p + dstPitch + j) = c;
|
const uint32_t D = (x == 0) ? E : *(src + x - 1);
|
||||||
}
|
const uint32_t F = (x == w - 1) ? E : *(src + x + 1);
|
||||||
}
|
const uint32_t H = (y == h - 1) ? E : *(src + x + srcPitch);
|
||||||
dst += dstPitch2;
|
|
||||||
src += srcPitch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void point3x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
|
|
||||||
dstPitch >>= 1;
|
|
||||||
const int dstPitch2 = dstPitch * 2;
|
|
||||||
const int dstPitch3 = dstPitch * 3;
|
|
||||||
while (h--) {
|
|
||||||
uint16_t *p = dst;
|
|
||||||
for (int i = 0; i < w; ++i, p += 3) {
|
|
||||||
const uint16_t c = *(src + i);
|
|
||||||
for (int j = 0; j < 3; ++j) {
|
|
||||||
*(p + j) = *(p + dstPitch + j) = *(p + dstPitch2 + j) = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dst += dstPitch3;
|
|
||||||
src += srcPitch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void point4x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
|
|
||||||
dstPitch >>= 1;
|
|
||||||
const int dstPitch2 = dstPitch * 2;
|
|
||||||
const int dstPitch3 = dstPitch * 3;
|
|
||||||
const int dstPitch4 = dstPitch * 4;
|
|
||||||
while (h--) {
|
|
||||||
uint16_t *p = dst;
|
|
||||||
for (int i = 0; i < w; ++i, p += 4) {
|
|
||||||
const uint16_t c = *(src + i);
|
|
||||||
for (int j = 0; j < 4; ++j) {
|
|
||||||
*(p + j) = *(p + dstPitch + j) = *(p + dstPitch2 + j) = *(p + dstPitch3 + j) = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dst += dstPitch4;
|
|
||||||
src += srcPitch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void scale2x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
|
|
||||||
dstPitch >>= 1;
|
|
||||||
const int dstPitch2 = dstPitch * 2;
|
|
||||||
while (h--) {
|
|
||||||
uint16_t *p = dst;
|
|
||||||
uint16_t D = *(src - 1);
|
|
||||||
uint16_t E = *(src);
|
|
||||||
for (int i = 0; i < w; ++i, p += 2) {
|
|
||||||
uint16_t B = *(src + i - srcPitch);
|
|
||||||
uint16_t F = *(src + i + 1);
|
|
||||||
uint16_t H = *(src + i + srcPitch);
|
|
||||||
if (B != H && D != F) {
|
if (B != H && D != F) {
|
||||||
*(p) = D == B ? D : E;
|
*(p) = D == B ? D : E;
|
||||||
*(p + 1) = B == F ? F : E;
|
*(p + 1) = B == F ? F : E;
|
||||||
|
@ -89,30 +29,39 @@ static void scale2x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPit
|
||||||
*(p + dstPitch) = E;
|
*(p + dstPitch) = E;
|
||||||
*(p + dstPitch + 1) = E;
|
*(p + dstPitch + 1) = E;
|
||||||
}
|
}
|
||||||
D = E;
|
|
||||||
E = F;
|
|
||||||
}
|
}
|
||||||
dst += dstPitch2;
|
dst += dstPitch2;
|
||||||
src += srcPitch;
|
src += srcPitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scale3x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
|
static void scale3x(uint32_t *dst, int dstPitch, const uint32_t *src, int srcPitch, int w, int h) {
|
||||||
dstPitch >>= 1;
|
|
||||||
const int dstPitch2 = dstPitch * 2;
|
const int dstPitch2 = dstPitch * 2;
|
||||||
const int dstPitch3 = dstPitch * 3;
|
const int dstPitch3 = dstPitch * 3;
|
||||||
while (h--) {
|
for (int y = 0; y < h; ++y) {
|
||||||
uint16_t *p = dst;
|
uint32_t *p = dst;
|
||||||
uint16_t A = *(src - srcPitch - 1);
|
for (int x = 0; x < w; ++x, p += 3) {
|
||||||
uint16_t B = *(src - srcPitch);
|
const uint32_t E = *(src + x);
|
||||||
uint16_t D = *(src - 1);
|
const uint32_t B = (y == 0) ? E : *(src + x - srcPitch);
|
||||||
uint16_t E = *(src);
|
const uint32_t D = (x == 0) ? E : *(src + x - 1);
|
||||||
uint16_t G = *(src + srcPitch - 1);
|
const uint32_t F = (x == w - 1) ? E : *(src + x + 1);
|
||||||
uint16_t H = *(src + srcPitch);
|
const uint32_t H = (y == h - 1) ? E : *(src + x + srcPitch);
|
||||||
for (int i = 0; i < w; ++i, p += 3) {
|
uint32_t A, C;
|
||||||
uint16_t C = *(src + i - srcPitch + 1);
|
if (y == 0) {
|
||||||
uint16_t F = *(src + i + 1);
|
A = D;
|
||||||
uint16_t I = *(src + i + srcPitch + 1);
|
C = F;
|
||||||
|
} else {
|
||||||
|
A = (x == 0) ? B : *(src + x - srcPitch - 1);
|
||||||
|
C = (x == w - 1) ? B : *(src + x - srcPitch + 1);
|
||||||
|
}
|
||||||
|
uint32_t G, I;
|
||||||
|
if (y == h - 1) {
|
||||||
|
G = D;
|
||||||
|
I = F;
|
||||||
|
} else {
|
||||||
|
G = (x == 0) ? H : *(src + x + srcPitch - 1);
|
||||||
|
I = (x == w - 1) ? H : *(src + x + srcPitch + 1);
|
||||||
|
}
|
||||||
if (B != H && D != F) {
|
if (B != H && D != F) {
|
||||||
*(p) = D == B ? D : E;
|
*(p) = D == B ? D : E;
|
||||||
*(p + 1) = (D == B && E != C) || (B == F && E != A) ? B : E;
|
*(p + 1) = (D == B && E != C) || (B == F && E != A) ? B : E;
|
||||||
|
@ -134,48 +83,62 @@ static void scale3x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPit
|
||||||
*(p + dstPitch2 + 1) = E;
|
*(p + dstPitch2 + 1) = E;
|
||||||
*(p + dstPitch2 + 2) = E;
|
*(p + dstPitch2 + 2) = E;
|
||||||
}
|
}
|
||||||
A = B;
|
|
||||||
B = C;
|
|
||||||
D = E;
|
|
||||||
E = F;
|
|
||||||
G = H;
|
|
||||||
H = I;
|
|
||||||
}
|
}
|
||||||
dst += dstPitch3;
|
dst += dstPitch3;
|
||||||
src += srcPitch;
|
src += srcPitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scale4x(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h) {
|
static void scale4x(uint32_t *dst, int dstPitch, const uint32_t *src, int srcPitch, int w, int h) {
|
||||||
static struct {
|
static struct {
|
||||||
uint16_t *ptr;
|
uint32_t *ptr;
|
||||||
int w, h, pitch;
|
int w, h, pitch;
|
||||||
int size;
|
int size;
|
||||||
} buf;
|
} buf;
|
||||||
const int size = (w * 2 + 2) * (h * 2 + 2) * sizeof(uint16_t);
|
const int size = (w * 2) * (h * 2) * sizeof(uint32_t);
|
||||||
if (buf.size < size) {
|
if (buf.size < size) {
|
||||||
free(buf.ptr);
|
free(buf.ptr);
|
||||||
buf.size = size;
|
buf.size = size;
|
||||||
buf.w = w * 2;
|
buf.w = w * 2;
|
||||||
buf.h = h * 2;
|
buf.h = h * 2;
|
||||||
buf.pitch = buf.w + 2;
|
buf.pitch = buf.w;
|
||||||
buf.ptr = (uint16_t *)malloc(buf.size);
|
buf.ptr = (uint32_t *)malloc(buf.size);
|
||||||
if (!buf.ptr) {
|
if (!buf.ptr) {
|
||||||
error("Unable to allocate scale4x intermediate buffer");
|
error("Unable to allocate scale4x intermediate buffer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scale2x(buf.ptr + buf.pitch + 1, buf.pitch * sizeof(uint16_t), src, srcPitch, w, h);
|
scale2x(buf.ptr, buf.pitch, src, srcPitch, w, h);
|
||||||
scale2x(dst, dstPitch, buf.ptr + buf.pitch + 1, buf.pitch, w * 2, h * 2);
|
scale2x(dst, dstPitch, buf.ptr, buf.pitch, buf.w, buf.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Scaler _scalers[] = {
|
static void scaleNx(int factor, uint32_t *dst, int dstPitch, const uint32_t *src, int srcPitch, int w, int h) {
|
||||||
{ "point1x", &point1x, 1 },
|
switch (factor) {
|
||||||
{ "point2x", &point2x, 2 },
|
case 2:
|
||||||
{ "scale2x", &scale2x, 2 },
|
return scale2x(dst, dstPitch, src, srcPitch, w, h);
|
||||||
{ "point3x", &point3x, 3 },
|
case 3:
|
||||||
{ "scale3x", &scale3x, 3 },
|
return scale3x(dst, dstPitch, src, srcPitch, w, h);
|
||||||
{ "point4x", &point4x, 4 },
|
case 4:
|
||||||
{ "scale4x", &scale4x, 4 },
|
return scale4x(dst, dstPitch, src, srcPitch, w, h);
|
||||||
{ 0, 0, 0 }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Scaler _internalScaler = {
|
||||||
|
SCALER_TAG,
|
||||||
|
"scaleNx",
|
||||||
|
2, 4,
|
||||||
|
scaleNx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static DynLib *dynLib;
|
||||||
|
|
||||||
|
static const char *kSoSym = "getScaler";
|
||||||
|
|
||||||
|
const Scaler *findScaler(const char *name) {
|
||||||
|
dynLib = new DynLib(name);
|
||||||
|
void *symbol = dynLib->getSymbol(kSoSym);
|
||||||
|
if (symbol) {
|
||||||
|
typedef const Scaler *(*GetScalerProc)();
|
||||||
|
return ((GetScalerProc)symbol)();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
29
scaler.h
29
scaler.h
|
@ -7,27 +7,28 @@
|
||||||
#ifndef SCALER_H__
|
#ifndef SCALER_H__
|
||||||
#define SCALER_H__
|
#define SCALER_H__
|
||||||
|
|
||||||
#include "intern.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef void (*ScaleProc)(uint16_t *dst, int dstPitch, const uint16_t *src, int srcPitch, int w, int h);
|
typedef void (*ScaleProc32)(int factor, uint32_t *dst, int dstPitch, const uint32_t *src, int srcPitch, int w, int h);
|
||||||
|
|
||||||
enum {
|
enum ScalerType {
|
||||||
SCALER_POINT_1X = 0,
|
kScalerTypePoint,
|
||||||
SCALER_POINT_2X,
|
kScalerTypeLinear,
|
||||||
SCALER_SCALE_2X,
|
kScalerTypeInternal,
|
||||||
SCALER_POINT_3X,
|
kScalerTypeExternal,
|
||||||
SCALER_SCALE_3X,
|
|
||||||
SCALER_POINT_4X,
|
|
||||||
SCALER_SCALE_4X,
|
|
||||||
NUM_SCALERS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SCALER_TAG 1
|
||||||
|
|
||||||
struct Scaler {
|
struct Scaler {
|
||||||
|
uint32_t tag;
|
||||||
const char *name;
|
const char *name;
|
||||||
ScaleProc proc;
|
int factorMin, factorMax;
|
||||||
uint8_t factor;
|
ScaleProc32 scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const Scaler _scalers[];
|
extern const Scaler _internalScaler;
|
||||||
|
|
||||||
|
const Scaler *findScaler(const char *name);
|
||||||
|
|
||||||
#endif // SCALER_H__
|
#endif // SCALER_H__
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
|
||||||
|
#include "screenshot.h"
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
static void TO_LE16(uint8_t *dst, uint16_t value) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
dst[i] = value & 255;
|
||||||
|
value >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define kTgaImageTypeUncompressedTrueColor 2
|
||||||
|
#define kTgaImageTypeRunLengthEncodedTrueColor 10
|
||||||
|
#define kTgaDirectionTop (1 << 5)
|
||||||
|
|
||||||
|
static const int TGA_HEADER_SIZE = 18;
|
||||||
|
|
||||||
|
void saveTGA(const char *filename, const uint8_t *rgba, int w, int h) {
|
||||||
|
|
||||||
|
static const uint8_t kImageType = kTgaImageTypeRunLengthEncodedTrueColor;
|
||||||
|
uint8_t buffer[TGA_HEADER_SIZE];
|
||||||
|
buffer[0] = 0; // ID Length
|
||||||
|
buffer[1] = 0; // ColorMap Type
|
||||||
|
buffer[2] = kImageType;
|
||||||
|
TO_LE16(buffer + 3, 0); // ColorMap Start
|
||||||
|
TO_LE16(buffer + 5, 0); // ColorMap Length
|
||||||
|
buffer[7] = 0; // ColorMap Bits
|
||||||
|
TO_LE16(buffer + 8, 0); // X-origin
|
||||||
|
TO_LE16(buffer + 10, 0); // Y-origin
|
||||||
|
TO_LE16(buffer + 12, w); // Image Width
|
||||||
|
TO_LE16(buffer + 14, h); // Image Height
|
||||||
|
buffer[16] = 24; // Pixel Depth
|
||||||
|
buffer[17] = kTgaDirectionTop; // Descriptor
|
||||||
|
|
||||||
|
File f;
|
||||||
|
if (f.open(filename, "wb", ".")) {
|
||||||
|
f.write(buffer, sizeof(buffer));
|
||||||
|
if (kImageType == kTgaImageTypeUncompressedTrueColor) {
|
||||||
|
for (int i = 0; i < w * h; ++i) {
|
||||||
|
f.writeByte(rgba[0]);
|
||||||
|
f.writeByte(rgba[1]);
|
||||||
|
f.writeByte(rgba[2]);
|
||||||
|
rgba += 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(kImageType == kTgaImageTypeRunLengthEncodedTrueColor);
|
||||||
|
int prevColor = rgba[2] + (rgba[1] << 8) + (rgba[0] << 16); rgba += 4;
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 1; i < w * h; ++i) {
|
||||||
|
int color = rgba[2] + (rgba[1] << 8) + (rgba[0] << 16); rgba += 4;
|
||||||
|
if (prevColor == color && count < 127) {
|
||||||
|
++count;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
f.writeByte(count | 0x80);
|
||||||
|
f.writeByte((prevColor >> 16) & 255);
|
||||||
|
f.writeByte((prevColor >> 8) & 255);
|
||||||
|
f.writeByte( prevColor & 255);
|
||||||
|
count = 0;
|
||||||
|
prevColor = color;
|
||||||
|
}
|
||||||
|
if (count != 0) {
|
||||||
|
f.writeByte(count | 0x80);
|
||||||
|
f.writeByte((prevColor >> 16) & 255);
|
||||||
|
f.writeByte((prevColor >> 8) & 255);
|
||||||
|
f.writeByte( prevColor & 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#ifndef SCREENSHOT_H__
|
||||||
|
#define SCREENSHOT_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void saveTGA(const char *filename, const uint8_t *rgb, int w, int h);
|
||||||
|
|
||||||
|
#endif
|
|
@ -2748,6 +2748,12 @@ const char *Menu::_passwordsFrAmiga[] = {
|
||||||
"CLOP", "CARA", "CALE", "FONT", "HASH", "FIBO", "TIPS", // hard
|
"CLOP", "CARA", "CALE", "FONT", "HASH", "FIBO", "TIPS", // hard
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *Menu::_passwordsEnAmiga[] = {
|
||||||
|
"WIND", "SPIN", "KAVA", "HIRO", "TEST", "GOLD", "WALL", // easy
|
||||||
|
"FIRE", "BURN", "EGGS", "GURT", "CHIP", "TREE", "BOLD", // normal
|
||||||
|
"MINE", "YOUR", "NEST", "LINE", "LISA", "MARY", "MICE", // hard
|
||||||
|
};
|
||||||
|
|
||||||
const uint8_t Video::_conradPal1[] = {
|
const uint8_t Video::_conradPal1[] = {
|
||||||
0x00, 0x00, 0xCC, 0x0C, 0x8F, 0x08, 0x7E, 0x07, 0x6C, 0x06, 0x5B, 0x05, 0x4A, 0x04, 0x63, 0x09,
|
0x00, 0x00, 0xCC, 0x0C, 0x8F, 0x08, 0x7E, 0x07, 0x6C, 0x06, 0x5B, 0x05, 0x4A, 0x04, 0x63, 0x09,
|
||||||
0x52, 0x07, 0x41, 0x06, 0x30, 0x06, 0x76, 0x0C, 0x14, 0x09, 0x25, 0x0B, 0x88, 0x08, 0xFF, 0x0F
|
0x52, 0x07, 0x41, 0x06, 0x30, 0x06, 0x76, 0x0C, 0x14, 0x09, 0x25, 0x0B, 0x88, 0x08, 0xFF, 0x0F
|
||||||
|
|
11
systemstub.h
11
systemstub.h
|
@ -8,6 +8,7 @@
|
||||||
#define SYSTEMSTUB_H__
|
#define SYSTEMSTUB_H__
|
||||||
|
|
||||||
#include "intern.h"
|
#include "intern.h"
|
||||||
|
#include "scaler.h"
|
||||||
|
|
||||||
struct PlayerInput {
|
struct PlayerInput {
|
||||||
enum {
|
enum {
|
||||||
|
@ -39,6 +40,14 @@ struct PlayerInput {
|
||||||
bool quit;
|
bool quit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ScalerParameters {
|
||||||
|
ScalerType type;
|
||||||
|
const Scaler *scaler;
|
||||||
|
int factor;
|
||||||
|
|
||||||
|
static ScalerParameters defaults();
|
||||||
|
};
|
||||||
|
|
||||||
struct SystemStub {
|
struct SystemStub {
|
||||||
typedef void (*AudioCallback)(void *param, int16_t *stream, int len);
|
typedef void (*AudioCallback)(void *param, int16_t *stream, int len);
|
||||||
|
|
||||||
|
@ -46,7 +55,7 @@ struct SystemStub {
|
||||||
|
|
||||||
virtual ~SystemStub() {}
|
virtual ~SystemStub() {}
|
||||||
|
|
||||||
virtual void init(const char *title, int w, int h, int scaler, bool fullscreen) = 0;
|
virtual void init(const char *title, int w, int h, bool fullscreen, ScalerParameters *scalerParameters) = 0;
|
||||||
virtual void destroy() = 0;
|
virtual void destroy() = 0;
|
||||||
|
|
||||||
virtual void setScreenSize(int w, int h) = 0;
|
virtual void setScreenSize(int w, int h) = 0;
|
||||||
|
|
|
@ -6,32 +6,39 @@
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include "scaler.h"
|
#include "scaler.h"
|
||||||
|
#include "screenshot.h"
|
||||||
#include "systemstub.h"
|
#include "systemstub.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static const int kAudioHz = 22050;
|
static const int kAudioHz = 22050;
|
||||||
|
|
||||||
|
static const char *kIconBmp = "icon.bmp";
|
||||||
|
|
||||||
static const int kJoystickIndex = 0;
|
static const int kJoystickIndex = 0;
|
||||||
static const int kJoystickCommitValue = 3200;
|
static const int kJoystickCommitValue = 3200;
|
||||||
|
|
||||||
|
static const uint32_t kPixelFormat = SDL_PIXELFORMAT_RGB888;
|
||||||
|
|
||||||
|
ScalerParameters ScalerParameters::defaults() {
|
||||||
|
ScalerParameters params;
|
||||||
|
params.type = kScalerTypeInternal;
|
||||||
|
params.scaler = &_internalScaler;
|
||||||
|
params.factor = _internalScaler.factorMin + (_internalScaler.factorMax - _internalScaler.factorMin) / 2;
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
struct SystemStub_SDL : SystemStub {
|
struct SystemStub_SDL : SystemStub {
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
SDL_Window *_window;
|
SDL_Window *_window;
|
||||||
SDL_Renderer *_renderer;
|
SDL_Renderer *_renderer;
|
||||||
SDL_Texture *_texture;
|
SDL_Texture *_texture;
|
||||||
int _texW, _texH;
|
int _texW, _texH;
|
||||||
SDL_GameController *_controller;
|
SDL_GameController *_controller;
|
||||||
#else
|
|
||||||
SDL_Surface *_surface;
|
|
||||||
#endif
|
|
||||||
SDL_PixelFormat *_fmt;
|
SDL_PixelFormat *_fmt;
|
||||||
const char *_caption;
|
const char *_caption;
|
||||||
uint16_t *_screenBuffer;
|
uint32_t *_screenBuffer;
|
||||||
uint16_t *_fadeScreenBuffer;
|
|
||||||
bool _fullscreen;
|
bool _fullscreen;
|
||||||
int _scaler;
|
|
||||||
uint8_t _overscanColor;
|
uint8_t _overscanColor;
|
||||||
uint16_t _pal[256];
|
uint32_t _rgbPalette[256];
|
||||||
int _screenW, _screenH;
|
int _screenW, _screenH;
|
||||||
SDL_Joystick *_joystick;
|
SDL_Joystick *_joystick;
|
||||||
SDL_Rect _blitRects[200];
|
SDL_Rect _blitRects[200];
|
||||||
|
@ -40,9 +47,12 @@ struct SystemStub_SDL : SystemStub {
|
||||||
void (*_audioCbProc)(void *, int16_t *, int);
|
void (*_audioCbProc)(void *, int16_t *, int);
|
||||||
void *_audioCbData;
|
void *_audioCbData;
|
||||||
int _screenshot;
|
int _screenshot;
|
||||||
|
ScalerType _scalerType;
|
||||||
|
const Scaler *_scaler;
|
||||||
|
int _scaleFactor;
|
||||||
|
|
||||||
virtual ~SystemStub_SDL() {}
|
virtual ~SystemStub_SDL() {}
|
||||||
virtual void init(const char *title, int w, int h, int scaler, bool fullscreen);
|
virtual void init(const char *title, int w, int h, bool fullscreen, ScalerParameters *scalerParameters);
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
virtual void setScreenSize(int w, int h);
|
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);
|
||||||
|
@ -64,31 +74,30 @@ struct SystemStub_SDL : SystemStub {
|
||||||
void processEvent(const SDL_Event &ev, bool &paused);
|
void processEvent(const SDL_Event &ev, bool &paused);
|
||||||
void prepareGraphics();
|
void prepareGraphics();
|
||||||
void cleanupGraphics();
|
void cleanupGraphics();
|
||||||
void changeGraphics(bool fullscreen, uint8_t scaler);
|
void changeGraphics(bool fullscreen, int scaleFactor);
|
||||||
void flipGraphics();
|
|
||||||
void forceGraphicsRedraw();
|
void forceGraphicsRedraw();
|
||||||
void drawRect(SDL_Rect *rect, uint8_t color, uint16_t *dst, uint16_t dstPitch);
|
void drawRect(SDL_Rect *rect, uint8_t color);
|
||||||
};
|
};
|
||||||
|
|
||||||
SystemStub *SystemStub_SDL_create() {
|
SystemStub *SystemStub_SDL_create() {
|
||||||
return new SystemStub_SDL();
|
return new SystemStub_SDL();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::init(const char *title, int w, int h, int scaler, bool fullscreen) {
|
void SystemStub_SDL::init(const char *title, int w, int h, bool fullscreen, ScalerParameters *scalerParameters) {
|
||||||
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);
|
||||||
_caption = title;
|
_caption = title;
|
||||||
memset(&_pi, 0, sizeof(_pi));
|
memset(&_pi, 0, sizeof(_pi));
|
||||||
_screenBuffer = 0;
|
_screenBuffer = 0;
|
||||||
_fadeScreenBuffer = 0;
|
|
||||||
_fadeOnUpdateScreen = false;
|
_fadeOnUpdateScreen = false;
|
||||||
_fullscreen = fullscreen;
|
_fullscreen = fullscreen;
|
||||||
_scaler = scaler;
|
_scalerType = scalerParameters->type;
|
||||||
memset(_pal, 0, sizeof(_pal));
|
_scaler = scalerParameters->scaler;
|
||||||
|
_scaleFactor = scalerParameters->factor;
|
||||||
|
memset(_rgbPalette, 0, sizeof(_rgbPalette));
|
||||||
_screenW = _screenH = 0;
|
_screenW = _screenH = 0;
|
||||||
setScreenSize(w, h);
|
setScreenSize(w, h);
|
||||||
_joystick = 0;
|
_joystick = 0;
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
_controller = 0;
|
_controller = 0;
|
||||||
if (SDL_NumJoysticks() > 0) {
|
if (SDL_NumJoysticks() > 0) {
|
||||||
SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
|
SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
|
||||||
|
@ -99,22 +108,15 @@ void SystemStub_SDL::init(const char *title, int w, int h, int scaler, bool full
|
||||||
_joystick = SDL_JoystickOpen(kJoystickIndex);
|
_joystick = SDL_JoystickOpen(kJoystickIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (SDL_NumJoysticks() > 0) {
|
|
||||||
_joystick = SDL_JoystickOpen(kJoystickIndex);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_screenshot = 1;
|
_screenshot = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::destroy() {
|
void SystemStub_SDL::destroy() {
|
||||||
cleanupGraphics();
|
cleanupGraphics();
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
if (_controller) {
|
if (_controller) {
|
||||||
SDL_GameControllerClose(_controller);
|
SDL_GameControllerClose(_controller);
|
||||||
_controller = 0;
|
_controller = 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (_joystick) {
|
if (_joystick) {
|
||||||
SDL_JoystickClose(_joystick);
|
SDL_JoystickClose(_joystick);
|
||||||
_joystick = 0;
|
_joystick = 0;
|
||||||
|
@ -127,9 +129,8 @@ void SystemStub_SDL::setScreenSize(int w, int h) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cleanupGraphics();
|
cleanupGraphics();
|
||||||
// allocate some extra bytes for the scaling routines
|
const int screenBufferSize = w * h * sizeof(uint32_t);
|
||||||
const int screenBufferSize = (w + 2) * (h + 2) * sizeof(uint16_t);
|
_screenBuffer = (uint32_t *)calloc(1, screenBufferSize);
|
||||||
_screenBuffer = (uint16_t *)calloc(1, screenBufferSize);
|
|
||||||
if (!_screenBuffer) {
|
if (!_screenBuffer) {
|
||||||
error("SystemStub_SDL::setScreenSize() Unable to allocate offscreen buffer, w=%d, h=%d", w, h);
|
error("SystemStub_SDL::setScreenSize() Unable to allocate offscreen buffer, w=%d, h=%d", w, h);
|
||||||
}
|
}
|
||||||
|
@ -144,16 +145,16 @@ void SystemStub_SDL::setPalette(const uint8_t *pal, int n) {
|
||||||
uint8_t r = pal[i * 3 + 0];
|
uint8_t r = pal[i * 3 + 0];
|
||||||
uint8_t g = pal[i * 3 + 1];
|
uint8_t g = pal[i * 3 + 1];
|
||||||
uint8_t b = pal[i * 3 + 2];
|
uint8_t b = pal[i * 3 + 2];
|
||||||
_pal[i] = SDL_MapRGB(_fmt, r, g, b);
|
_rgbPalette[i] = SDL_MapRGB(_fmt, r, g, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::setPaletteEntry(int i, const Color *c) {
|
void SystemStub_SDL::setPaletteEntry(int i, const Color *c) {
|
||||||
_pal[i] = SDL_MapRGB(_fmt, c->r, c->g, c->b);
|
_rgbPalette[i] = SDL_MapRGB(_fmt, c->r, c->g, c->b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::getPaletteEntry(int i, Color *c) {
|
void SystemStub_SDL::getPaletteEntry(int i, Color *c) {
|
||||||
SDL_GetRGB(_pal[i], _fmt, &c->r, &c->g, &c->b);
|
SDL_GetRGB(_rgbPalette[i], _fmt, &c->r, &c->g, &c->b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::setOverscanColor(int i) {
|
void SystemStub_SDL::setOverscanColor(int i) {
|
||||||
|
@ -194,53 +195,37 @@ void SystemStub_SDL::copyRect(int x, int y, int w, int h, const uint8_t *buf, in
|
||||||
br->h = h;
|
br->h = h;
|
||||||
++_numBlitRects;
|
++_numBlitRects;
|
||||||
|
|
||||||
uint16_t *p = _screenBuffer + (br->y + 1) * _screenW + (br->x + 1);
|
uint32_t *p = _screenBuffer + br->y * _screenW + br->x;
|
||||||
buf += y * pitch + x;
|
buf += y * pitch + x;
|
||||||
|
|
||||||
while (h--) {
|
while (h--) {
|
||||||
for (int i = 0; i < w; ++i) {
|
for (int i = 0; i < w; ++i) {
|
||||||
p[i] = _pal[buf[i]];
|
p[i] = _rgbPalette[buf[i]];
|
||||||
}
|
}
|
||||||
p += _screenW;
|
p += _screenW;
|
||||||
buf += pitch;
|
buf += pitch;
|
||||||
}
|
}
|
||||||
if (_pi.dbgMask & PlayerInput::DF_DBLOCKS) {
|
if (_pi.dbgMask & PlayerInput::DF_DBLOCKS) {
|
||||||
drawRect(br, 0xE7, _screenBuffer + _screenW + 1, _screenW * 2);
|
drawRect(br, 0xE7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::fadeScreen() {
|
void SystemStub_SDL::fadeScreen() {
|
||||||
const int bufferSize = _screenH * _screenW * sizeof(uint16_t);
|
|
||||||
if (!_fadeScreenBuffer) {
|
|
||||||
_fadeScreenBuffer = (uint16_t *)malloc(bufferSize);
|
|
||||||
if (!_fadeScreenBuffer) {
|
|
||||||
warning("SystemStub_SDL::fadeScreen() Unable to allocate buffer size %d", bufferSize);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_fadeOnUpdateScreen = true;
|
_fadeOnUpdateScreen = true;
|
||||||
memcpy(_fadeScreenBuffer, _screenBuffer + _screenW + 1, bufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t blendPixel16(uint16_t colorSrc, uint16_t colorDst, uint32_t mask, int step) {
|
|
||||||
const uint32_t pSrc = (colorSrc | (colorSrc << 16)) & mask;
|
|
||||||
const uint32_t pDst = (colorDst | (colorDst << 16)) & mask;
|
|
||||||
const uint32_t pRes = ((pDst - pSrc) * step / 16 + pSrc) & mask;
|
|
||||||
return pRes | (pRes >> 16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::updateScreen(int shakeOffset) {
|
void SystemStub_SDL::updateScreen(int shakeOffset) {
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
if (_texW != _screenW || _texH != _screenH) {
|
if (_texW != _screenW || _texH != _screenH) {
|
||||||
void *dst = 0;
|
void *dst = 0;
|
||||||
int pitch = 0;
|
int pitch = 0;
|
||||||
if (SDL_LockTexture(_texture, 0, &dst, &pitch) == 0) {
|
if (SDL_LockTexture(_texture, 0, &dst, &pitch) == 0) {
|
||||||
(*_scalers[_scaler].proc)((uint16_t *)dst, pitch, _screenBuffer + _screenW + 1, _screenW, _screenW, _screenH);
|
assert((pitch & 3) == 0);
|
||||||
|
_scaler->scale(_scaleFactor, (uint32_t *)dst, pitch / sizeof(uint32_t), _screenBuffer, _screenW, _screenW, _screenH);
|
||||||
SDL_UnlockTexture(_texture);
|
SDL_UnlockTexture(_texture);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SDL_UpdateTexture(_texture, 0, _screenBuffer + _screenW + 1, _screenW * sizeof(uint16_t));
|
SDL_UpdateTexture(_texture, 0, _screenBuffer, _screenW * sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
SDL_RenderClear(_renderer);
|
SDL_RenderClear(_renderer);
|
||||||
if (_fadeOnUpdateScreen) {
|
if (_fadeOnUpdateScreen) {
|
||||||
|
@ -256,12 +241,13 @@ void SystemStub_SDL::updateScreen(int shakeOffset) {
|
||||||
SDL_Delay(30);
|
SDL_Delay(30);
|
||||||
}
|
}
|
||||||
_fadeOnUpdateScreen = false;
|
_fadeOnUpdateScreen = false;
|
||||||
|
SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_NONE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (shakeOffset != 0) {
|
if (shakeOffset != 0) {
|
||||||
SDL_Rect r;
|
SDL_Rect r;
|
||||||
r.x = 0;
|
r.x = 0;
|
||||||
r.y = shakeOffset * _scalers[_scaler].factor;
|
r.y = shakeOffset * _scaleFactor;
|
||||||
SDL_GetRendererOutputSize(_renderer, &r.w, &r.h);
|
SDL_GetRendererOutputSize(_renderer, &r.w, &r.h);
|
||||||
r.h -= r.y;
|
r.h -= r.y;
|
||||||
SDL_RenderCopy(_renderer, _texture, 0, &r);
|
SDL_RenderCopy(_renderer, _texture, 0, &r);
|
||||||
|
@ -269,65 +255,6 @@ void SystemStub_SDL::updateScreen(int shakeOffset) {
|
||||||
SDL_RenderCopy(_renderer, _texture, 0, 0);
|
SDL_RenderCopy(_renderer, _texture, 0, 0);
|
||||||
}
|
}
|
||||||
SDL_RenderPresent(_renderer);
|
SDL_RenderPresent(_renderer);
|
||||||
#else
|
|
||||||
const int mul = _scalers[_scaler].factor;
|
|
||||||
if (_fadeOnUpdateScreen) {
|
|
||||||
const int tempScreenBufferSize = (_screenH + 2) * (_screenW + 2) * sizeof(uint16_t);
|
|
||||||
uint16_t *tempScreenBuffer = (uint16_t *)calloc(tempScreenBufferSize, 1);
|
|
||||||
assert(tempScreenBuffer);
|
|
||||||
const uint32_t colorMask = (_fmt->Gmask << 16) | (_fmt->Rmask | _fmt->Bmask);
|
|
||||||
const uint16_t *screenBuffer = _screenBuffer + _screenW + 1;
|
|
||||||
for (int i = 1; i <= 16; ++i) {
|
|
||||||
for (int x = 0; x < _screenH * _screenW; ++x) {
|
|
||||||
tempScreenBuffer[_screenW + 1 + x] = blendPixel16(_fadeScreenBuffer[x], screenBuffer[x], colorMask, i);
|
|
||||||
}
|
|
||||||
SDL_LockSurface(_surface);
|
|
||||||
uint16_t *dst = (uint16_t *)_surface->pixels;
|
|
||||||
const uint16_t *src = tempScreenBuffer + _screenW + 1;
|
|
||||||
(*_scalers[_scaler].proc)(dst, _surface->pitch, src, _screenW, _screenW, _screenH);
|
|
||||||
SDL_UnlockSurface(_surface);
|
|
||||||
SDL_UpdateRect(_surface, 0, 0, _screenW * mul, _screenH * mul);
|
|
||||||
SDL_Delay(30);
|
|
||||||
}
|
|
||||||
free(tempScreenBuffer);
|
|
||||||
_fadeOnUpdateScreen = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (shakeOffset == 0) {
|
|
||||||
for (int i = 0; i < _numBlitRects; ++i) {
|
|
||||||
SDL_Rect *br = &_blitRects[i];
|
|
||||||
int dx = br->x * mul;
|
|
||||||
int dy = br->y * mul;
|
|
||||||
SDL_LockSurface(_surface);
|
|
||||||
uint16_t *dst = (uint16_t *)_surface->pixels + dy * _surface->pitch / 2 + dx;
|
|
||||||
const uint16_t *src = _screenBuffer + (br->y + 1) * _screenW + (br->x + 1);
|
|
||||||
(*_scalers[_scaler].proc)(dst, _surface->pitch, src, _screenW, br->w, br->h);
|
|
||||||
SDL_UnlockSurface(_surface);
|
|
||||||
br->x *= mul;
|
|
||||||
br->y *= mul;
|
|
||||||
br->w *= mul;
|
|
||||||
br->h *= mul;
|
|
||||||
}
|
|
||||||
SDL_UpdateRects(_surface, _numBlitRects, _blitRects);
|
|
||||||
} else {
|
|
||||||
SDL_LockSurface(_surface);
|
|
||||||
int w = _screenW;
|
|
||||||
int h = _screenH - shakeOffset;
|
|
||||||
uint16_t *dst = (uint16_t *)_surface->pixels + shakeOffset * mul * _surface->pitch / 2;
|
|
||||||
const uint16_t *src = _screenBuffer + _screenW + 1;
|
|
||||||
(*_scalers[_scaler].proc)(dst, _surface->pitch, src, _screenW, w, h);
|
|
||||||
SDL_UnlockSurface(_surface);
|
|
||||||
|
|
||||||
SDL_Rect r;
|
|
||||||
r.x = 0;
|
|
||||||
r.y = 0;
|
|
||||||
r.w = _screenW * mul;
|
|
||||||
r.h = shakeOffset * mul;
|
|
||||||
SDL_FillRect(_surface, &r, _pal[_overscanColor]);
|
|
||||||
|
|
||||||
SDL_UpdateRect(_surface, 0, 0, _screenW * mul, _screenH * mul);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_numBlitRects = 0;
|
_numBlitRects = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,11 +276,10 @@ void SystemStub_SDL::processEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
||||||
switch (ev.type) {
|
switch (ev.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
_pi.quit = true;
|
_pi.quit = true;
|
||||||
break;
|
break;
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
case SDL_WINDOWEVENT:
|
case SDL_WINDOWEVENT:
|
||||||
switch (ev.window.event) {
|
switch (ev.window.event) {
|
||||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||||
|
@ -363,14 +289,6 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#else
|
|
||||||
case SDL_ACTIVEEVENT:
|
|
||||||
if (ev.active.state & SDL_APPINPUTFOCUS) {
|
|
||||||
paused = ev.active.gain == 0;
|
|
||||||
SDL_PauseAudio(paused ? 1 : 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case SDL_JOYHATMOTION:
|
case SDL_JOYHATMOTION:
|
||||||
if (_joystick) {
|
if (_joystick) {
|
||||||
_pi.dirMask = 0;
|
_pi.dirMask = 0;
|
||||||
|
@ -430,7 +348,6 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
case SDL_CONTROLLERAXISMOTION:
|
case SDL_CONTROLLERAXISMOTION:
|
||||||
if (_controller) {
|
if (_controller) {
|
||||||
switch (ev.caxis.axis) {
|
switch (ev.caxis.axis) {
|
||||||
|
@ -515,118 +432,133 @@ void SystemStub_SDL::processEvent(const SDL_Event &ev, bool &paused) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
case SDL_KEYUP:
|
||||||
case SDL_KEYUP:
|
if (ev.key.keysym.mod & KMOD_ALT) {
|
||||||
switch (ev.key.keysym.sym) {
|
switch (ev.key.keysym.sym) {
|
||||||
case SDLK_LEFT:
|
|
||||||
_pi.dirMask &= ~PlayerInput::DIR_LEFT;
|
|
||||||
break;
|
|
||||||
case SDLK_RIGHT:
|
|
||||||
_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
|
|
||||||
break;
|
|
||||||
case SDLK_UP:
|
|
||||||
_pi.dirMask &= ~PlayerInput::DIR_UP;
|
|
||||||
break;
|
|
||||||
case SDLK_DOWN:
|
|
||||||
_pi.dirMask &= ~PlayerInput::DIR_DOWN;
|
|
||||||
break;
|
|
||||||
case SDLK_SPACE:
|
|
||||||
_pi.space = false;
|
|
||||||
break;
|
|
||||||
case SDLK_RSHIFT:
|
|
||||||
case SDLK_LSHIFT:
|
|
||||||
_pi.shift = false;
|
|
||||||
break;
|
|
||||||
case SDLK_RETURN:
|
case SDLK_RETURN:
|
||||||
_pi.enter = false;
|
changeGraphics(!_fullscreen, _scaleFactor);
|
||||||
break;
|
break;
|
||||||
case SDLK_ESCAPE:
|
case SDLK_KP_PLUS:
|
||||||
_pi.escape = false;
|
case SDLK_PAGEUP:
|
||||||
|
changeGraphics(_fullscreen, _scaleFactor + 1);
|
||||||
break;
|
break;
|
||||||
default:
|
case SDLK_KP_MINUS:
|
||||||
|
case SDLK_PAGEDOWN:
|
||||||
|
changeGraphics(_fullscreen, _scaleFactor - 1);
|
||||||
|
break;
|
||||||
|
case SDLK_s: {
|
||||||
|
char name[32];
|
||||||
|
snprintf(name, sizeof(name), "screenshot-%03d.tga", _screenshot);
|
||||||
|
saveTGA(name, (const uint8_t *)_screenBuffer, _screenW, _screenH);
|
||||||
|
++_screenshot;
|
||||||
|
debug(DBG_INFO, "Written '%s'", name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDLK_x:
|
||||||
|
_pi.quit = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SDL_KEYDOWN:
|
} else if (ev.key.keysym.mod & KMOD_CTRL) {
|
||||||
if (ev.key.keysym.mod & KMOD_ALT) {
|
|
||||||
if (ev.key.keysym.sym == SDLK_RETURN) {
|
|
||||||
changeGraphics(!_fullscreen, _scaler);
|
|
||||||
} else if (ev.key.keysym.sym == SDLK_KP_PLUS || ev.key.keysym.sym == SDLK_PAGEUP) {
|
|
||||||
uint8_t s = _scaler + 1;
|
|
||||||
if (s < NUM_SCALERS) {
|
|
||||||
changeGraphics(_fullscreen, s);
|
|
||||||
}
|
|
||||||
} else if (ev.key.keysym.sym == SDLK_KP_MINUS || ev.key.keysym.sym == SDLK_PAGEDOWN) {
|
|
||||||
int8_t s = _scaler - 1;
|
|
||||||
if (_scaler > 0) {
|
|
||||||
changeGraphics(_fullscreen, s);
|
|
||||||
}
|
|
||||||
} else if (ev.key.keysym.sym == SDLK_s) {
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
#else
|
|
||||||
char name[32];
|
|
||||||
snprintf(name, sizeof(name), "screenshot-%03d.bmp", _screenshot);
|
|
||||||
SDL_SaveBMP(_surface, name);
|
|
||||||
++_screenshot;
|
|
||||||
debug(DBG_INFO, "Written '%s'", name);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else if (ev.key.keysym.mod & KMOD_CTRL) {
|
|
||||||
if (ev.key.keysym.sym == SDLK_f) {
|
|
||||||
_pi.dbgMask ^= PlayerInput::DF_FASTMODE;
|
|
||||||
} else if (ev.key.keysym.sym == SDLK_b) {
|
|
||||||
_pi.dbgMask ^= PlayerInput::DF_DBLOCKS;
|
|
||||||
} else if (ev.key.keysym.sym == SDLK_i) {
|
|
||||||
_pi.dbgMask ^= PlayerInput::DF_SETLIFE;
|
|
||||||
} else if (ev.key.keysym.sym == SDLK_s) {
|
|
||||||
_pi.save = true;
|
|
||||||
} else if (ev.key.keysym.sym == SDLK_l) {
|
|
||||||
_pi.load = true;
|
|
||||||
} else if (ev.key.keysym.sym == SDLK_KP_PLUS || ev.key.keysym.sym == SDLK_PAGEUP) {
|
|
||||||
_pi.stateSlot = 1;
|
|
||||||
} else if (ev.key.keysym.sym == SDLK_KP_MINUS || ev.key.keysym.sym == SDLK_PAGEDOWN) {
|
|
||||||
_pi.stateSlot = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_pi.lastChar = ev.key.keysym.sym;
|
|
||||||
switch (ev.key.keysym.sym) {
|
switch (ev.key.keysym.sym) {
|
||||||
case SDLK_LEFT:
|
case SDLK_f:
|
||||||
_pi.dirMask |= PlayerInput::DIR_LEFT;
|
_pi.dbgMask ^= PlayerInput::DF_FASTMODE;
|
||||||
break;
|
break;
|
||||||
case SDLK_RIGHT:
|
case SDLK_b:
|
||||||
_pi.dirMask |= PlayerInput::DIR_RIGHT;
|
_pi.dbgMask ^= PlayerInput::DF_DBLOCKS;
|
||||||
break;
|
break;
|
||||||
case SDLK_UP:
|
case SDLK_i:
|
||||||
_pi.dirMask |= PlayerInput::DIR_UP;
|
_pi.dbgMask ^= PlayerInput::DF_SETLIFE;
|
||||||
break;
|
break;
|
||||||
case SDLK_DOWN:
|
case SDLK_s:
|
||||||
_pi.dirMask |= PlayerInput::DIR_DOWN;
|
_pi.save = true;
|
||||||
break;
|
break;
|
||||||
case SDLK_BACKSPACE:
|
case SDLK_l:
|
||||||
case SDLK_TAB:
|
_pi.load = true;
|
||||||
_pi.backspace = true;
|
|
||||||
break;
|
break;
|
||||||
case SDLK_SPACE:
|
case SDLK_KP_PLUS:
|
||||||
_pi.space = true;
|
case SDLK_PAGEUP:
|
||||||
|
_pi.stateSlot = 1;
|
||||||
break;
|
break;
|
||||||
case SDLK_RSHIFT:
|
case SDLK_KP_MINUS:
|
||||||
case SDLK_LSHIFT:
|
case SDLK_PAGEDOWN:
|
||||||
_pi.shift = true;
|
_pi.stateSlot = -1;
|
||||||
break;
|
|
||||||
case SDLK_RETURN:
|
|
||||||
_pi.enter = true;
|
|
||||||
break;
|
|
||||||
case SDLK_ESCAPE:
|
|
||||||
_pi.escape = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
_pi.lastChar = ev.key.keysym.sym;
|
||||||
|
switch (ev.key.keysym.sym) {
|
||||||
|
case SDLK_LEFT:
|
||||||
|
_pi.dirMask &= ~PlayerInput::DIR_LEFT;
|
||||||
|
break;
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
|
||||||
|
break;
|
||||||
|
case SDLK_UP:
|
||||||
|
_pi.dirMask &= ~PlayerInput::DIR_UP;
|
||||||
|
break;
|
||||||
|
case SDLK_DOWN:
|
||||||
|
_pi.dirMask &= ~PlayerInput::DIR_DOWN;
|
||||||
|
break;
|
||||||
|
case SDLK_SPACE:
|
||||||
|
_pi.space = false;
|
||||||
|
break;
|
||||||
|
case SDLK_RSHIFT:
|
||||||
|
case SDLK_LSHIFT:
|
||||||
|
_pi.shift = false;
|
||||||
|
break;
|
||||||
|
case SDLK_RETURN:
|
||||||
|
_pi.enter = false;
|
||||||
|
break;
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
_pi.escape = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
if (ev.key.keysym.mod & (KMOD_ALT | KMOD_CTRL)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (ev.key.keysym.sym) {
|
||||||
|
case SDLK_LEFT:
|
||||||
|
_pi.dirMask |= PlayerInput::DIR_LEFT;
|
||||||
|
break;
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
_pi.dirMask |= PlayerInput::DIR_RIGHT;
|
||||||
|
break;
|
||||||
|
case SDLK_UP:
|
||||||
|
_pi.dirMask |= PlayerInput::DIR_UP;
|
||||||
|
break;
|
||||||
|
case SDLK_DOWN:
|
||||||
|
_pi.dirMask |= PlayerInput::DIR_DOWN;
|
||||||
|
break;
|
||||||
|
case SDLK_BACKSPACE:
|
||||||
|
case SDLK_TAB:
|
||||||
|
_pi.backspace = true;
|
||||||
|
break;
|
||||||
|
case SDLK_SPACE:
|
||||||
|
_pi.space = true;
|
||||||
|
break;
|
||||||
|
case SDLK_RSHIFT:
|
||||||
|
case SDLK_LSHIFT:
|
||||||
|
_pi.shift = true;
|
||||||
|
break;
|
||||||
|
case SDLK_RETURN:
|
||||||
|
_pi.enter = true;
|
||||||
|
break;
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
_pi.escape = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::sleep(int duration) {
|
void SystemStub_SDL::sleep(int duration) {
|
||||||
|
@ -678,48 +610,38 @@ void SystemStub_SDL::unlockAudio() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::prepareGraphics() {
|
void SystemStub_SDL::prepareGraphics() {
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
_texW = _screenW;
|
||||||
switch (_scaler) {
|
_texH = _screenH;
|
||||||
case SCALER_SCALE_2X:
|
switch (_scalerType) {
|
||||||
case SCALER_SCALE_3X:
|
case kScalerTypePoint:
|
||||||
case SCALER_SCALE_4X:
|
|
||||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
|
|
||||||
_texW = _screenW * _scalers[_scaler].factor;
|
|
||||||
_texH = _screenH * _scalers[_scaler].factor;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); // nearest pixel sampling
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); // nearest pixel sampling
|
||||||
_texW = _screenW;
|
break;
|
||||||
_texH = _screenH;
|
case kScalerTypeLinear:
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
|
||||||
|
break;
|
||||||
|
case kScalerTypeInternal:
|
||||||
|
case kScalerTypeExternal:
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
|
||||||
|
_texW *= _scaleFactor;
|
||||||
|
_texH *= _scaleFactor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const int windowW = _screenW * _scalers[_scaler].factor;
|
const int windowW = _screenW * _scaleFactor;
|
||||||
const int windowH = _screenH * _scalers[_scaler].factor;
|
const int windowH = _screenH * _scaleFactor;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (_fullscreen) {
|
if (_fullscreen) {
|
||||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
}
|
}
|
||||||
_window = SDL_CreateWindow(_caption, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowW, windowH, flags);
|
_window = SDL_CreateWindow(_caption, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowW, windowH, flags);
|
||||||
|
SDL_Surface *icon = SDL_LoadBMP(kIconBmp);
|
||||||
|
if (icon) {
|
||||||
|
SDL_SetWindowIcon(_window, icon);
|
||||||
|
SDL_FreeSurface(icon);
|
||||||
|
}
|
||||||
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
|
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
SDL_RenderSetLogicalSize(_renderer, windowW, windowH);
|
SDL_RenderSetLogicalSize(_renderer, windowW, windowH);
|
||||||
static const uint32_t kPixelFormat = SDL_PIXELFORMAT_RGB565;
|
|
||||||
_texture = SDL_CreateTexture(_renderer, kPixelFormat, SDL_TEXTUREACCESS_STREAMING, _texW, _texH);
|
_texture = SDL_CreateTexture(_renderer, kPixelFormat, SDL_TEXTUREACCESS_STREAMING, _texW, _texH);
|
||||||
_fmt = SDL_AllocFormat(kPixelFormat);
|
_fmt = SDL_AllocFormat(kPixelFormat);
|
||||||
#else
|
|
||||||
SDL_WM_SetCaption(_caption, NULL);
|
|
||||||
const int w = _screenW * _scalers[_scaler].factor;
|
|
||||||
const int h = _screenH * _scalers[_scaler].factor;
|
|
||||||
int flags = SDL_HWSURFACE;
|
|
||||||
if (_fullscreen) {
|
|
||||||
flags |= SDL_FULLSCREEN;
|
|
||||||
}
|
|
||||||
static const int kBitDepth = 16;
|
|
||||||
_surface = SDL_SetVideoMode(w, h, kBitDepth, flags);
|
|
||||||
if (!_surface) {
|
|
||||||
error("SystemStub_SDL::prepareGraphics() Unable to allocate _screen buffer");
|
|
||||||
}
|
|
||||||
_fmt = _surface->format;
|
|
||||||
#endif
|
|
||||||
forceGraphicsRedraw();
|
forceGraphicsRedraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,11 +650,6 @@ void SystemStub_SDL::cleanupGraphics() {
|
||||||
free(_screenBuffer);
|
free(_screenBuffer);
|
||||||
_screenBuffer = 0;
|
_screenBuffer = 0;
|
||||||
}
|
}
|
||||||
if (_fadeScreenBuffer) {
|
|
||||||
free(_fadeScreenBuffer);
|
|
||||||
_fadeScreenBuffer = 0;
|
|
||||||
}
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
if (_window) {
|
if (_window) {
|
||||||
SDL_DestroyWindow(_window);
|
SDL_DestroyWindow(_window);
|
||||||
_window = 0;
|
_window = 0;
|
||||||
|
@ -745,20 +662,9 @@ void SystemStub_SDL::cleanupGraphics() {
|
||||||
SDL_FreeFormat(_fmt);
|
SDL_FreeFormat(_fmt);
|
||||||
_fmt = 0;
|
_fmt = 0;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (_surface) {
|
|
||||||
// freed by SDL_Quit()
|
|
||||||
_surface = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::changeGraphics(bool fullscreen, uint8_t scaler) {
|
void SystemStub_SDL::changeGraphics(bool fullscreen, int scaleFactor) {
|
||||||
if (_fadeScreenBuffer) {
|
|
||||||
free(_fadeScreenBuffer);
|
|
||||||
_fadeScreenBuffer = 0;
|
|
||||||
}
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
if (_window) {
|
if (_window) {
|
||||||
SDL_DestroyWindow(_window);
|
SDL_DestroyWindow(_window);
|
||||||
_window = 0;
|
_window = 0;
|
||||||
|
@ -771,28 +677,11 @@ void SystemStub_SDL::changeGraphics(bool fullscreen, uint8_t scaler) {
|
||||||
SDL_FreeFormat(_fmt);
|
SDL_FreeFormat(_fmt);
|
||||||
_fmt = 0;
|
_fmt = 0;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
SDL_FreeSurface(_surface);
|
|
||||||
_surface = 0;
|
|
||||||
#endif
|
|
||||||
_fullscreen = fullscreen;
|
_fullscreen = fullscreen;
|
||||||
_scaler = scaler;
|
if (scaleFactor >= _scaler->factorMin && scaleFactor <= _scaler->factorMax) {
|
||||||
prepareGraphics();
|
_scaleFactor = scaleFactor;
|
||||||
forceGraphicsRedraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemStub_SDL::flipGraphics() {
|
|
||||||
uint16_t scanline[256];
|
|
||||||
assert(_screenW <= 256);
|
|
||||||
uint16_t *p = _screenBuffer + _screenW + 1;
|
|
||||||
for (int y = 0; y < _screenH; ++y) {
|
|
||||||
p += _screenW;
|
|
||||||
for (int x = 0; x < _screenW; ++x) {
|
|
||||||
scanline[x] = *--p;
|
|
||||||
}
|
|
||||||
memcpy(p, scanline, _screenW * sizeof(uint16_t));
|
|
||||||
p += _screenW;
|
|
||||||
}
|
}
|
||||||
|
prepareGraphics();
|
||||||
forceGraphicsRedraw();
|
forceGraphicsRedraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,17 +693,16 @@ void SystemStub_SDL::forceGraphicsRedraw() {
|
||||||
_blitRects[0].h = _screenH;
|
_blitRects[0].h = _screenH;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStub_SDL::drawRect(SDL_Rect *rect, uint8_t color, uint16_t *dst, uint16_t dstPitch) {
|
void SystemStub_SDL::drawRect(SDL_Rect *rect, uint8_t color) {
|
||||||
dstPitch >>= 1;
|
|
||||||
int x1 = rect->x;
|
int x1 = rect->x;
|
||||||
int y1 = rect->y;
|
int y1 = rect->y;
|
||||||
int x2 = rect->x + rect->w - 1;
|
int x2 = rect->x + rect->w - 1;
|
||||||
int y2 = rect->y + rect->h - 1;
|
int y2 = rect->y + rect->h - 1;
|
||||||
assert(x1 >= 0 && x2 < _screenW && y1 >= 0 && y2 < _screenH);
|
assert(x1 >= 0 && x2 < _screenW && y1 >= 0 && y2 < _screenH);
|
||||||
for (int i = x1; i <= x2; ++i) {
|
for (int i = x1; i <= x2; ++i) {
|
||||||
*(dst + y1 * dstPitch + i) = *(dst + y2 * dstPitch + i) = _pal[color];
|
*(_screenBuffer + y1 * _screenW + i) = *(_screenBuffer + y2 * _screenW + i) = _rgbPalette[color];
|
||||||
}
|
}
|
||||||
for (int j = y1; j <= y2; ++j) {
|
for (int j = y1; j <= y2; ++j) {
|
||||||
*(dst + j * dstPitch + x1) = *(dst + j * dstPitch + x2) = _pal[color];
|
*(_screenBuffer + j * _screenW + x1) = *(_screenBuffer + j * _screenW + x2) = _rgbPalette[color];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue