Well, the cd boot sector is split into two parts - the IPL for the MD side, and then the loader code for the CD side. The MD initial program loader is in the first sector and looks like this
Code: Select all
| SEGA CD Loader code
| by Chilly Willy
| First part of cdrom header
|
| Main-CPU IP, comprising sectors 0 and 1. Sector 0 is loaded automatically,
| while sector 1 is from the header.
.text
| Standard MegaCD Volume Header at 0x0
.ascii "SEGADISCSYSTEM "
.asciz "CDBOOTLOADR"
.word 0x0100
.word 0x0001
.asciz "SEGACD BOOT"
.word 0x0001
.word 0x0000
.long 0x00000800 /* main 68000 initial program cd offset */
.long 0x00000800 /* main 68000 initial program cd size */
.long 0x00000000 /* main 68000 initial program entry offset */
.long 0x00000000 /* main 68000 initial program Work RAM size */
.long 0x00001000 /* sub 68000 initial program cd offset */
.long 0x00007000 /* sub 68000 initial program cd size */
.long 0x00000000 /* sub 68000 initial program entry offset */
.long 0x00000000 /* sub 68000 initial program Work RAM size */
.ascii "03242013 " /* date - MMDDYYYY */
.space 160, 0x20
| Standard MegaDrive ROM header at 0x100
.ascii "SEGA CD Loader "
.ascii "(C)2013 "
.ascii "CD Boot Loader "
.ascii "CD Boot Loader "
.ascii "GM MK-0000 -00 "
.ascii "J6 " /* controller info */
.ascii " "
.ascii " " /* modem info */
.ascii " "
.ascii "JUE " /* region info */
| Standard MegaCD startup code at 0x200
|
| This data and the code following is copied to the Main-CPU Work RAM at
| 0xFF0000 and run.
.global _start
_start:
.ifdef REGION_US
.incbin "ipl/us.bin", 0, 0x584
.endif
.ifdef REGION_EU
.incbin "ipl/eu.bin", 0, 0x56E
.endif
.ifdef REGION_JP
.incbin "ipl/jp.bin", 0, 0x156
.endif
| fall into startup code for Main-CPU
lea 0xA10000.l,a5
move.b #0,0x200E(a5) /* clear main comm port */
| wait for MD init handshake from CD
0:
cmpi.b #'I,0x200F(a5)
bne.b 0b
bset #1,0x2003(a5) /* give Sub-CPU Word RAM */
move.b #'B,0x200E(a5) /* main comm port - do boot */
| wait for MD code handshake from CD
1:
cmpi.b #'M,0x200F(a5)
bne.b 1b
2:
btst #0,0x2003(a5) /* Main-CPU has Word RAM? */
beq.b 2b
move.w #0x2700,sr
lea 0xFFFD00,a0
movea.l a0,sp
jmp 0x200000.l
It is a couple headers followed by the security blob which then falls into the main MD loader code. The security blob is checksummed by the CD BIOS, which is why it's incbin'd into the code. This is legal in the US because copyright cannot be used for security, so the binary blob fails as copyrightable content. This was decided when Lexmark lost their case where they tried a similar trick on printer cart heads.
The MD loader must know how the CD loader works - note how I look for bytes in the comm regs. This code should be short - it's for loading code, not being game code. I tend to load the main MD code for a CD game into word ram, then jump to 0x200000. That code copies code to 0xF01000 and then jumps to that, so I'm not actually running from word ram, I run from work ram.
The CD side of the boot sector code looks like this
Code: Select all
.org 0x1000
| Second part of cdrom header
|
| Sub-CPU IP, comprising sectors 2 to 15 from the header.
| Standard MegaCD Sub-CPU Program Header at 0x1000 (loaded to 0x6000)
SPHeader:
.asciz "MAIN-SUBCPU"
.word 0x0001,0x0000
.long 0x00000000
.long 0x00000000
.long SPHeaderOffsets-SPHeader
.long 0x00000000
SPHeaderOffsets:
.word SPInit-SPHeaderOffsets
.word SPMain-SPHeaderOffsets
.word SPInt2-SPHeaderOffsets
.word SPNull-SPHeaderOffsets
.word 0x0000
| Sub-CPU Program Initialization (VBlank not enabled yet)
SPInit:
lea GlobalVars(pc),a0
move.l #0,VBLANK_HANDLER(a0) /* clear VBlank handler vector */
lea InitCD(pc),a1
move.l a1,INIT_CD(a0) /* set InitCD vector */
lea ReadCD(pc),a1
move.l a1,READ_CD(a0) /* set ReadCD vector */
lea SetCWD(pc),a1
move.l a1,SET_CWD(a0) /* set SetCWD vector */
lea FirstDirSector(pc),a1
move.l a1,FIRST_DIR_SEC(a0) /* set FirstDirSector vector */
lea NextDirSector(pc),a1
move.l a1,NEXT_DIR_SEC(a0) /* set NextDirSector vector */
lea FindDirEntry(pc),a1
move.l a1,FIND_DIR_ENTRY(a0) /* set FindDirEntry vector */
lea NextDirEntry(pc),a1
move.l a1,NEXT_DIR_ENTRY(a0) /* set NextDirEntry vector */
lea LoadFile(pc),a1
move.l a1,LOAD_FILE(a0) /* set LoadFile vector */
andi.b #0xE2,0x8003.w /* Priority Mode = off, 2M mode */
move.b #'I,0x800F.w /* send MD init handshake to MD */
rts
| Sub-CPU Program Main Entry Point (VBlank now enabled)
SPMain:
lea GlobalVars(pc),a6
lea iso_pvd_magic(pc),a5
bsr InitCD
| wait for boot handshake from main
0:
cmpi.b #'B,0x800E.w
bne.b 0b
move.b #0,0x800F.w /* clear sub comm port */
| read boot file from cd
lea root_dirname(pc),a0
bsr SetCWD /* set current working directory to root */
lea boot_name(pc),a0
lea LOAD_BUFFER.l,a1
bsr LoadFile
bne.b exit /* no Sub-CPU boot file */
1:
lea LOAD_BUFFER.l,a0 /* char *start(void) */
jsr (a0)
| app exited - if we return, the BIOS will call SPMain again
|
| my own idea - return NULL if done, else return a pointer to the filename
| to load and run, thus allowing apps to launch other apps
move.w #0x2700,sr /* disallow interrupts */
lea GlobalVars(pc),a6
clr.l VBLANK_HANDLER(a6)
clr.l VBLANK_PARAM(a6)
move.w #0x2000,sr /* allow interrupts */
tst.l d0
beq exit
move.l d0,-(sp)
andi.b #0xE2,0x8003.w /* Priority Mode = off, 2M mode */
move.b #'I,0x800F.w /* send init - switch Word RAM to Sub-CPU */
2:
cmpi.b #'I,0x800E.w
bne.b 2b /* wait for command ACK */
move.b #0,0x800F.w /* ACK handshake */
lea iso_pvd_magic(pc),a5
bsr InitCD
lea root_dirname(pc),a0
bsr SetCWD /* set current working directory to root */
movea.l (sp)+,a0
lea LOAD_BUFFER.l,a1
bsr LoadFile
beq.b 1b /* load okay */
exit:
rts
| Sub-CPU Program VBlank (INT02) Service Handler
SPInt2:
lea GlobalVars(pc),a0
tst.l VBLANK_HANDLER(a0)
bne.b 0f
rts
0:
move.l VBLANK_PARAM(a0),d0
move.l d0,-(sp)
movea.l VBLANK_HANDLER(a0),a0
jsr (a0)
addq.l #4,sp
rts
| Sub-CPU program Reserved Function - we use it get the loader global vars pointer
SPNull:
lea GlobalVars(pc),a0
move.l a0,d0
rts
It's a couple more headers and the main CD function entries: SPInit - called first before the vblank int is enabled; this should initialize the CD state, like the word ram mode and the like. SPMain - the main CD entry point; this should use the BIOS calls to load the game itself. SPInt2 - this is the main vblank int call; when the MD side asserts INT2 inside the MD vblank int code, the CD BIOS calls this function on the CD side. Note that while the MD side COULD assert INT2 any time it feels like, the BIOS assumes that it's only asserted once per vblank. If you don't use the CD BIOS after the game is loaded, you could use this int for other purposes, but that's beyond most examples or games. SPNull - this is a reserved call for the BIOS... I use it in my code to return a global variable table so that I can call pieces of the loader code from the game without worrying about where they are in memory.
After that code, you can have more code used for loading, but it should still be fairly small. I include a routine to call the BIOS to read the CD, and some really low-level ISO9660 helper functions.
Here's an arc of my current cdboot code:
http://www.mediafire.com/file/bh3845u25 ... 31.7z/file
That has everything to make a SCD boot sector for any region.
Here's an arc of my MOD player for the SCD:
http://www.mediafire.com/file/a46r5bmox ... ds.7z/file
That includes an older version of cdboot, my library for using the SCD PCM chip, and the mod player code. It's also got an ISO of the resulting player with some mods.
Here's the raycasting demo:
http://www.mediafire.com/file/tg1hp1wax ... 09.7z/file
Here's a recent set of files to setup my toolchain for MD/CD/32X:
http://www.mediafire.com/file/4wt3dym1g ... 7.zip/file
This should give you everything you need to get started, but looking over other code examples is always recommended. If you have questions, just ask. I'm always willing to answer questions if I know the answer, and this gets a bit complicated compared to plain cart games. CD32X added one more layer on top of it all - you load like a normal CD game, look for the 32X, and put a special boot record into the 32X frame buffer to start it up for CD32X games.
And here's an arc of my CD32X MOD player:
http://www.mediafire.com/file/dn069tm15 ... 25.7z/file
Not sure if you plan on looking at CD32X, but I might as well stick it here as one more link for anyone looking for my CD/CD32X code.
Good luck!