Scaling hardware?

Ask anything your want about Mega/SegaCD programming.

Moderator: Mask of Destiny

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Mon May 21, 2012 11:19 pm

You DO know that 75 ints/sec is one int per sector, right (stupid question, but best to get it out of the way). After waiting 1/75th sec, process one sector. Perhaps that int coincides with a specific portion of the CD sector decoding process and your CD sector processing is not in sync with what the BIOS expects when the int occurs.

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Tue May 22, 2012 8:07 am

Eke wrote:Well, I was wrong: in fact, running opcode by opcode does not make any good, the only thing that somehow made it go past the black screen on startup was to significantly increase either the number of SUB-CPU cycles executed per line (I forgot I still had this slightly modified in my previous test... oops) or the CDD/CDC interrupts frequency.
Are you syncing the sub cpu to VDP lines? That doesn't sound good. There's really no sync with the VDP itself -- just the level 2 INT which can be triggered at an arbitrary time (usually sometime during V-INT).

There is only a loose relation between the CDC [decoder] @ 75Hz and V-INT @60Hz/NTSC, in that there are 5 CDC-INT for every 4 V-INT. The similar PAL ratio would be 6:4.

Time Gal doesn't appear to do anything super weird, except that it does a lot of syncing. But there are some shaky things, like it may possible for the sub cpu to get completely cut off during a function when the next L2-INT comes. Don't know how close it really comes to fubar, but... hmm.

The game does use the wordram 'swap request' flag. All the CD access is pretty standard bios stuff. The sub doesn't hook any of the peripheral interrupts, no direct register access, none of that kind of stuff. It's pretty vanilla in that respect.

The main cpu may halt the sub at some point, but it doesn't appear to happen often, if at all. The code does use TRAP instructions a lot, but that kinda sticks out like a sore thumb anyway. If there is a bug in the game code that effects its emulation, it's not obvious.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Tue May 22, 2012 8:48 am

I tried to look into Gens sources to bring back to my memory some CDD/CDC stuff... well, what a mess ! i really wonder how i did to get that actually working X'D
What i saw is that each 1/75th of second i am doing the following :
I check if a CDD command completed, if it is the case i update CDD status according to the result and launching INT 4.
Then i check if CDC is actually reading data, if it is the case i actually wait for a delay (File_Add_Delay variable) to expire before returning data so it takes severals frames before actually reading data, updating CDC status and launching INT 5.

Here is the code of the method called each 1/75th of second :

Code: Select all

void Check_CD_Command(void)
{
	// Check CDD
	
	if (CDD_Complete)
	{
		CDD_Complete = 0;
		CDD_Export_Status();
		if (Int_Mask_S68K & 0x10) sub68k_interrupt(4, -1);
	}

	// Check CDC

	if (SCD.Status_CDC & 1)			// CDC is reading data ...
	{
		// DATA ?
		if (SCD.TOC.Tracks[SCD.Cur_Track - SCD.TOC.First_Track].Type) CDD.Control |= 0x0100;
		else CDD.Control &= ~0x0100;			// AUDIO

		if (File_Add_Delay == 0)
		{
			if (CD_Load_System == CDROM_) ASPI_Read_One_LBA_CDC();
			else FILE_Read_One_LBA_CDC();
		}
		else File_Add_Delay--;
	}

	if (SCD.Status_CDD == FAST_FOW)
	{
		SCD.Cur_LBA += 10;
		CDC_Update_Header();		
	}
	else if (SCD.Status_CDD == FAST_REV)
	{
		SCD.Cur_LBA -= 10;
		if (SCD.Cur_LBA < -150) SCD.Cur_LBA = -150;
		CDC_Update_Header();
	}
}
Do you see this "File_Add_Delay" variable ?
It contains the number of CD frame (1/75th of second) to wait before actually read data.
The delay is shorter with ASPI as the command reply later asynchronously where it reply immediately from file.
The FILE_Read_One_LBA_CDC() will actually read data, update CDC status and registers then launch int 5.
Last edited by Stef on Fri May 25, 2012 8:54 am, edited 2 times in total.

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Tue May 22, 2012 9:11 pm

