First pass at keyboard/control mapping. More to do. Screenshot function fixed.

This commit is contained in:
Scott Duensing 2020-03-08 19:06:58 -05:00
parent 24cf564401
commit f7a10cc921
7 changed files with 224 additions and 169 deletions

View file

@ -1,3 +1,26 @@
--[[
*
* Singe 2
* Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
--]]
-- Singe 2.xx Features
SCANCODE = {

35
singe/embedded.c Normal file
View file

@ -0,0 +1,35 @@
/*
*
* Singe 2
* Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#define EMBED_HERE
#include "font.h"
#include "icon.h"
#include "kangarooPunchLogo.h"
#include "singeLogo.h"
#include "laserDisc.h"
#include "magnifyingGlass.h"
#include "indexing.h"
#include "Framework_singe.h"
#include "controls_cfg.h"
#undef EMBED_HERE

38
singe/embedded.h Normal file
View file

@ -0,0 +1,38 @@
/*
*
* Singe 2
* Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef EMBEDDED_H
#define EMBEDDED_H
#include "font.h"
#include "icon.h"
#include "kangarooPunchLogo.h"
#include "singeLogo.h"
#include "laserDisc.h"
#include "magnifyingGlass.h"
#include "indexing.h"
#include "Framework_singe.h"
#include "controls_cfg.h"
#endif // EMBEDDED_H

View file

@ -42,7 +42,7 @@
#include "videoPlayer.h"
#include "singe.h"
#include "extensions.h"
#include "icon.h"
#include "embedded.h"
typedef struct RatioS {
@ -61,9 +61,22 @@ typedef struct ModeS {
} ModeT;
void extractFile(char *filename, unsigned char *data, int32_t length);
void showUsage(char *name, char *message);
void extractFile(char *filename, unsigned char *data, int32_t length) {
FILE *out;
if (!utilFileExists(filename)) {
out = fopen(filename, "wb");
if (!out) utilDie("Unable to create %s", filename);
fwrite(data, length, 1, out);
fclose(out);
}
}
__attribute__((noreturn))
void showUsage(char *name, char *message) {
int32_t result = 0;
@ -601,6 +614,11 @@ int main(int argc, char *argv[]) {
// Finish our setup
SDL_DisableScreenSaver();
// Extract any missing support files.
if (!utilPathExists("Singe")) utilMkDirP("Singe", 0777);
extractFile("Singe/Framework.singe", Framework_singe, Framework_singe_len);
// Run Singe!
singe(window, renderer);
// Shutdown

View file

@ -193,8 +193,14 @@ function createEmbeddedBinary() {
local BLOCKER=$3
if [[ ! -e "${SOURCEFILE}" ]]; then
outputHeader ${BLOCKER} > ${SOURCEFILE}
outputLicense > ${SOURCEFILE}
outputHeader ${BLOCKER} >> ${SOURCEFILE}
printf "\n#ifdef EMBED_HERE\n\n" >> ${SOURCEFILE}
xxd -i ${BINFILE} >> ${SOURCEFILE}
printf "\n#else // EMBED_HERE\n\n" >> ${SOURCEFILE}
printf "extern unsigned char ${BINFILE/\./_}[];\n" >> ${SOURCEFILE}
printf "extern unsigned int ${BINFILE/\./_}_len;\n" >> ${SOURCEFILE}
printf "\n#endif // EMBED_HERE\n\n" >> ${SOURCEFILE}
outputFooter ${BLOCKER} >> ${SOURCEFILE}
fi
}
@ -216,6 +222,7 @@ function createExtensionHeader() {
local a=
local c=0
outputLicense
outputHeader FFMPEG_EXTENSIONS_H
printf "static char *ffmpegExtensions[] = {\n"
printf "\t"
@ -263,6 +270,13 @@ function outputFooter() {
function outputHeader() {
local BLOCKER=$1
printf "\n\n#ifndef ${BLOCKER}\n#define ${BLOCKER}\n\n\n"
printf "// ===== THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT =====\n\n\n"
printf "#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wunused-variable\"\n"
}
function outputLicense() {
cat <<-LICENSE
/*
*
@ -285,12 +299,8 @@ function outputHeader() {
*
*/
LICENSE
printf "\n\n#ifndef ${BLOCKER}\n#define ${BLOCKER}\n\n\n"
printf "// ===== THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT =====\n\n\n"
printf "#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wunused-variable\"\n"
}
# === zlib ===
if [[ ! -e "${G_INSTALLED}/lib/libz.a" ]]; then
echo ${G_L}
@ -486,6 +496,8 @@ if [[ ! -e "${G_INSTALLED}/lib/everything.a" ]]; then
popd
fi
rm font.h icon.h kangarooPunchLogo.h singeLogo.h laserDisc.h magnifyingGlass.h indexing.h Framework_singe.h controls_cfg.h
# === Overlay Font ===
createEmbeddedImage font

