S3 ViRGE fixes by TC995 and switched threads on Windows builds back to Win32 threads since the C++ threads were breaking the ViRGE blitting in some cases (eg. CD Gamer on 24 bpp).
This commit is contained in:
@@ -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()
|
||||
|
||||
|
||||
179
src/qt/win_thread.c
Normal file
179
src/qt/win_thread.c
Normal file
@@ -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, <http://pcem-emulator.co.uk/>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2017-2018 Fred N. van Kempen.
|
||||
*/
|
||||
#define UNICODE
|
||||
#define BITMAP WINDOWS_BITMAP
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <process.h>
|
||||
#undef BITMAP
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user