diff --git a/build-debug-os2-sdl2.cmd b/build-debug-os2-sdl2.cmd new file mode 100644 index 000000000..620d73ff9 --- /dev/null +++ b/build-debug-os2-sdl2.cmd @@ -0,0 +1,9 @@ +echo off +bash autogen.sh +dash configure --enable-sdl2 --disable-gamelink --enable-debug +REM since cpu cores need a lot of memory, +REM we don't want to build parallel +cd src\cpu +make +cd ..\.. +make -j5 diff --git a/build-debug-os2.cmd b/build-debug-os2.cmd new file mode 100644 index 000000000..072a14244 --- /dev/null +++ b/build-debug-os2.cmd @@ -0,0 +1,9 @@ +echo off +bash autogen.sh +dash configure --enable-debug +REM since cpu cores need a lot of memory, +REM we don't want to build parallel +cd src\cpu +make +cd ..\.. +make -j5 diff --git a/build-os2-sdl2.cmd b/build-os2-sdl2.cmd new file mode 100644 index 000000000..98382ab36 --- /dev/null +++ b/build-os2-sdl2.cmd @@ -0,0 +1,9 @@ +echo off +bash autogen.sh +dash configure --enable-sdl2 --disable-gamelink +REM since cpu cores need a lot of memory, +REM we don't want to build parallel +cd src\cpu +make +cd ..\.. +make -j5 diff --git a/configure.ac b/configure.ac index f50a1a681..850d2a9a9 100644 --- a/configure.ac +++ b/configure.ac @@ -375,6 +375,7 @@ if test x$host = xi386-pc-os2-emx ; then CXXFLAGS="$CXXFLAGS -DOS2 -march=pentium4 -idirafter /@unixroot/usr/include/os2tk45" CFLAGS="$CFLAGS -DOS2 -march=pentium4 -idirafter /@unixroot/usr/include/os2tk45" LDFLAGS="$LDFLAGS -Zomf -Zhigh-mem -lcx" + AM_CONDITIONAL(OS2, true) fi dnl I would like to know of any concerns given by the C++ compiler. diff --git a/src/Makefile.am b/src/Makefile.am index 2664be963..bc61f0484 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,6 +34,14 @@ dosbox_x_LDADD = debug/libdebug.a dos/libdos.a shell/libshell.a builtin/libbuilt cpu/libcpu.a hardware/reSID/libresid.a fpu/libfpu.a gui/libgui.a \ misc/libmisc.a output/liboutput.a hardware/mame/libmame.a libs/zmbv/libzmbv.a libs/decoders/internal/libopusint.a +if OS2 +dosbox_x_LDADD += os2res.res + +.rc.res: + wrc $< -i=. -r $@ + +endif + if !EMSCRIPTEN dosbox_x_LDADD += aviwriter/libaviwriter.a endif @@ -73,7 +81,7 @@ dosbox_x_js_install: sudo cp -v dosbox-x.js dosbox-x.wasm /var/www/html/em/ endif -EXTRA_DIST = winres.rc ../contrib/icons/dosbox-x.ico +EXTRA_DIST = winres.rc ../contrib/icons/dosbox-x.ico os2res.rc # Ensure the macOS universal executables are correctly removed when cleaning distclean-local: diff --git a/src/dos/Makefile.am b/src/dos/Makefile.am index 9f9595102..c3ec1da8d 100644 --- a/src/dos/Makefile.am +++ b/src/dos/Makefile.am @@ -13,4 +13,3 @@ if MACOSX libdos_a_SOURCES += \ ../libs/physfs/physfs_platform_apple.mm endif - diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 4d2793e77..3a3a144d9 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -64,6 +64,19 @@ #include "../ints/int10.h" #include "../output/output_opengl.h" #include "paging.h" + +#if defined(OS2) +#define INCL DOSFILEMGR +#define INCL_DOSERRORS +#define INCL_WINWINDOWMGR +#define INCL_WINDIALOGS +#define INCL_WINERRORS +#define INCL_WINSTDFILE +#include "os2.h" + +typedef char host_cnv_char_t; +host_cnv_char_t *CodePageGuestToHost(const char *s); +#endif #if defined(_MSC_VER) #include "../libs/tinyfiledialogs/tinyfiledialogs.h" #elif !defined(HX_DOS) @@ -131,15 +144,6 @@ void WriteChar(uint16_t col,uint16_t row,uint8_t page,uint16_t chr,uint8_t attr, #include "ioapi.h" #include "zipcppstdbuf.h" -#if defined(OS2) -#define INCL DOSFILEMGR -#define INCL_DOSERRORS -#include "os2.h" - -typedef char host_cnv_char_t; -host_cnv_char_t *CodePageGuestToHost(const char *s); -#endif - #if defined(WIN32) #ifndef S_ISDIR #define S_ISDIR(m) (((m)&S_IFMT)==S_IFDIR) diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 2dfbfd0fe..45e30de36 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -36,6 +36,7 @@ # define INCL_DOS # define INCL_WIN # define INCL_DOSERRORS +# define INCL_WINDIALOGS # include #endif @@ -7775,6 +7776,7 @@ int main(int argc, char* argv[]) SDL_MAIN_NOEXCEPT { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #endif + /* -- parse command line arguments */ if (!DOSBOX_parse_argv()) return 1; diff --git a/src/libs/tinyfiledialogs/tinyfiledialogs.c b/src/libs/tinyfiledialogs/tinyfiledialogs.c index 229ab2232..a332d4786 100644 --- a/src/libs/tinyfiledialogs/tinyfiledialogs.c +++ b/src/libs/tinyfiledialogs/tinyfiledialogs.c @@ -172,6 +172,15 @@ char tinyfd_needs[] = "\ \n a graphic display\ \nor dialog.exe (curses console mode ** Disabled by default **)\ \nor a console for basic input"; +#elif defined(OS2) +char tinyfd_needs[] = "\ + ___________\n\ +/ \\ \n\ +| tiny file |\n\ +| dialogs |\n\ +\\_____ ____/\n\ + \\|\ +\ntiny file dialogs on Windows needs a graphic display"; #else char tinyfd_needs[] = "\ ___________\n\ @@ -3398,6 +3407,237 @@ char * tinyfd_colorChooser( return lDefaultHexRGB; } +#elif defined(OS2) + +int tinyfd_notifyPopup( + char const * aTitle, /* NULL or "" */ + char const * aMessage, /* NULL or "" may contain \n \t */ + char const * aIconType) /* "info" "warning" "error" */ + /* return has only meaning for tinyfd_query */ +{ + return tinyfd_messageBox(aTitle, aMessage, NULL, aIconType, 0); +} + +int tinyfd_messageBox( + char const * aTitle , /* NULL or "" */ + char const * aMessage , /* NULL or "" may contain \n \t */ + char const * aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */ + char const * aIconType , /* "info" "warning" "error" "question" */ + int aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */ +{ +// TODO aDefaultButton cf Windows implementation + ULONG style = MB_NOICON; + // Build the dialog style + if (aDialogType) + { + if (!strcasecmp(aDialogType, "ok")) + style |= MB_OK; + else if (!strcasecmp(aDialogType, "okcancel")) + style |= MB_OKCANCEL; + else if (!strcasecmp(aDialogType, "yesno")) + style |= MB_YESNO; + else if (!strcasecmp(aDialogType, "yesnocancel")) + style |= MB_YESNOCANCEL; + } + + // Build the icon style + if (aIconType) + { + if (!strcasecmp(aIconType, "info")) + style |= MB_INFORMATION; + else if (!strcasecmp(aIconType, "warning")) + style |= MB_WARNING; + else if (!strcasecmp(aIconType, "error")) + style |= MB_ERROR; + else if (!strcasecmp(aIconType, "question")) + style |= MB_QUERY; + } + + ULONG result = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, (PCSZ)aMessage, (PCSZ)aTitle, 1, style); + if (result == MBID_NO && !strcasecmp("yesnocancel", aDialogType)) + return 2; + else if (result == MBID_OK || result == MBID_YES) + return 1; + else + return 0; +} + +MRESULT EXPENTRY InputBox_Callback(HWND hWnd, ULONG message, MPARAM wParam, MPARAM lParam) +{ + int wmId, wmEvent; + + switch (message) + { + case WM_CONTROL: + { + wmId = SHORT1FROMMP(wParam); + wmEvent = SHORT2FROMMP(wParam); + + } + break; + + case WM_COMMAND: + { + wmId = SHORT1FROMMP(wParam); + wmEvent = SHORT2FROMMP(wParam); + + WinDismissDlg(hWnd, wmId == DID_OK); + + } + break; + + case WM_INITDLG: + { + + // Fill the commands combobox + WinSendMsg(launcher.listCMD, LM_INSERTITEM, MPFROMSHORT(LIT_END), MPFROMP("Select command")); + + { + char buf[128]; + strcpy(buf, ((launcher_enable + 1) % launcher_enable_count == launcher_enable_never ? "Disable" : "Enable")); + strcat(buf, " this Launcher for future use"); + WinSendMsg(launcher.listCMD, LM_INSERTITEM, MPFROMSHORT(LIT_END), MPFROMP(buf)); + } + + + return (MRESULT)1; + + case WM_DESTROY: + break; + + default: + /* + * Any event messages that the dialog procedure has not processed + * come here and are processed by WinDefDlgProc. + * This call MUST exist in your dialog procedure. + */ + return WinDefDlgProc(hWnd, message, wParam, lParam); + } + return 0; +} + +char * tinyfd_inputBox( + char const * aTitle , /* NULL or "" */ + char const * aMessage , /* NULL or "" (\n and \t have no effect) */ + char const * aDefaultInput ) /* NULL = passwordBox, "" = inputbox */ + /* returns NULL on cancel */ +{ + ULONG result = WinDlgBox(HWND_DESKTOP, WinQueryActiveWindow(HWND_DESKTOP), InputBox_Callback, NULLHANDLE, 100, NULL); + if (result == DID_ERROR) + { + printf("hDialog %lx\n",WinGetLastError(0)); + } + return NULL; +} + +inline static void setupFILEDLG( + PFILEDLG filedlg, + char const * aTitle, + int aNumOfFilterPatterns, + char const * const * aFilterPatterns, + int aAllowMultipleSelects +) { + int i; + char *j; + + memset(filedlg, 0, sizeof(FILEDLG)); + filedlg->cbSize = sizeof(FILEDLG); + filedlg->fl = FDS_CENTER; + if (aAllowMultipleSelects) + { + filedlg->fl |= FDS_MULTIPLESEL; + } + filedlg->pszTitle = (PSZ)aTitle; + + j = filedlg->szFullFile; + for(i = 0; i < aNumOfFilterPatterns; i++) + { + size_t len = strlen(aFilterPatterns[i]); + if (j + len >= filedlg->szFullFile+CCHMAXPATH) + break; // Too long for buffer + + strcpy(j, aFilterPatterns[i]); + j += len; + *j = ';'; // Insert separator + j++; + } + *(j-1) = 0; // End the string + +} + +char * tinyfd_saveFileDialog( + char const * aTitle , /* NULL or "" */ + char const * aDefaultPathAndOrFile , /* NULL or "" , ends with / to set only a directory */ + int aNumOfFilterPatterns , /* 0 (1 in the following example) */ + char const * const * aFilterPatterns , /* NULL or char const * lFilterPatterns[1]={"*.txt"} */ + char const * aSingleFilterDescription ) /* NULL or "text files" */ + /* returns NULL on cancel */ +{ +// TODO Refactor file dialogs + FILEDLG filedlg; + HWND hwndDlg; + + setupFILEDLG(&filedlg, aTitle, aNumOfFilterPatterns, aFilterPatterns, 0); + hwndDlg = WinFileDlg(HWND_DESKTOP, HWND_DESKTOP, &filedlg); + if (hwndDlg && filedlg.lReturn == DID_OK) + { + char *result = (char*)malloc(strlen(filedlg.szFullFile)+1); + strcpy(result, filedlg.szFullFile); + return result; + } + return NULL; +} + +char * tinyfd_openFileDialog( + char const * aTitle, /* NULL or "" */ + char const * aDefaultPathAndOrFile, /* NULL or "" , ends with / to set only a directory */ + int aNumOfFilterPatterns , /* 0 (2 in the following example) */ + char const * const * aFilterPatterns, /* NULL or char const * lFilterPatterns[2]={"*.png","*.jpg"}; */ + char const * aSingleFilterDescription, /* NULL or "image files" */ + int aAllowMultipleSelects ) /* 0 or 1 */ + /* in case of multiple files, the separator is | */ + /* returns NULL on cancel */ +{ +// TODO Refactor file dialogs + FILEDLG filedlg; + HWND hwndDlg; + + setupFILEDLG(&filedlg, aTitle, aNumOfFilterPatterns, aFilterPatterns, aAllowMultipleSelects); + filedlg.fl |= FDS_OPEN_DIALOG; + // TODO React to multiple selects + hwndDlg = WinFileDlg(HWND_DESKTOP, HWND_DESKTOP, &filedlg); + if (hwndDlg && filedlg.lReturn == DID_OK) + { + // TODO React to multiple selects + char *result = (char*)malloc(strlen(filedlg.szFullFile)+1); + strcpy(result, filedlg.szFullFile); + return result; + } + return NULL; +} + +char * tinyfd_selectFolderDialog( + char const * aTitle, /* NULL or "" */ + char const * aDefaultPath) /* NULL or "" */ + /* returns NULL on cancel */ +{ + return NULL; +} + +char * tinyfd_colorChooser( + char const * aTitle, /* NULL or "" */ + char const * aDefaultHexRGB, /* NULL or "" or "#FF0000" */ + unsigned char const aDefaultRGB[3] , /* unsigned char lDefaultRGB[3] = { 0 , 128 , 255 }; */ + unsigned char aoResultRGB[3] ) /* unsigned char lResultRGB[3]; */ + /* aDefaultRGB is used only if aDefaultHexRGB is absent */ + /* aDefaultRGB and aoResultRGB can be the same array */ + /* returns NULL on cancel */ + /* returns the hexcolor as a string "#FF0000" */ + /* aoResultRGB also contains the result */ +{ + return NULL; +} + #else /* unix */