View file

@ -37,14 +37,7 @@
#include "frameFile.h"
#include "videoPlayer.h"
#include "singe.h"
#include "font.h"
#include "kangarooPunchLogo.h"
#include "singeLogo.h"
#include "laserDisc.h"
#include "magnifyingGlass.h"
#include "indexing.h"
#include "Framework_singe.h"
#include "controls_cfg.h"
#include "embedded.h"
//#define DEBUG_TOOLS
@ -58,33 +51,6 @@
#define MOUSE_ARRAY_SIZE 6
// Index into _controlMappings array
#define INPUT_UP 0
#define INPUT_LEFT 1
#define INPUT_DOWN 2
#define INPUT_RIGHT 3
#define INPUT_1P_START 4
#define INPUT_2P_START 5
#define INPUT_ACTION_1 6
#define INPUT_ACTION_2 7
#define INPUT_ACTION_3 8
#define INPUT_1P_COIN 9
#define INPUT_2P_COIN 10
#define INPUT_SKILL_EASY 11
#define INPUT_SKILL_MEDIUM 12
#define INPUT_SKILL_HARD 13
#define INPUT_SERVICE 14
#define INPUT_TEST_MODE 15
#define INPUT_SCREENSHOT 16
#define INPUT_QUIT 17
#define INPUT_PAUSE 18
#define INPUT_CONSOLE 19
#define INPUT_ACTION_4 20
#define INPUT_TILT 21
#define INPUT_RESET_CPU 22
#define INPUT_COUNT 23
typedef struct MouseS {
int32_t x;
int32_t y;
@ -137,6 +103,7 @@ typedef struct MappingS {
} MappingT;
//***TODO*** Replacing these with INPUT_* defines.
enum {
SWITCH_UP,
SWITCH_LEFT,
@ -238,54 +205,40 @@ static bool _refreshDisplay = false;
static bool _running = true;
static bool _discStopped = true;
static bool _mouseEnabled = true;
static bool _requestScreenShot = false;
static SpriteT *_spriteList = NULL;
static SoundT *_soundList = NULL;
static FontT *_fontList = NULL;
static FontT *_fontCurrent = NULL;
static int _keyDefs[SWITCH_COUNT][2] = {
{ SDLK_UP, SDLK_KP_8 }, // Up
{ SDLK_LEFT, SDLK_KP_4 }, // Left
{ SDLK_DOWN, SDLK_KP_2 }, // Down
{ SDLK_RIGHT, SDLK_KP_6 }, // Right
{ SDLK_1, 0 }, // 1 player start
{ SDLK_2, 0 }, // 2 player start
{ SDLK_SPACE, SDLK_LCTRL }, // Action button 1
{ SDLK_LALT, 0 }, // Action button 2
{ SDLK_LSHIFT, 0 }, // Action button 3
{ SDLK_5, SDLK_c }, // Coin chute left
{ SDLK_6, 0 }, // Coin chute right
{ SDLK_KP_DIVIDE, 0 }, // Skill easy
{ SDLK_KP_MULTIPLY, 0 }, // Skill medium
{ SDLK_KP_MINUS, 0 }, // Skill hard
{ SDLK_9, 0 }, // Service coin
{ SDLK_F2, 0 }, // Test mode
{ SDLK_F3, 0 }, // Reset cpu
{ SDLK_F12, SDLK_F11 }, // Take screenshot
{ SDLK_ESCAPE, SDLK_q }, // Quit
{ SDLK_p, 0 }, // Pause game
{ SDLK_BACKQUOTE, 0 }, // Toggle console
{ SDLK_t, 0 } // Tilt/Slam switch
};
// Index into _controlMappings array
#define INPUT_UP 0
#define INPUT_LEFT 1
#define INPUT_DOWN 2
#define INPUT_RIGHT 3
#define INPUT_1P_START 4
#define INPUT_2P_START 5
#define INPUT_ACTION_1 6
#define INPUT_ACTION_2 7
#define INPUT_ACTION_3 8
#define INPUT_1P_COIN 9
#define INPUT_2P_COIN 10
#define INPUT_SKILL_EASY 11
#define INPUT_SKILL_MEDIUM 12
#define INPUT_SKILL_HARD 13
#define INPUT_SERVICE 14
#define INPUT_TEST_MODE 15
#define INPUT_RESET_CPU 16
#define INPUT_SCREENSHOT 17
#define INPUT_QUIT 18
#define INPUT_PAUSE 19
#define INPUT_CONSOLE 20
// Added in Singe 2.x
#define INPUT_ACTION_4 21
#define INPUT_TILT 22
#define INPUT_COUNT 23
static int _fullKeybdDefs[] = {
SDLK_BACKSPACE,
SDLK_TAB,
SDLK_RETURN,
SDLK_PAUSE,
SDLK_SPACE,
SDLK_QUOTE,
SDLK_COMMA,
SDLK_SEMICOLON,
SDLK_EQUALS,
SDLK_LEFTBRACKET,
SDLK_RIGHTBRACKET,
SDLK_BACKSLASH,
SDLK_SLASH,
SDLK_DELETE,
SDLK_PERIOD
};
static MappingT _controlMappings[] = {
{ "INPUT_UP", 0, 0, NULL },
@ -304,13 +257,13 @@ static MappingT _controlMappings[] = {
{ "INPUT_SKILL_HARD", 13, 0, NULL },
{ "INPUT_SERVICE", 14, 0, NULL },
{ "INPUT_TEST_MODE", 15, 0, NULL },
{ "INPUT_RESET_CPU", 16, 0, NULL },
{ "INPUT_SCREENSHOT", 17, 0, NULL },
{ "INPUT_QUIT", 18, 0, NULL },
{ "INPUT_PAUSE", 19, 0, NULL },
{ "INPUT_CONSOLE", 20, 0, NULL },
{ "INPUT_ACTION_4", 21, 0, NULL },
{ "INPUT_TILT", 22, 0, NULL },
{ "INPUT_RESET_CPU", 23, 0, NULL }
{ "INPUT_TILT", 22, 0, NULL }
};
@ -384,7 +337,8 @@ void channelFinished(int channel);
void luaDie(lua_State *L, char *method, char *fmt, ...);
int32_t luaError(lua_State *L);
void luaTrace(lua_State *L, char *method, char *fmt, ...);
void processKey(bool down, int keysym);
void processKey(bool down, int keysym, int32_t scancode);
void takeScreenshot(void);
#ifdef DEBUG_TOOLS
void luaStackDump(lua_State *L);
@ -483,35 +437,9 @@ int32_t apiDaphneGetWidth(lua_State *L) {
int32_t apiDaphneScreenshot(lua_State *L) {
int32_t x = 0;
int32_t y = 0;
Uint32 format = 0;
char filename[128];
void *pixels = NULL;
SDL_Surface *surface = NULL;
SDL_Texture *texture = NULL;
(void)L;
while (x <= 999) {
snprintf(filename, 128, "singe%03d", x);
if (!utilFileExists(filename)) break;
x++;
}
if (x > 999) luaDie(L, "daphneScreenshot", "Seriously? You have 1000 screenshots in this folder? Remove some.");
luaTrace(L, "daphneScreenshot", "%s", filename);
texture = SDL_GetRenderTarget(_renderer);
if (SDL_QueryTexture(texture, &format, NULL, &x, &y) < 0) luaDie(L, "daphneScreenshot", "%s", SDL_GetError());
pixels = malloc((size_t)x * (size_t)y * SDL_BYTESPERPIXEL(format));
if (!pixels) luaDie(L, "daphneScreenshot", "Unable to allocate screenshot.");
if (SDL_RenderReadPixels(_renderer, NULL, format, pixels, (Uint16)x * SDL_BYTESPERPIXEL(format)) < 0) luaDie(L, "daphneScreenshot", "%s", SDL_GetError());
surface = SDL_CreateRGBSurfaceWithFormatFrom(pixels, x, y, SDL_BITSPERPIXEL(format), (Uint16)x * SDL_BYTESPERPIXEL(format), format);
if (!surface) luaDie(L, "daphneScreenshot", "%s", SDL_GetError());
if (IMG_SavePNG(surface, filename) < 0) luaDie(L, "daphneScreenshot", "%s", IMG_GetError());
SDL_FreeSurface(surface);
free(pixels);
luaTrace(L, "daphneScreenshot", "Screenshot requested.");
_requestScreenShot = true;
return 0;
}
@ -2198,22 +2126,25 @@ void luaTrace(lua_State *L, char *method, char *fmt, ...) {
}
void processKey(bool down, int32_t keysym) {
void processKey(bool down, int32_t keysym, int32_t scancode) {
int32_t move;
int32_t index;
if (_keyboardMode == KEYBD_NORMAL) {
// Daphne keys
for (move=0; move<SWITCH_COUNT; move++) {
if ((keysym == _keyDefs[move][0]) || (keysym == _keyDefs[move][1])) {
// Mappable keys
for (move=0; move<INPUT_COUNT; move++) {
if (_controlMappings[move].inputCount > 0) {
for (index=0; index<_controlMappings[move].inputCount; index++) {
if (_controlMappings[move].input[index] == scancode) {
if (!down) {
if ((move == SWITCH_PAUSE) && (_pauseEnabled)) {
//***TODO*** g_game->toggle_game_pause();
}
if ((move == SWITCH_QUIT) || (keysym == SDLK_ESCAPE)) {
if (move == SWITCH_QUIT) {
_running = false;
}
if (move == SWITCH_SCREENSHOT) {
//***TODO*** g_ldp->request_screenshot();
_requestScreenShot = true;
}
}
if (move != SWITCH_PAUSE) {
@ -2221,45 +2152,12 @@ void processKey(bool down, int32_t keysym) {
}
}
}
}
}
} else {
//***TODO*** Why is RDG filtering keys?
// Full keyboard
if (keysym >= SDLK_a && keysym <= SDLK_z)
callLua(down ? "onInputPressed" : "onInputReleased", "ii", keysym, NOMOUSE);
// check to see if key is a number on the top row of the keyboard (not keypad)
else if (keysym >= SDLK_MINUS && keysym <= SDLK_9)
callLua(down ? "onInputPressed" : "onInputReleased", "ii", keysym, NOMOUSE);
// numeric keypad keys
else if (keysym >= SDLK_KP_0 && keysym <= SDLK_KP_EQUALS)
callLua(down ? "onInputPressed" : "onInputReleased", "ii", keysym, NOMOUSE);
// arrow keys and insert, delete, home, end, pgup, pgdown
else if (keysym >= SDLK_UP && keysym <= SDLK_PAGEDOWN)
callLua(down ? "onInputPressed" : "onInputReleased", "ii", keysym, NOMOUSE);
// function keys
else if (keysym >= SDLK_F1 && keysym <= SDLK_F15)
callLua(down ? "onInputPressed" : "onInputReleased", "ii", keysym, NOMOUSE);
// Key state modifier keys (left and right ctrls, alts)
else if (keysym >= SDLK_NUMLOCKCLEAR && keysym <= SDLK_LGUI)
callLua(down ? "onInputPressed" : "onInputReleased", "ii", keysym, NOMOUSE);
// International keys
/*
else if (keysym >= SDLK_WORLD_0 && keysym <= SDLK_WORLD_95)
callLua(down ? "onInputPressed" : "onInputReleased", "ii", keysym, NOMOUSE);
*/
else {
/*
* SDLK_BACKSPACE, SDLK_TAB, SDLK_RETURN, SDLK_PAUSE,
* SDLK_SPACE, SDLK_QUOTE, SDLK_COMMA, SDLK_SEMICOLON,
* SDLK_EQUALS, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET,
* SDLK_BACKSLASH, SDLK_SLASH, SDLK_DELETE, SDLK_PERIOD };
*/
for (move=0; move<KEYBD_ARRAY_SIZE; move++) {
if (keysym == _fullKeybdDefs[move]) {
callLua(down ? "onInputPressed" : "onInputReleased", "ii", keysym, NOMOUSE);
break;
}
}
}
callLua(down ? "onKeyPressed" : "onKeyReleased", "i", scancode);
}
}
@ -2608,12 +2506,12 @@ void singe(SDL_Window *window, SDL_Renderer *renderer) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
processKey(true, event.key.keysym.sym);
processKey(true, event.key.keysym.sym, event.key.keysym.scancode);
//***TODO*** RDG used "g" to re-grab/re-scan for mice
break;
case SDL_KEYUP:
processKey(false, event.key.keysym.sym);
processKey(false, event.key.keysym.sym, event.key.keysym.scancode);
break;
case SDL_MOUSEMOTION:
@ -2797,6 +2695,11 @@ void singe(SDL_Window *window, SDL_Renderer *renderer) {
// Show it
SDL_RenderPresent(_renderer);
_refreshDisplay = false;
// Save it?
if (_requestScreenShot) {
_requestScreenShot = false;
takeScreenshot();
}
}
}
@ -2855,3 +2758,27 @@ void singe(SDL_Window *window, SDL_Renderer *renderer) {
SDL_ShowCursor(SDL_ENABLE);
ManyMouse_Quit();
}
void takeScreenshot(void) {
int32_t x = 0;
char filename[1024];
void *pixels = NULL;
SDL_Surface *surface = NULL;
SDL_Rect viewport;
while (x <= 999) {
snprintf(filename, 1024, "%ssinge%03d.png", _confDataDir, x);
if (!utilFileExists(filename)) break;
x++;
}
if (x > 999) utilDie("Seriously? You have 1000 screenshots in this folder? Remove some.");
SDL_RenderGetViewport(_renderer, &viewport);
surface = SDL_CreateRGBSurface(0, viewport.w, viewport.h, 32, 0, 0, 0, 0);
if (!surface) utilDie("%s", SDL_GetError());
if (SDL_RenderReadPixels(_renderer, NULL, surface->format->format, surface->pixels, surface->pitch) != 0) utilDie("%s", SDL_GetError());
if (IMG_SavePNG(surface, filename) < 0) utilDie("%s", IMG_GetError());
SDL_FreeSurface(surface);
free(pixels);
}

View file

@ -132,6 +132,7 @@ HEADERS += \
videoPlayer.h \
singe.h \
extensions.h \
embedded.h \
font.h \
singeLogo.h \
kangarooPunchLogo.h \
@ -146,6 +147,7 @@ SOURCES += \
frameFile.c \
util.c \
videoPlayer.c \
embedded.c \
singe.c \
main.c
@ -234,7 +236,7 @@ OTHER_FILES += \
postLink.sh \
buildRelease.sh \
singe.rc \
config.lua \
controls.cfg \
Framework.singe
platformLinux {