Program behavior not the same on MegaCD

Ask anything your want about Mega/SegaCD programming.

Moderator: Mask of Destiny

Post Reply
Orion_
Very interested
Posts: 52
Joined: Mon May 02, 2011 2:26 pm
Location: France
Contact:

Program behavior not the same on MegaCD

Post by Orion_ » Fri May 24, 2013 1:08 pm

Hello,
I want to code for the MegaCD, but didn't succeed in using the classic SGDK, so I started coding a little test program in 100% 68k asm
It works great as a megadrive rom, but when switching to MegaCD, it doesn't work anymore.

First I tried the cdboot example of Chilly Willy, I compiled the program with org $200000, skipping the cartridge header, making an APP.BIN, an iso image with this file in root directory, and replacing the first 32k of iso file with EU_BOOT.BIN
Test in emulator doesn't work, it keep reading the CD after the "sega sonic" animation. (can't find the file ?)

Then I tried this cd boot kit: http://gendev.spritesmind.net/files/mcd ... jectCD.zip
(see viewtopic.php?t=872 )

Now, I have the program loading and booting, but while transferring the Tile data to vram, it seems that the program stop working during the transfer and jump in random position (!?)
I can see in the debugger of the emulator that my palette is set correctly, and that a partial amount of tile have been transfered, but not the entire tile data.
The same code works perfectly on megadrive as a rom cartridge !
so, can anyone help me about this strange behavior ? Did I miss to do something specifically related to megacd ?

Thank you
Retro game programming !

SoullessSentinel
Interested
Posts: 24
Joined: Wed Feb 03, 2010 12:53 am
Location: Grimsby, England

Post by SoullessSentinel » Fri May 24, 2013 3:51 pm

I can understand if you do not wish to share it, but it would be a great help if you could post the source code to your test application, that way we can attempt to diagnose the problem you're having.

Orion_
Very interested
Posts: 52
Joined: Mon May 02, 2011 2:26 pm
Location: France
Contact:

Post by Orion_ » Fri May 24, 2013 4:01 pm

yeah, sorry, that will be easier :)

Code: Select all

	org	$200000

	jmp	Continue  ; Skip header (this is for cartridge rom only)

	dc.l	$00FFFE00	; Stack
	dc.l	_Entry_Point
	dc.l	_Error_Exception
	dc.l	_Error_Exception
	dc.l	_Error_Exception
	dc.l	_Error_Exception
	dc.l	_Error_Exception
	dc.l	_Error_Exception
	dc.l	_Error_Exception
	dc.l	_Error_Exception
	dc.l	_Line_1010_Emulation
	dc.l	_Line_1111_Emulation
	dc.l	_Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
	dc.l	_Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
	dc.l	_Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
	dc.l	_Error_Exception, _INT, _EXTINT, _INT
	dc.l	_HINT
	dc.l	_INT
	dc.l	_VINT
	dc.l	_INT
	dc.l	_INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
	dc.l	_INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
	dc.l	_INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
	dc.l	_INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT

	dc.b	"SEGA MEGA DRIVE "	; Console Name
	dc.b	"<=- Orion_ =->  "	; Copyright
	dc.b	"SAMPLE PROGRAM                                  "	; Game Name
	dc.b	"SAMPLE PROGRAM                                  "	; Overseas Name
	dc.b	"GM 00000000-00"	; Serial
	dc.w	$0000			; Checksum
	dc.b	"JD              "	; IO Support
	dc.l	$00000000	; Rom Start
	dc.l	$00010000	; Rom End
	dc.l	$00FF0000	; Backup RAM Start
	dc.l	$00FFFFFF	; Backup RAM End
	dc.b	"  "		; "RA" for Backup RAM
	dc.w	$0000		; $F820 for Backup RAM on odd bytes
	dc.l	$00200000	; SRAM Start
	dc.l	$002001FF	; SRAM End
	dc.b	"            "	; Modem
	dc.b	"DEMONSTRATION PROGRAM                   "	; Note
	dc.b	"JUE             "	; Country

;---------------------------------------->