Chilly Willy wrote:You DO know that 75 ints/sec is one int per sector, right (stupid question, but best to get it out of the way). After waiting 1/75th sec, process one sector. Perhaps that int coincides with a specific portion of the CD sector decoding process and your CD sector processing is not in sync with what the BIOS expects when the int occurs.
Yes, I do know. In fact, no game would even boot to Sonic logo if this is not properly emulated, most of my work was actually spent on getting BIOS booting CD, and this involves correct emulation of CDD interrupt & commands as well as CDC decoder interrupt and registers.
Stef wrote:What i saw is that each 1/75th of second i am doing the following :
I check if a CDD command completed, if it is the case i update CDD status according to the result and launching INT 4.
Then i check if CDC is actually reading data, if it is the case i actually wait for a delay (File_Add_Delay variable) to expire before returning data so it takes severals frames before actually reading data, updating CDC status and launching INT 5.

Here is the code of the method called each 1/75th of second :
I am doing something very similar, only differences are that I update CDD status registers when the last command word is sent (but it doesn't matter since those registers are always read on next CDD interrupt) and that I first process CDC decoding/buffer write and level 5 interrupt before triggering level 4interrupt (again, it does not make any difference since no SUB-CPU cycles is executed between the two interrupts, so, just like in Gens, level 5 interrupt callback is executed first, then level 4)

Do you see this "File_Add_Delay" variable ?
It contains the number of CD frame (1/75th of second) to wait before actually read data.
The delay is shorter with ASPI as the command reply later asynchronously where it reply immediately from file.
Yes, that's the delay I was talking about earlier. It is initialized when you receive a PLAY command and depends on the delta between current block address and goal block address.

TascoDlx wrote:Are you syncing the sub cpu to VDP lines? That doesn't sound good. There's really no sync with the VDP itself -- just the level 2 INT which can be triggered at an arbitrary time (usually sometime during V-INT).
Not exactly, but indirectly yes. Because most events are, like in most emulators, processed on a "line" granularity. Gens does exactly the same actually as Check_CD_Command is only processed between lines, when 75hz counter expires. I also use global cycle counters for SCD/CDD/Timer/etc, which are updated between each lines and are used to trigger events at the "right" timing.



Time Gal doesn't appear to do anything super weird, except that it does a lot of syncing. But there are some shaky things, like it may possible for the sub cpu to get completely cut off during a function when the next L2-INT comes. Don't know how close it really comes to fubar, but... hmm.
Thanks for looking anyway. I came to the same observations , and I'm quite convinced it's something related to Interrupt (INT2 or INT4 or both together) timings on SUB-CPU side. I tried to sync SUB-CPU on INT2 register writes but it did not change anything sadly.

What I don't understand is what triggers those CDC host reads. I guess it's initially coming from a ROMREADxxx command sent to the BIOS but I can't seem to find what make the BIOS initialize CDC (CDCSTART command ?), enable buffer RAM writes for a few sectors then suddenly stop it (CDCSTOP command ?). Data transfer seem to start after an INT2 has been processed, by first setting the destination (write $03 to $FF8004 at PC=$009D74) .

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Wed May 23, 2012 4:55 am

Eke wrote:What I don't understand is what triggers those CDC host reads. I guess it's initially coming from a ROMREADxxx command sent to the BIOS but I can't seem to find what make the BIOS initialize CDC (CDCSTART command ?), enable buffer RAM writes for a few sectors then suddenly stop it (CDCSTOP command ?). Data transfer seem to start after an INT2 has been processed, by first setting the destination (write $03 to $FF8004 at PC=$009D74) .
In a nutshell:
- A call to ROMREADxxx will eventually lead to CDCSTART.
- CDCSTOP will stop the CDC transfer (actually, INT5 is masked and LC's DOUTEN bit is cycled to abort DT).
- LC's WRRQ is disabled by the bios when the read is complete or in case of an uncorrectable error.

When stopping a transfer using CDCSTOP, ROMPAUSEON may be called to avoid a runaway disc read. It might be possible to resume a transfer using CDCSTART when ROMPAUSE is used, but I'm not entirely sure. I've haven't seen it attempted.

I noticed that the TimeGal code you are referring to writes $FF8004 before reading out each sector, instead of just once for the whole stretch. All that writing this register does is set the destination for the CDC. If you're accidentally overwriting the top two bits of this register, that would be bad, as those bits are supposed to be read-only.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Wed May 23, 2012 8:57 am

Eke wrote:
Do you see this "File_Add_Delay" variable ?
It contains the number of CD frame (1/75th of second) to wait before actually read data.
The delay is shorter with ASPI as the command reply later asynchronously where it reply immediately from file.
Yes, that's the delay I was talking about earlier. It is initialized when you receive a PLAY command and depends on the delta between current block address and goal block address.
So may be you was right and that is the problem, i guess i added it because replying too fast could cause the BIOS to "miss" the sector...
Did you tried to add some sort of delay ?

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Thu May 24, 2012 6:51 pm

Stef wrote:
Eke wrote:
Do you see this "File_Add_Delay" variable ?
It contains the number of CD frame (1/75th of second) to wait before actually read data.
The delay is shorter with ASPI as the command reply later asynchronously where it reply immediately from file.
Yes, that's the delay I was talking about earlier. It is initialized when you receive a PLAY command and depends on the delta between current block address and goal block address.
So may be you was right and that is the problem, i guess i added it because replying too fast could cause the BIOS to "miss" the sector...
Did you tried to add some sort of delay ?
and that was it :D

something I did not see when I first tried to copy your delay implementation was that you were actually adding a delay of 20 CDD interrupt when a PLAY command was sent with the drive being paused or stopped.

adding this delay solved the issue (in fact, the minimal delay needed is 6 interrupts): what happened was that the game was actually in the middle of a long copy routine (PC=$9030) when the PLAY command was sent by CDD interrupt processing and would only start CDC transfer when above routines were finished, which, if I immediately start CDC decoding after the PLAY command, would be too late and cause the BIOS to abort the transfer.

this also fix Road Avenger and Cobra Command which apparently use the exact same booting code , what a relief when I finally saw this damn Wolf Team logo and FMV displayed fine

:P

Thank you all for the help, this was very much appreciated

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Fri May 25, 2012 9:03 am

Glad you fixed it, well done !
By the way, did you manage to get Mortal Kombat working properly ? I'm curious about this one as it gave me serious headaches ;)

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Fri May 25, 2012 10:55 am

It is next on my list (as well as Ecco CD and Jaguar XJ220 which both suffer from graphic glitches in game).

I noticed this game do two unusual things:

1) writes to communication flags registers (FF800F / A1200E) are done using word access: preventing read-only part from being updated when this happen actually make the game boots and intro FMV play fine.

2) it hangs later on a black screen when starting a fight, just before entering fighting arena: from looking at my logs, it appears SUB-CPU is writing some value ($03) to $FF800F in order to indicate to MAIN-CPU it should return Word-RAM to SUB side, then a few cycles later, try to access Word-RAM without checking status of RET bit or DMNA bit. If MAIN-CPU did not run during the interval, Word-RAM would not have been returned and SUB-CPU access to Word-RAM does nothing. I think that this is the kind of situation you were refering to when saying that synchronization on shared memory access was required.

