SEGA CD Mode 1

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

SEGA CD Mode 1

Post by Chilly Willy » Sat Dec 17, 2011 2:12 am

There's been a lot of talk since the release of Sonic 1 with Redbook Audio, mainly people asking for code. I can see why they might not want to post their code since it's probably hacked into Sonic 1 pretty bad. However, there still exists a need to show how to use Mode 1. To that end, I did a small demo - this is a tiny CD player done using Mode 1 of the SEGA CD, and includes full source. From this, you should get a good idea of how Mode 1 works. If not, ask questions in the thread here and I'll answer them.

The project was compiled with my gcc toolchain, but it wouldn't take much work to convert the code to whatever you normally use. The player goes beyond what you would use in a game, but it's an example.

Controls:
A - play from current track to end of disc
B - play current track once
C - stop playing
X - show current track info
Y - play current track repeatedly
Z - pause/resume
START - check disc

Notes: The TOC is invalid until you check the disc. The CDBIOS doesn't initialize its TOC until you call DRVINIT (which is what my check disc routine does). So when you first start the player, the status may show wildly wrong disc info (first and last tracks being over 99, e.g.). If the tray/lid is open, it will show that. Insert a disc and press START - you should get proper disc info after the status is done showing "Reading TOC" and goes to "PAUSED". The current track may not be the same as the playing track - you can start a track playing and then change the "current" track to something else. Pressing X to see the track info shows the info for the current track displayed on the screen, not the track playing. The track info consists of the track time and track type; the track type is pretty straightforward - it's either a DATA track (track 1 of mixed mode discs), or a CDDA track for audio tracks. The track time shows the BCD minutes/seconds/frames/track number as MMSSFFTN. It shows where the track starts, while the track number is the same as the track number you asked for info on, or 00 is an error occured.

While this example is a CD audio player, I could have easily also read data discs, showing sector data. I did the audio player since that's mainly what people wanted - to see how to play CDDA from a game in rom. The Sub-CPU program is really simple - wait for commands from the Main-CPU, then do them. The commands all pertain to handling the CD audio, but they could as easily use the ASIC, use the PCM chip, read data from sectors, etc. When I start doing some ASIC tests, this will be the test bed to start from as it's easier for me to write the test file to SD card and run in Mode 1 than to keep burning CDRs.

I've tested this on a Model 2 Genesis + Model 2 CD and on a CDX. Let me know if you have any trouble on other models, but it SHOULD work on anything.

mode1player.zip

Update - 20111219: Should work on the WonderMega and X'Eye, and MIGHT work on the LaserActive. Also changed this version to init the drive if a disc is in place when started so that you can immediately play tracks.

mode1player2.zip

EDIT (KanedaFR) : lastest version Mode1Example-20120104 is on Sega16 thread
Last edited by Chilly Willy on Tue Dec 20, 2011 5:16 am, edited 1 time in total.

Bitybity
Interested
Posts: 36
Joined: Wed Dec 07, 2011 2:09 am

Post by Bitybity » Sat Dec 17, 2011 3:26 pm

Very thanks for this. Will be useful for me because I'm studying how to work 32x CD.

I've tested this on my Sega CD with my Sega Genesis model 1 and worked very well.

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

Post by Chilly Willy » Sat Dec 17, 2011 7:36 pm

CD32X booted from a disc, or from a cart? If from a cart, you'd do it like this demo, but with the regular 32X headers and code. The 32X would send a command to the MD side which would then send it on to the CD. If you mean from a disc, the disc would be just like a regular MCD disc, but after starting up the CD, the CD would send a command and data to the MD side which would turn on the 32X, and copy the data to the 32X frame buffer. That data would be the 32X headers and code - the 32X BIOS has the SH2s look for the headers in rom if you are using a cart, or to look in the frame buffer if there is no cart inserted.

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Tue Dec 20, 2011 12:13 am