_Entry_Point:
	move	#$2700,sr
	tst.l	$a10008
	bne.s	SkipJoyDetect
	tst.w	$a1000c
SkipJoyDetect:
	bne.s	SkipSetup

Continue:

	; Sega Security Code (SEGA)
	move.b	$A10001,d0
	andi.b	#$0f,d0
	beq.s	WrongVersion
	move.l	#$53454741,$A14000
WrongVersion:

	move.w	#$0100,d0
	move.w	d0,$A11100	; Z80 Bus Request
	move.w	d0,$A11200	; Z80 Request Reset

SkipSetup:

	; Clear RAM
	lea	$ff0000,a0
	moveq	#0,d0
	move.w	#$3FFF,d1
ClearRam:
	move.l	d0,(a0)+
	dbra	d1,ClearRam

	; Init VDP
	lea	VDPtable,a0
	lea	$C00004,a1
	moveq	#19-1,d0
	move.w	#$8000,d1
VDPiLoop:
	move.b	(a0)+,d1	; Reg Value from Table
	move.w	d1,(a1)		; Send to VDP
	add.w	#$0100,d1	; Reg++
	dbra	d0,VDPiLoop


;---------------------------------------->
; Main Code

VDP_DATA	equ	$C00000
VDP_CTRL	equ	$C00004

	lea	Image,a0

	moveq	#0,d0		; Palette Address
	moveq	#(4*16)-1,d1	; N Colors
	bsr	SetCramAddress
	lea	VDP_DATA,a1
PalLoop:
	move.w	(a0)+,(a1)		; Copy Color
	dbra	d1,PalLoop


	move.w	#$C000,d0	; Map A VRAM address
	bsr	SetVramAddress

	lea	VDP_DATA,a1
	moveq	#28-1,d2
MapLoopY:
	moveq	#40-1,d1
MapLoopX:
	move.w	(a0)+,(a1)		; Copy Map Data
	dbra	d1,MapLoopX

	moveq	#(64-40)-1,d1
MapLoopX2:
	move.w	#0,(a1)			; Clear OffScreen
	dbra	d1,MapLoopX2

	dbra	d2,MapLoopY


;	move.l	a0,d0		; From Address
;	move.w	#0,d1		; To Address (VRAM)
;	move.w	#1120*32,d2	; Lenght (n tiles * 32 bytes per tile)
;	bsr	TransferDMAtoVRAM

	move.w	#0,d0
	bsr	SetVramAddress

	move.l	a0,d0			; From Address
	move.w	#((1120*32)/2)-1,d2	; Lenght (n tiles * 32 bytes per tile)

	lea	VDP_DATA,a1
TileLoop:
	move.w	(a0)+,(a1)		; Copy Tile
	dbra	d2,TileLoop


;------>
	moveq	#0,d1

Loop:
	lea	VDP_CTRL,a0
.waitvbl1:
	move.w	(a0),d0
	andi.w	#8,d0
	bne.s	.waitvbl1
.waitvbl2:
	move.w	(a0),d0
	andi.w	#8,d0
	beq.s	.waitvbl2

	moveq	#2,d0		; Palette Address
	bsr	SetCramAddress
	move.w	d1,VDP_DATA  ; Color loop test dbug
	addq.w	#1,d1

	jmp	Loop


;---------------------------------------->
; Utils


SetVramAddress:	; d0 = Address
	movem.l	d1-d4,-(a7)
	move.w	#$4000,d3
	move.b	#$00,d4
	bra.s	iSetVDPAddress

SetVramAddressDMA:	; d0 = Address
	movem.l	d1-d4,-(a7)
	move.w	#$4000,d3
	move.b	#$80,d4
	bra.s	iSetVDPAddress

SetCramAddress:	; d0 = Address
	movem.l	d1-d4,-(a7)
	move.w	#$C000,d3
	move.b	#$00,d4
	bra.s	iSetVDPAddress

SetCramAddressDMA:	; d0 = Address
	movem.l	d1-d4,-(a7)
	move.w	#$C000,d3
	move.b	#$80,d4