I do not have the abilty to test it yet but it seems to me the easiest (but not 100% accurate off course) way to handle this is to allow access to Word RAM to both CPU anytime...

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Fri May 25, 2012 12:56 pm

Eke wrote: 2) it hangs later on a black screen when starting a fight, just before entering fighting arena: from looking at my logs, it appears SUB-CPU is writing some value ($03) to $FF800F in order to indicate to MAIN-CPU it should return Word-RAM to SUB side, then a few cycles later, try to access Word-RAM without checking status of RET bit or DMNA bit. If MAIN-CPU did not run during the interval, Word-RAM would not have been returned and SUB-CPU access to Word-RAM does nothing. I think that this is the kind of situation you were refering to when saying that synchronization on shared memory access was required.

I do not have the abilty to test it yet but it seems to me the easiest (but not 100% accurate off course) way to handle this is to allow access to Word RAM to both CPU anytime...
Yep, that is typically the weird things i was speaking about for MK...
I'm not sure allowing Word RAM access from both CPU at anytime is a viable solution as it can break some others (bad programmed) games.
But you should try it as it's quite easy to change that :)

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Tue May 29, 2012 3:53 pm

Yep, that is typically the weird things i was speaking about for MK...
I'm not sure allowing Word RAM access from both CPU at anytime is a viable solution as it can break some others (bad programmed) games.
But you should try it as it's quite easy to change that :)
Seems like Picodrive is doing this by default (with a comment mentionning it's done like in Gens, although from reading your asm code, i'm not 100% sure). Anyway, it indeed fixed Mortal Kombat which now runs fine. All games tested (~50) seem to work fine btw, with only Ecco CD giving me some trouble with random tile corruptions, but my CPU synchronization seem to be ok for all sensitive games (until i find one that hangs i guess).

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Wed May 30, 2012 1:17 pm