Awesome, thanks for this code Chilly Willy! I think this'll be very useful when I try dumping MegaLD games for the LaserActive again soon. I wasn't able to successfully start the CD subsystem from a cartridge. With your working and proven code, I should be able to make some more progress next time around.

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

Post by Chilly Willy » Tue Dec 20, 2011 2:50 am

Just some notes about things: when you startup with a disc in the CD, the TOC is invalid and it won't play the tracks (properly/at all) until you do a DRVINIT to make it read the TOC. When have it running and open the tray to swap discs, the BIOS automatically reads the TOC when you close the tray/lid. So doing DRVINIT is only need the first time you start with a disc in place. On my program, press START to do the DRVINIT.

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Wed Dec 28, 2011 8:56 am

Ok, this boot code doesn't work on a LaserActive. I tried the other sub-cpu bios at 0x40D500, same result. The sub-cpu bios is decompressed into the program memory, and the sub-cpu apparently starts running, but when your code enters the wait loop reading 0xA1200F, it times out and displays the message "CD failed to start". I lengthened the wait timeout and made it simply try and proceed regardless, but then of course the boot code just hangs the first time it tries to send a command to the sub-cpu bios.

I've tested the flux rom, and it can't boot a laseractive either. It starts, but none of the controls work, and it doesn't manage to read the track list. It seems the normal mode 1 boot procedure doesn't work on the LaserActive. This is the same problem I had with my attempts, it seemed I could never get the sub-cpu booted successfully and responding to commands. Best as I can figure, the sub-cpu does boot and start running code, but it can't talk to the CD hardware, and seems to lock up, or wait forever for some state which the hardware never reaches.

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

Post by Chilly Willy » Wed Dec 28, 2011 5:29 pm

Is that with or without a disc in the drive?

SEGA made "mode 1" by making the startup in the CD BIOS this:
init hardware
init BIOS variables
loop:
check for boot code at 0x6000
if there - run
if not - try to load boot code from CD and loop

Notice how it checks for the boot code BEFORE attempting to load it - that gives the main CPU a chance to stick some boot code at the load location rather than pull it off the CD. That is what makes mode 1.

So far, the only difference we've seen in the CD BIOSes is where they are in the main BIOS and "SEGA" vs "WONDER". I would imagine the LaserActive to be more different than that. I might need to reverse engineer the CD BIOSes a bit to see if something stands out from the others.

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Wed Dec 28, 2011 7:38 pm

I tested with and without a CD in the drive I believe, but I'll test again to be sure. I didn't test with an LD in the drive.

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

Post by Chilly Willy » Wed Dec 28, 2011 8:53 pm

It's possible they simply removed mode 1 support. That would be the easiest explanation. It's not like anything used it... there was Flux, but the LaserActive came out before Flux, so as far as they were concerned, there was nothing out using mode 1.

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Thu Dec 29, 2011 2:22 pm

It doesn't seem like they removed mode 1 support. My tests show that the sub-cpu code at 0x1AD00 is loaded by the LaserActive bios when a CD is inserted, while the sub-cpu code at 0xD500 is loaded when an LD is inserted. The LD sub-cpu code has a lot of differences to the normal MegaCD boot code, but the CD sub-cpu code is identical, byte for byte, to the sub-cpu code in the standard V1 SegaCD model 1 bios. This means the hardware itself must have a compatibility mode for the LC8951 CDD controller in the standard MegaCD, and it also means, when it is initialized correctly, it should behave identically. As for the LD sub-cpu code, I've been disassembling the sub-cpu bioses, and it seems that mode 1 is also supported by the LD sub-cpu bios, so it should be possible to use mode 1 to access either a CD or an LD on the LaserActive.

