Skip to content

Commit 0fc55a2

Browse files
authored
Merge pull request #95 from Provenance-Emu/libretro/feature/counter-accuracy
Improve counter/timer accuracy (HC, JERRY PITs)
2 parents 6b282a2 + f6aa434 commit 0fc55a2

9 files changed

Lines changed: 65 additions & 12 deletions

File tree

libretro.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,11 +347,17 @@ static void check_variables(void)
347347

348348
for (i = 0; i < 2; i++)
349349
{
350+
int j;
350351
char base[20];
351352
char key[64];
352353
size_t _len = strlcpy(base, "virtualjaguar_p", sizeof(base));
353354
snprintf(base + _len, sizeof(base) - _len, "%d", i + 1);
354355

356+
/* Initialize all retropad mappings to BUTTON_NONE so unmapped
357+
* entries don't accidentally trigger BUTTON_U (index 0). */
358+
for (j = 0; j < 24; j++)
359+
jag_retropad[i][j] = BUTTON_NONE;
360+
355361
strlcpy(key, base, sizeof(key));
356362
strlcat(key, "_numpad_to_kb", sizeof(key));
357363
var.key = key;

src/dsp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ void DSPReset(void)
822822

823823
// Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
824824
for(i=0; i<8192; i+=4)
825-
*((uint32_t *)(&dsp_ram_8[i])) = rand();
825+
*((uint32_t *)(&dsp_ram_8[i])) = JaguarRand();
826826
}
827827

828828
void DSPDone(void)

src/gpu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ void GPUReset(void)
666666

667667
// Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
668668
for(i=0; i<4096; i+=4)
669-
*((uint32_t *)(&gpu_ram_8[i])) = rand();
669+
*((uint32_t *)(&gpu_ram_8[i])) = JaguarRand();
670670
}
671671

672672
uint32_t GPUReadPC(void)

src/jaguar.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
#include <string.h>
1717
#include <stdlib.h>
1818

19-
#include <time.h>
20-
2119
#include "jaguar.h"
2220

2321
#include "cdrom.h"
@@ -35,6 +33,24 @@
3533

3634
static bool frameDone;
3735

36+
// Platform-independent xorshift32 PRNG for deterministic RAM initialization.
37+
// libc rand() produces different sequences on different platforms (glibc vs
38+
// macOS libsystem), which causes cross-platform baseline mismatches.
39+
static uint32_t jaguar_prng_state = 12345;
40+
41+
void JaguarSeedPRNG(uint32_t seed)
42+
{
43+
jaguar_prng_state = seed ? seed : 1;
44+
}
45+
46+
uint32_t JaguarRand(void)
47+
{
48+
jaguar_prng_state ^= jaguar_prng_state << 13;
49+
jaguar_prng_state ^= jaguar_prng_state >> 17;
50+
jaguar_prng_state ^= jaguar_prng_state << 5;
51+
return jaguar_prng_state;
52+
}
53+
3854
#define ALPINE_FUNCTIONS
3955