Great news :) I don't remember if i permit access from both CPU at any time, that sounds strange as it can cause tons of problems with games doing wrong access... but if that works.
Glad your sync code is ok for sensitive games for the moment :)
I do not remember specific problems about ecco but i guess you'll get ride of them soon =)

notaz
Very interested
Posts: 193
Joined: Mon Feb 04, 2008 11:58 pm
Location: Lithuania

Post by notaz » Fri Jun 01, 2012 12:28 pm

Yeah lots of timing sensitive things in CD emulation, I spent good deal of time on this too, and it's still mostly wrong all around, just enough to get games running. Maybe I should get back to this someday..

Is Radical Rex working for you, Eke? Never got that one running (neither did Gens at that time), I did some research into it but don't really remember anything (it has been some years)..

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Fri Jun 01, 2012 6:29 pm

notaz wrote: Is Radical Rex working for you, Eke? Never got that one running (neither did Gens at that time), I did some research into it but don't really remember anything (it has been some years)..
I just tested it and yes, it works

I finished testing the entire Mega CD / Sega CD library (~215 unique games, not counting region variations), here are the only remaining problematic games :
NOT WORKING (16 GAMES)

A-Rank Thunder Tanjouhen (hangs during intro cinematic)
Arslan Senki - The Heroic Legend of Arslan (hangs at copyright screen)
Batman Returns (hangs after start intro)
Corpse Killer (random "drive error" hangs during game)
Cosmic Fantasy Stories (hangs when starting new game)
Earnest Evans (hangs after Wolf Team logo)
ESPN Sunday Night NFL (hangs when starting new game + gfx errors during intro)
i'm problably a spammer International Soccer (hangs after Sega logo)
Jeopardy (hangs during intro)
Joe Montana's NFL Football (hangs when starting a game)
NFL Football Trivia Challenge (hangs when starting a game)
NHL '94 (hangs after intro)
Sangokushi III - Romance of the Three Kingdoms (hangs at Sega logo)
Seima Densetsu 3x3 Eyes (hangs after Sega logo)
Seirei Shinseiki - Fhey Area (hangs after Wolf Team logo)
Shadow of the Beast 2 (hangs at Sega logo)
GRAPHICAL ISSUES (8 GAMES)

Adventures of Willy Beamish, The (swapped tiles)
AH3 Thunderstrike / Thunderhawk (corrupted maps)
Battle Frenzy / Blood Shot (graphic issues)
Chuck Rock (corrupted tiles)
Citizen X (corrupted menu bar)
Ecco the Dolphin (random corrupted tiles)
Ecco: The Tides of Time (random corrupted tiles)
World Cup USA 94 (corrupted tiles)
Other issues I noticed:

- random lock-out issue when starting with original Japanese Mega CD BIOS (using MEGA CD 2 BIOS seems more stable)

- lock-out when restarting games (A+B+C+START) or when games want you to return to BIOS menu (for example when backup RAM is full)

EDIT:
Adventures of Willy Beamish, The (swapped tiles)
AH3 Thunderstrike / Thunderhawk (corrupted maps)
Citizen X (corrupted menu bar)
Shadow of the Beast 2 (hangs at Sega logo)
Those games actually need Word-RAM data to be preserved when switching modes.

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Sun Jun 03, 2012 4:27 pm

Batman Returns (hangs after start intro)
Found the cause for this one: a graphics operation ended with level 1 interrupt being masked and I was keeping the interrupt pending, so it was later triggered when the game resets interrupt mask register, which cause the game to reset itself (and crashes).

So it seems like GFX interrupt is simply dismissed if masked and is not made pending.

I think CDC (INT5) and CDD (INT4) interrupts remain pending when masked in $FF8033 register as IRQ lines are handled by external chips but what about Timer (INT3) and Main-CPU (INT2) interrupts ? What happen if they are masked when Timer expires or Main-CPU sets the IFL2 flag, then later unmasked ?

EDIT: well, it seems like that game
Arslan Senki - The Heroic Legend of Arslan (hangs at copyright screen)
wants IFL2 bit to be cleared (even if written to 1 before) when INT2 is disabled so I guess there is no pending level 2 interrupt either

Post Reply