I think the answer lies in the main cpu code for the LaserActive bios. I think there's some extra step that the CD bios performs on the LaserActive, which selects either LD or CD mode. If LD mode is selected, the LD sub-cpu bios needs to be loaded. If CD mode is selected, the CD sub-cpu bios needs to be loaded. The hardware most likely either defaults to LD mode, or neither, and this is why mode 1 boot fails for the LaserActive currently. The CD sub-cpu bios is loaded, but the hardware isn't in CD mode, so the bios doesn't work. I've checked, and the LD sub-cpu bios is loaded when the CD bios menu is running on the main cpu, so this supports the theory that CD mode isn't the default. What we need to do is dig through the LaserActive bios a little more, and figure out what needs to be done to get the LaserActive hardware to transition from LD to CD mode.

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

Post by Chilly Willy » Thu Dec 29, 2011 6:52 pm

Nemesis wrote:It doesn't seem like they removed mode 1 support. My tests show that the sub-cpu code at 0x1AD00 is loaded by the LaserActive bios when a CD is inserted, while the sub-cpu code at 0xD500 is loaded when an LD is inserted. The LD sub-cpu code has a lot of differences to the normal MegaCD boot code, but the CD sub-cpu code is identical, byte for byte, to the sub-cpu code in the standard V1 SegaCD model 1 bios. This means the hardware itself must have a compatibility mode for the LC8951 CDD controller in the standard MegaCD, and it also means, when it is initialized correctly, it should behave identically. As for the LD sub-cpu code, I've been disassembling the sub-cpu bioses, and it seems that mode 1 is also supported by the LD sub-cpu bios, so it should be possible to use mode 1 to access either a CD or an LD on the LaserActive.

I think the answer lies in the main cpu code for the LaserActive bios. I think there's some extra step that the CD bios performs on the LaserActive, which selects either LD or CD mode. If LD mode is selected, the LD sub-cpu bios needs to be loaded. If CD mode is selected, the CD sub-cpu bios needs to be loaded. The hardware most likely either defaults to LD mode, or neither, and this is why mode 1 boot fails for the LaserActive currently. The CD sub-cpu bios is loaded, but the hardware isn't in CD mode, so the bios doesn't work. I've checked, and the LD sub-cpu bios is loaded when the CD bios menu is running on the main cpu, so this supports the theory that CD mode isn't the default. What we need to do is dig through the LaserActive bios a little more, and figure out what needs to be done to get the LaserActive hardware to transition from LD to CD mode.
Yeah, sure sounds like it. There's a register that needs to be initialized from the MD side first that makes no difference to the regular CDs, but makes the LA start in the proper mode... I'll try disassembling the LA BIOS I have to see how it compares to the regular BIOS for MD side init.

At least I guessed right that the sub-cpu bios at 0x1AD00 was the CD bios. :)

It also makes sense now that my example worked fine with the LA BIOS in Fusion... the Sub-CPU BIOS is the same, so it works fine. What's missing is the extra for the LA init.

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

Post by Chilly Willy » Fri Dec 30, 2011 6:36 pm

Well, I haven't seen anything that stands out. It loads the CD BIOS at $802 and the LD BIOS at $864, but neither seems to do anything special other than decompress the BIOS and keep clearing ram to $25400 - which brings me to why I'm posting. One thing my startup doesn't do is clear memory. The LA BIOS clears ALL of Program RAM, and then (as mentioned) clears from the end of the decompressed BIOS to offset $5400. The code should probably clear the first bank of Program RAM, at least.

Code: Select all

    put_str("Decompressing Sub-CPU BIOS", GREEN_TEXT, 2, 3);
    write_word(0xA12002, 0x0002); // no write-protection, bank 0, 2M mode, Word RAM assigned to Sub-CPU
    memset(0x420000, 0, 0x20000);
    Kos_Decomp(bios, (uint8_t *)0x420000);
Perhaps the BIOS needs certain areas in the work area to be cleared initially to startup okay.

