Starting the 32X from Sega CD

Ask anything your want about the 32X Mushroom programming.

Moderator: BigEvilCorporation

Post Reply
Posts: 24
Joined: Wed Feb 03, 2010 12:53 am
Location: Grimsby, England

Starting the 32X from Sega CD

Post by SoullessSentinel » Mon Oct 22, 2012 6:34 pm

Firstly, I apologise if this post is badly written, I'm quite tired and I'm not too good at asking for things anyway.

I've already wrote my own bootloader for the Sega CD, that loads an
executable into the shared Word RAM and runs it, so I'm fine with the Sega CD side of things.

How would I go about starting the 32X? From what I understand, it requires it's header to be in a specific place in the cartridge. I've read somewhere that it can be started with an alternative header placed in the frame buffer from a CD Program, but I have found no other information on this subject.

Ordinarily, I'd dissassemble the boot sequence of a 32X CD game, however, I dislike the idea of downloading an ISO just for that purpose, and I know many people here are extremely knowledgeable about these things.

Any help you could give would be amazing, thanks.

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

Post by Chilly Willy » Mon Oct 22, 2012 7:07 pm

I did a small CD32X test which shows how to start up the 32X.

On the CD side, you need to send a command and the data/code to the MD side since the CD side cannot access the 32X.

Code: Select all

    memcpy(temp, &sh2_app_start[8], sh2_app_length - 8);
    do_md_cmd2(MD_CMD_INIT_32X, 0x200000, sh2_app_length);
On the MD side, you need to check for the 32X, enable it, init the resources, copy the data/code to the frame buffer, then start the 32X.

Code: Select all

| int init_32x(void *data, int length);
| init 32x, return status
| entry: arg1 = 32X code/data (in word ram), arg2 = length of data
| exit:  d0 = status
        move.l  0xA130EC,d0
        cmpi.l  #0x4D415253,d0          /* 'MARS' */
        beq.b   0f
        moveq   #-2,d0                  /* no 32X detected */
        move.w  #0x2700,sr              /* disable ints */
        lea     0xA15000,a0
        move.b  #1,0x0101(a0)           /* activate 32X, assert SH2 RESET */

        /* wait 10ms for 32X */
        move.w  #19170,d1
        dbra    d1,1b

        moveq   #0,d0
        move.l  d0,0x0120(a0)           /* clear COMM0 */
        move.l  d0,0x0124(a0)           /* clear COMM4 */
        move.b  #3,0x0101(a0)           /* deassert SH2 RESET */
        bclr    #7,0x0100(a0)           /* get access to 32X VDP resources */
        bne.b   2b
        move.w  d0,0x0102(a0)           /* clear interrupt reg */
        move.w  d0,0x0104(a0)           /* clear bank reg */
        move.w  d0,0x0106(a0)           /* clear dreq control reg */
        move.l  d0,0x0108(a0)           /* clear dreq src reg */
        move.l  d0,0x010C(a0)           /* clear dreq dst reg */
        move.w  d0,0x0110(a0)           /* clear dreq length reg */
        move.w  d0,0x0130(a0)           /* clear pwm control reg */
        move.w  d0,0x0132(a0)           /* clear pwm cycle reg */
        move.w  d0,0x0138(a0)           /* clear pwm mono reg */
        move.w  d0,0x0180(a0)           /* clear vdp mode reg */
        move.w  d0,0x0182(a0)           /* clear vdp shift reg */
        bclr    #0,0x018B(a0)           /* switch to frame 0 */
        bne.b   3b
        moveq   #-1,d1
        lea     0x840000,a1             /* frame buffer */
        move.w  d0,(a1)+                /* clear frame buffer */
        dbra    d1,4b
        bset    #0,0x018B(a0)           /* switch to frame 1 */
        beq.b   5b
        moveq   #-1,d1
        lea     0x840000,a1             /* frame buffer */
        move.w  d0,(a1)+                /* clear frame buffer */
        dbra    d1,6b

        moveq   #0x7F,d1
        lea     0xA15200,a1             /* palette cram */
        move.l  d0,(a1)+                /* clear palette */
        dbra    d1,7b

        move.l  0x0120(a0),d0           /* check Master SH2 */
        cmpi.l  #0x53444552,d0          /* 'SDER' */
        bne.b   8f
        move.w  #0x2000,sr              /* enable ints */
        moveq   #-3,d0                  /* sdram error */
        /* 32X initialized and ready, copy data/code to frame buffer */
        movea.l 4(sp),a0                /* data/code */
        move.l  8(sp),d0                /* length */
        lea     0x840000,a1             /* frame buffer */
        move.l  (a0)+,(a1)+
        subq.l  #4,d0
        bgt.b   9b

        lea     0xA15000,a0
        move.l  #0x5F43445F,0x0120(a0)  /* Master SH2 CD handshake '_CD_' */

        move.l  0x0120(a0),d0
        cmpi.l  #0x4D5F4F4B,d0          /* 'M_OK' */
        bne.b   0b
        move.l  0x0124(a0),d0
        cmpi.l  #0x535F4F4B,d0          /* 'S_OK' */
        bne.b   1b

        moveq   #1,d7                   /* 32X initialized */
        moveq   #0,d0
        move.l  d0,0x0120(a0)           /* start Master SH2 */
        move.l  d0,0x0124(a0)           /* start Slave SH2 */

        move.w  #0x2000,sr              /* enable ints */
Now the 32X is running the data/code you transferred. It should be designed to run from sdram as there is no cart. That means another linker script designed to put everything in sdram.

I'm including an arc of the whole example so you can see everything from the makefile to the linker scripts.

It requires my toolchain, plus you copy the two new linker scripts (in the arc) to /opt/toolchains/sega/ldscripts/. You "make clean" to clean the project, "make" to built the project, and "make cd" to build the iso image. This has been tested on a real CD32X.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest