Alright dudes, I need your help! (soft-reset bug)

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Sun Apr 24, 2016 4:11 pm

I got a problem with a thing you guys. It runs fine up until you soft-reset it. This is a problem for me because my only flash cart is a megacart--which my ROM doesn't work on at all, so I'm assuming a Megacart does a soft-reset when a ROM is selected. So I can't run on real hardware because I get nothing but a black screen. I am using GEMS 2.8 also and I suspect I might be doing something wrong with it as well.

Cold boot works fine in emulators. TMSS should be satisfied as I am using the standard header layout + the official Sega ICD_BLK4 initialization code. The only custom code in my startup is some C support code (copy data segment, clear BSS) and I doubt that has anything to do with anything.

My game loop is structured:

startup code -> main() -> initialization (vdp settings, gemsinit() etc) -> enable interrupts (andi.w #$F8FF,sr) -> main falls through into a for(;;); loop -> logic is done every frame in vblankmain(). vblankmain() ends with an RTE and the code spins in the for loop until the next interrupt.

in vblankmain() I have some DMA wrapped in calls to gemsdmastart() / gemsdmaend(). Again, works fine in emulators from a cold boot, everything works as expected. In Exodus however after a soft reset it hangs on gemsdmastart(), particularly the bus request:

Code: Select all

		move.w    sr,-(SP)
		or.w #$0700,sr      ; disable ints

.dsretry
		move.w    #$100,BUSREQ        ; Z80 bus request on
.dslp      btst.b    #0,BUSREQ      ; spin on bus grant
		bne.s     .dslp
It gets stuck on the btst and I'm stumped. I can post a ROM if someone needs it but I figure someone here will know what the problem is straight away. I am doing a dummy DMA (out of RAM) as part of my initialization--I seem to remember hearing that this was necessary, and the GEMS "Ship" demo does it too, so I figured it couldn't hurt. I also remember seeing various Sega Tech Bulletins about stuff related to soft-resets but I can't seem to find them online (I might be misremembering what they're called).

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Sun Apr 24, 2016 4:15 pm

I am assuming that the busreq is maybe happening twice somehow and locking it but I am having trouble understanding how this might be happening.

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Sun Apr 24, 2016 5:55 pm

Here is a ROM.

https://mega.nz/#!upRVzQzC!SdqjX3jIn4Wr ... JutgH1Rvlk

It's a homebrew sound test for X-Men 2: Clone Wars. I have a youtube channel (https://www.youtube.com/user/DUSTINODELLOFFICIAL) where I do recordings of Genesis music from the real machine so it needs to work on the real hardware.

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Sun Apr 24, 2016 6:34 pm

Interrupts should be disabled on reset, right? as in, move.w #$2700,sr

Does most startup code not do this??

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Sun Apr 24, 2016 6:36 pm

Disabling interrupts has no effect, either. Still hangs on z80 busreq

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Sun Apr 24, 2016 7:11 pm

If I comment out any of the GEMS stuff the code just blows up elsewhere, so I must be handling a reset situation really incorrectly.

What needs to be done for reset?

Sik
Very interested
Posts: 890
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: Alright dudes, I need your help! (soft-reset bug)

Post by Sik » Sun Apr 24, 2016 8:18 pm

powerofrecall wrote:Interrupts should be disabled on reset, right? as in, move.w #$2700,sr
In theory, yes. That's the default state of the 68000.

In practice, I've found that the firmware of some flashcarts will leave interrupts enabled... so you have been warned.
Sik is pronounced as "seek", not as "sick".

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Sun Apr 24, 2016 8:19 pm

It has something to do with the pad routines. I'm baffled

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Sun Apr 24, 2016 8:25 pm

Here's my pad code, copied & modified from various sources. The pad read functions don't anything with the bus because I'm using the GEMS functions (gemsholdz80/gemsreleasez80) for it:

Code: Select all

BUSREQ	equ	$A11100

	xdef _pad_init
	xdef _read_pad_a
	xdef _read_pad_b

; int read_pad_a(void);	
; bit0: up
; bit1: down
; bit2: left
; bit3: right
; bit4: B
; bit5: C
; bit6: A
; bit7: start

_pad_init:
 		move.w	#$100,BUSREQ		; Stop Z80
 
.waitZ80:
		btst.b	#0,BUSREQ			; Has the Z80 stopped?
		bne.s	.waitZ80			; If not, wait.
 
		moveq	#$40,d0				; PD6 is an output
		move.b	d0,$A10009			; Configure port A
		move.b	d0,$A1000B			; Configure port B
		move.b	d0,$A1000D			; Configure port C
 
		move.w	#0,BUSREQ			; Restart the Z80
		rts

_read_pad_a:
		lea		$A10003,a1
		bra.s	read_pad

; int read_pad_b(void);
_read_pad_b:
		lea		$A10005,a1

read_pad:
		move.b	#$00,(a1)	; clear bit 6 output
		nop
		nop
		move.b	(a1),d0		; read start & A
		lsl.b	#2,d0		; move them into position
		andi.b	#$c0,d0		; turn off 0s
		move.b	#$40,(a1)	; set bit 6 output
		nop
		nop
		move.b	(a1),d1		; read B, C, UDRL
		andi.b	#$3f,d1		; mask off 0s
		or.b	d1,d0		; merge them
		not.b	d0			; change sense
		rts

		end
I noticed on BUSREQ some games BTST $A11100 and some do $A11101. Is there a functional difference?

