Mega CD LEDs

If you're using the BIOS, then the BIOS will take care of the LEDs for you. The information here is for when you aren't using the BIOS. If you absolutely have to override the BIOS, check the LEDSET call in the BIOS documentation.

Mega CD model 2 only includes the Access LED (not the Ready one). Flashcarts and emulators may not show the lights at all. Even when they do, they may be easy to miss. Do not rely on the LEDs to show any important information.

Setting the LEDs

The LEDs can only be changed from the Sub-CPU.

To change whether the LEDs are on/off, you have to write to the upper byte of CdSubCtrl ($FF8000). You can use byte-wide writes, and in fact it's encouraged to reduce the risk of touching something you shouldn't.

Here is what the value to write should be:

LED_NONE:   equ %00
LED_GREEN:  equ %10  ; READY
LED_RED:    equ %01  ; ACCESS
LED_BOTH:   equ %11  ; READY+ACCESS

Then if e.g. you want to turn on only the green LED, you can do this:

    move.b  #LED_GREEN, (CdSubCtrl)

Common LED meanings

While in theory you could set the LEDs to anything, there are some combinations with common meanings (as used by the BIOS) and as such it's a good idea to stick to them:

Common LED meanings
GreenRedMeaning
OffOffNot running
OnOffReady
OnBlinkNo disc
OnOnCD access
BlinkOffStand-by
BlinkBlinkError

In the case of error, both LEDs should blink together (not alternating).

Simple error handler

This is a simple error handler snippet for the Sub CPU that will blink both LEDs if it crashes for whatever reason. It gives you a quick way to know that something went wrong on its side before having to resort to debugging.

This doesn't rely on any timers for blinking but on burning lots of cycles.

ErrorInt:
    ; Disable all interrupts
    ; (some errors don't disable them!)
    move.w  #$2700, sr
    
@Loop:
    ; Turn on both LEDs and wait
    move.b  #LED_BOTH, (CdSubCtrl)
    dbf     d0, *
    dbf     d0, *
    dbf     d0, *
    dbf     d0, *
    dbf     d0, *
    dbf     d0, *
    
    ; Turn off both LEDs and wait
    move.b  #LED_NONE, (CdSubCtrl)
    dbf     d0, *
    dbf     d0, *
    dbf     d0, *
    dbf     d0, *
    dbf     d0, *
    dbf     d0, *
    
    ; Repeat
    bra.s   @Loop