More work on getting Java to run. Still not there.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 01 Nov 2016 21:38:48 -0400
changeset 74 50eae5a78040
parent 73 b8295997c8d2
child 75 d6286f62f959
More work on getting Java to run. Still not there.
lx_loader.h
native/doscalls.c
native/nls.c
native/nls.h
native/sesmgr.c
native/sesmgr.h
--- a/lx_loader.h	Tue Nov 01 21:37:57 2016 -0400
+++ b/lx_loader.h	Tue Nov 01 21:38:48 2016 -0400
@@ -13,10 +13,12 @@
 typedef uint8_t uint8;
 typedef uint16_t uint16;
 typedef uint32_t uint32;
+typedef uint64_t uint64;
 
 typedef int8_t sint8;
 typedef int16_t sint16;
 typedef int32_t sint32;
+typedef int64_t sint64;
 
 typedef unsigned int uint;
 
--- a/native/doscalls.c	Tue Nov 01 21:37:57 2016 -0400
+++ b/native/doscalls.c	Tue Nov 01 21:38:48 2016 -0400
@@ -1,4 +1,4 @@
-#include "os2native.h"
+#include "os2native16.h"
 #include "doscalls.h"
 
 #include <unistd.h>
@@ -36,6 +36,17 @@
 // This is also undocumented (no idea about this at all, including function params). Of course, Java uses it.
 APIRET DosR3ExitAddr(void);
 
+// These are 16-bit APIs that aren't in the 4.5 toolkit headers. Yeah, Java uses them! Winging it.
+typedef int HSEM16, *PHSEM16;
+static APIRET16 DosSemRequest(PHSEM16 sem, LONG ms);
+static APIRET16 DosSemClear(PHSEM16 sem);
+static APIRET16 DosSemWait(PHSEM16 sem, LONG ms);
+static APIRET16 DosSemSet(PHSEM16 sem);
+static APIRET16 bridge16to32_DosSemRequest(uint8 *args);
+static APIRET16 bridge16to32_DosSemClear(uint8 *args);
+static APIRET16 bridge16to32_DosSemWait(uint8 *args);
+static APIRET16 bridge16to32_DosSemSet(uint8 *args);
+
 
 static pthread_mutex_t GMutexDosCalls;
 
@@ -117,6 +128,13 @@
 static DirFinder GHDir1;
 
 
+LX_NATIVE_MODULE_16BIT_SUPPORT()
+    LX_NATIVE_MODULE_16BIT_API(DosSemRequest)
+    LX_NATIVE_MODULE_16BIT_API(DosSemClear)
+    LX_NATIVE_MODULE_16BIT_API(DosSemWait)
+    LX_NATIVE_MODULE_16BIT_API(DosSemSet)
+LX_NATIVE_MODULE_16BIT_SUPPORT_END()
+
 LX_NATIVE_MODULE_DEINIT({
     GLoaderState->dosExit = NULL;
 
@@ -137,10 +155,19 @@
     MaxHFiles = 0;
 
     pthread_mutex_destroy(&GMutexDosCalls);
+
+    LX_NATIVE_MODULE_DEINIT_16BIT_SUPPORT();
 })
 
 static int initDoscalls(void)
 {
+    LX_NATIVE_MODULE_INIT_16BIT_SUPPORT()
+        LX_NATIVE_INIT_16BIT_BRIDGE(DosSemRequest, 8)
+        LX_NATIVE_INIT_16BIT_BRIDGE(DosSemClear, 4)
+        LX_NATIVE_INIT_16BIT_BRIDGE(DosSemWait, 8)
+        LX_NATIVE_INIT_16BIT_BRIDGE(DosSemSet, 4)
+    LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END()
+
     GLoaderState->dosExit = DosExit;
 
     if (pthread_mutex_init(&GMutexDosCalls, NULL) == -1) {
@@ -183,6 +210,10 @@
 } // initDoscalls
 
 LX_NATIVE_MODULE_INIT({ if (!initDoscalls()) return NULL; })
+    LX_NATIVE_EXPORT16(DosSemRequest, 140),
+    LX_NATIVE_EXPORT16(DosSemClear, 141),
+    LX_NATIVE_EXPORT16(DosSemWait, 142),
+    LX_NATIVE_EXPORT16(DosSemSet, 143),
     LX_NATIVE_EXPORT(DosSetMaxFH, 209),
     LX_NATIVE_EXPORT(DosSetPathInfo, 219),
     LX_NATIVE_EXPORT(DosQueryPathInfo, 223),
@@ -2861,5 +2892,108 @@
 	".size	_DosSelToFlat, .-_DosSelToFlat  \n\t"
 );
 