iSetVDPAddress:
	move.w	d0,d2		; Address
	and.w	#$3FFF,d2	; Lower Bits
	or.w	d3,d2		; Add VDP Command
	swap	d2

	move.w	d0,d1		; Address
	lsr.w	#8,d1
	lsr.w	#14-8,d1	; Upper Bits
	move.w	d1,d2
	or.b	d4,d2		; Add VDP Command

	move.l	d2,VDP_CTRL

	movem.l	(a7)+,d1-d4
	rts

;------>

TransferDMAtoVRAM:
	movem.l	d3/a0,-(a7)

	lea	VDP_CTRL,a0

	lsr.w	#1,d2		; lenght in word
	move.w	#$9300,d3
	move.b	d2,d3		; msb
	move.w	d3,(a0)

	lsr.w	#8,d2		; lsb
	or.w	#$9400,d2
	move.w	d2,(a0)

	lsr.w	#1,d0		; address in word
	move.w	#$9500,d3
	move.b	d0,d3
	move.w	d3,(a0)

	lsr.w	#8,d0
	move.w	#$9600,d3
	move.b	d0,d3
	move.w	d3,(a0)

	lsr.w	#8,d0
	or.w	#$9700,d0
	move.w	d0,(a0)

	move.w	d1,d0		; Tile VRAM address
	bsr	SetVramAddressDMA

	movem.l	(a7)+,d3/a0
	rts


;---------------------------------------->
; Interrupts

_Line_1010_Emulation:
_Line_1111_Emulation:
	rte

_Error_Exception:
	rte

_INT:
	rte

_EXTINT:
	rte

_HINT:
	rte

_VINT:
	rte


;---------------------------------------->
; Datas

; VDP Ram
;Tile Data	$0000	44k
;Window		$B000	2k	Unused !
;HScroll	$B800	1k
;Sprite		$BC00	1k
;Map A		$c000	8k
;Map B		$e000	8k

VDPtable:	dc.b	$04,$74,$30,$2C,$07,$5E,$00,$00,$00,$00,$01,$00,$81,$2E,$00,$02,$11,$00,$FF

	even

Image:	incbin	"title1.bin"

	org	$00010000
Retro game programming !

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

Re: Program behavior not the same on MegaCD

Post by Mask of Destiny » Fri May 24, 2013 11:06 pm

Orion_ wrote:First I tried the cdboot example of Chilly Willy, I compiled the program with org $200000, skipping the cartridge header, making an APP.BIN, an iso image with this file in root directory, and replacing the first 32k of iso file with EU_BOOT.BIN
Test in emulator doesn't work, it keep reading the CD after the "sega sonic" animation. (can't find the file ?)
What exactly is in EU_BOOT.BIN? Is it just the european security code chunk? If so that won't work. You need a chunk of sub CPU code for reading the disc and and some main CPU code that coordinates with the sub CPU and jumps to the loaded code at $200000.