EDIT: Sik had a very interesting idea - boot the LD BIOS first, then try booting the CD BIOS. Since the CD BIOS is the same, but doesn't work, maybe you have to boot the LD BIOS to initialize the hardware, then the CD may work. So I guess what we should try is decompress 0xD500 to the program ram, start the Sub-CPU, wait awhile, stop the Sub-CPU, decompress the CD BIOS to program ram, and then reset the Sub-CPU.

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Mon Jan 02, 2012 4:44 am

I've just made a discovery. I've been disassembling the LaserActive and standard SegaCD bioses, and while looking through the code, I've discovered another mode of SegaCD booting which is completely undocumented, and which I've never heard of before. It appears that the MegaCD supports loading a CD boot program directly from a cartridge, where the cartridge doesn't assert the "cart in" line, so it's mapped at 0x400000, and the MegaCD bios boots first. This means that rather than what we've been doing, where we initialize the MegaCD hardware manually, in this mode, the MegaCD initializes itself, then simply loads a sub-cpu program from the cartridge and executes it, and jumps to your custom the main cpu code at 0x400200, rather than showing the MegaCD bios interface.

Actually, after looking at the documentation again, I'm beginning to suspect this mode of booting is the "real" mode 1 that Sega was referring to, but no actual released game makes use of it. Flux could have made use of mode 1 booting, but chose instead to manually load and initialize the CD subsystem itself. I don't think this method is actually called anything, it's just an officially unsupported, but technically possible, method of initializing the CD hardware manually, but mode 1 seems to be quite a separate thing.

I haven't tested this on the hardware yet, but my analysis of the bios shows that mode 1, or booting from the cartridge, is done automatically, when a cartridge is inserted matching the following criteria:
1. The cart must not be asserting the cart in line, so that it appears in the memory map at 0x400000, and the MegaCD bios starts first.
2. The cart must have "SEGA" appearing at 0x100 in the header.
3. The cartridge must have the normal CD security program for the correct region located immediately after the header, at 0x200.

If these requirements are met, the MegaCD bios will try and boot from the cartridge immediately after initialization. The order of boot steps the MegaCD bios uses is as follows:
1. Load the sub-cpu bios
2. Load data from address pointed at by 0x4001A8.l into sub-cpu program ram at 0x6000, for the number of bytes specified in 0x4001AC.l, or until the end of the last bank of program ram is reached, and start the sub-cpu program running.
3. Jump to 0x400200 to start running the security program, followed by the custom main cpu program.

So, this means in order to do a mode 1 boot, you just need a ROM which has "SEGA" at 0x100, the correct boot program you would normally use on a CD located at 0x200, and then whatever main cpu code you want appearing directly after the boot program. If you also want to load a sub-cpu program, as you normally would when loading from a CD, you put the address of the sub-cpu program at 0x1A8 in the header, and the length of the program data at 0x1AC in the header. Compile the whole thing for a base address of 0x400000, and it should work.

There is one compication with trying to use this boot mode on the actual hardware with a flashcart. If the flashcart has a boot menu, such as the EverDrive, it won't work directly, since the boot menu will be mapped in on power-up, not your ROM data. This can be worked around with some runtime toggling of cart-in and resetting, but the easiest way is to use a more basic flashcart, such as the tototek flashcart, where you can directly load your code at corret address on power on, without having to run a boot menu.


Oh, and since we've been talking about the LaserActive, I should note that the LaserActive bios has half disabled mode 1 boot support. The bios still has the code to test for a mode 1 boot cart, and jump to 0x400200 to boot it, but the code which loads the sub-cpu program has been removed. This means you should be able to boot the system, but you won't be able to load a sub-cpu program automatically on boot up.

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Mon Jan 02, 2012 5:02 am

