Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CRTC6845 VSync output, use it for GTS3 DMD (fix Teed Off timings) #305

Merged
merged 1 commit into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/vidhrdw/crtc6845.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ typedef struct {
int cursor;
int light_pen;
int page_flip; /* This seems to be present in the HD46505 */
mame_timer* vsync_timer;
double clock_freq;
} CRTC6845;

static CRTC6845 crtc6845[MAX_6845];
Expand All @@ -50,6 +52,35 @@ void crtc6845_init(int chipnum)
memset(&crtc6845[chipnum],0,sizeof(CRTC6845));
}

void update_vsync_timer(int chipnum)
{
if (crtc6845[chipnum].vsync_timer)
{
// Each scanline is (horiz_total+1) clock cycles
// VSync happens after (vert_total+1) rows of characters + vert_total_adj scanlines, each character is made of (max_ras_addr+1) scanlines
int nCycles = (crtc6845[chipnum].horiz_total + 1) * ((crtc6845[chipnum].vert_total + 1) * (crtc6845[chipnum].max_ras_addr + 1) + crtc6845[chipnum].vert_total_adj);
double period = nCycles / crtc6845[chipnum].clock_freq;
if (period < 1e-3) // Hack: disable timer if values are too low (less than 1ms here)
timer_enable(crtc6845[chipnum].vsync_timer, 0);
else
timer_adjust(crtc6845[chipnum].vsync_timer, period, chipnum, period);
//if (period > 1e-3) printf("CRT #%d PC %04x: VSync freq:%5.1fHz\n", chipnum, activecpu_get_pc(), 1.0 / period);
}
}

void crtc6845_set_vsync(int chipnum, double clockFreq, void (*handler)(int))
{
if (crtc6845[chipnum].vsync_timer != NULL)
timer_remove(crtc6845[chipnum].vsync_timer);
crtc6845[chipnum].vsync_timer = NULL;
crtc6845[chipnum].clock_freq = clockFreq;
if (handler && clockFreq > 0.)
{
crtc6845[chipnum].vsync_timer = timer_alloc(handler);
update_vsync_timer(chipnum);
}
}

