diff --git a/Makefile b/Makefile index 497cd7e8d..e984b8369 100644 --- a/Makefile +++ b/Makefile @@ -127,7 +127,7 @@ serenityos: $(MAKE) $(ENAME) PLAT=serenityos irix: $(MAKE) $(ENAME) PLAT=irix - + # consoles builds require special handling, so are moved to # separate makefiles to avoid having one giant messy makefile dreamcast: @@ -161,6 +161,8 @@ switch: $(MAKE) -f misc/switch/Makefile PLAT=switch ds: $(MAKE) -f misc/ds/Makefile PLAT=ds +os/2: + $(MAKE) -f misc/os2/Makefile PLAT=os2 clean: $(DEL) $(OBJECTS) diff --git a/misc/os2/Makefile b/misc/os2/Makefile new file mode 100644 index 000000000..967bd65ae --- /dev/null +++ b/misc/os2/Makefile @@ -0,0 +1,58 @@ +#-------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# +# NO_ICON: if set to anything, do not use icon. +# NO_NACP: if set to anything, no .nacp file is generated. +# APP_TITLE is the name of the app stored in the .nacp file (Optional) +# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) +# APP_VERSION is the version of the app stored in the .nacp file (Optional) +# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) +# ICON is the filename of the icon (.jpg), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .jpg +# - icon.jpg +# - /default_icon.jpg +# +# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .json +# - config.json +# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead +# of a homebrew executable (.nro). This is intended to be used for sysmodules. +# NACP building is skipped as well. +#--------------------------------------------------------------------------------- +TARGET := ClassiCube +BUILD_DIR := build +SOURCE_DIR:= src +DATA := data +C_SOURCES := $(wildcard $(SOURCE_DIR)/*.c) +C_OBJECTS := $(patsubst $(SOURCE_DIR)/%.c, $(BUILD_DIR)/%.o, $(C_SOURCES)) + +OBJECTS := $(C_OBJECTS) $(BUILD_DIR)/$(TARGET).res misc/os2/classicube.def +ENAME = ClassiCube +DEL = rm -f +APP_TITLE := ClassiCube +APP_AUTHOR := UnknownShadow200 + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +CC := gcc +CFLAGS := -pipe -fno-math-errno -O0 -g -mtune=pentium4 -msse2 -march=i686 -idirafter /@unixroot/usr/include/os2tk45 -DOS2 +LDFLAGS := -Zhigh-mem -Zomf -Zargs-wild -Zargs-resp -Zlinker DISABLE -Zlinker 1121 +LIBS := -lcx -lmmpm2 -lpthread -lSDL2 + +$(TARGET).exe: $(BUILD_DIR) $(OBJECTS) + $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +$(C_OBJECTS): $(BUILD_DIR)/%.o : $(SOURCE_DIR)/%.c + $(CC) $(CFLAGS) -c $< -o $@ +$(BUILD_DIR)/$(TARGET).res: misc/os2/$(TARGET).rc misc/os2/$(TARGET).ico + wrc -r misc/os2/$(TARGET).rc -fo=$@ + diff --git a/misc/os2/classicube.ICO b/misc/os2/classicube.ICO new file mode 100644 index 000000000..04b06fca3 Binary files /dev/null and b/misc/os2/classicube.ICO differ diff --git a/src/AudioBackend.c b/src/AudioBackend.c index 016e388ab..5f750b9c1 100644 --- a/src/AudioBackend.c +++ b/src/AudioBackend.c @@ -1553,6 +1553,12 @@ cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) { static cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) { return false; } cc_bool Audio_DescribeError(cc_result res, cc_string* dst) { return false; } + +cc_result Audio_AllocChunks(cc_uint32 size, void** chunks, int numChunks) { + return ERR_NOT_SUPPORTED; +} + +void Audio_FreeChunks(void** chunks, int numChunks) { } #endif diff --git a/src/Core.h b/src/Core.h index 8b691795a..41ea903a9 100644 --- a/src/Core.h +++ b/src/Core.h @@ -366,6 +366,13 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_NOSOUNDS #undef CC_BUILD_RESOURCES #undef CC_BUILD_NETWORKING +#elif defined OS2 + #define CC_BUILD_OS2 + #define CC_BUILD_POSIX + #define CC_BUILD_SOFTGPU + #define CC_BUILD_SDL2 + #define CC_BUILD_CURL + #define CC_BUILD_FREETYPE #endif #endif diff --git a/src/Graphics_SoftGPU.c b/src/Graphics_SoftGPU.c index 48297207e..76754130b 100644 --- a/src/Graphics_SoftGPU.c +++ b/src/Graphics_SoftGPU.c @@ -283,9 +283,9 @@ void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, f /*########################################################################################################################* *---------------------------------------------------------Rendering-------------------------------------------------------* *#########################################################################################################################*/ -typedef struct Vector4 { float X, Y, Z, W; } Vector4; -typedef struct Vector3 { float X, Y, Z; } Vector3; -typedef struct Vector2 { float X, Y; } Vector2; +typedef struct Vector4 { float x, y, z, w; } Vector4; +typedef struct Vector3 { float x, y, z; } Vector3; +typedef struct Vector2 { float x, y; } Vector2; static void TransformVertex(int index, Vector4* frag, Vector2* uv, PackedCol* color) { // TODO: avoid the multiply, just add down in DrawTriangles @@ -301,7 +301,7 @@ static void TransformVertex(int index, Vector4* frag, Vector2* uv, PackedCol* co frag->x = vp_hwidth * (1 + coord.x / coord.w); frag->y = vp_hheight * (1 - coord.y / coord.w); frag->z = coord.z / coord.w; - frag.w = 1.0f / coord.w; + frag->w = 1.0f / coord.w; if (gfx_format != VERTEX_FORMAT_TEXTURED) { struct VertexColoured* v = (struct VertexColoured*)ptr; diff --git a/src/Http_Web.c b/src/Http_Web.c index 7dbc35e9e..c6374acec 100644 --- a/src/Http_Web.c +++ b/src/Http_Web.c @@ -70,7 +70,7 @@ static void Http_StartNextDownload(void) { String_EncodeUtf8(urlStr, &url); res = interop_DownloadAsync(urlStr, req->requestType, req->id); - + if (res) { /* interop error code -> ClassiCube error code */ if (res == 1) res = ERR_INVALID_DATA_URL; diff --git a/src/Http_Worker.c b/src/Http_Worker.c index 5d825513c..b7c0a625d 100644 --- a/src/Http_Worker.c +++ b/src/Http_Worker.c @@ -179,6 +179,9 @@ static const cc_string curlAlt = String_FromConst("libcurl.so"); #elif defined CC_BUILD_SERENITY static const cc_string curlLib = String_FromConst("/usr/local/lib/libcurl.so"); static const cc_string curlAlt = String_FromConst("/usr/local/lib/libcurl.so"); +#elif defined CC_BUILD_OS2 +static const cc_string curlLib = String_FromConst("/@unixroot/usr/lib/curl4.dll"); +static const cc_string curlAlt = String_FromConst("/@unixroot/usr/local/lib/curl4.dll"); #else static const cc_string curlLib = String_FromConst("libcurl.so.4"); static const cc_string curlAlt = String_FromConst("libcurl.so.3"); @@ -186,10 +189,17 @@ static const cc_string curlAlt = String_FromConst("libcurl.so.3"); static cc_bool LoadCurlFuncs(void) { static const struct DynamicLibSym funcs[] = { +#if !defined CC_BUILD_OS2 DynamicLib_Sym(curl_global_init), DynamicLib_Sym(curl_global_cleanup), DynamicLib_Sym(curl_easy_init), DynamicLib_Sym(curl_easy_perform), DynamicLib_Sym(curl_easy_setopt), DynamicLib_Sym(curl_easy_cleanup), DynamicLib_Sym(curl_slist_free_all), DynamicLib_Sym(curl_slist_append) +#else + DynamicLib_SymC(curl_global_init), DynamicLib_SymC(curl_global_cleanup), + DynamicLib_SymC(curl_easy_init), DynamicLib_SymC(curl_easy_perform), + DynamicLib_SymC(curl_easy_setopt), DynamicLib_SymC(curl_easy_cleanup), + DynamicLib_SymC(curl_slist_free_all), DynamicLib_SymC(curl_slist_append) +#endif }; cc_bool success; void* lib; @@ -225,7 +235,6 @@ static void HttpBackend_Init(void) { if (!LoadCurlFuncs()) { Logger_WarnFunc(&msg); return; } res = _curl_global_init(CURL_GLOBAL_DEFAULT); if (res) { Logger_SimpleWarn(res, "initing curl"); return; } - curl = _curl_easy_init(); if (!curl) { Logger_SimpleWarn(res, "initing curl_easy"); return; } diff --git a/src/LWeb.c b/src/LWeb.c index 3cf6124a7..d623abe13 100644 --- a/src/LWeb.c +++ b/src/LWeb.c @@ -219,6 +219,7 @@ static void LWebTask_Reset(struct LWebTask* task) { void LWebTask_Tick(struct LWebTask* task, LWebTask_ErrorCallback errorCallback) { struct HttpRequest item; + if (task->completed) return; if (!Http_GetResult(task->reqID, &item)) return; diff --git a/src/Launcher.c b/src/Launcher.c index 79d80cf83..18c939cbc 100644 --- a/src/Launcher.c +++ b/src/Launcher.c @@ -419,6 +419,7 @@ static cc_result Launcher_ProcessZipEntry(const cc_string* path, struct Stream* struct Bitmap bmp; cc_result res; + if (String_CaselessEqualsConst(path, "default.png")) { if (hasBitmappedFont) return 0; hasBitmappedFont = false; @@ -455,7 +456,6 @@ static cc_result ExtractTexturePack(const cc_string* path) { res = Zip_Extract(&stream, Launcher_SelectZipEntry, Launcher_ProcessZipEntry); - if (res) { Logger_SysWarn(res, "extracting texture pack"); } /* No point logging error for closing readonly file */ (void)stream.Close(&stream); diff --git a/src/Logger.c b/src/Logger.c index 5ae5868e2..06795c5d3 100644 --- a/src/Logger.c +++ b/src/Logger.c @@ -20,9 +20,13 @@ #include static HANDLE curProcess = CUR_PROCESS_HANDLE; #elif defined CC_BUILD_OPENBSD || defined CC_BUILD_HAIKU || defined CC_BUILD_SERENITY - #include - /* These operating systems don't provide sys/ucontext.h */ - /* But register constants be found from includes in */ +#include +/* These operating systems don't provide sys/ucontext.h */ +/* But register constants be found from includes in */ +#elif defined CC_BUILD_OS2 +#include +#include <386/ucontext.h> + #elif defined CC_BUILD_LINUX || defined CC_BUILD_ANDROID /* Need to define this to get REG_ constants */ #define _GNU_SOURCE @@ -244,7 +248,7 @@ static void DumpFrame(cc_string* trace, void* addr) { cc_uintptr addr_ = (cc_uintptr)addr; String_Format1(trace, "%x", &addr_); } -#elif defined CC_BUILD_POSIX +#elif defined CC_BUILD_POSIX && !defined CC_BUILD_OS2 /* need to define __USE_GNU for dladdr */ #ifndef __USE_GNU #define __USE_GNU @@ -379,7 +383,7 @@ void Logger_Backtrace(cc_string* trace, void* ctx) { } #elif defined CC_BACKTRACE_BUILTIN /* Implemented later at end of the file */ -#elif defined CC_BUILD_POSIX +#elif defined CC_BUILD_POSIX && !defined CC_BUILD_OS2 #include void Logger_Backtrace(cc_string* trace, void* ctx) { void* addrs[MAX_BACKTRACE_FRAMES]; diff --git a/src/Platform.h b/src/Platform.h index f5415ec14..7c78eb0d6 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -121,6 +121,9 @@ extern const cc_string DynamicLib_Ext; #define DYNAMICLIB_QUOTE(x) #x #define DynamicLib_Sym(sym) { DYNAMICLIB_QUOTE(sym), (void**)&_ ## sym } #define DynamicLib_Sym2(name, sym) { name, (void**)&_ ## sym } +#if defined CC_BUILD_OS2 +#define DynamicLib_SymC(sym) { DYNAMICLIB_QUOTE(_ ## sym), (void**)&_ ## sym } +#endif CC_API cc_result DynamicLib_Load(const cc_string* path, void** lib); /* OBSOLETE */ CC_API cc_result DynamicLib_Get(void* lib, const char* name, void** symbol); /* OBSOLETE */ diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index b5bc9f114..663476eeb 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -61,6 +61,10 @@ cc_bool Platform_SingleProcess; /* TODO: Use load_image/resume_thread instead of fork */ /* Otherwise opening browser never works because fork fails */ #include +#elif defined CC_BUILD_OS2 +#include +#define INCL_DOSPROCESS +#include #endif @@ -263,18 +267,31 @@ cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCall static cc_result File_Do(cc_file* file, const cc_string* path, int mode) { char str[NATIVE_STR_LEN]; String_EncodeUtf8(str, path); + *file = open(str, mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); return *file == -1 ? errno : 0; } cc_result File_Open(cc_file* file, const cc_string* path) { +#if !defined CC_BUILD_OS2 return File_Do(file, path, O_RDONLY); +#else + return File_Do(file, path, O_RDONLY | O_BINARY); +#endif } cc_result File_Create(cc_file* file, const cc_string* path) { +#if !defined CC_BUILD_OS2 return File_Do(file, path, O_RDWR | O_CREAT | O_TRUNC); +#else + return File_Do(file, path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY); +#endif } cc_result File_OpenOrCreate(cc_file* file, const cc_string* path) { +#if !defined CC_BUILD_OS2 return File_Do(file, path, O_RDWR | O_CREAT); +#else + return File_Do(file, path, O_RDWR | O_CREAT | O_BINARY); +#endif } cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) { @@ -518,6 +535,11 @@ void Platform_LoadSysFonts(void) { static const cc_string dirs[] = { String_FromConst("/res/fonts") }; +#elif defined CC_BUILD_OS2 + static const cc_string dirs[] = { + String_FromConst("/@unixroot/usr/share/fonts"), + String_FromConst("/@unixroot/usr/local/share/fonts") + }; #else static const cc_string dirs[] = { String_FromConst("/usr/share/fonts"), @@ -533,6 +555,10 @@ void Platform_LoadSysFonts(void) { /*########################################################################################################################* *---------------------------------------------------------Socket----------------------------------------------------------* *#########################################################################################################################*/ +#if defined CC_BUILD_OS2 +#undef AF_INET6 +#endif + union SocketAddress { struct sockaddr raw; struct sockaddr_in v4; @@ -865,6 +891,16 @@ static cc_result Process_RawGetExePath(char* path, int* len) { *len = file.length; return 0; } +#elif defined CC_BUILD_OS2 +static cc_result Process_RawGetExePath(char* path, int* len) { + PPIB pib; + DosGetInfoBlocks(NULL, &pib); + if (pib && pib->pib_pchcmd) { + Mem_Copy(path, pib->pib_pchcmd, strlen(pib->pib_pchcmd)); + *len = strlen(pib->pib_pchcmd); + } + return 0; +} #endif @@ -1064,7 +1100,8 @@ void* DynamicLib_Load2(const cc_string* path) { } void* DynamicLib_Get2(void* lib, const char* name) { - return dlsym(lib, name); + void *result = dlsym(lib, name); + return result; } cc_bool DynamicLib_DescribeError(cc_string* dst) { diff --git a/src/Window_SDL.c b/src/Window_SDL.c index e026e32d7..8360878d5 100644 --- a/src/Window_SDL.c +++ b/src/Window_SDL.c @@ -9,7 +9,34 @@ #include static SDL_Window* win_handle; -#warning "Some features are missing from the SDL2 backend. If possible, it is recommended that you use a native windowing backend instead" +#ifndef CC_BUILD_OS2 +#error "Some features are missing from the SDL backend. If possible, it is recommended that you use a native windowing backend instead" +#else +#define INCL_PM +#include +// Internal OS/2 driver data +typedef struct _WINDATA { + SDL_Window *window; + void *pOutput; /* Video output routines */ + HWND hwndFrame; + HWND hwnd; + PFNWP fnUserWndProc; + PFNWP fnWndFrameProc; + + void *pVOData; /* Video output data */ + + HRGN hrgnShape; + HPOINTER hptrIcon; + RECTL rectlBeforeFS; + + LONG lSkipWMSize; + LONG lSkipWMMove; + LONG lSkipWMMouseMove; + LONG lSkipWMVRNEnabled; + LONG lSkipWMAdjustFramePos; +} WINDATA; +#endif + static void RefreshWindowBounds(void) { SDL_GetWindowSize(win_handle, &Window_Main.Width, &Window_Main.Height); @@ -51,7 +78,11 @@ static void DoCreateWindow(int width, int height, int flags) { /* TODO grab using SDL_SetWindowGrab? seems to be unnecessary on Linux at least */ } void Window_Create2D(int width, int height) { DoCreateWindow(width, height, 0); } +#if !defined CC_BUILD_SOFTGPU void Window_Create3D(int width, int height) { DoCreateWindow(width, height, SDL_WINDOW_OPENGL); } +#else +void Window_Create3D(int width, int height) { DoCreateWindow(width, height, 0); } +#endif void Window_SetTitle(const cc_string* title) { char str[NATIVE_STR_LEN]; @@ -280,11 +311,53 @@ static void ShowDialogCore(const char* title, const char* msg) { } cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { +#if defined CC_BUILD_OS2 + FILEDLG fileDialog; + HWND hDialog; + + memset(&fileDialog, 0, sizeof(FILEDLG)); + fileDialog.cbSize = sizeof(FILEDLG); + fileDialog.fl = FDS_HELPBUTTON | FDS_CENTER | FDS_PRELOAD_VOLINFO | FDS_OPEN_DIALOG; + fileDialog.pszTitle = args->description; + fileDialog.pszOKButton = NULL; + fileDialog.pfnDlgProc = WinDefFileDlgProc; + + Mem_Copy(fileDialog.szFullFile, *args->filters, CCHMAXPATH); + hDialog = WinFileDlg(HWND_DESKTOP, 0, &fileDialog); + if (fileDialog.lReturn == DID_OK) { + cc_string temp = String_FromRaw(fileDialog.szFullFile, CCHMAXPATH); + args->Callback(&temp); + } + + return 0; +#else return ERR_NOT_SUPPORTED; +#endif } cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { +#if defined CC_BUILD_OS2 + FILEDLG fileDialog; + HWND hDialog; + + memset(&fileDialog, 0, sizeof(FILEDLG)); + fileDialog.cbSize = sizeof(FILEDLG); + fileDialog.fl = FDS_HELPBUTTON | FDS_CENTER | FDS_PRELOAD_VOLINFO | FDS_SAVEAS_DIALOG; + fileDialog.pszTitle = args->titles; + fileDialog.pszOKButton = NULL; + fileDialog.pfnDlgProc = WinDefFileDlgProc; + + Mem_Copy(fileDialog.szFullFile, *args->filters, CCHMAXPATH); + hDialog = WinFileDlg(HWND_DESKTOP, 0, &fileDialog); + if (fileDialog.lReturn == DID_OK) { + cc_string temp = String_FromRaw(fileDialog.szFullFile, CCHMAXPATH); + args->Callback(&temp); + } + + return 0; +#else return ERR_NOT_SUPPORTED; +#endif } static SDL_Surface* win_surface; @@ -395,5 +468,6 @@ void GLContext_SetFpsLimit(cc_bool vsync, float minFrameMs) { SDL_GL_SetSwapInterval(vsync); } void GLContext_GetApiInfo(cc_string* info) { } + #endif #endif