mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 18:08:20 -07:00
Accumulated changes. Update copyright year in anticipation of 2025. More PGRAPH stuff. Start working on guest CPU independent timer (RivaTimer) but not really tested or used yet. Add more docs
This commit is contained in:
24
doc/RIVA fansites.txt
Normal file
24
doc/RIVA fansites.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
RIVA fansites (?????):
|
||||
RIVA User's Group http://tiger.tnstate.edu:8080/
|
||||
RIVA 128 Homepage http://pages.prodigy.net/babblin5/Main.html -> Riva3D (riva3d.com)
|
||||
Zone 128 http://www.tc.umn.edu/~reda0003/zone128/
|
||||
RIVAZone https://web.archive.org/web/19981212032348/http://www.rivazone.com/ (Launched January 2, 1998)
|
||||
Dimension 128 (early domain name that was never archived) -> d128.com (1999-2001)
|
||||
Riva3D https://web.archive.org/web/20000525110305/http://riva3d.gxnetwork.com/s3.html
|
||||
nVNews https://web.archive.org/web/20001205171202/http://www.nvnews.net/ (1999-2015)
|
||||
|
||||
BluesNews has stuff https://www.bluesnews.com/archives/
|
||||
(July 1996-present!)
|
||||
|
||||
https://www.bluesnews.com/archives/july97-3.html July 21, 1997 ("unreleased nvidia RIVA chipset is indeed faster than 3dfx" (carmack)
|
||||
|
||||
"However, using the nvidia RIVA 128 chip it runs 1 f/s faster"
|
||||
|
||||
https://web.archive.org/web/19980615024744/http://www.ogr.com/columns/techtalk/technology_talk_0611_2.shtml First mention of NV10 (June 1998)
|
||||
|
||||
"RIVA 128 Turbo" early ZX name
|
||||
"Riva4" early TNT name
|
||||
|
||||
https://web.archive.org/web/20001002193706/http://www.rivazone.com/files/rivalog.txt
|
||||
|
||||
https://web.archive.org/web/20010422044820/http://www.rivazone.com/finger/finger.cgi?nick@finger.nvidia.com nvidia .plan files
|
||||
8
doc/Versions.txt
Normal file
8
doc/Versions.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Name Base Version Notes Date API Support Platform
|
||||
0.75_nt4 Version 0.75 No Resource Manager (miniport) 1997-08-15 GDI NT4.0
|
||||
0.77_win9x Version 0.77 Symbols (COFF/VXD) 1997-09-02 GDI, D3D5
|
||||
nv3quake.zip Version 1.21 OpenGL Alpha 1 1997-11-14 GDI, D3D5, OpenGL 1.1 (alpha; Build 151) Win9x
|
||||
quakea2f.zip Version 1.21 OpenGL Alpha 2 1997-12-02 GDI, D3D5, OpenGL 1.1 (alpha; Build 258) Win9x
|
||||
win95_131.zip Version 1.31 OpenGL Beta 1 1998-02-04 GDI, D3D5, OpenGL 1.1 (beta; Build 661) Win9x
|
||||
|
||||
|
||||
63
doc/gpucompanies.txt
Normal file
63
doc/gpucompanies.txt
Normal file
@@ -0,0 +1,63 @@
|
||||
GPU companies (the period they made gpus)
|
||||
|
||||
DEC 19xx-1998
|
||||
HP 19xx-2000+ (possibly until present)
|
||||
IBM 19xx-2002+ (possibly until present)
|
||||
E&S 1968-2006
|
||||
Intergraph 1969-2000
|
||||
Apple 1976-present (some break)
|
||||
Motorola 1977-1994+ (???)
|
||||
TI 1979-1988+
|
||||
Matrox 1979-2014
|
||||
Hitachi 1981-1986
|
||||
SGI 1981-2009
|
||||
Intel 1983-present
|
||||
Number Nine 1983-2000
|
||||
Tseng Labs 1983-1997
|
||||
Cirrus Logic 1984-1998
|
||||
Video 7 1985-1991
|
||||
C&T 1985-1999
|
||||
Imagination 1985-present
|
||||
NCR 1986-1993
|
||||
Paradise/WD 1986-1996
|
||||
Gemini 1987-1990
|
||||
Genoa Systems 1987-1991
|
||||
Trident 1987-2003
|
||||
Oak Technology 1988-1997
|
||||
Realtek 1988-1997
|
||||
Compaq 1989-1991
|
||||
Sun 1989-2002(+?)
|
||||
S3 Graphics 1989-2010
|
||||
Macronix 1989-1998
|
||||
Winbond 1989-1996+
|
||||
Tamarack 198x-1991+
|
||||
UMC 198x-1993
|
||||
Sigma Designs 198x-1996
|
||||
Acer 198x-1998 (roughly)
|
||||
Fujitsu 198x-1998
|
||||
AMD 1991-present (really starting in 2006)
|
||||
HMC 1991-1994
|
||||
Avance Logic 1991-1995
|
||||
Weitek <1991-1996
|
||||
Bitboys 1991-2006
|
||||
IIT 1992-1994
|
||||
Weitek 1992-1996(?)
|
||||
Rendition 1993-1998
|
||||
ARK Logic 1993-1999
|
||||
S-MOS/Stellar 1994-1999
|
||||
Nvidia 1993-present
|
||||
Alliance 1994-1997
|
||||
iGS 1994-1999
|
||||
3dfx 1994-2000
|
||||
3dlabs 1994-2006
|
||||
Silicon Motion 1995-200?
|
||||
SiS 1995-2007
|
||||
Dynamic Pictures1996-1997
|
||||
NeoMagic 1996-2000
|
||||
GigaPixel 1997-2000
|
||||
Philips 1997-199x
|
||||
Tatung 199x-199x
|
||||
ASPEED 2004-present
|
||||
Jingjia 2006-present
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
#include <86box/machine_status.h>
|
||||
#include <86box/apm.h>
|
||||
#include <86box/acpi.h>
|
||||
#include <86box/nv/vid_nv_rivatimer.h>
|
||||
|
||||
// Disable c99-designator to avoid the warnings about int ng
|
||||
#ifdef __clang__
|
||||
@@ -1421,6 +1422,9 @@ pc_run(void)
|
||||
pc_reset_hard_init();
|
||||
}
|
||||
|
||||
/* Update the guest-CPU independent timer for devices with independent clock speed */
|
||||
rivatimer_update_all();
|
||||
|
||||
/* Run a block of code. */
|
||||
startblit();
|
||||
cpu_exec((int32_t) cpu_s->rspeed / 100);
|
||||
|
||||
@@ -318,14 +318,30 @@ extern const device_config_t nv3_config[];
|
||||
#define NV3_PGRAPH_CONTEXT_USER 0x400194 // Current DMA context state, may rename
|
||||
#define NV3_PGRAPH_CONTEXT_CACHE(i) 0x4001A0+(i*4) // Context Cache
|
||||
#define NV3_PGRAPH_CONTEXT_CACHE_SIZE 8
|
||||
#define NV3_PGRAPH_SRC_CANVAS_MIN 0x440550 // Minimum Source Canvas for Blit, X,Y position
|
||||
#define NV3_PGRAPH_SRC_CANVAS_MAX 0x440554 // Maximum Source Canvas for Blit, X,Y position
|
||||
#define NV3_PGRAPH_DST_CANVAS_MIN 0x440558 // Minimum Destination Canvas for Blit, X,Y position
|
||||
#define NV3_PGRAPH_DST_CANVAS_MAX 0x44055C // Maximum Destination Canvas for Blit, X,Y position
|
||||
#define NV3_PGRAPH_CLIP0_MIN 0x440690 // Clip for Blitting 0 Min
|
||||
#define NV3_PGRAPH_CLIP0_MAX 0x440694 // Clip for Blitting 0 Max
|
||||
#define NV3_PGRAPH_CLIP1_MIN 0x440698 // Clip for Blitting 1 Min
|
||||
#define NV3_PGRAPH_CLIP1_MAX 0x44069C // Clip for Blitting 1 Max
|
||||
#define NV3_PGRAPH_ABS_UCLIP_XMIN 0x40053C // Clip X minimum
|
||||
#define NV3_PGRAPH_ABS_UCLIP_XMAX 0x400540 // Clip X maximum
|
||||
#define NV3_PGRAPH_ABS_UCLIP_YMIN 0x400544 // Clip Y minimum
|
||||
#define NV3_PGRAPH_ABS_UCLIP_YMAX 0x400548 // Clip Y maximum
|
||||
#define NV3_PGRAPH_SRC_CANVAS_MIN 0x400550 // Minimum Source Canvas for Blit, X,Y position
|
||||
#define NV3_PGRAPH_SRC_CANVAS_MAX 0x400554 // Maximum Source Canvas for Blit, X,Y position
|
||||
#define NV3_PGRAPH_DST_CANVAS_MIN 0x400558 // Minimum Destination Canvas for Blit, X,Y position
|
||||
#define NV3_PGRAPH_DST_CANVAS_MAX 0x40055C // Maximum Destination Canvas for Blit, X,Y position
|
||||
#define NV3_PGRAPH_PATTERN_COLOR_0_0 0x400600
|
||||
#define NV3_PGRAPH_PATTERN_COLOR_0_1 0x400604
|
||||
#define NV3_PGRAPH_PATTERN_COLOR_1_0 0x400608
|
||||
#define NV3_PGRAPH_PATTERN_COLOR_1_1 0x40060C // pattern color
|
||||
#define NV3_PGRAPH_PATTERN_BITMAP_HIGH 0x400610 // pattern bitmap [31:0]
|
||||
#define NV3_PGRAPH_PATTERN_BITMAP_LOW 0x400614 // pattern bitmap [63:32]
|
||||
#define NV3_PGRAPH_PATTERN_SHAPE 0x400618
|
||||
#define NV3_PGRAPH_ROP3 0x400624 // ROP3
|
||||
#define NV3_PGRAPH_PLANE_MASK 0x400628
|
||||
#define NV3_PGRAPH_CHROMA_KEY 0x40062C
|
||||
#define NV3_PGRAPH_BETA 0x400640 // Beta factor (30:23 fractional, 22:0 before fraction)
|
||||
#define NV3_PGRAPH_NOTIFY 0x400684 // Notifier for PGRAPH
|
||||
#define NV3_PGRAPH_CLIP0_MIN 0x400690 // Clip for Blitting 0 Min
|
||||
#define NV3_PGRAPH_CLIP0_MAX 0x400694 // Clip for Blitting 0 Max
|
||||
#define NV3_PGRAPH_CLIP1_MIN 0x400698 // Clip for Blitting 1 Min
|
||||
#define NV3_PGRAPH_CLIP1_MAX 0x40069C // Clip for Blitting 1 Max
|
||||
#define NV3_PGRAPH_FIFO_ACCESS 0x4006A4 // Is PGRAPH enabled?
|
||||
#define NV3_PGRAPH_FIFO_ACCESS_DISABLED 0x0
|
||||
#define NV3_PGRAPH_FIFO_ACCESS_ENABLED 0x1
|
||||
@@ -335,6 +351,8 @@ extern const device_config_t nv3_config[];
|
||||
#define NV3_PGRAPH_TRAPPED_DATA 0x4006B8
|
||||
#define NV3_PGRAPH_TRAPPED_INSTANCE 0x4006BC
|
||||
|
||||
#define NV3_PGRAPH_DMA_INTR_0 0x401000 // PGRAPH DMA Interrupt Status
|
||||
#define NV3_PGRAPH_DMA_INTR_EN_0 0x401140 // PGRAPH DMA Interrupt Enable 0
|
||||
|
||||
// not sure about the class ids
|
||||
// these are NOT what each class is, just uSed to manipulate it (there isn't a one to one class->reg mapping anyway)
|
||||
|
||||
83
src/include/86box/nv/vid_nv_rivatimer.h
Normal file
83
src/include/86box/nv/vid_nv_rivatimer.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Fast, high-frequency, guest CPU-independent timer for Riva emulation.
|
||||
*
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
/*
|
||||
RivaTimer
|
||||
|
||||
This is a fast, high-frequency, guest CPU-independent timer.
|
||||
|
||||
The main 86box timer is dependent on the TSC (time-stamp counter) register of the emulated CPU core.
|
||||
This is fine for most purposes and has advantages in the fields of synchronisation and integrates neatly with
|
||||
the clock dividers of the PC architecture, but in the case of the RIVA 128 it does not particularly suffice
|
||||
(although it can be made to work with various techniques) since the clock source on the RIVA 128 is on the board itself
|
||||
and the GPU has several different clocks that control different parts of the GPU (e.g., PTIMER runs on the memory clock but the core gpu is using the pixel clock).
|
||||
|
||||
As faster graphics cards that offload more and more of the 3D graphics pipeline are emulated in the future, more and more work needs to be done by the emulator and
|
||||
issues of synchronisation with a host CPU will simply make that work harder. Some features that are required for
|
||||
|
||||
Architecture Brand Name 3D Features
|
||||
NV1 (1995) NV1 Some weird URBS rectangle crap but feature set generally similar to nv3 but a bit worse
|
||||
NV3 (1997) RIVA 128 (ZX) Triangle setup, edge-slope calculations, edge interpolation, span-slope calculations, span interpolation (Color-buffer, z-buffer, texture mapping, filtering)
|
||||
NV4 (1998) RIVA TNT NV3 + 2x1 pixel pipelines + 32-bit colour + larger textures + trilinear + more ram (16mb)
|
||||
NV5 (1999) RIVA TNT2 NV4 + higher clock speed
|
||||
NV10 (1999) GeForce 256 NV5 + initial geometry transformation + lighting (8x lights) + MPEG-2 motion compensation + 4x1 pixel pipelines
|
||||
NV15 (2000) GeForce 2 NV10 + First attempt at programmability + 4x2 pixel pipelines
|
||||
NV20 (2001) GeForce 3 Programmable shaders!
|
||||
|
||||
As you can see, the performance basically exponentially increases over a period of only 4 years.
|
||||
|
||||
So I decided to create this timer that is completely separate from the CPU Core.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <86Box\86box.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
// Linux & MacOS should have the same API since OSX 10.12
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
typedef struct rivatimer_s
|
||||
{
|
||||
struct rivatimer_s* prev; // Previous Rivatimer
|
||||
double period; // Period in uS before firing
|
||||
double value; // The current value of the rivatimer
|
||||
bool running; // Is this RivaTimer running?
|
||||
struct rivatimer_s* next; // Next RivaTimer
|
||||
void (*callback)(); // Callback to call on fire
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER starting_time; // Starting time.
|
||||
#else
|
||||
struct timespec starting_time; // Starting time.
|
||||
#endif
|
||||
double time; // Accumulated time in uS.
|
||||
} rivatimer_t;
|
||||
|
||||
void rivatimer_init(); // Initialise the Rivatimer.
|
||||
rivatimer_t* rivatimer_create(double period, void (*callback)());
|
||||
void rivatimer_destroy(rivatimer_t* rivatimer_ptr);
|
||||
|
||||
void rivatimer_update_all();
|
||||
void rivatimer_start(rivatimer_t* rivatimer_ptr);
|
||||
void rivatimer_stop(rivatimer_t* rivatimer_ptr);
|
||||
double rivatimer_get_time(rivatimer_t* rivatimer_ptr);
|
||||
void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)());
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86Box/nv/vid_nv_rivatimer.h>
|
||||
|
||||
uint64_t TIMER_USEC;
|
||||
uint32_t timer_target;
|
||||
@@ -168,6 +169,9 @@ timer_init(void)
|
||||
timer_target = 0ULL;
|
||||
tsc = 0;
|
||||
|
||||
/* Initialise the CPU-independent timer */
|
||||
rivatimer_init();
|
||||
|
||||
timer_inited = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c
|
||||
vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_mga.c vid_nga.c
|
||||
vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c
|
||||
vid_bochs_vbe.c
|
||||
nv/nv_base.c
|
||||
nv/nv3/nv3_core.c nv/nv3/nv3_core_config.c nv/nv3/nv3_core_arbiter.c nv/nv3/nv3_interrupt.c
|
||||
nv/nv_base.c nv/nv_rivatimer.c
|
||||
nv/nv3/nv3_core.c nv/nv3/nv3_core_config.c nv/nv3/nv3_core_arbiter.c
|
||||
nv/nv3/subsystems/nv3_pramdac.c
|
||||
nv/nv3/subsystems/nv3_pfifo.c
|
||||
nv/nv3/subsystems/nv3_pgraph.c
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
// STANDARD NV3 includes
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email dataess ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
// nv3_pramdac.c: NV3 RAMDAC
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024 starfrost
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
// Common NV1/3/4... init
|
||||
|
||||
248
src/video/nv/nv_rivatimer.c
Normal file
248
src/video/nv/nv_rivatimer.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Fast, high-frequency, CPU-independent timer.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
/* See vid_nv_rivatimer.h comments for rationale behind not using the regular timer system
|
||||
|
||||
Notes applicable to this file:
|
||||
Since Windows XP, QueryPerformanceCounter and QueryPerformanceFrequency cannot fail so they are not checked.
|
||||
|
||||
*/
|
||||
|
||||
#include <86Box/nv/vid_nv_rivatimer.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER performance_frequency;
|
||||
#endif
|
||||
|
||||
rivatimer_t* rivatimer_head; // The head of the rivatimer list.
|
||||
rivatimer_t* rivatimer_tail; // The tail of the rivatimer list.
|
||||
|
||||
/* Functions only used in this translation unit */
|
||||
bool rivatimer_really_exists(rivatimer_t* rivatimer); // Determine if a rivatimer really exists in the linked list.
|
||||
|
||||
void rivatimer_init()
|
||||
{
|
||||
// Destroy all the rivatimers.
|
||||
rivatimer_t* rivatimer_ptr = rivatimer_head;
|
||||
|
||||
if (!rivatimer_ptr)
|
||||
return;
|
||||
|
||||
while (rivatimer_ptr->next)
|
||||
rivatimer_destroy(rivatimer_ptr);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Query the performance frequency.
|
||||
QueryPerformanceFrequency(&performance_frequency);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Creates a rivatimer.
|
||||
rivatimer_t* rivatimer_create(double period, void (*callback)())
|
||||
{
|
||||
rivatimer_t* new_rivatimer = NULL;
|
||||
|
||||
// See i
|
||||
if (period <= 0
|
||||
|| !callback)
|
||||
{
|
||||
fatal("Invalid rivatimer_create call: period <= 0 or no callback");
|
||||
}
|
||||
|
||||
// If there are no rivatimers, create one
|
||||
if (!rivatimer_head)
|
||||
{
|
||||
rivatimer_head = calloc(1, sizeof(rivatimer_t));
|
||||
rivatimer_head->prev = NULL; // indicate this is the first in the list even if we don't strictly need to
|
||||
rivatimer_tail = rivatimer_head;
|
||||
new_rivatimer = rivatimer_head;
|
||||
}
|
||||
else // Otherwise add a new one to the list
|
||||
{
|
||||
rivatimer_tail->next = calloc(1, sizeof(rivatimer_t));
|
||||
rivatimer_tail = rivatimer_tail->next;
|
||||
new_rivatimer = rivatimer_tail;
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if (new_rivatimer)
|
||||
{
|
||||
new_rivatimer->running = false;
|
||||
new_rivatimer->period = period;
|
||||
new_rivatimer->next = NULL; // indicate this is the last in the list
|
||||
new_rivatimer->callback = callback;
|
||||
}
|
||||
|
||||
return new_rivatimer;
|
||||
}
|
||||
|
||||
// Determines if a rivatimer really exists.
|
||||
bool rivatimer_really_exists(rivatimer_t* rivatimer)
|
||||
{
|
||||
rivatimer_t* current = rivatimer_head;
|
||||
|
||||
if (!current)
|
||||
return false;
|
||||
|
||||
while (current->next != NULL)
|
||||
{
|
||||
if (current == rivatimer)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Destroy a rivatimer.
|
||||
void rivatimer_destroy(rivatimer_t* rivatimer_ptr)
|
||||
{
|
||||
if (!rivatimer_really_exists(rivatimer_ptr))
|
||||
fatal("rivatimer_destroy: The timer was already destroyed, or never existed in the first place. Punch starfrost in the face");
|
||||
|
||||
// Case: We are destroying the head
|
||||
if (rivatimer_ptr == rivatimer_head)
|
||||
{
|
||||
// This is the only rivatimer
|
||||
if (rivatimer_ptr->next == NULL)
|
||||
{
|
||||
rivatimer_head = NULL;
|
||||
rivatimer_tail = NULL;
|
||||
}
|
||||
// This is not the only rivatimer
|
||||
else
|
||||
{
|
||||
rivatimer_head = rivatimer_ptr->next;
|
||||
rivatimer_head->prev = NULL;
|
||||
// This is the only rivatimer and now there is only one
|
||||
if (!rivatimer_head->next)
|
||||
rivatimer_tail = rivatimer_head;
|
||||
}
|
||||
}
|
||||
// Case: We are destroying the tail
|
||||
else if (rivatimer_ptr == rivatimer_tail)
|
||||
{
|
||||
// We already covered the case where there is only one item above
|
||||
rivatimer_tail = rivatimer_ptr->prev;
|
||||
rivatimer_tail->next = NULL;
|
||||
}
|
||||
// Case: This is not the first or last rivatimer, so we don't need to set the head or tail
|
||||
else
|
||||
{
|
||||
// Fix the break in the chain that this
|
||||
if (rivatimer_ptr->next)
|
||||
rivatimer_ptr->prev->next = rivatimer_ptr->next;
|
||||
if (rivatimer_ptr->prev)
|
||||
rivatimer_ptr->next->prev = rivatimer_ptr->prev;
|
||||
}
|
||||
|
||||
free(rivatimer_ptr);
|
||||
rivatimer_ptr = NULL; //explicitly set to null
|
||||
}
|
||||
|
||||
void rivatimer_update_all()
|
||||
{
|
||||
rivatimer_t* rivatimer_ptr = rivatimer_head;
|
||||
|
||||
if (!rivatimer_ptr)
|
||||
return;
|
||||
|
||||
while (rivatimer_ptr->next)
|
||||
{
|
||||
if (!rivatimer_ptr->running)
|
||||
continue;
|
||||
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER current_time;
|
||||
|
||||
QueryPerformanceCounter(¤t_time);
|
||||
|
||||
double microseconds = ((double)current_time.QuadPart / 1000000.0) - (rivatimer_ptr->starting_time.QuadPart / 1000000.0);
|
||||
#else
|
||||
struct timespec current_time;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, ¤t_time);
|
||||
|
||||
double microseconds = ((double)current_time.tv_sec * 1000000.0) + ((double)current_time.tv_nsec / 1000.0);
|
||||
#endif
|
||||
|
||||
rivatimer_ptr->time += microseconds;
|
||||
|
||||
// Reset the current time so we can actually restart
|
||||
#ifdef _WIN32
|
||||
QueryPerformanceCounter(&rivatimer_ptr->starting_time);
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &rivatimer_ptr->starting_time);
|
||||
#endif
|
||||
|
||||
// Time to fire
|
||||
if (microseconds > rivatimer_ptr->period)
|
||||
{
|
||||
if (!rivatimer_ptr->callback)
|
||||
{
|
||||
pclog("Eh? No callback in RivaTimer?");
|
||||
continue;
|
||||
}
|
||||
|
||||
rivatimer_ptr->callback();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void rivatimer_start(rivatimer_t* rivatimer_ptr)
|
||||
{
|
||||
if (!rivatimer_really_exists(rivatimer_ptr))
|
||||
fatal("rivatimer_start: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face");
|
||||
|
||||
if (rivatimer_ptr->period <= 0)
|
||||
fatal("rivatimer_start: Zero period!");
|
||||
|
||||
rivatimer_ptr->running = true;
|
||||
|
||||
// Start off so rivatimer_update_all can actually update.
|
||||
#ifdef _WIN32
|
||||
QueryPerformanceCounter(&rivatimer_ptr->starting_time);
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &rivatimer_ptr->starting_time);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rivatimer_stop(rivatimer_t* rivatimer_ptr)
|
||||
{
|
||||
if (!rivatimer_really_exists(rivatimer_ptr))
|
||||
fatal("rivatimer_stop: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face");
|
||||
|
||||
rivatimer_ptr->running = false;
|
||||
}
|
||||
|
||||
// Get the current time value of a rivatimer
|
||||
double rivatimer_get_time(rivatimer_t* rivatimer_ptr)
|
||||
{
|
||||
if (!rivatimer_really_exists(rivatimer_ptr))
|
||||
fatal("rivatimer_get_time: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face");
|
||||
}
|
||||
|
||||
void rivatimer_set_callback(rivatimer_t* rivatimer_ptr, void (*callback)())
|
||||
{
|
||||
if (!rivatimer_really_exists(rivatimer_ptr))
|
||||
fatal("rivatimer_set_callback: The timer has been destroyed, or never existed in the first place. Punch starfrost in the face");
|
||||
|
||||
if (!callback)
|
||||
fatal("rivatimer_set_callback: No callback!");
|
||||
|
||||
rivatimer_ptr->callback = callback;
|
||||
}
|
||||
Reference in New Issue
Block a user