READ_HANDLER( crtc6845_register_r )
{
int retval=0;
Expand Down Expand Up @@ -132,6 +163,7 @@ LOG(("CRT #0 PC %04x: WRITE reg 0x%02x data 0x%02x\n",activecpu_get_pc(),crtc684
{
case 0:
crtc6845[offset].horiz_total=data;
update_vsync_timer(offset);
break;
case 1:
crtc6845[offset].horiz_disp=data;
Expand All @@ -144,9 +176,11 @@ LOG(("CRT #0 PC %04x: WRITE reg 0x%02x data 0x%02x\n",activecpu_get_pc(),crtc684
break;
case 4:
crtc6845[offset].vert_total=data&0x7f;
update_vsync_timer(offset);
break;
case 5:
crtc6845[offset].vert_total_adj=data&0x1f;
update_vsync_timer(offset);
break;
case 6:
crtc6845[offset].vert_disp=data&0x7f;
Expand All @@ -159,6 +193,7 @@ LOG(("CRT #0 PC %04x: WRITE reg 0x%02x data 0x%02x\n",activecpu_get_pc(),crtc684
break;
case 9:
crtc6845[offset].max_ras_addr=data&0x1f;
update_vsync_timer(offset);
break;
case 10:
crtc6845[offset].cursor_start_ras=data&0x7f;
Expand Down
1 change: 1 addition & 0 deletions src/vidhrdw/crtc6845.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define MAX_6845 2

void crtc6845_init(int chipnum);
void crtc6845_set_vsync(int chipnum, double clockFreq, void (*handler)(int));

/*Direct handlers*/
READ_HANDLER( crtc6845_register_r );
Expand Down
44 changes: 12 additions & 32 deletions src/wpc/gts3.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ static READ_HANDLER(alpha_u4_pb_r)
PB0-2: Output only
PB3: Test Switch
PB4: Tilt Switch
PB5- A1P3-3 - Display Controller - Status1 (Not labeled on Schematic)
PB5- A1P3-3 - Display Controller - Status1 (Not labeled on Schematic, toggled by the DMD CPU when data is received to tell it is ready to get another byte)
PB6- A1P3-1 - Display Controller - DMD Display Strobe (DSTB) - Output only, but might be read!
PB7- A1P3-2 - Display Controller - Status2 (Not labeled on Schematic)
*/
Expand Down Expand Up @@ -213,27 +213,6 @@ static WRITE_HANDLER( xvia_0_b_w ) {
else
{ // DMD generation
GTS3_dmdlocals[0].dstrb = (data & DSTRB) != 0;
if (GTS3_dmdlocals[0].version) { // probably wrong, but the only way to show *any* display
if (GTS3_dmdlocals[0].dstrb) {
GTS3locals.bitSet++;
if (GTS3locals.bitSet == 4)
{
// 12/17/16 (djrobx) - Teed Off's animations are running way too fast. Vblank
// appears to be firing too often. Seems to be closer to correct if you do it every
// 3rd time this bit is set, but probably means this method is not right as the
// above comment suggests.
GTS3locals.vblank_counter++;
if (GTS3locals.vblank_counter == 3)
{
GTS3locals.vblank_counter = 0;
dmd_vblank(0);
if(GTS3_dmdlocals[0].version == 2)
dmd_vblank(1);
}
}
} else
GTS3locals.bitSet = 0;
}
}

GTS3locals.u4pb = data;
Expand Down Expand Up @@ -613,6 +592,7 @@ static void gts3dmd_init(void) {

//Init 6845
crtc6845_init(0);
crtc6845_set_vsync(0, 3579545. / 2., dmd_vblank);

/*DMD*/
/*copy last 32K of ROM into last 32K of CPU region*/
Expand Down Expand Up @@ -781,6 +761,7 @@ static MACHINE_INIT(gts3dmd2) {

//Init 2nd 6845
crtc6845_init(1);
crtc6845_set_vsync(1, 3579545. / 2., dmd_vblank);

/*copy last 32K of DMD ROM into last 32K of CPU region*/
if (memory_region(GTS3_MEMREG_DCPU2)) {
Expand Down Expand Up @@ -883,12 +864,19 @@ static WRITE_HANDLER(alpha_display){
/* DMD GENERATION
----------------
DMD Strobe & Reset:
DS0 = Pulse the DMD CPU IRQ Line
DS0 = Pulse the DMD CPU IRQ Line (data ready)
DS1 = Reset the DMD CPU
DS2 = Not Used
DS3 = Not Used
*/
static WRITE_HANDLER(dmd_display){
/*
CPU board - DMD communication:
- CPU sends data by writing bytes to to 0x2020, triggering DS0 (DMD board latch data and set IRQ to process it)
- DMD board acq received data by toggling PB5 pin
Note that the written data is latched on the CPU board on all CPU writes, not just the ones to dmd, but the dmd
board only latches it when DS0 is fired (so the emulation here is not perfect).
*/
//Latch DMD Data from U7
GTS3_dmdlocals[0].dmd_latch = data;
if (offset == 0) {
Expand Down Expand Up @@ -969,14 +957,6 @@ static WRITE_HANDLER(dmd_aux) {
//Store it since the data is referred elsewhere
GTS3locals.ax[4+offset] = data;

//Generate an dmd vblank?
if (!offset) {
dmd_vblank(0);
//2nd DMD for Strikes N Spares
if(GTS3_dmdlocals[0].version == 2)
dmd_vblank(1);
}

//Strikes N Spares Stuff
if (GTS3_dmdlocals[0].version == 2)
{
Expand All @@ -994,7 +974,7 @@ static WRITE_HANDLER(dmd_aux) {
}
}

//Update the DMD Frames during a simulated DMD VBLANK - Supports 2 DMD Displays
//Update the DMD Frames during the DMD VBLANK generated by the CRTC6845 - Supports 2 DMD Displays
static void dmd_vblank(int which) {
int offset = crtc6845_start_address_r(which) >> 2;
if (which)
Expand Down
2 changes: 0 additions & 2 deletions src/wpc/gts3.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,6 @@ typedef struct {
UINT8 sound_data;
UINT8 prn[8];

int bitSet;
UINT8 vblank_counter;
UINT8 irq;

int modsol_rate_counter;
Expand Down
Loading