When I remove any calls to this code, everything works as expected (except for controls, of course).

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Sun Apr 24, 2016 8:43 pm

Removing the pad initialization and inserting jumps to _gemsholdz80 and _gemsreleasez80 directly into the pad read code makes everything work (at least in Fusion). I doubt this would work on the real hardware though--right?

edit: it leads to broken controls in Exodus, about like you'd predict. So what's the problem...?? No soft reset in exodus either, but everything is OK in Fusion.

Charles MacDonald
Very interested
Posts: 283
Joined: Sat Apr 21, 2007 1:14 am

Re: Alright dudes, I need your help! (soft-reset bug)

Post by Charles MacDonald » Sun Apr 24, 2016 10:34 pm

If the Z80 is held in the reset state (by $A12000) then busreq will never be asserted and the loop will never exit. This is because the Z80 reset logic has a higher priority than the bus request logic.

Maybe check for any unintended writes to $A12000 in the sound/joypad routines and verify the Z80 is running. You could also change the loop to time-out after a while and print some kind of error message (maybe if a timeout happens, forcibly take the Z80 out of reset by writing to $A12000 and retry the loop just as a sanity check)

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Mon Apr 25, 2016 3:06 pm

OK I stepped through it with IDA+GensIDA and I think I found the problem (which ironically, doesn't affect Gens in the slightest). This is something I REALLY should probably know, but: is it forbidden to mess with the SR inside an interrupt? (I mean, I don't know why you would, but is it "bad?") The problem is coming down to vblank firing off right in the middle of a bus reset -> bus request -> bus release which obviously messes the whole order of things up and it hangs. It's because GEMS pushes the old SR, OR's SR with #$700, and then pops it back the old one when it's done, and immediately after popping it back vblank starts (which makes NO sense to me, interrupts should be disabled up to this point!) and interrupts aren't explicitly getting enabled up to this point. It's set up so that interrupts don't get enabled until everything is initialized and I want to start my game loop--or at least that is what I would like it to do!

Mask of Destiny
Very interested
Posts: 591
Joined: Thu Nov 30, 2006 6:30 am

Re: Alright dudes, I need your help! (soft-reset bug)

Post by Mask of Destiny » Mon Apr 25, 2016 5:18 pm

powerofrecall wrote:OK I stepped through it with IDA+GensIDA and I think I found the problem (which ironically, doesn't affect Gens in the slightest). This is something I REALLY should probably know, but: is it forbidden to mess with the SR inside an interrupt? (I mean, I don't know why you would, but is it "bad?")
I suppose it's somewhat error prone, but there's nothing fundamentally wrong with it.
powerofrecall wrote:The problem is coming down to vblank firing off right in the middle of a bus reset -> bus request -> bus release which obviously messes the whole order of things up and it hangs.
That does sound bad.
powerofrecall wrote:It's because GEMS pushes the old SR, OR's SR with #$700, and then pops it back the old one when it's done,
That seems pretty reasonable. It's temporarily masking all interrupts and then restoring the old interrupt mask. This should not allow any interrupts to fire that wouldn't have fired anyway unless the copy of SR on the stack is getting corrupted somehow
powerofrecall wrote:and immediately after popping it back vblank starts (which makes NO sense to me, interrupts should be disabled up to this point!) and interrupts aren't explicitly getting enabled up to this point. It's set up so that interrupts don't get enabled until everything is initialized and I want to start my game loop--or at least that is what I would like it to do!
How are they disabled? In the VDP or by the interrupt mask in SR?

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Alright dudes, I need your help! (soft-reset bug)

Post by powerofrecall » Mon Apr 25, 2016 6:24 pm

I found the problem: a stray move #$2000,sr at the end of one of my VDP functions that I forgot to remove when I restructured my code to run in vblank! I had it set up to disable/enable interrupts before, when I couldn't guarantee an interrupt wouldn't happen, but that shouldn't happen now. The tricky part is it wouldn't cause problems 99% of the time except at the very beginning, while interrupts were (I had assumed) off and initialization code was running. It got called at startup, the interrupt got turned on by that stray move to SR and then some cycles later (coinciding with that SR restore that GEMS does, damn it!) vblank would happen. So stupid me was all confused by what I thought was happening when I could have just looked at the SR and figured it out sooner.

It's good that this is sorted as that sound test ROM is part of a bigger codebase that is somewhere between a library and an engine right now...

The downside to all this though? It tests and works 100% in Exodus, Blastem ;) , and all the less accurate emulators. It STILL won't run on my (admittedly old, outdated) Megacart. Granted, I should have at least gotten myself an Everdrive by now, but I wonder what is keeping it from working? I don't like that it isn't, because most commercial games work on it just fine.

Mask of Destiny
Very interested
Posts: 591
Joined: Thu Nov 30, 2006 6:30 am

Re: Alright dudes, I need your help! (soft-reset bug)

Post by Mask of Destiny » Mon Apr 25, 2016 6:35 pm

powerofrecall wrote:The downside to all this though? It tests and works 100% in Exodus, Blastem ;) , and all the less accurate emulators. It STILL won't run on my (admittedly old, outdated) Megacart. Granted, I should have at least gotten myself an Everdrive by now, but I wonder what is keeping it from working? I don't like that it isn't, because most commercial games work on it just fine.
Is this the old one with the stray move #$2000, sr or is it still broken even with that fix? Whichever it is, can you send me the ROM that is working in BlastEm, but not on your Megacart? I'd like to investigate why that is.

Post Reply