EDIT: Sik had a very interesting idea - boot the LD BIOS first, then try booting the CD BIOS. Since the CD BIOS is the same, but doesn't work, maybe you have to boot the LD BIOS to initialize the hardware, then the CD may work. So I guess what we should try is decompress 0xD500 to the program ram, start the Sub-CPU, wait awhile, stop the Sub-CPU, decompress the CD BIOS to program ram, and then reset the Sub-CPU.
I think that's probably the answer. The LD bios definitely starts with the LD sub-cpu program loaded first, then transitions to the CD sub-cpu program after that if required. I've been looking through the startup code, and there are a few things that the bios does that we're not, but this is definitely the main one.

If this is the case, getting your code working should actually be as simple as starting up the MegaLD bios, then while it's running, toggle cart-in and reset, so that the system boots from the cart, already having the LD sub-cpu program loaded. I'll give this a try on the hardware when I'm able.

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

Post by Chilly Willy » Mon Jan 02, 2012 5:57 pm

I noticed that "attempt to run special cart at 0x400200" as well, but put it down to a BRAM cart that needed custom read/write code. I think you're right about it being the REAL mode 1 support. The requirements as you stated them are a "normal" SEGA licensed cart that passes TMSS with SEGA's "standard" security block for the startup. The only difference is the start address, and the ability to specify the sub-cpu program in the header.

I don't think most flash carts out have the ability to take advantage of this mode without hacking them - the Neo Myth might, but the others almost certainly don't. You'd have to tape over the cart line on the Tototek MD-Pro to experiment with it. Anywho, given the LA seems to have removed part of this mode, it's probably better to continue on as we have trying to get the current experiment working. It already works for everything but the LA, and on all current flash carts without change.

Basically, if the sub-cpu bios is found at 0x41AD00, we know it's an LA, so we decompress the bios at 0x40D500, start the sub-cpu, wait awhile, stop the sub-cpu, then continue with the rest of the program like normal.

EDIT: Something like this

Code: Select all

    sprintf(text, "CD Sub-CPU BIOS detected at 0x%6X", (uint32_t)bios);
    put_str(text, GREEN_TEXT, 2, 2);

    /*
     * Reset the Sub-CPU, request the bus
     */
    write_byte(0xA12001, 0x02);
    while (!(read_byte(0xA12001) & 2)) write_byte(0xA12001, 0x02); // wait on bus acknowledge

    /*
     * If LaserActive, load and start the LD BIOS, wait for it to init, then continue
     */
    if (bios == (uint8_t *)0x41AD00)
    {
        int now;

        /*
        * Decompress Sub-CPU LD BIOS to Program RAM at 0x00000
        */
        put_str("Decompressing LD BIOS", GREEN_TEXT, 2, 3);
        write_word(0xA12002, 0x0002); // no write-protection, bank 0, 2M mode, Word RAM assigned to Sub-CPU
        memset(0x420000, 0, 0x20000);
        Kos_Decomp(0x40D500, (uint8_t *)0x420000);

        write_byte(0xA12002, 0x2A); // write-protect up to 0x05400
        write_byte(0xA12001, 0x01); // clear bus request, deassert reset - allow CD Sub-CPU to run
        while (!(read_byte(0xA12001) & 1)) write_byte(0xA12001, 0x01); // wait on Sub-CPU running

        /*
        * Set the vertical blank handler to generate Sub-CPU level 2 ints.
        * The Sub-CPU BIOS needs these in order to run.
        */
        write_long((uint32_t)&vblank_vector, (uint32_t)&gen_lvl2);
        set_sr(0x2000); // enable interrupts

        /*
         * Wait for the LD BIOS to init the hardware
         */
        now = gTicks;
        while (gTicks < (now + 200)) ; // wait a few seconds (remember, needs ints enabled)

        /*
         * Stop Sub-CPU
         */
        set_sr(0x2700); // disable interrupts
        write_long((uint32_t)&vblank_vector, 0);
        write_byte(0xA12001, 0x02); // reset cpu and request bus
        while (!(read_byte(0xA12001) & 2)) write_byte(0xA12001, 0x02); // wait on bus acknowledge
    }

Post Reply