Keyboard and mouse mostly implemented.

This commit is contained in:
Scott Duensing 2019-12-05 21:30:23 -06:00
parent fa91f8e281
commit 9f44dc055c
4 changed files with 608 additions and 68 deletions

View file

@ -450,6 +450,8 @@ int main(int argc, char *argv[]) {
window = SDL_CreateWindow("SINGE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _confXResolution, _confYResolution, SDL_WINDOW_RESIZABLE);
if (window == NULL) utilDie("%s", SDL_GetError());
//***TODO*** Window Icon
// Do we want full screen of some kind?
if (_confFullScreen || _confFullScreenWindow) {
flags = _confFullScreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP;

View file

@ -31,6 +31,7 @@
#include <lauxlib.h>
#include "thirdparty/uthash.h"
#include "thirdparty/manymouse/manymouse.h"
#include "common.h"
#include "util.h"
@ -38,10 +39,31 @@
#include "singe.h"
#define AUDIO_MAX_VOLUME 63
#define MAX_TITLE_LENGTH 1024
#define AUDIO_MAX_VOLUME 63
#define MAX_TITLE_LENGTH 1024
#define MAX_MICE 128
#define SCROLLWHEEL_DISPLAY_TICKS 100
#define NOMOUSE -1
#define KEYBD_ARRAY_SIZE 15
typedef struct MouseS {
int x;
int y;
int relx;
int rely;
char name[64];
bool connected;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpadded"
Uint32 buttons;
#pragma GCC diagnostic pop
Uint32 scrolluptick;
Uint32 scrolldowntick;
Uint32 scrolllefttick;
Uint32 scrollrighttick;
} MouseT;
typedef struct SpriteS {
int id;
#pragma GCC diagnostic push
@ -70,6 +92,35 @@ typedef struct FontS {
} FontT;
enum {
SWITCH_UP,
SWITCH_LEFT,
SWITCH_DOWN,
SWITCH_RIGHT,
SWITCH_START1,
SWITCH_START2,
SWITCH_BUTTON1,
SWITCH_BUTTON2,
SWITCH_BUTTON3,
SWITCH_COIN1,
SWITCH_COIN2,
SWITCH_SKILL1,
SWITCH_SKILL2,
SWITCH_SKILL3,
SWITCH_SERVICE,
SWITCH_TEST,
SWITCH_RESET,
SWITCH_SCREENSHOT,
SWITCH_QUIT,
SWITCH_PAUSE,
SWITCH_CONSOLE,
SWITCH_TILT,
SWITCH_MOUSE_SCROLL_UP,
SWITCH_MOUSE_SCROLL_DOWN,
SWITCH_MOUSE_DISCONNECT,
SWITCH_COUNT
};
enum {
KEYBD_NORMAL = 0,
KEYBD_FULL
@ -107,6 +158,7 @@ int _confYResolution = -1;
// Other globals
static MouseT _mice[MAX_MICE];
static lua_State *_luaContext = NULL;
static SDL_Color _colorForeground = { 255, 255, 255, 255 };
static SDL_Color _colorBackground = { 0, 0, 0, 255 };
@ -120,16 +172,63 @@ static int _effectsVolume = AUDIO_MAX_VOLUME;
static int _keyboardMode = KEYBD_NORMAL;
static int _videoHandle = -1;
static int _fontQuality = 1;
static double _overlayScaleX = 1;
static double _overlayScaleY = 1;
static int _mouseMode = MOUSE_SINGLE;
static int _mouseCount = 0;
static double _overlayScaleX = 1; // Difference between overlay and video
static double _overlayScaleY = 1; // Difference between overlay and video
static bool _pauseState = false; // by RDG2010
static bool _pauseEnabled = true; // by RDG2010
static bool _running = true;
static bool _discStopped = true;
static bool _mouseEnabled = true;
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
};
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
};
int apiColorBackground(lua_State *L);
int apiColorForeground(lua_State *L);
@ -194,16 +293,64 @@ int apiSingeQuit(lua_State *L);
int apiSingeVersion(lua_State *L);
int apiSingeSetGameName(lua_State *L);
int apiSingeGetScriptPath(lua_State *L);
void callLua(const char *func, const char *sig, ...);
int luaError(lua_State *L);
void processKey(bool down, int keysym);
int apiColorBackground(lua_State *L) {
int n = lua_gettop(L);
if ((n == 3) || (n == 4)) {
if (lua_isinteger(L, 1)) {
if (lua_isinteger(L, 2)) {
if (lua_isinteger(L, 3)) {
_colorBackground.r = (byte)lua_tointeger(L, 1);
_colorBackground.g = (byte)lua_tointeger(L, 2);
_colorBackground.b = (byte)lua_tointeger(L, 3);
if (n == 3) {
_colorBackground.a = (byte)255;
} else {
if (lua_isinteger(L, 4)) {
_colorBackground.a = (byte)lua_tointeger(L, 4);
} else {
_colorBackground.a = (byte)255;
}
}
}
}
}
}
return 0;
}
int apiColorForeground(lua_State *L) {
int n = lua_gettop(L);
if ((n == 3) || (n == 4)) {
if (lua_isinteger(L, 1)) {
if (lua_isinteger(L, 2)) {
if (lua_isinteger(L, 3)) {
_colorForeground.r = (byte)lua_tointeger(L, 1);
_colorForeground.g = (byte)lua_tointeger(L, 2);
_colorForeground.b = (byte)lua_tointeger(L, 3);
if (n == 3) {
_colorForeground.a = (byte)255;
} else {
if (lua_isinteger(L, 4)) {
_colorForeground.a = (byte)lua_tointeger(L, 4);
} else {
_colorForeground.a = (byte)255;
}
}
}
}
}
}
return 0;
}
@ -224,7 +371,37 @@ int apiDaphneGetWidth(lua_State *L) {
int apiDaphneScreenshot(lua_State *L) {
int x = 0;
int 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) utilDie("Seriously? You have 1000 screenshots in this folder? Remove some.");
SDL_SetRenderTarget(_renderer, NULL);
texture = SDL_GetRenderTarget(_renderer);
SDL_QueryTexture(texture, &format, NULL, &x, &y);
pixels = malloc((size_t)x * (size_t)y * SDL_BYTESPERPIXEL(format));
if (!pixels) utilDie("Unable to allocate screenshot.");
if (SDL_RenderReadPixels(_renderer, NULL, format, pixels, (Uint16)x * SDL_BYTESPERPIXEL(format)) < 0) utilDie("%s", SDL_GetError());
surface = SDL_CreateRGBSurfaceWithFormatFrom(pixels, x, y, SDL_BITSPERPIXEL(format), (Uint16)x * SDL_BYTESPERPIXEL(format), format);
if (!surface) utilDie("%s", SDL_GetError());
if (IMG_SavePNG(surface, filename) < 0) utilDie("%s", IMG_GetError());
SDL_FreeSurface(surface);
free(pixels);
SDL_SetRenderTarget(_renderer, _overlay);
return 0;
}
@ -242,7 +419,25 @@ int apiDebugPrint(lua_State *L) {
int apiDiscAudio(lua_State *L) {
int n = lua_gettop(L);
int channel = 0;
int left = 0;
int right = 0;
bool onOff = false;
if (n == 2) {
if (lua_isinteger(L, 1)) {
if (lua_isboolean(L, 2)) {
channel = (int)lua_tointeger(L, 1);
onOff = (bool)lua_toboolean(L, 2);
if ((channel == 1) && onOff) left = _confVolumeVldp;
if ((channel == 2) && onOff) right = _confVolumeVldp;
videoSetVolume(_videoHandle, left, right);
}
}
}
return 0;
}
@ -254,14 +449,20 @@ int apiDiscChangeSpeed(lua_State *L) {
int apiDiscGetFrame(lua_State *L) {
lua_pushinteger(L, videoGetFrame(_videoHandle));
if (_discStopped) {
lua_pushinteger(L, 0);
} else {
lua_pushinteger(L, videoGetFrame(_videoHandle));
}
return 1;
}
int apiDiscPause(lua_State *L) {
(void)L;
videoPause(_videoHandle);
if (!_discStopped) {
videoPause(_videoHandle);
}
return 0;
}
@ -269,10 +470,12 @@ int apiDiscPause(lua_State *L) {
int apiDiscPauseAtFrame(lua_State *L) {
int n = lua_gettop(L);
if (n == 1) {
if (lua_isinteger(L, 1)) {
videoSeek(_videoHandle, (int)lua_tointeger(L, 1));
videoPause(_videoHandle);
if (!_discStopped) {
if (n == 1) {
if (lua_isinteger(L, 1)) {
videoSeek(_videoHandle, (int)lua_tointeger(L, 1));
videoPause(_videoHandle);
}
}
}
@ -283,15 +486,18 @@ int apiDiscPauseAtFrame(lua_State *L) {
int apiDiscPlay(lua_State *L) {
(void)L;
videoPlay(_videoHandle);
_discStopped = false;
}
int apiDiscSearch(lua_State *L) {
int n = lua_gettop(L);
if (n == 1) {
if (lua_isinteger(L, 1)) {
videoSeek(_videoHandle, (int)lua_tointeger(L, 1));
if (!_discStopped) {
if (n == 1) {
if (lua_isinteger(L, 1)) {
videoSeek(_videoHandle, (int)lua_tointeger(L, 1));
}
}
}
@ -316,9 +522,11 @@ int apiDiscSetFps(lua_State *L) {
int apiDiscSkipBackward(lua_State *L) {
int n = lua_gettop(L);
if (n == 1) {
if (lua_isinteger(L, 1)) {
videoSeek(_videoHandle, videoGetFrame(_videoHandle) - (int)lua_tointeger(L, 1));
if (!_discStopped) {
if (n == 1) {
if (lua_isinteger(L, 1)) {
videoSeek(_videoHandle, videoGetFrame(_videoHandle) - (int)lua_tointeger(L, 1));
}
}
}
@ -336,9 +544,11 @@ int apiDiscSkipBlanking(lua_State *L) {
int apiDiscSkipForward(lua_State *L) {
int n = lua_gettop(L);
if (n == 1) {
if (lua_isinteger(L, 1)) {
videoSeek(_videoHandle, videoGetFrame(_videoHandle) + (int)lua_tointeger(L, 1));
if (!_discStopped) {
if (n == 1) {
if (lua_isinteger(L, 1)) {
videoSeek(_videoHandle, videoGetFrame(_videoHandle) + (int)lua_tointeger(L, 1));
}
}
}
@ -354,22 +564,26 @@ int apiDiscSkipToFrame(lua_State *L) {
int apiDiscStepBackward(lua_State *L) {
(void)L;
videoSeek(_videoHandle, videoGetFrame(_videoHandle) - 1);
if (!_discStopped) {
videoSeek(_videoHandle, videoGetFrame(_videoHandle) - 1);
}
return 0;
}
int apiDiscStepForward(lua_State *L) {
(void)L;
videoSeek(_videoHandle, videoGetFrame(_videoHandle) + 1);
if (!_discStopped) {
videoSeek(_videoHandle, videoGetFrame(_videoHandle) + 1);
}
return 0;
}
int apiDiscStop(lua_State *L) {
(void)L;
//***TODO*** Add a real stopped state
videoPause(_videoHandle);
_discStopped = true;
}
@ -391,9 +605,9 @@ int apiFontLoad(lua_State *L) {
font->font = TTF_OpenFont(name, points);
if (!font->font) utilDie("%s", TTF_GetError());
// Make it the current font and mark it as loaded.
_fontCurrent = _nextFontId++;
font->id = _fontCurrent;
result = _fontCurrent;
font->id = _nextFontId;
result = _nextFontId++;
_fontCurrent = font;
HASH_ADD_INT(_fontList, id, font);
}
}
@ -405,7 +619,53 @@ int apiFontLoad(lua_State *L) {
int apiFontPrint(lua_State *L) {
int n = lua_gettop(L);
const char *message = NULL;
SDL_Surface *textSurface = NULL;
SDL_Texture *texture = NULL;
SDL_Rect dest;
if (n == 3) {
if (lua_isinteger(L, 1)) {
if (lua_isinteger(L, 2)) {
if (lua_isstring(L, 3)) {
if (_fontCurrent) {
dest.x = (int)lua_tointeger(L, 1);
dest.y = (int)lua_tointeger(L, 2);
textSurface = NULL;
message = lua_tostring(L, 3);
switch (_fontQuality) {
case 1:
textSurface = TTF_RenderText_Solid(_fontCurrent->font, message, _colorForeground);
break;
case 2:
textSurface = TTF_RenderText_Shaded(_fontCurrent->font, message, _colorForeground, _colorBackground);
break;
case 3:
textSurface = TTF_RenderText_Blended(_fontCurrent->font, message, _colorForeground);
break;
}
if (!textSurface) {
utilDie("Font surface is null!");
} else {
SDL_SetSurfaceBlendMode(textSurface, SDL_BLENDMODE_BLEND);
// Transparent index is 0
SDL_SetColorKey(textSurface, true, 0);
texture = SDL_CreateTextureFromSurface(_renderer, textSurface);
SDL_FreeSurface(textSurface);
if (!texture) utilDie("%s", SDL_GetError());
if (SDL_QueryTexture(texture, NULL, NULL, &dest.w, &dest.h) < 0) utilDie("%s", SDL_GetError());
SDL_RenderCopy(_renderer, texture, NULL, &dest);
}
}
}
}
}
}
return 0;
}
@ -443,7 +703,7 @@ int apiFontSelect(lua_State *L) {
int apiFontToSprite(lua_State *L) {
int n = lua_gettop(L);
int result = -1;
const char *message = NULL;
const char *message = NULL;
SDL_Surface *textSurface = NULL;
SpriteT *sprite = NULL;
@ -525,7 +785,19 @@ int apiOverlayGetWidth(lua_State *L) {
int apiOverlayPrint(lua_State *L) {
int n = lua_gettop(L);
if (n == 3) {
if (lua_isinteger(L, 1)) {
if (lua_isinteger(L, 2)) {
if (lua_isinteger(L, 3)) {
//***TODO*** g_pSingeIn->draw_string((char *)lua_tostring(L, 3), lua_tonumber(L, 1), lua_tonumber(L, 2), g_se_surface);
}
}
}
}
return 0;
}
@ -564,6 +836,7 @@ int apiSoundPlay(lua_State *L) {
HASH_FIND_INT(_soundList, &id, sound);
if (!sound) utilDie("No sound at index %d in apiSoundPlay.", id);
result = Mix_PlayChannel(-1, sound->chunk, 0);
Mix_Volume(result, _effectsVolume * 2);
}
}
lua_pushnumber(L, result);
@ -711,7 +984,6 @@ int apiSoundSetVolume(lua_State *L) {
if (thisValue >= 0 && thisValue <= AUDIO_MAX_VOLUME) {
_effectsVolume = thisValue;
Mix_Volume(-1, _effectsVolume * 2);
//***TODO*** Handle laser volume
} else {
utilDie("Invalid sound volume value.");
}
@ -862,7 +1134,37 @@ int apiVldpGetHeight(lua_State *L) {
int apiVldpGetPixel(lua_State *L) {
int n = lua_gettop(L);
bool result = false;
byte pixel[SDL_BYTESPERPIXEL(SDL_PIXELFORMAT_BGRA32)];
SDL_Rect rect;
if (n == 2) {
if (lua_isinteger(L, 1)) {
if (lua_isinteger(L, 2)) {
rect.h = 1;
rect.w = 1;
rect.x = (int)lua_tointeger(L, 1);
rect.y = (int)lua_tointeger(L, 2);
SDL_SetRenderTarget(_renderer, NULL);
if (SDL_RenderReadPixels(_renderer, &rect, SDL_PIXELFORMAT_BGRA32, pixel, SDL_BYTESPERPIXEL(SDL_PIXELFORMAT_BGRA32)) < 0) utilDie("%s", SDL_GetError());
SDL_SetRenderTarget(_renderer, _overlay);
result = true;
}
}
}
if (result) {
lua_pushinteger(L, (int)pixel[2]); // R
lua_pushinteger(L, (int)pixel[1]); // G
lua_pushinteger(L, (int)pixel[0]); // B
} else {
lua_pushinteger(L, -1);
lua_pushinteger(L, -1);
lua_pushinteger(L, -1);
}
return 3;
}
@ -917,7 +1219,7 @@ int apiKeyboardSetMode(lua_State *L) {
int apiMouseEnable(lua_State *L) {
// Enables mouse monitoring
(void)L;
//***TODO*** g_pSingeIn->dll_side_mouse_enable(g_pSingeIn->pSingeInstance);
_mouseEnabled = (bool)!_confNoMouse;
return 0;
}
@ -925,7 +1227,7 @@ int apiMouseEnable(lua_State *L) {
int apiMouseDisable(lua_State *L) {
// Disables mouse monitoring
(void)L;
//***TODO*** g_pSingeIn->dll_side_mouse_disable(g_pSingeIn->pSingeInstance);
_mouseEnabled = false;
return 0;
}
@ -949,24 +1251,22 @@ int apiMouseSetMode(lua_State *L) {
// --rdg
int n = lua_gettop(L);
int thisValue = 0;
bool result = false;
if (n == 1) {
if (lua_isinteger(L, 1)) {
thisValue = (int)lua_tointeger(L, 1);
//***TODO*** result = g_pSingeIn->dll_side_set_mouse_mode(thisValue);
if (!result) utilDie("mouseSetMode failed. Is mouse enabled?");
_mouseMode = (int)lua_tointeger(L, 1);
result = true;
}
}
lua_pushboolean(L, result);
return 1;
}
int apiMouseHowMany(lua_State *L) {
int total = 1; //***TODO*** g_pSingeIn->dll_side_mouse_get_how_many(g_pSingeIn->pSingeInstance);
lua_pushinteger(L, total);
lua_pushinteger(L, _mouseCount);
return 1;
}
@ -985,9 +1285,8 @@ int apiDiscGetState(lua_State *L) {
*
*/
//***TODO*** Add a STOPPED state where a black screen is displayed
// Our player isn't as sophisticated as the one in Daphne
lua_pushinteger(L, videoIsPlaying(_videoHandle) ? LDP_PLAYING : LDP_PAUSE);
lua_pushinteger(L, _discStopped ? LDP_STOPPED : (videoIsPlaying(_videoHandle) ? LDP_PLAYING : LDP_PAUSE));
return 1;
}
@ -1067,7 +1366,8 @@ int apiSingeSetGameName(lua_State *L) {
if (n == 1) {
if (lua_isstring(L, 1)) {
sprintf(thisName,"%.40s",lua_tostring(L, 1)); // Need a better way to do this...
//***TODO*** g_pSingeIn->dll_side_set_caption(g_pSingeIn->pSingeInstance, thisName);
SDL_SetWindowTitle(_window, thisName);
result = true;
}
}
@ -1200,18 +1500,99 @@ int luaError(lua_State *L) {
}
void processKey(bool down, int keysym) {
int move;
if (_keyboardMode == KEYBD_NORMAL) {
// Daphne keys
for (move=0; move<SWITCH_COUNT; move++) {
if ((keysym == _keyDefs[move][0]) || (keysym == _keyDefs[move][1])) {
if (!down) {
if ((move == SWITCH_PAUSE) && (_pauseEnabled)) {
//***TODO*** g_game->toggle_game_pause();
}
if ((move == SWITCH_QUIT) || (keysym == SDLK_ESCAPE)) {
_running = false;
}
if (move == SWITCH_SCREENSHOT) {
//***TODO*** g_ldp->request_screenshot();
}
}
if (move != SWITCH_PAUSE) {
callLua(down ? "onInputPressed" : "onInputReleased", "ii", move, NOMOUSE);
}
}
}
} 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;
}
}
}
}
}
void singe(SDL_Window *window, SDL_Renderer *renderer) {
int thisFrame = -1;
int lastFrame = -1;
int intReturn = 0;
bool refresh = false;
SDL_Texture *videoTexture = NULL;
SpriteT *sprite = NULL;
SpriteT *spriteTemp = NULL;
SoundT *sound = NULL;
SoundT *soundTemp = NULL;
FontT *font = NULL;
FontT *fontTemp = NULL;
int x = 0;
int y = 0;
int xr = 0;
int yr = 0;
int thisFrame = -1;
int lastFrame = -1;
int intReturn = 0;
bool refresh = false;
SDL_Texture *videoTexture = NULL;
SpriteT *sprite = NULL;
SpriteT *spriteTemp = NULL;
SoundT *sound = NULL;
SoundT *soundTemp = NULL;
FontT *font = NULL;
FontT *fontTemp = NULL;
SDL_Event event;
ManyMouseEvent mouseEvent;
MouseT *mouse = NULL;
int mouseButtonMap[] = {
SWITCH_BUTTON1, // Left
SWITCH_BUTTON3, // Middle
SWITCH_BUTTON2, // Right
SWITCH_BUTTON1, // Wheel Up
SWITCH_BUTTON2, // Wheel Down
SWITCH_MOUSE_DISCONNECT
};
// Hang on to some SDL stuff
_window = window;
@ -1301,11 +1682,28 @@ void singe(SDL_Window *window, SDL_Renderer *renderer) {
// Open main video file
_videoHandle = videoLoad(_confVideoFile, _confDataDir, (bool)_confStretchVideo, _renderer);
if (_videoHandle < 0) utilDie("Unable to load video file: %s", _confVideoFile);
videoPlay(_videoHandle);
videoSetVolume(_videoHandle, _confVolumeVldp, _confVolumeVldp);
// Mouse setup
_mouseCount = ManyMouse_Init();
if (_mouseCount < 1) utilDie("No mice detected.");
if (_mouseCount > MAX_MICE) {
_mouseCount = MAX_MICE;
}
memset(_mice, 0, sizeof(_mice));
_mouseEnabled = (bool)!_confNoMouse;
for (x=0; x<_mouseCount; x++) {
strncpy(_mice[x].name, ManyMouse_DeviceName((unsigned)x), sizeof(_mice[x].name));
_mice[x].name[sizeof(_mice[x].name) - 1] = 0;
_mice[x].x = videoGetWidth(_videoHandle) / 2;
_mice[x].y = videoGetHeight(_videoHandle) / 2;
}
SDL_SetWindowGrab(_window, SDL_TRUE);
// Create overlay texture
_overlay = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_TARGET, videoGetWidth(_videoHandle), videoGetHeight(_videoHandle));
if (_overlay == NULL) utilDie("%s", SDL_GetError());
SDL_SetTextureBlendMode(_overlay, SDL_BLENDMODE_BLEND);
if (_confStretchVideo) {
SDL_RenderSetLogicalSize(_renderer, videoGetWidth(_videoHandle), videoGetHeight(_videoHandle));
}
@ -1313,39 +1711,118 @@ void singe(SDL_Window *window, SDL_Renderer *renderer) {
// Set volume
_effectsVolume = (int)((float)AUDIO_MAX_VOLUME * (float)_confVolumeNonVldp * (float)0.01);
Mix_Volume(-1, _effectsVolume * 2);
//***TODO*** Handle laser volume
// Start video
videoPlay(_videoHandle);
_discStopped = false;
//***TODO*** Sound completed callback
// Game Loop
while (_running) {
// Event Loop
SDL_Event event;
// SDL Event Loop
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
default:
//***TODO*** Process key
break;
}
processKey(true, event.key.keysym.sym);
//***TODO*** RDG used "g" to re-grab/re-scan for mice
break;
case SDL_KEYUP:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
_running = false;
break;
default:
//***TODO*** Process key
break;
}
processKey(false, event.key.keysym.sym);
break;
case SDL_QUIT:
_running = 0;
break;
}
// Mouse Event Loop
while (ManyMouse_PollEvent(&mouseEvent)) {
if (mouseEvent.device >= (unsigned)_mouseCount) continue;
mouse = &_mice[mouseEvent.device];
switch (mouseEvent.type) {
case MANYMOUSE_EVENT_RELMOTION:
switch (mouseEvent.item) {
case 0:
mouse->relx += mouseEvent.value;
break;
case 1:
mouse->rely += mouseEvent.value;
break;
}
// Clamp to video size
if (mouse->relx < 0) mouse->relx = 0;
if (mouse->relx > videoGetWidth(_videoHandle)) mouse->relx = videoGetWidth(_videoHandle) - 1;
if (mouse->rely < 0) mouse->rely = 0;
if (mouse->rely > videoGetHeight(_videoHandle)) mouse->rely = videoGetHeight(_videoHandle) - 1;
x *= _overlayScaleX;
y *= _overlayScaleY;
xr *= _overlayScaleX;
yr *= _overlayScaleY;
callLua("onMouseMoved", "iiiii", x, y, xr, yr, mouseEvent.device);
break;
case MANYMOUSE_EVENT_ABSMOTION:
switch (mouseEvent.item) {
case 0:
mouse->x += mouseEvent.value;
break;
case 1:
mouse->y += mouseEvent.value;
break;
}
x *= _overlayScaleX;
y *= _overlayScaleY;
xr *= _overlayScaleX;
yr *= _overlayScaleY;
callLua("onMouseMoved", "iiiii", x, y, xr, yr, mouseEvent.device);
break;
case MANYMOUSE_EVENT_BUTTON:
if (mouseEvent.item < 32) {
if (mouseEvent.value == 1) {
// Button pressed
callLua("onInputPressed", "ii", mouseButtonMap[mouseEvent.item], mouseEvent.device);
mouse->buttons |= (1 << mouseEvent.item);
} else {
// Button released
callLua("onInputReleased", "ii", mouseButtonMap[mouseEvent.item], mouseEvent.device);
mouse->buttons &= ~(1 << mouseEvent.item);
}
}
break;
case MANYMOUSE_EVENT_SCROLL:
if (mouseEvent.item == 0) {
if (mouseEvent.value > 0) {
// Scroll up
callLua("onInputPressed", "ii", SWITCH_MOUSE_SCROLL_UP, mouseEvent.device);
callLua("onInputReleased", "ii", SWITCH_MOUSE_SCROLL_UP, mouseEvent.device);
} else {
// Scroll down
callLua("onInputPressed", "ii", SWITCH_MOUSE_SCROLL_DOWN, mouseEvent.device);
callLua("onInputReleased", "ii", SWITCH_MOUSE_SCROLL_DOWN, mouseEvent.device);
}
}
break;
case MANYMOUSE_EVENT_DISCONNECT:
mouse->connected = false;
callLua("onInputPressed", "ii", SWITCH_MOUSE_DISCONNECT, mouseEvent.device);
callLua("onInputReleased", "ii", SWITCH_MOUSE_DISCONNECT, mouseEvent.device);
break;
case MANYMOUSE_EVENT_MAX:
// We don't use this
break;
}
}
}
// Call game code
@ -1412,4 +1889,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer) {
// Unload video
videoUnload(_videoHandle);
// Stop mice
ManyMouse_Quit();
}

View file

@ -44,6 +44,8 @@ typedef struct VideoPlayerS {
byte audioSampleBytes;
byte *audioSilenceRaw;
char errMsg[1024];
int volumeLeft;
int volumeRight;
int audioTrack;
int videoTrack;
int frame;
@ -91,6 +93,9 @@ void _dequeueVideoAudio(int channel, void *stream, int bytes, void *udata) {
int bytesToCopy = bytes;
int available = SDL_AudioStreamAvailable(v->audioStream);
int remainder = 0;
int bytesRead = 0;
int i = 0;
Sint16 *data = stream;
(void)channel;
@ -103,7 +108,22 @@ void _dequeueVideoAudio(int channel, void *stream, int bytes, void *udata) {
remainder = bytesToCopy % v->audioSampleSize;
bytesToCopy -= remainder;
if (SDL_AudioStreamGet(v->audioStream, stream, bytesToCopy) < 0) utilDie("%s", SDL_GetError());
// Read audio data
bytesRead = SDL_AudioStreamGet(v->audioStream, stream, bytesToCopy);
if (bytesRead < 0) utilDie("%s", SDL_GetError());
// We do our own volume per channel here in the mixer
if (_mixChannels < 2) {
// Mono output, average volume levels together
Mix_Volume(channel, (int)((float)MIX_MAX_VOLUME * ((float)v->volumeLeft * (float)v->volumeRight / (float)2) * (float)0.01));
} else {
// Stereo output. Assumes MIX_DEFAULT_FORMAT for now.
Mix_Volume(channel, MIX_MAX_VOLUME);
for (i=0; i<bytesRead / 2; i+=2) {
data[i] = (Sint16)((float)data[i] * (float)v->volumeLeft * (float)0.01);
data[i + 1] = (Sint16)((float)data[i] * (float)v->volumeRight * (float)0.01);
}
}
}
@ -120,6 +140,7 @@ int FFMS_CC _indexCallBack(int64_t current, int64_t total, void *ICPrivate) {
if (thisPercent != lastPercent) {
lastPercent = thisPercent;
utilSay("Indexing: %d%%", thisPercent);
//***TODO*** GUI
}
}
@ -138,6 +159,9 @@ int videoInit(void) {
if (!Mix_QuerySpec(&_mixRate, &_mixFormat, &channels)) utilDie("%s", Mix_GetError());
_mixChannels = (Uint8)channels;
// Volume only works with MIX_DEFAULT_FORMAT
if (_mixFormat != MIX_DEFAULT_FORMAT) utilDie("videoInit: Only MIX_DEFAULT_FORMAT audio is supported.");
return 0;
}
@ -186,6 +210,20 @@ int videoGetWidth(int playerIndex) {
}
int videoGetVolume(int playerIndex, int *leftPercent, int *rightPercent) {
VideoPlayerT *v = NULL;
// Get our player structure
HASH_FIND_INT(_videoPlayerHash, &playerIndex, v);
if (!v) utilDie("No video player at index %d in videoGetVolume.", playerIndex);
if (leftPercent != NULL) *leftPercent = v->volumeLeft;
if (rightPercent != NULL) *rightPercent = v->volumeRight;
return 0;
}
int videoLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer) {
char indexName[1024];
int pixelFormats[2];
@ -321,6 +359,10 @@ int videoLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Renderer *
// Register effect to provide video stream audio on this channel
Mix_RegisterEffect(v->audioSilenceChannel, _dequeueVideoAudio, NULL, v);
// Default volume, in percent
v->volumeLeft = 100;
v->volumeRight = 100;
/*
utilSay("Frames: %d (%dx%d) Audio Samples: %ld (%d Hz) %d Channel%s",
v->videoProps->NumFrames,
@ -407,6 +449,20 @@ int videoSeek(int playerIndex, int seekFrame) {
}
int videoSetVolume(int playerIndex, int leftPercent, int rightPercent) {
VideoPlayerT *v = NULL;
// Get our player structure
HASH_FIND_INT(_videoPlayerHash, &playerIndex, v);
if (!v) utilDie("No video player at index %d in videoSetVolume.", playerIndex);
v->volumeLeft = leftPercent;
v->volumeRight = rightPercent;
return 0;
}
int videoUnload(int playerIndex) {
VideoPlayerT *v = NULL;

View file

@ -34,11 +34,13 @@ int videoIsPlaying(int playerIndex);
int videoGetFrame(int playerIndex);
int videoGetHeight(int playerIndex);
int videoGetWidth(int playerIndex);
int videoGetVolume(int playerIndex, int *leftPercent, int *rightPercent);
int videoLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Renderer *renderer);
int videoPause(int playerIndex);
int videoPlay(int playerIndex);
int videoQuit(void);
int videoSeek(int playerIndex, int seekFrame);
int videoSetVolume(int playerIndex, int leftPercent, int rightPercent);
int videoUnload(int playerIndex);
int videoUpdate(int playerIndex, SDL_Texture **texture);