Skip to content

Commit

Permalink
VFRCRATE PITSYNC command
Browse files Browse the repository at this point in the history
  • Loading branch information
joncampbell123 committed Sep 5, 2023
1 parent 769a792 commit 20f8389
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ Next version:
- Add "VRD" debugger command to force redraw of the VGA screen.
- Add VGA debug set commands to force a video start address and another
to clear all debug settings.
- Add "PITSYNC" option to VFRCRATE command. "VFRCRATE PITSYNC ON"
directs the system timer interrupt to synchronize tick rate with
vertical refresh rate of VGA emulation if the game or demo set
the timer tick rate to a value close enough to vertical refresh.
This is intended for games or demos that use the system timer for
a vsync interrupt.

2023.09.01
- Disable by default message confirmation after snapshot and AVI video
Expand Down
16 changes: 16 additions & 0 deletions src/hardware/timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#include "setup.h"
#include "control.h"

extern bool VGA_PITsync;
extern double vga_fps;

// This is only set in PC-98 mode and only if emulating PC-9801.
// There is at least one game (PC-98 port of Thexder) that depends on PC-9801 PIT 1
// behavior where the counter cycles at all times whether or not the PC speaker is
Expand Down Expand Up @@ -308,13 +311,26 @@ static bool latched_timerstatus_locked;

unsigned long PIT_TICK_RATE = PIT_TICK_RATE_IBM;

pic_tickindex_t VGA_PITSync_delay(void);

static void PIT0_Event(Bitu /*val*/) {
PIC_ActivateIRQ(0);
/* NTS: "Days of Thunder" leaves PIT 0 in mode 1 for some reason, which triggers once and then stops. "start" does not advance in that mode.
* For any non-periodic mode, this code would falsely detect an ever increasing error and act badly. */
if (pit[0].mode == 2 || pit[0].mode == 3) {
pit[0].track_time(PIC_FullIndex());

/* If enabled option and VGA refresh rate is close to PIT 0 timer tick rate,
* make them line up so that demos that use PIT0 for vsync can run without
* shearing artifacts */
if (VGA_PITsync) {
pic_tickindex_t vga_delay = 1000.0 / vga_fps;
if (fabs(vga_delay - pit[0].delay) < (vga_delay * 0.05)) {
PIC_AddEvent(PIT0_Event,VGA_PITSync_delay());
return;
}
}

/* event timing error checking */
pic_tickindex_t err = PIC_GetCurrentEventTime() - pit[0].start;

Expand Down
12 changes: 12 additions & 0 deletions src/hardware/vga.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ void VGA_CaptureStartNextFrame(void);
void VGA_CaptureMarkError(void);
bool VGA_CaptureValidateCurrentFrame(void);

bool VGA_PITsync = false;

unsigned int vbe_window_granularity = 0;
unsigned int vbe_window_size = 0;

Expand Down Expand Up @@ -528,6 +530,13 @@ void VGA_SetCGA4Table(uint8_t val0,uint8_t val1,uint8_t val2,uint8_t val3) {
}
}

void SetPITSync(char *x) {
if (!strncasecmp(x,"off",3))
VGA_PITsync = false;
else if (!strncasecmp(x,"on",3))
VGA_PITsync = true;
}

void SetRate(char *x) {
if (!strncasecmp(x,"off",3))
vga_force_refresh_rate = -1;
Expand Down Expand Up @@ -574,11 +583,14 @@ class VFRCRATE : public Program {
WriteOut(" SET rate Lock to integer frame rate, e.g. 15\n");
WriteOut(" SET rate Lock to decimal frame rate, e.g. 29.97\n");
WriteOut(" SET rate Lock to fractional frame rate, e.g. 60000/1001\n\n");
WriteOut(" PITSYNC <ON|OFF> Make PIT timer tick at refresh rate if close enough\n\n");
WriteOut("Type VFRCRATE without a parameter to show the current status.\n");
return;
}
if (cmd->FindString("SET",temp_line,false))
SetRate((char *)temp_line.c_str());
if (cmd->FindString("PITSYNC",temp_line,false))
SetPITSync((char *)temp_line.c_str());
#if defined(USE_TTF)
if (TTF_using()) PIC_AddEvent(&resetSize, 1);
#endif
Expand Down
9 changes: 9 additions & 0 deletions src/hardware/vga_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5428,6 +5428,15 @@ void FreeRawImage(void) {
rawshot.free();
}

pic_tickindex_t VGA_PITSync_delay(void) {
pic_tickindex_t current_time = PIC_GetCurrentEventTime();
pic_tickindex_t dt = current_time - vga.draw.delay.framestart;
pic_tickindex_t et = vga.draw.delay.vrstart - dt;
if (et < (vga.draw.delay.vtotal/2.0)) et += vga.draw.delay.vtotal;
// LOG_MSG("dt %.3f et %.3f\n",double(dt),double(et));
return et;
}

static void VGA_VerticalTimer(Bitu /*val*/) {
double current_time = PIC_GetCurrentEventTime();

Expand Down

0 comments on commit 20f8389

Please sign in to comment.