+static inline int trySpinLock(int *lock)
+{
+    return (__sync_lock_test_and_set(lock, 1) == 0);
+} // trySpinLock
+
+static APIRET16 DosSemRequest(PHSEM16 sem, LONG ms)
+{
+    TRACE_NATIVE("DosSemRequest(%p, %u)", sem, (uint) ms);
+    if (ms == 0) {
+        return !trySpinLock(sem) ? ERROR_TIMEOUT : NO_ERROR;
+    } else if (ms < 0) {
+        while (!trySpinLock(sem))
+            usleep(1000);
+        return NO_ERROR;
+    }
+
+    struct timespec ts;
+
+    clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+    const uint64 end = (((uint64) ts.tv_sec) * 1000) + (((uint64) ts.tv_nsec) / 1000000) + ms;
+
+    while (1) {
+        if (trySpinLock(sem))
+            return NO_ERROR;
+        clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+        const uint64 now = (((uint64) ts.tv_sec) * 1000) + (((uint64) ts.tv_nsec) / 1000000);
+        if (now >= end)
+            return ERROR_TIMEOUT;
+        usleep(1000);
+    } // while
+
+    return NO_ERROR;
+} // DosSemRequest
+
+static APIRET16 DosSemClear(PHSEM16 sem)
+{
+    TRACE_NATIVE("DosSemClear(%p)", sem);
+    __sync_lock_release(sem);
+    return NO_ERROR;
+} // DosSemClear
+
+static APIRET16 DosSemWait(PHSEM16 sem, LONG ms)
+{
+    TRACE_NATIVE("DosSemWait(%p, %u)", sem, (uint) ms);
+    if (ms == 0) {
+        return __sync_bool_compare_and_swap(sem, 0, 1) ? NO_ERROR : ERROR_TIMEOUT;
+    } else if (ms < 0) {
+        while (!__sync_bool_compare_and_swap(sem, 0, 1))
+            usleep(1000);
+        return NO_ERROR;
+    }
+
+    struct timespec ts;
+
+    clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+    const uint64 end = (((uint64) ts.tv_sec) * 1000) + (((uint64) ts.tv_nsec) / 1000000) + ms;
+
+    while (1) {
+        if (__sync_bool_compare_and_swap(sem, 0, 1))
+            return NO_ERROR;
+        clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+        const uint64 now = (((uint64) ts.tv_sec) * 1000) + (((uint64) ts.tv_nsec) / 1000000);
+        if (now >= end)
+            return ERROR_TIMEOUT;
+        usleep(1000);
+    } // while
+
+    return NO_ERROR;
+} // DosSemWait
+
+static APIRET16 DosSemSet(PHSEM16 sem)
+{
+    TRACE_NATIVE("DosSemSet(%p)", sem);
+    __sync_bool_compare_and_swap(sem, 1, 0);
+    return NO_ERROR;
+} // DosSemSet
+
+static APIRET16 bridge16to32_DosSemRequest(uint8 *args)
+{
+    LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(LONG, ms);
+    LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PHSEM16, sem);
+    return DosSemRequest(sem, ms);
+} // bridge16to32_DosSemRequest
+
+static APIRET16 bridge16to32_DosSemClear(uint8 *args)
+{
+    LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PHSEM16, sem);
+    return DosSemClear(sem);
+} // bridge16to32_DosSemClear
+
+static APIRET16 bridge16to32_DosSemWait(uint8 *args)
+{
+    LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(LONG, ms);
+    LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PHSEM16, sem);
+    return DosSemWait(sem, ms);
+} // bridge16to32_DosSemWait
+
+static APIRET16 bridge16to32_DosSemSet(uint8 *args)
+{
+    LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PHSEM16, sem);
+    return DosSemSet(sem);
+} // bridge16to32_DosSemSet
+
 // end of doscalls.c ...
 
--- a/native/nls.c	Tue Nov 01 21:37:57 2016 -0400
+++ b/native/nls.c	Tue Nov 01 21:38:48 2016 -0400
@@ -26,8 +26,49 @@
     return NO_ERROR;
 } // DosMapCase
 
