diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0841fabdd..ad339040f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -27,7 +27,9 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux")
add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1)
endif()
-if(CPPTHREADS)
+if(WIN32)
+ target_sources(86Box PRIVATE qt/win_thread.c)
+else()
target_sources(86Box PRIVATE thread.cpp)
endif()
diff --git a/src/qt/win_thread.c b/src/qt/win_thread.c
new file mode 100644
index 000000000..9a4f046b3
--- /dev/null
+++ b/src/qt/win_thread.c
@@ -0,0 +1,179 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implement threads and mutexes for the Win32 platform.
+ *
+ *
+ *
+ * Authors: Sarah Walker,
+ * Fred N. van Kempen,
+ *
+ * Copyright 2008-2018 Sarah Walker.
+ * Copyright 2017-2018 Fred N. van Kempen.
+ */
+#define UNICODE
+#define BITMAP WINDOWS_BITMAP
+#include
+#include
+#include
+#undef BITMAP
+#include
+#include
+#include
+#include
+#include
+#include <86box/86box.h>
+#include <86box/plat.h>
+#include <86box/thread.h>
+
+typedef struct {
+ HANDLE handle;
+} win_event_t;
+
+/* For compatibility with thread.h, but Win32 does not allow named threads. */
+thread_t *
+thread_create_named(void (*func)(void *param), void *param, UNUSED(const char *name))
+{
+ uintptr_t bt = _beginthread(func, 0, param);
+ return ((thread_t *) bt);
+}
+
+int
+thread_test_mutex(thread_t *arg)
+{
+ if (arg == NULL)
+ return (0);
+
+ return (WaitForSingleObject(arg, 0) == WAIT_OBJECT_0) ? 1 : 0;
+}
+
+int
+thread_wait(thread_t *arg)
+{
+ if (arg == NULL)
+ return (0);
+
+ if (WaitForSingleObject(arg, INFINITE))
+ return (1);
+
+ return (0);
+}
+
+event_t *
+thread_create_event(void)
+{
+ win_event_t *ev = malloc(sizeof(win_event_t));
+
+ ev->handle = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ return ((event_t *) ev);
+}
+
+void
+thread_set_event(event_t *arg)
+{
+ win_event_t *ev = (win_event_t *) arg;
+
+ if (arg == NULL)
+ return;
+
+ SetEvent(ev->handle);
+}
+
+void
+thread_reset_event(event_t *arg)
+{
+ win_event_t *ev = (win_event_t *) arg;
+
+ if (arg == NULL)
+ return;
+
+ ResetEvent(ev->handle);
+}
+
+int
+thread_wait_event(event_t *arg, int timeout)
+{
+ win_event_t *ev = (win_event_t *) arg;
+
+ if (arg == NULL)
+ return (0);
+
+ if (ev->handle == NULL)
+ return (0);
+
+ if (timeout == -1)
+ timeout = INFINITE;
+
+ if (WaitForSingleObject(ev->handle, timeout))
+ return (1);
+
+ return (0);
+}
+
+void
+thread_destroy_event(event_t *arg)
+{
+ win_event_t *ev = (win_event_t *) arg;
+
+ if (arg == NULL)
+ return;
+
+ CloseHandle(ev->handle);
+
+ free(ev);
+}
+
+mutex_t *
+thread_create_mutex(void)
+{
+ mutex_t *mutex = malloc(sizeof(CRITICAL_SECTION));
+
+ InitializeCriticalSection(mutex);
+
+ return mutex;
+}
+
+int
+thread_wait_mutex(mutex_t *mutex)
+{
+ if (mutex == NULL)
+ return (0);
+
+ LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex;
+
+ EnterCriticalSection(critsec);
+
+ return 1;
+}
+
+int
+thread_release_mutex(mutex_t *mutex)
+{
+ if (mutex == NULL)
+ return (0);
+
+ LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex;
+
+ LeaveCriticalSection(critsec);
+
+ return 1;
+}
+
+void
+thread_close_mutex(mutex_t *mutex)
+{
+ if (mutex == NULL)
+ return;
+
+ LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex;
+
+ DeleteCriticalSection(critsec);
+
+ free(critsec);
+}
diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c
index 155380480..24f325c49 100644
--- a/src/video/vid_s3_virge.c
+++ b/src/video/vid_s3_virge.c
@@ -1804,13 +1804,34 @@ fifo_thread(void *param) {
}
static void
-s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) {
+s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type)
+{
fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK];
+ int limit = 0;
- if (FIFO_FULL) {
- thread_reset_event(virge->fifo_not_full_event);
- if (FIFO_FULL)
- thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
+ if (type == FIFO_WRITE_DWORD) {
+ switch (addr & 0xfffc) {
+ case 0xa500:
+ if (val & CMD_SET_AE)
+ limit = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (limit) {
+ if (FIFO_ENTRIES >= 16) {
+ thread_reset_event(virge->fifo_not_full_event);
+ if (FIFO_ENTRIES >= 16)
+ thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
+ }
+ } else {
+ if (FIFO_FULL) {
+ thread_reset_event(virge->fifo_not_full_event);
+ if (FIFO_FULL)
+ thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
+ }
}
fifo->val = val;
@@ -2190,13 +2211,13 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) {
for (y = 0; y < 4; y++) {
for (x = 0; x < 8; x++) {
if (virge->s3d.mono_pat_0 & (1 << (x + y * 8)))
- mono_pattern[y * 8 + x] = virge->s3d.pat_fg_clr;
+ mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_fg_clr;
else
- mono_pattern[y * 8 + x] = virge->s3d.pat_bg_clr;
+ mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_bg_clr;
if (virge->s3d.mono_pat_1 & (1 << (x + y * 8)))
- mono_pattern[(y + 4) * 8 + x] = virge->s3d.pat_fg_clr;
+ mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_fg_clr;
else
- mono_pattern[(y + 4) * 8 + x] = virge->s3d.pat_bg_clr;
+ mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_bg_clr;
}
}
}
@@ -3312,7 +3333,7 @@ tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int
state->dest_rgba.g = ((state->dest_rgba.g * a) + (s3d_tri->fog_g * (255 - a))) / 255;
state->dest_rgba.b = ((state->dest_rgba.b * a) + (s3d_tri->fog_b * (255 - a))) / 255;
}
-
+
if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) {
uint32_t src_col;
int src_r = 0;
@@ -3375,7 +3396,7 @@ tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int
virge->pixel_count++;
}
}
-
+
tri_skip_line:
state->x1 += dx1;
state->x2 += dx2;