4056
// Private function prototypes
@@ -541,12 +557,12 @@ void JaguarSetScreenPitch(uint32_t pitch)
541557
void JaguarInit(void)
542558
{
543559
unsigned i;
544-
// For randomizing RAM
545-
srand(time(NULL));
560+
// Reset the platform-independent PRNG for deterministic RAM fill
561+
JaguarSeedPRNG(12345);
546562

547563
// Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
548564
for(i=0; i<0x200000; i+=4)
549-
*((uint32_t *)(&jaguarMainRAM[i])) = rand();
565+
*((uint32_t *)(&jaguarMainRAM[i])) = JaguarRand();
550566

551567
lowerField = false; // Reset the lower field flag
552568
memset(jaguarMainRAM + 0x804, 0xFF, 4);
@@ -631,8 +647,9 @@ void JaguarReset(void)
631647

632648
// Only problem with this approach: It wipes out RAM loaded files...!
633649
// Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
650+
JaguarSeedPRNG(12345);
634651
for(i=8; i<0x200000; i+=4)
635-
*((uint32_t *)(&jaguarMainRAM[i])) = rand();
652+
*((uint32_t *)(&jaguarMainRAM[i])) = JaguarRand();
636653

637654
// New timer base code stuffola...
638655
InitializeEventList();

src/jaguar.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ void JaguarSetScreenPitch(uint32_t pitch);
1616
void JaguarInit(void);
1717
void JaguarReset(void);
1818
void JaguarDone(void);
19+
void JaguarSeedPRNG(uint32_t seed);
20+
uint32_t JaguarRand(void);
1921

2022
uint8_t JaguarReadByte(uint32_t offset, uint32_t who);
2123
uint16_t JaguarReadWord(uint32_t offset, uint32_t who);

src/jerry.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,18 @@ uint8_t JERRYReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
386386
// F1003C R xxxxxxxx xxxxxxxx JPIT4 - timer 2 divider
387387
else if ((offset >= 0xF10036) && (offset <= 0xF1003D))
388388
{
389-
/* Unhandled timer read (BYTE) */
389+
uint16_t value;
390+
391+
switch (offset & 0xFFFFFFFE)
392+
{
393+
case 0xF10036: value = JERRYPIT1Prescaler; break;
394+
case 0xF10038: value = JERRYPIT1Divider; break;
395+
case 0xF1003A: value = JERRYPIT2Prescaler; break;
396+
case 0xF1003C: value = JERRYPIT2Divider; break;
397+
default: value = 0; break;
398+
}
399+
400+
return (offset & 0x01) ? (value & 0xFF) : (value >> 8);
390401
}
391402
else if (offset >= 0xF14000 && offset <= 0xF14003)
392403
{
@@ -426,7 +437,14 @@ uint16_t JERRYReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
426437
// F1003C R xxxxxxxx xxxxxxxx JPIT4 - timer 2 divider
427438
else if ((offset >= 0xF10036) && (offset <= 0xF1003D))
428439
{
429-
/* Unhandled timer read (WORD) */
440+
switch (offset & 0xFFFFFFFE)
441+
{
442+
case 0xF10036: return JERRYPIT1Prescaler;
443+
case 0xF10038: return JERRYPIT1Divider;
444+
case 0xF1003A: return JERRYPIT2Prescaler;
445+
case 0xF1003C: return JERRYPIT2Divider;
446+
default: return 0;
447+
}
430448
}
431449
else if (offset == 0xF10020)
432450
return jerryPendingInterrupt;

src/tom.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@
256256
#include "tom.h"
257257

258258
#include <string.h> // For memset()
259-
#include <stdlib.h> // For rand()
260259
#include "blitter.h"
261260
#include "event.h"
262261
#include "gpu.h"
@@ -732,9 +731,19 @@ void TOMExecHalfline(uint16_t halfline, bool render)
732731
uint32_t * TOMCurrentLine = 0;
733732
uint16_t topVisible;
734733
uint16_t bottomVisible;
734+
uint16_t hp = GET16(tomRam8, HP);
735735

736736
halfline &= 0x07FF;
737737

738+
// Update HC to approximate position within the scanline.
739+
// Bit 10 (0x0400) is the half-line indicator, analogous to VC's
740+
// field bit 11. The OP tests this via CONDITION_SECOND_HALF_LINE.
741+
// Bits 0-9 approximate the position within the half-line.
742+
if (halfline & 0x01)
743+
SET16(tomRam8, HC, 0x0400 | (hp > 0 ? (hp + 1) / 2 : 0));
744+
else
745+
SET16(tomRam8, HC, 0);
746+
738747
if (halfline & 0x01) // Execute OP only on even halflines (non-interlaced only!)
739748
// Execute OP only on even halflines (skip higher resolutions for now...)
740749
return;
@@ -919,7 +928,8 @@ uint16_t TOMReadWord(uint32_t offset, uint32_t who)
919928
return data;
920929
}
921930
else if (offset == 0xF00004)
922-
return rand() & 0x03FF;
931+
// Return the current HC value from tomRam8 (updated each halfline)
932+
return GET16(tomRam8, HC);
923933
else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE + 0x20))
924934
return GPUReadWord(offset, who);
925935
else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))

test/baselines/yarc.png

4.31 KB
Loading

test/roms/yarc.j64

1 MB
Binary file not shown.

0 commit comments

Comments
 (0)