+APIRET DosQueryCtryInfo(ULONG cb, PCOUNTRYCODE pcc, PCOUNTRYINFO pci, PULONG pcbActual)
+{
+    // From the 4.5 toolkit docs: "If this area is too small to hold all of
+    //  the available information, then as much information as possible is
+    //  provided in the available space (in the order in which the data would
+    //  appear)."  ...so we fill in a local struct and memcpy it at the end.
+    COUNTRYINFO ci;
+    memset(&ci, '\0', sizeof (ci));
+
+    // From the 4.5 toolkit docs: "If the amount of data returned is not
+    //  enough to fill the memory area provided by the caller, then the memory
+    //  that is unaltered by the available data is zeroed out." ...so blank
+    //  it all out now.
+    memset(pci, '\0', cb);
+
+    if ((pcc->country != 0) || (pcc->codepage != 0))
+        return ERROR_CODE_PAGE_NOT_FOUND;
+
+    // !!! FIXME: this is just what OS/2 Warp 4.52 returns by default for my USA system.
+    ci.country = 1;
+    ci.codepage = 437;
+    ci.fsDateFmt = 0;
+    ci.szCurrency[0] = '$';
+    ci.szThousandsSeparator[0] = ',';
+    ci.szDecimal[0] = '.';
+    ci.szDateSeparator[0] = '-';
+    ci.szTimeSeparator[0] = ':';
+    ci.fsCurrencyFmt = 0;;
+    ci.cDecimalPlace = 2;
+    ci.fsTimeFmt = 0;
+    //USHORT abReserved1[2];
+    ci.szDataSeparator[0] = ',';
+    //USHORT abReserved2[5];
+
+    if (pcbActual)
+        *pcbActual = 38;  // OS/2 Warp 4.52 doesn't count the abReserved[5] at the end.
+
+    return NO_ERROR;
+} // DosQueryCtryInfo
+
 LX_NATIVE_MODULE_INIT()
     LX_NATIVE_EXPORT(DosQueryDBCSEnv, 6),
+    LX_NATIVE_EXPORT(DosQueryCtryInfo, 5),
     LX_NATIVE_EXPORT(DosMapCase, 7)
 LX_NATIVE_MODULE_INIT_END()
 
--- a/native/nls.h	Tue Nov 01 21:37:57 2016 -0400
+++ b/native/nls.h	Tue Nov 01 21:38:48 2016 -0400
@@ -7,14 +7,33 @@
 extern "C" {
 #endif
 
-typedef struct COUNTRYCODE
+typedef struct
 {
     ULONG country;
     ULONG codepage;
 } COUNTRYCODE, *PCOUNTRYCODE;
 
+typedef struct
+{
+    ULONG country;
+    ULONG codepage;
+    ULONG fsDateFmt;
+    CHAR szCurrency[5];
+    CHAR szThousandsSeparator[2];
+    CHAR szDecimal[2];
+    CHAR szDateSeparator[2];
+    CHAR szTimeSeparator[2];
+    UCHAR fsCurrencyFmt;
+    UCHAR cDecimalPlace;
+    UCHAR fsTimeFmt;
+    USHORT abReserved1[2];
+    CHAR szDataSeparator[2];
+    USHORT abReserved2[5];
+} COUNTRYINFO, *PCOUNTRYINFO;
+
 APIRET OS2API DosQueryDBCSEnv(ULONG cb, PCOUNTRYCODE pcc, PCHAR pBuf);
 APIRET OS2API DosMapCase(ULONG cb, PCOUNTRYCODE pcc, PCHAR pch);
+APIRET OS2API DosQueryCtryInfo(ULONG cb, PCOUNTRYCODE pcc, PCOUNTRYINFO pci, PULONG pcbActual);
 
 #ifdef __cplusplus
 }
--- a/native/sesmgr.c	Tue Nov 01 21:37:57 2016 -0400
+++ b/native/sesmgr.c	Tue Nov 01 21:38:48 2016 -0400
@@ -2,7 +2,15 @@
 #include "sesmgr.h"
 
 LX_NATIVE_MODULE_INIT()
+    LX_NATIVE_EXPORT(DosStartSession, 37)
 LX_NATIVE_MODULE_INIT_END()
 
+APIRET DosStartSession(PSTARTDATA psd, PULONG pidSession, PPID ppid)
+{
+    TRACE_NATIVE("DosStartSession(%p, %p, %p)", psd, pidSession, ppid);
+printf("'%s', '%s', '%s'\n", psd->PgmTitle, psd->PgmName, psd->IconFile);
+    return ERROR_NOT_ENOUGH_MEMORY;
+} // DosStartSession
+
 // end of sesmgr.c ...
 
--- a/native/sesmgr.h	Tue Nov 01 21:37:57 2016 -0400
+++ b/native/sesmgr.h	Tue Nov 01 21:38:48 2016 -0400
@@ -7,6 +7,33 @@
 extern "C" {
 #endif
 
+typedef struct
+{
+    USHORT Length;
+    USHORT Related;
+    USHORT FgBg;
+    USHORT TraceOpt;
+    PSZ PgmTitle;
+    PSZ PgmName;
+    PBYTE PgmInputs;
+    PBYTE TermQ;
+    PBYTE Environment;
+    USHORT InheritOpt;
+    USHORT SessionType;
+    PSZ IconFile;
+    ULONG PgmHandle;
+    USHORT PgmControl;
+    USHORT InitXPos;
+    USHORT InitYPos;
+    USHORT InitXSize;
+    USHORT InitYSize;
+    USHORT Reserved;
+    PSZ ObjectBuffer;
+    ULONG ObjectBuffLen;
+} STARTDATA, *PSTARTDATA;
+
+APIRET OS2API DosStartSession(PSTARTDATA psd, PULONG pidSession, PPID ppid);
+
 #ifdef __cplusplus
 }
 #endif