I would also completely remove the cartridge header. It serves no purpose here and just takes up space. You should probably also remove the standard "init" code as the Megadrive hardware is already initialized by the Mega CD bios (zero-ing RAM may be one exception, but don't zero the entirety of Word RAM as the BIOS uses part of it for interrupt handling).
Orion_ wrote:Now, I have the program loading and booting, but while transferring the Tile data to vram, it seems that the program stop working during the transfer and jump in random position (!?)
I can see in the debugger of the emulator that my palette is set correctly, and that a partial amount of tile have been transfered, but not the entire tile data.
DMA from Word RAM is kind of flaky though it should only be off by a single word from what I remember. You can compensate for this, but I don't remember the exact adjustment that needs to be made. Seems like your problem is a bit more than that though.

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

Post by Chilly Willy » Sat May 25, 2013 12:20 am

First, there were a couple errors in old versions of the boot loader. Make sure you use the latest:

http://www.mediafire.com/download/bh384 ... 0130331.7z

Second, make sure that whatever example you work from compiles and works for you before you try altering it for your own usage. Here's the libpcm and the latest cd mod player source:

http://www.mediafire.com/download/fwa2e ... 0130331.7z
http://www.mediafire.com/download/297a8 ... 0130411.7z

Finally, in the code you posted, you are still clearing ALL the MD ram... which causes a crash since you overwrote areas that the CD uses. You MUST leave 0xFF0000 to 0xFF0FFF and 0xFFFD00 to 0xFFFFFF alone. They are reserved for use by the CD - the first range holds the main 68K IPL, and the second holds the interrupt jump table and BIOS vars for the MD side. While you can probably get away with using the first range (if you know what you're doing), you CANNOT mess with the second range (other than replacing certain vectors, again, only if you know what you're doing).

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

Post by Mask of Destiny » Sat May 25, 2013 12:36 am

I was thinking along the same lines, but the first thing his code does is mask all interrupts with move #2700, sr. Is he unmasking them somewhere that I've missed?

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

Post by Chilly Willy » Sat May 25, 2013 4:01 am

Mask of Destiny wrote:I was thinking along the same lines, but the first thing his code does is mask all interrupts with move #2700, sr. Is he unmasking them somewhere that I've missed?
Not that I can see, so it's probably not an interrupt, but it could be an exception. Also, this is running for word ram, but we don't see any of the rest of the code, so we don't know if the code/data has been properly loaded and switched to the MD side, or that the MD side IPL is even calling it.

Also, since he isn't setting the Level 2 int bit to the CD as part of a vertical blank on the MD side, the CD is failing pretty quick, and who knows what the word ram does when the CD crashes.

The CD isn't like the MD - you just can't turn off ints and pretend nothing is going to happen. You have to have a lot of infrastructure for the program or it's going to fail in unexpected ways. Hence the reason I posted an entire working example.

Well, if you know what you're doing, you COULD pretend the CD isn't there, but you'd need to disable the CD, which also means not using the word ram. Basically, if you know enough to do that, you wouldn't be doing it anyway. :D

Orion_
Very interested
Posts: 52
Joined: Mon May 02, 2011 2:26 pm
Location: France
Contact:

Post by Orion_ » Sat May 25, 2013 8:37 am

Chilly Willy wrote:First, there were a couple errors in old versions of the boot loader. Make sure you use the latest:
I used the latest, it's not working.

http://www.mediafire.com/download/bh384 ... 0130331.7z
Chilly Willy wrote: Second, make sure that whatever example you work from compiles and works for you before you try altering it for your own usage. Here's the libpcm and the latest cd mod player source:
I did not used your example has a base, I just used your loader, and it seems there is a bug inside, because it can't find the "APP.BIN" file.
I'm using mkisofs like this:
mkisofs -iso-level 1 -o filesystem.iso -pad rootdir
Chilly Willy wrote: Finally, in the code you posted, you are still clearing ALL the MD ram...
ok, that was the problem, now it works perfectly (with Luke_ProjectCD.zip boot loader), thank you :)
Retro game programming !

SoullessSentinel
Interested
Posts: 24
Joined: Wed Feb 03, 2010 12:53 am
Location: Grimsby, England

Post by SoullessSentinel » Sat May 25, 2013 12:36 pm

Just so you know, my loader (Luke_ProjectCD) does still have some issues.

It's mostly okay for an application that will start and then never touch the CD Hardware again (I left Columns running for a few hours on a EU Mega CD Model 1 to test stability) however, as it doesn't trigger the correct interrupts, it does cause the Mega CD hardware to die after a short period of time.

It can quite easily be fixed, but I'm busy with other projects this moment in time.

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

Post by Chilly Willy » Sat May 25, 2013 6:09 pm

My loader clearly DOES find "APP.BIN" as that's what I call the mod player in the example. One limitation on the loader is the app to load needs to be in the root directory of the CD, not a subdirectory. Other than that, it can be anywhere in the root with any name (you must match the name in the loader - so if you wish to use a different name, you would need to recompile the loader). Note also that ISO9660 names are all uppercase. Trying to load "app.bin" would fail.

Beyond that, my loader requires the loaded app to start at 0x8000 in the CD ram. If you look at the link script, you'd see that. Maybe you're not using the proper ld script for your app when trying to use my loader. Also note that my loader has a MD IPL that runs a loop looking for certain commands. You MUST use those commands the way they were written for or it doesn't work. Again, it's all in the example mod player.

Post Reply