From cc724dbb1dd0d5f06959f3c745119caa7fc4b36f Mon Sep 17 00:00:00 2001 From: tmaul Date: Sun, 1 Jan 2012 17:12:53 +0000 Subject: [PATCH] More sdl bits - no makefile as it all needs updating --- src/burner/platform/sdl/burner_sdl.h | 100 ++++++ src/burner/platform/sdl/config.cpp | 110 ++++++ src/burner/platform/sdl/drv.cpp | 181 ++++++++++ src/burner/platform/sdl/inpdipsw.cpp | 144 ++++++++ src/burner/platform/sdl/main.cpp | 139 ++++++++ src/burner/platform/sdl/run.cpp | 326 ++++++++++++++++++ src/burner/platform/sdl/stated.cpp | 27 ++ src/burner/platform/sdl/tchar.h | 60 ++++ src/interface/video/sdl/vid_sdlopengl.cpp | 392 ++++++++++++++++++++++ 9 files changed, 1479 insertions(+) create mode 100644 src/burner/platform/sdl/burner_sdl.h create mode 100644 src/burner/platform/sdl/config.cpp create mode 100644 src/burner/platform/sdl/drv.cpp create mode 100644 src/burner/platform/sdl/inpdipsw.cpp create mode 100644 src/burner/platform/sdl/main.cpp create mode 100644 src/burner/platform/sdl/run.cpp create mode 100644 src/burner/platform/sdl/stated.cpp create mode 100644 src/burner/platform/sdl/tchar.h create mode 100644 src/interface/video/sdl/vid_sdlopengl.cpp diff --git a/src/burner/platform/sdl/burner_sdl.h b/src/burner/platform/sdl/burner_sdl.h new file mode 100644 index 000000000..eb10399e0 --- /dev/null +++ b/src/burner/platform/sdl/burner_sdl.h @@ -0,0 +1,100 @@ +#include "SDL.h" + +#ifndef _WIN32 +typedef struct tagRECT { + int left; + int top; + int right; + int bottom; +} RECT,*PRECT,*LPRECT; +typedef const RECT *LPCRECT; +#endif + +#ifndef MAX_PATH +#define MAX_PATH 511 +#endif + +#ifndef __cdecl +#define __cdecl +#endif + +//main.cpp +int SetBurnHighCol(int nDepth); +extern int nAppVirtualFps; +extern bool bRunPause; +extern bool bAlwaysProcessKeyboardInput; +TCHAR* ANSIToTCHAR(const char* pszInString, TCHAR* pszOutString, int nOutSize); +char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, int nOutSize); +bool AppProcessKeyboardInput(); + + +//config.cpp +int ConfigAppLoad(); +int ConfigAppSave(); + +// drv.cpp +extern int bDrvOkay; // 1 if the Driver has been initted okay, and it's okay to use the BurnDrv functions +extern char szAppRomPaths[DIRS_MAX][MAX_PATH]; +int DrvInit(int nDrvNum, bool bRestore); +int DrvInitCallback(); // Used when Burn library needs to load a game. DrvInit(nBurnSelect, false) +int DrvExit(); +int ProgressUpdateBurner(double dProgress, const TCHAR* pszText, bool bAbs); +int AppError(TCHAR* szText, int bWarning); + +//run.cpp +extern int RunMessageLoop(); +extern int RunReset(); + +//inpdipsw.cpp +void InpDIPSWResetDIPs(); + +//interface/inp_interface.cpp +int InputInit(); +int InputExit(); +int InputMake(bool bCopy); +extern int nAppVirtualFps; // virtual fps + +extern TCHAR szAppExeName[EXE_NAME_SIZE + 1]; +extern TCHAR szAppBurnVer[16]; + +extern bool bCmdOptUsed; +extern bool bAlwaysProcessKeyboardInput; + +extern bool bNoChangeNumLock; +extern bool bMonitorAutoCheck; + +// Used for the load/save dialog in commdlg.h +extern TCHAR szChoice[MAX_PATH]; // File chosen by the user + +// Used to convert strings when possibly needed +/* const */ char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, int nOutSize); +/* const */ TCHAR* ANSIToTCHAR(const char* pszString, TCHAR* pszOutString, int nOutSize); + +CHAR *astring_from_utf8(const char *s); +char *utf8_from_astring(const CHAR *s); + +WCHAR *wstring_from_utf8(const char *s); +char *utf8_from_wstring(const WCHAR *s); + +#ifdef _UNICODE +#define tstring_from_utf8 wstring_from_utf8 +#define utf8_from_tstring utf8_from_wstring +#else // !_UNICODE +#define tstring_from_utf8 astring_from_utf8 +#define utf8_from_tstring utf8_from_astring +#endif // _UNICODE + +int dprintf(TCHAR* pszFormat, ...); // Use instead of printf() in the UI + +void MonitorAutoCheck(); + + +// Misc +#define _TtoA(a) TCHARToANSI(a, NULL, 0) +#define _AtoT(a) ANSIToTCHAR(a, NULL, 0) +int __cdecl ZipLoadOneFile(const char* arcName, const char* fileName, void** Dest, int* pnWrote); + +// numpluscommas.cpp +TCHAR* FormatCommasNumber(__int64); +#define _uInt64ToCommaFormattedTCHAR(szOUT, nIN) \ + _stprintf(szOUT, _T("%s"), FormatCommasNumber(nIN)); diff --git a/src/burner/platform/sdl/config.cpp b/src/burner/platform/sdl/config.cpp new file mode 100644 index 000000000..2dee47deb --- /dev/null +++ b/src/burner/platform/sdl/config.cpp @@ -0,0 +1,110 @@ +// Burner Config file module +#include "burner.h" +int nIniVersion = 0; + +static void CreateConfigName(char* szConfig) +{ + memcpy(szConfig, "fbasdl.ini", 12); + return; +} + +// Read in the config file for the whole application +int ConfigAppLoad() +{ + char szConfig[MAX_PATH]; + char szLine[256]; + FILE *h; + + CreateConfigName(szConfig); + + if ((h = fopen(szConfig,"rt")) == NULL) { + return 1; + } + + // Go through each line of the config file + while (fgets(szLine, sizeof(szLine), h)) { + int nLen; + + nLen = strlen(szLine); + + // Get rid of the linefeed at the end + if (szLine[nLen - 1] == 10) { + szLine[nLen - 1] = 0; + nLen--; + } + +#define VAR(x) { char *szValue = LabelCheck(szLine,#x); \ + if (szValue) x = strtol(szValue, NULL, 0); } +#define FLT(x) { char *szValue = LabelCheck(szLine,#x); \ + if (szValue) x = atof(szValue); } +#define STR(x) { char *szValue = LabelCheck(szLine,#x " "); \ + if (szValue) strcpy(x,szValue); } + + VAR(nIniVersion); + VAR(nVidSelect); // video mode select + VAR(bBurnUseASMCPUEmulation); // if you have a poor mans PC + + // Other + STR(szAppRomPaths[0]); + STR(szAppRomPaths[1]); + STR(szAppRomPaths[2]); + STR(szAppRomPaths[3]); + STR(szAppRomPaths[4]); + STR(szAppRomPaths[5]); + STR(szAppRomPaths[6]); + STR(szAppRomPaths[7]); +#undef STR +#undef FLT +#undef VAR + } + + fclose(h); + return 0; +} + +// Write out the config file for the whole application +int ConfigAppSave() +{ + char szConfig[MAX_PATH]; + FILE *h; + + CreateConfigName(szConfig); + + if ((h = fopen(szConfig, "wt")) == NULL) { + return 1; + } + + +#define VAR(x) fprintf(h, #x " %d\n", x) +#define FLT(x) fprintf(h, #x " %f\n", x) +#define STR(x) fprintf(h, #x " %s\n", x) + + fprintf(h,"\n// The application version this file was saved from\n"); + // We can't use the macros for this! + fprintf(h, "nIniVersion 0x%06X", nBurnVer); + + fprintf(h,"\n// video mode 0 = standard SDL 1= (very expiermental) opengl\n"); + VAR(nVidSelect); // video mode select + + fprintf(h,"\n// use asm cpu cores (i.e. you need to buy a new PC)\n"); + VAR(bBurnUseASMCPUEmulation); + + fprintf(h,"\n// The paths to search for rom zips. (include trailing backslash)\n"); + STR(szAppRomPaths[0]); + STR(szAppRomPaths[1]); + STR(szAppRomPaths[2]); + STR(szAppRomPaths[3]); + STR(szAppRomPaths[4]); + STR(szAppRomPaths[5]); + STR(szAppRomPaths[6]); + STR(szAppRomPaths[7]); + + fprintf(h,"\n\n\n"); + +#undef STR +#undef FLT +#undef VAR + + fclose(h); + return 0; +} diff --git a/src/burner/platform/sdl/drv.cpp b/src/burner/platform/sdl/drv.cpp new file mode 100644 index 000000000..bd4d6be68 --- /dev/null +++ b/src/burner/platform/sdl/drv.cpp @@ -0,0 +1,181 @@ +// Driver Init module +#include "burner.h" + +int bDrvOkay = 0; // 1 if the Driver has been initted okay, and it's okay to use the BurnDrv functions + +char szAppRomPaths[DIRS_MAX][MAX_PATH] = {{"/usr/local/share/roms/"},{"roms/"}, }; + +static bool bSaveRAM = false; + +static int DoLibInit() // Do Init of Burn library driver +{ + int nRet; + + BzipOpen(false); + + // If there is an error with the romset, report it + if (nBzipError) { + /* char *szTitle; + int nIcon, nButton; + + // Make the correct title and icon + if (nBzipError & 1) { + nIcon = MB_ICONERROR; + szTitle = APP_TITLE " Error"; + } else { + nIcon = MB_ICONWARNING; + szTitle = APP_TITLE " Warning"; + } + + if (nBzipError & 0x08) { + nButton = MB_OK; // no data at all - pretty basic! + } else { + BzipText.Add("\nWould you like more detailed information?\n(For experts only!)\n"); + nButton = MB_DEFBUTTON2 | MB_YESNO; + } + + // We can't use AppError, so use MessageBox directly + if (MessageBox(hScrnWnd, BzipText.szText, szTitle, nButton | nIcon | MB_SETFOREGROUND) == IDYES) { + // Give the more detailed information string + MessageBox(hScrnWnd, BzipDetail.szText, szTitle, MB_OK | nIcon | MB_SETFOREGROUND); + } +*/ } + + //ProgressCreate(); + + nRet = BurnDrvInit(); + + BzipClose(); + +// ProgressDestroy(); + + if (nRet) { + return 1; + } else { + return 0; + } +} + +// Catch calls to BurnLoadRom() once the emulation has started; +// Intialise the zip module before forwarding the call, and exit cleanly. +static int DrvLoadRom(unsigned char* Dest, int* pnWrote, int i) +{ + int nRet; + + BzipOpen(false); + + if ((nRet = BurnExtLoadRom(Dest, pnWrote, i)) != 0) { + char szText[256] = ""; + char* pszFilename; + + BurnDrvGetRomName(&pszFilename, i, 0); + sprintf(szText, "Error loading %s, requested by %s.\nThe emulation will likely suffer problems.", pszFilename, BurnDrvGetTextA(0)); + } + + BzipClose(); + + BurnExtLoadRom = DrvLoadRom; + + //ScrnTitle(); + + return nRet; +} + +int DrvInit(int nDrvNum, bool bRestore) +{ + DrvExit(); // Make sure exitted + AudSoundInit(); // Init Sound (not critical if it fails) + + nBurnSoundRate = 0; // Assume no sound + pBurnSoundOut = NULL; + if (bAudOkay) { + nBurnSoundRate = nAudSampleRate; + nBurnSoundLen = nAudSegLen; + } nBurnDrvSelect = nDrvNum; // Set the driver number + + // Define nMaxPlayers early; GameInpInit() needs it (normally defined in DoLibInit()). + nMaxPlayers = BurnDrvGetMaxPlayers(); + GameInpInit(); // Init game input + + ConfigGameLoad(true); + InputMake(true); + + GameInpDefault(); + + if (DoLibInit()) { // Init the Burn library's driver + char szTemp[512]; + + BurnDrvExit(); // Exit the driver + + _stprintf (szTemp, _T("There was an error starting '%s'.\n"), BurnDrvGetText(DRV_FULLNAME)); + return 1; + } + + BurnExtLoadRom = DrvLoadRom; + + bDrvOkay = 1; // Okay to use all BurnDrv functions + + bSaveRAM = false; + nBurnLayer = 0xFF; // show all layers + + // Reset the speed throttling code, so we don't 'jump' after the load + RunReset(); + return 0; +} + +int DrvInitCallback() +{ + return DrvInit(nBurnDrvSelect, false); +} + +int DrvExit() +{ + if (bDrvOkay) { + +// StopReplay(); + + VidExit(); + + if (nBurnDrvSelect < nBurnDrvCount) { + + //MemCardEject(); // Eject memory card if present + + if (bSaveRAM) { + //StatedAuto(1); // Save NV (or full) RAM + bSaveRAM = false; + } + + ConfigGameSave(bSaveInputs); + + GameInpExit(); // Exit game input + BurnDrvExit(); // Exit the driver + } + } + + BurnExtLoadRom = NULL; + + bDrvOkay = 0; // Stop using the BurnDrv functions + + //bRunPause = 0; // Don't pause when exitted + + if (bAudOkay) { +// // Write silence into the sound buffer on exit, and for drivers which don't use pBurnSoundOut + memset(nAudNextSound, 0, nAudSegLen << 2); + } + + nBurnDrvSelect = ~0U; // no driver selected + + return 0; +} + +int ProgressUpdateBurner(double dProgress, const TCHAR* pszText, bool bAbs) +{ + printf("."); + return 0; +} + +int AppError(TCHAR* szText, int bWarning) +{ + return 0; +} + diff --git a/src/burner/platform/sdl/inpdipsw.cpp b/src/burner/platform/sdl/inpdipsw.cpp new file mode 100644 index 000000000..ec09e37cb --- /dev/null +++ b/src/burner/platform/sdl/inpdipsw.cpp @@ -0,0 +1,144 @@ +// Burner DipSwitches Dialog module +#include "burner.h" + +static unsigned char nPrevDIPSettings[4]; + +static int nDIPOffset; + +static bool bOK; + +static void InpDIPSWGetOffset() +{ + BurnDIPInfo bdi; + + nDIPOffset = 0; + for (int i = 0; BurnDrvGetDIPInfo(&bdi, i) == 0; i++) { + if (bdi.nFlags == 0xF0) { + nDIPOffset = bdi.nInput; + break; + } + } +} + +void InpDIPSWResetDIPs() +{ + int i = 0; + BurnDIPInfo bdi; + struct GameInp* pgi; + + InpDIPSWGetOffset(); + + while (BurnDrvGetDIPInfo(&bdi, i) == 0) { + if (bdi.nFlags == 0xFF) { + pgi = GameInp + bdi.nInput + nDIPOffset; + pgi->Input.Constant.nConst = (pgi->Input.Constant.nConst & ~bdi.nMask) | (bdi.nSetting & bdi.nMask); + } + i++; + } +} + +static int InpDIPSWListBegin() +{ + + + + + return 0; +} + +static bool CheckSetting(int i) +{ + BurnDIPInfo bdi; + BurnDrvGetDIPInfo(&bdi, i); + struct GameInp* pgi = GameInp + bdi.nInput + nDIPOffset; + + if ((pgi->Input.Constant.nConst & bdi.nMask) == bdi.nSetting) { + unsigned char nFlags = bdi.nFlags; + if ((nFlags & 0x0F) <= 1) { + return true; + } else { + for (int j = 1; j < (nFlags & 0x0F); j++) { + BurnDrvGetDIPInfo(&bdi, i + j); + pgi = GameInp + bdi.nInput + nDIPOffset; + if (nFlags & 0x80) { + if ((pgi->Input.Constant.nConst & bdi.nMask) == bdi.nSetting) { + return false; + } + } else { + if ((pgi->Input.Constant.nConst & bdi.nMask) != bdi.nSetting) { + return false; + } + } + } + return true; + } + } + return false; +} + +// Make a list view of the DIPswitches +static int InpDIPSWListMake() +{ + + return 0; +} + +static int InpDIPSWInit() +{ + BurnDIPInfo bdi; + struct GameInp *pgi; + + InpDIPSWGetOffset(); + + InpDIPSWListBegin(); + InpDIPSWListMake(); + + for (int i = 0, j = 0; BurnDrvGetDIPInfo(&bdi, i) == 0; i++) { + if (bdi.nInput >= 0 && bdi.nFlags == 0xFF) { + pgi = GameInp + bdi.nInput + nDIPOffset; + nPrevDIPSettings[j] = pgi->Input.Constant.nConst; + j++; + } + } + + return 0; +} + +static int InpDIPSWExit() +{ + GameInpCheckMouse(); + return 0; +} + +static void InpDIPSWCancel() +{ + if (!bOK) { + int i = 0, j = 0; + BurnDIPInfo bdi; + struct GameInp *pgi; + while (BurnDrvGetDIPInfo(&bdi, i) == 0) { + if (bdi.nInput >= 0 && bdi.nFlags == 0xFF) { + pgi = GameInp + bdi.nInput + nDIPOffset; + pgi->Input.Constant.nConst = nPrevDIPSettings[j]; + j++; + } + i++; + } + } +} + +// Create the list of possible values for a DIPswitch +static void InpDIPSWSelect() +{ +} + +int InpDIPSWCreate() +{ + if (bDrvOkay == 0) { // No game is loaded + return 1; + } + + bOK = false; + + return 0; +} diff --git a/src/burner/platform/sdl/main.cpp b/src/burner/platform/sdl/main.cpp new file mode 100644 index 000000000..8e2e7cfeb --- /dev/null +++ b/src/burner/platform/sdl/main.cpp @@ -0,0 +1,139 @@ +/*---------------- +Stuff to finish: + +It wouldn't be a stretch of the imagination to think the whole of the sdl 'port' needs a redo but here are the main things wrong with this version: + +The burner directory has a few common files with the windows version, so they should be updated at some point. +There is OSD of any kind which makes it hard to display info to the users. +There are lots of problems with the audio output code. +There are lots of problems with the opengl renderer +I need to merge in the stuff from the only non intel version of fba so we have a C z80 core +probably many other things. +------------------*/ +#include "burner.h" + +int nAppVirtualFps = 6000; // App fps * 100 +bool bRunPause=0; +bool bAlwaysProcessKeyboardInput=0; + + +void init_emu(int gamenum) +{ + // by default use C 68000, and soon C Z80 + bBurnUseASMCPUEmulation=0; + bCheatsAllowed=false; + ConfigAppLoad(); + ConfigAppSave(); + //CreateDirectory(".:\\cfg", NULL); + //CreateDirectory(".:\\state", NULL); + DrvInit(gamenum,0); +} + +void CheckFirstTime() +{ + +} + +void ProcessCommandLine(int argc, char *argv[]) +{ + +} + +int main(int argc, char *argv[]) +{ + unsigned int i=0; + + ConfigAppLoad(); + + CheckFirstTime(); // check for first time run + + SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO); + + BurnLibInit(); + + SDL_WM_SetCaption( "FBA, SDL port.", "FBA, SDL port."); + SDL_ShowCursor(SDL_DISABLE); + + if (argc == 2) + { + for (i = 0; i < nBurnDrvCount; i++) { + nBurnDrvSelect = i; + if (strcmp(BurnDrvGetTextA(0), argv[1]) == 0) { + break; + } + } + + if (i == nBurnDrvCount) { + printf("%s is not supported by FB Alpha.",argv[1]); + return 1; + } + } + + InputInit(); + init_emu(i); + + RunMessageLoop(); + InputExit(); + + DrvExit(); + ConfigAppSave(); + BurnLibExit(); + SDL_Quit(); + + return 0; +} + + +/* const */ TCHAR* ANSIToTCHAR(const char* pszInString, TCHAR* pszOutString, int nOutSize) +{ +#if defined (UNICODE) + static TCHAR szStringBuffer[1024]; + + TCHAR* pszBuffer = pszOutString ? pszOutString : szStringBuffer; + int nBufferSize = pszOutString ? nOutSize * 2 : sizeof(szStringBuffer); + + if (MultiByteToWideChar(CP_ACP, 0, pszInString, -1, pszBuffer, nBufferSize)) { + return pszBuffer; + } + + return NULL; +#else + if (pszOutString) { + _tcscpy(pszOutString, pszInString); + return pszOutString; + } + + return (TCHAR*)pszInString; +#endif +} + + +/* const */ char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, int nOutSize) +{ +#if defined (UNICODE) + static char szStringBuffer[1024]; + memset(szStringBuffer, 0, sizeof(szStringBuffer)); + + char* pszBuffer = pszOutString ? pszOutString : szStringBuffer; + int nBufferSize = pszOutString ? nOutSize * 2 : sizeof(szStringBuffer); + + if (WideCharToMultiByte(CP_ACP, 0, pszInString, -1, pszBuffer, nBufferSize, NULL, NULL)) { + return pszBuffer; + } + + return NULL; +#else + if (pszOutString) { + strcpy(pszOutString, pszInString); + return pszOutString; + } + + return (char*)pszInString; +#endif +} + + +bool AppProcessKeyboardInput() +{ + return true; +} diff --git a/src/burner/platform/sdl/run.cpp b/src/burner/platform/sdl/run.cpp new file mode 100644 index 000000000..d8793e549 --- /dev/null +++ b/src/burner/platform/sdl/run.cpp @@ -0,0 +1,326 @@ +// Run module +#include "burner.h" +//#include "app.h" +//#include "kailleraclient.h" + +bool bAltPause = 0; + +int bAlwaysDrawFrames = 0; + +static bool bShowFPS = false; + +//int kNetGame = 0; // Non-zero if Kaillera is being used + +int counter; // General purpose variable used when debugging + +static unsigned int nNormalLast = 0; // Last value of timeGetTime() +static int nNormalFrac = 0; // Extra fraction we did + +static bool bAppDoStep = 0; +static bool bAppDoFast = 0; +static int nFastSpeed = 6; + +static int GetInput(bool bCopy) +{ + static int i = 0; + InputMake(bCopy); // get input + + // Update Input dialog ever 3 frames + if (i == 0) { + //InpdUpdate(); + } + + i++; + + if (i >= 3) { + i = 0; + } + + // Update Input Set dialog + //InpsUpdate(); + return 0; +} + +static void DisplayFPS() +{ + static time_t fpstimer; + static unsigned int nPreviousFrames; + + char fpsstring[8]; + time_t temptime = clock(); + float fps = static_cast(nFramesRendered - nPreviousFrames) * CLOCKS_PER_SEC / (temptime - fpstimer); + sprintf(fpsstring, "%2.1f", fps); + VidSNewShortMsg(fpsstring, 0xDFDFFF, 480, 0); + + fpstimer = temptime; + nPreviousFrames = nFramesRendered; +} + +// define this function somewhere above RunMessageLoop() +void ToggleLayer(unsigned char thisLayer) +{ + nBurnLayer ^= thisLayer; // xor with thisLayer + VidRedraw(); + VidPaint(0); +} + +// With or without sound, run one frame. +// If bDraw is true, it's the last frame before we are up to date, and so we should draw the screen +static int RunFrame(int bDraw, int bPause) +{ + static int bPrevPause = 0; + static int bPrevDraw = 0; + + if (bPrevDraw && !bPause) { + VidPaint(0); // paint the screen (no need to validate) + } + + if (!bDrvOkay) { + return 1; + } + + if (bPause) + { + GetInput(false); // Update burner inputs, but not game inputs + if (bPause != bPrevPause) + { + VidPaint(2); // Redraw the screen (to ensure mode indicators are updated) + } + } + else + { + nFramesEmulated++; + nCurrentFrame++; + + /* { + if (nReplayStatus == 2) { + GetInput(false); // Update burner inputs, but not game inputs + if (ReplayInput()) { // Read input from file + bAltPause = 1; + bRunPause = 1; + MenuEnableItems(); + InputSetCooperativeLevel(false, false); + } + } + else + */ { + GetInput(true); // Update inputs + } + } +/* if (nReplayStatus == 1) { + RecordInput(); // Write input to file + } +*/ if (bDraw) { + nFramesRendered++; + if (VidFrame()) { // Do one frame + AudBlankSound(); + } + } + else { // frame skipping + pBurnDraw = NULL; // Make sure no image is drawn + BurnDrvFrame(); + } +/* + if (bShowFPS) { + if (nDoFPS < nFramesRendered) { + DisplayFPS(); + nDoFPS = nFramesRendered + 30; + } + } +*/ + bPrevPause = bPause; + bPrevDraw = bDraw; + + return 0; +} + + +// Callback used when DSound needs more sound +static int RunGetNextSound(int bDraw) +{ + if (nAudNextSound == NULL) { + return 1; + } + + if (bRunPause) { + if (bAppDoStep) { + RunFrame(bDraw, 0); + memset(nAudNextSound, 0, nAudSegLen << 2); // Write silence into the buffer + } else { + RunFrame(bDraw, 1); + } + + bAppDoStep = 0; // done one step + return 0; + } + + if (bAppDoFast) { // do more frames + for (int i = 0; i < nFastSpeed; i++) { + RunFrame(0, 0); + } + } + + // Render frame with sound + pBurnSoundOut = nAudNextSound; + RunFrame(bDraw, 0); +/* + if (WaveLog != NULL && pBurnSoundOut != NULL) { // log to the file + fwrite(pBurnSoundOut, 1, nBurnSoundLen << 2, WaveLog); + pBurnSoundOut = NULL; + } +*/ + if (bAppDoStep) { + memset(nAudNextSound, 0, nAudSegLen << 2); // Write silence into the buffer + } + bAppDoStep = 0; // done one step + + return 0; +} + +int RunIdle() +{ + int nTime, nCount; + + if (bAudPlaying) { + // Run with sound + AudSoundCheck(); + return 0; + } + + // Run without sound + nTime = SDL_GetTicks() - nNormalLast; + nCount = (nTime * nAppVirtualFps - nNormalFrac) / 100000; + if (nCount <= 0) { // No need to do anything for a bit + SDL_Delay(3); + + return 0; + } + + nNormalFrac += nCount * 100000; + nNormalLast += nNormalFrac / nAppVirtualFps; + nNormalFrac %= nAppVirtualFps; + + if (bAppDoFast){ // Temporarily increase virtual fps + nCount *= nFastSpeed; + } + if (nCount > 100) { // Limit frame skipping + nCount = 100; + } + if (bRunPause) { + if (bAppDoStep) { // Step one frame + nCount = 10; + } else { + RunFrame(1, 1); // Paused + return 0; + } + } + bAppDoStep = 0; + + for (int i = nCount / 10; i > 0; i--) { // Mid-frames + RunFrame(!bAlwaysDrawFrames, 0); + } + RunFrame(1, 0); // End-frame + // temp added for SDLFBA + //VidPaint(0); + return 0; +} + +int RunReset() +{ + // Reset the speed throttling code + nNormalLast = 0; nNormalFrac = 0; + if (!bAudPlaying) { + // run without sound + nNormalLast = SDL_GetTicks(); + } + return 0; +} + +static int RunInit() +{ + // Try to run with sound + AudSetCallback(RunGetNextSound); + AudSoundPlay(); + + RunReset(); + + return 0; +} + +static int RunExit() +{ + nNormalLast = 0; + // Stop sound if it was playing + AudSoundStop(); + return 0; +} + +// The main message loop +int RunMessageLoop() +{ + int bRestartVideo; + int finished= 0; + do { + bRestartVideo = 0; + + //MediaInit(); + + if (!bVidOkay) { + + // Reinit the video plugin + VidInit(); + if (!bVidOkay && nVidFullscreen) { + + nVidFullscreen = 0; + + // MediaExit(bRestartVideo); + // MediaInit(); + VidInit(); + } + if (!nVidFullscreen) { + //ScrnSize(); + } + + /* if (!bVidOkay && (bDrvOkay || bVidUsePlaceholder)) { + // Maske sure the error will be visible + SplashDestroy(1); + + AppError("VidInit Failed", 0); + } +*/ +/* if (bVidOkay && (bRunPause || !bDrvOkay)) { + VidRedraw(); + } +*/ } + + RunInit(); + + // ShowWindow(hScrnWnd, nAppShowCmd); // Show the screen window + // nAppShowCmd = SW_NORMAL; + + // SetForegroundWindow(hScrnWnd); + + //GameInpCheckLeftAlt(); + GameInpCheckMouse(); // Hide the cursor + while (!finished) { + SDL_Event event; + if ( SDL_PollEvent(&event) ) { + switch (event.type) { + case SDL_QUIT: /* Windows was closed */ + finished=1; + break; + } + } + else + { + // No messages are waiting + //SplashDestroy(0); + RunIdle(); + } + } + RunExit(); + } while (bRestartVideo); + + return 0; +} + diff --git a/src/burner/platform/sdl/stated.cpp b/src/burner/platform/sdl/stated.cpp new file mode 100644 index 000000000..a1df0939c --- /dev/null +++ b/src/burner/platform/sdl/stated.cpp @@ -0,0 +1,27 @@ +// State dialog module +#include "burner.h" + +int bDrvSaveAll=0; + + +// The automatic save +int StatedAuto(int bSave) +{ + return 0; +} + +static void CreateStateName(int nSlot) +{ + +} + +int StatedLoad(int nSlot) // int nSlot = 0 +{ + return 0; +} + +int StatedSave(int nSlot) // int nSlot = 0 +{ + + return 0; +} diff --git a/src/burner/platform/sdl/tchar.h b/src/burner/platform/sdl/tchar.h new file mode 100644 index 000000000..0d82828b7 --- /dev/null +++ b/src/burner/platform/sdl/tchar.h @@ -0,0 +1,60 @@ + +#ifdef _UNICODE +//TODO: bah +#include +#define __TEXT(q) L##q + +typedef wchar_t TCHAR; +typedef wchar_t _TCHAR; + +#else + + +#define __TEXT(q) q + +#ifndef RC_INVOKED +typedef char TCHAR; +typedef char _TCHAR; +#endif + +// WTF? This is a normal string function! +// damn linux. :) +#define wcslen(void) + +#define _tcslen strlen +#define _tcscpy strcpy +#define _tcsncpy strncpy + +#define _tprintf printf +#define _vstprintf vsprintf +#define _vsntprintf vsnprintf +#define _stprintf sprintf +#define _sntprintf snprintf +#define _ftprintf fprintf +#define _tsprintf sprintf + +#define _tcscmp strcmp +#define _tcsncmp strncmp +#define _tcsicmp strcasecmp +#define _tcsnicmp strncasecmp +#define _tcstol strtol + +#define _fgetts fgets +#define _fputts fputs + +#define _istspace isspace + +#define _tfopen fopen + +#define _stricmp strcmp +#define _strnicmp strncmp + +// FBA function, change this! +#define dprintf printf + + +#endif + +#define _TEXT(x) __TEXT(x) +#define _T(x) __TEXT(x) + diff --git a/src/interface/video/sdl/vid_sdlopengl.cpp b/src/interface/video/sdl/vid_sdlopengl.cpp new file mode 100644 index 000000000..515ea2aeb --- /dev/null +++ b/src/interface/video/sdl/vid_sdlopengl.cpp @@ -0,0 +1,392 @@ +// OpenGL via SDL +#include "burner.h" +#include "vid_support.h" +#include "vid_softfx.h" + +#include +#include +#include + +#ifdef frame_timer +#include +#endif + +static int nInitedSubsytems = 0; + +static int nGamesWidth = 0, nGamesHeight = 0; // screen size + +static SDL_Surface* screen=NULL; +static unsigned char* texture = NULL; +static unsigned char* gamescreen=NULL; + +static GLint color_type = GL_RGB; +static GLint texture_type= GL_UNSIGNED_BYTE; + +static int nTextureWidth=512; +static int nTextureHeight=512; + +static int nSize; +static int nUseBlitter; + +static int nRotateGame = 0; +unsigned int g_Texture[1]; + +static int PrimClear() +{ + return 0; +} + +// Create a secondary DD surface for the screen +static int BlitFXMakeSurf() +{ + + return 0; +} + +static int BlitFXExit() +{ + SDL_FreeSurface(screen); + + free(texture); + free(gamescreen); + nRotateGame = 0; + + return 0; +} +static int GetTextureSize(int Size) +{ + int nTextureSize = 128; + while (nTextureSize < Size) { + nTextureSize <<= 1; + } + return nTextureSize; +} + +static int BlitFXInit() +{ + nVidImageWidth = nGamesWidth; + nVidImageHeight = nGamesHeight; + + nVidImageDepth = bDrvOkay ? 15 : 32; + nVidImageBPP = (nVidImageDepth + 7) >> 3; + nBurnBpp = nVidImageBPP; + SetBurnHighCol(nVidImageDepth); + + int nMemLen = 0; + if (!nRotateGame) + { + nVidImagePitch = nVidImageWidth * nVidImageBPP; + } + else + { + nVidImagePitch = nVidImageHeight * nVidImageBPP; + } + nMemLen = (nVidImageHeight) * nVidImagePitch; + gamescreen=(unsigned char*)malloc(nMemLen); + nBurnPitch=nVidImagePitch; + + texture = (unsigned char*)malloc(nTextureWidth*nTextureHeight*nVidImageBPP); + + if (gamescreen) { + memset(gamescreen, 0, nMemLen); + pVidImage = gamescreen + nVidImagePitch; + return 0; + } else { + pVidImage = NULL; + return 1; + } + + return 0; +} + +static int Exit() +{ + free(gamescreen); + free(texture); + if (!(nInitedSubsytems & SDL_INIT_VIDEO)) { + SDL_QuitSubSystem(SDL_INIT_VIDEO); + } + nInitedSubsytems = 0; + + return 0; +} + +void init_gl() +{ + const unsigned char * glVersion; + int isGL12=GL_FALSE; + printf("opengl config\n"); + + if ((BurnDrvGetFlags() & BDF_16BIT_ONLY)||(nVidImageBPP!=3)) + { + texture_type= GL_UNSIGNED_SHORT_5_6_5_REV; + } + else + { + texture_type=GL_UNSIGNED_BYTE; + } + + glShadeModel (GL_FLAT); + glDisable (GL_POLYGON_SMOOTH); + glDisable (GL_LINE_SMOOTH); + glDisable (GL_POINT_SMOOTH); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_2D); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, nVidImageBPP, nTextureWidth, nTextureHeight, 0,GL_RGB, texture_type, texture); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (!nRotateGame) + { + glRotatef(0.0, 0.0, 0.0, 1.0); + glOrtho(0, nGamesWidth, nGamesHeight, 0, -1,1); + } + else + { + glRotatef(90.0, 0.0, 0.0, 1.0); + glOrtho(0, nGamesHeight, nGamesWidth, 0, -1,5); + } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + printf("opengl config done . . . \n"); +} + +int VidSScaleImage(RECT* pRect) +{ + int nScrnWidth, nScrnHeight; + + int nGameAspectX = 4, nGameAspectY = 3; + int nWidth = pRect->right - pRect->left; + int nHeight = pRect->bottom - pRect->top; + + if (bVidFullStretch) { // Arbitrary stretch + return 0; + } + + if (bDrvOkay) { + if ((BurnDrvGetFlags() & (BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED))) { + BurnDrvGetAspect(&nGameAspectY, &nGameAspectX); + } else { + BurnDrvGetAspect(&nGameAspectX, &nGameAspectY); + } + } + + nScrnWidth =nGameAspectX; + nScrnHeight = nGameAspectY; + + int nWidthScratch; + nWidthScratch = nHeight * nVidScrnAspectY * nGameAspectX * nScrnWidth / (nScrnHeight * nVidScrnAspectX * nGameAspectY); + if (nWidthScratch > nWidth) { // The image is too wide + if (nGamesWidth < nGamesHeight) { // Vertical games + nHeight = nWidth * nVidScrnAspectY * nGameAspectY * nScrnWidth / (nScrnHeight * nVidScrnAspectX * nGameAspectX); + } else { // Horizontal games + nHeight = nWidth * nVidScrnAspectX * nGameAspectY * nScrnHeight / (nScrnWidth * nVidScrnAspectY * nGameAspectX); + } + } else { + nWidth = nWidthScratch; + } + pRect->left = (pRect->right + pRect->left) / 2; + pRect->left -= nWidth / 2; + pRect->right = pRect->left + nWidth; + + pRect->top = (pRect->top + pRect->bottom) / 2; + pRect->top -= nHeight / 2; + pRect->bottom = pRect->top + nHeight; + + return 0; +} + +static int Init() +{ + nInitedSubsytems = SDL_WasInit(SDL_INIT_VIDEO); + + if (!(nInitedSubsytems & SDL_INIT_VIDEO)) { + SDL_InitSubSystem(SDL_INIT_VIDEO); + } + nGamesWidth = nVidImageWidth; + nGamesHeight = nVidImageHeight; + + nRotateGame = 0; + if (bDrvOkay) + { + // Get the game screen size + BurnDrvGetVisibleSize(&nGamesWidth, &nGamesHeight); + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) + { + if (nVidRotationAdjust & 1) + { + int n = nGamesWidth; + nGamesWidth = nGamesHeight; + nGamesHeight = n; + nRotateGame |= (nVidRotationAdjust & 2); + } + else + { + nRotateGame |= 1; + } + } + + if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) + { + nRotateGame ^= 2; + } + } + + if(!nRotateGame) + { + nTextureWidth=GetTextureSize(nGamesWidth); + nTextureHeight=GetTextureSize(nGamesHeight); + }else + { + nTextureWidth=GetTextureSize(nGamesHeight); + nTextureHeight=GetTextureSize(nGamesWidth); + } + nSize = 2; + bVidScanlines = 0; + + RECT test_rect; + test_rect.left=0; + test_rect.right= nGamesWidth; + test_rect.top=0; + test_rect.bottom=nGamesHeight; + printf("correctx before %d, %d\n",test_rect.right,test_rect.bottom ); + VidSScaleImage(&test_rect); + printf("correctx after %d, %d\n",test_rect.right,test_rect.bottom ); + screen=SDL_SetVideoMode(test_rect.right * nSize, test_rect.bottom*nSize,32 , SDL_OPENGL); + SDL_WM_SetCaption("FB Alpha",NULL); + + // Initialize the buffer surfaces + BlitFXInit(); + //Init opengl + init_gl(); + return 0; +} + + +// Run one frame and render the screen +static int Frame(bool bRedraw) // bRedraw = 0 +{ + if (pVidImage == NULL) { + return 1; + } + + if (bDrvOkay) + { + if (bRedraw) + { // Redraw current frame + if (BurnDrvRedraw()) + { + BurnDrvFrame(); // No redraw function provided, advance one frame + } + } + else + { + BurnDrvFrame(); // Run one frame and draw the screen + } + } + return 0; +} +typedef unsigned char byte; + +void SurfToTex() +{ + unsigned char* Surf = (unsigned char*)gamescreen; + int nPitch = nVidImagePitch; + //printf("nvidImagePitch %d\n",nVidImagePitch); + + unsigned char* VidSurf = (unsigned char*)texture; + int nVidPitch = nTextureWidth*nVidImageBPP; + + unsigned char *pd, *ps; + + int nHeight = nGamesHeight; + pd = VidSurf; ps = Surf; + for (int y = 0; y < nHeight; y++, pd += nVidPitch, ps += nPitch) + { + memcpy(pd, ps, nPitch); + } +/* if (nVidImageBPP==3) + { + glTexImage2D(GL_TEXTURE_2D, 0, nVidImageBPP, nTextureWidth, nTextureHeight, 0, color_type,texture_type, texture); + } + else +*/ { + glTexImage2D(GL_TEXTURE_2D, 0,3, nTextureWidth, nTextureHeight, 0, GL_RGB, texture_type, texture); + } +} + +void TexToQuad() +{ +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer + // glColor3f(1,1,1); + + glBegin(GL_QUADS); + glTexCoord2f(0,0); + glVertex2i(0,0); + glTexCoord2f(0,1); + glVertex2i(0,nTextureHeight); + glTexCoord2f(1,1); + glVertex2i(nTextureWidth,nTextureHeight); + glTexCoord2f(1,0); + glVertex2i(nTextureWidth,0); + glEnd(); + //glFlush(); + glFinish(); + } + + +// Paint the BlitFX surface onto the primary surface +static int Paint(int bValidate) +{ +#ifdef frame_timer + timeval start , end; + time_t sec; + suseconds_t usec; + gettimeofday(&start,NULL); +#endif + SurfToTex(); + TexToQuad(); + SDL_GL_SwapBuffers(); + +#ifdef frame_timer + gettimeofday(&end,NULL); + sec = end.tv_sec - start.tv_sec; + usec = end.tv_usec - start.tv_usec; + if(usec < 0){ + usec += 1000000; + sec--; + } + printf("Elapsed time : %ld.%ld\n", sec, usec); +#endif + return 0; +} + +static int vidScale(RECT* , int, int) +{ + return 0; +} + + +static int GetSettings(InterfaceInfo* pInfo) +{ + TCHAR szString[MAX_PATH] = _T(""); + + _sntprintf(szString, MAX_PATH, _T("Prescaling using %s (%i× zoom)"), VidSoftFXGetEffect(nUseBlitter), nSize); + IntInfoAddStringModule(pInfo, szString); + + if (nRotateGame) { + IntInfoAddStringModule(pInfo, _T("Using software rotation")); + } + + return 0; +} + +// The Video Output plugin: +struct VidOut VidOutSDLOpenGL = { Init, Exit, Frame, Paint, vidScale, GetSettings, _T("SDL OpenGL Video output") }; +