Difference between revisions of "Sega MegaDrive"

From SizeCoding
Jump to: navigation, search
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
== SEGA MegaDrive / Genesis ==
 
== SEGA MegaDrive / Genesis ==
The Sinclair QL (for Quantum Leap) is a personal computer launched by Sinclair Research in 1984, as an upper-end counterpart to the ZX Spectrum.
+
The SEGA MegaDrive / Genesis is a 16-bit videogame console released by SEGA in 1989.
It was aimed at the serious home user and professional and executive users markets from small to medium-sized businesses and higher educational establishments, but failed to achieve commercial success.
+
 
The Sinclair QL uses a Motorola 68008.CPU with 32-bit internal data registers, but an 8-bit external data bus.
+
It features:
 +
* 320x240 resolution (PAL)
 +
* 4x 16 color palettes
 +
* Tile based display chip with 2 scrolling tilemaps
 +
* 64 Sprites (up to 4x4tiles in size each)
 +
* 64K of dedicated Video Memory (VRAM)
 +
* YM2612 Sound Chip
  
 
=== Setting up ===
 
=== Setting up ===
Line 84: Line 90:
 
dc.l  INT_Null ; Unused (reserved)
 
dc.l  INT_Null ; Unused (reserved)
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
This vector table is then followed by the ROM header at 0x100
  
 
=== ROM Header ===
 
=== ROM Header ===
Further header information at: https://plutiedev.com/rom-header
+
The ROM Header is a structure located at 0x100 that specifies some metadata about the ROM, like its name, author, version number, release date, region, and any special peripherals used.
 +
 
 +
Note that the Mega Drive console itself doesn't read any of this, it's more a convenience for the programmer, but most emulators will read the title and region. Further header information at: https://plutiedev.com/rom-header
  
 
=== Memory map ===
 
=== Memory map ===
  
 
<syntaxhighlight lang="">
 
<syntaxhighlight lang="">
 +
Start address End address Description 32X SH-2 address
 +
$000000 $3FFFFF Cartridge ROM/RAM $2000000-$23FFFFF
 +
$400000 $7FFFFF Reserved (used by the Mega-CD and 32X)
 +
$800000 $9FFFFF Reserved (used by the 32X)
 +
$840000 $85FFFF 32X frame buffer $4000000-$401FFFF
 +
$860000 $87FFFF 32X frame buffer overwrite mode $4020000-$403FFFF
 +
$880000 $8FFFFF 32X cartridge ROM (first 512kB bank only)
 +
$900000 $9FFFFF 32X cartridge bankswitched ROM (any 512kB bank, controlled by 32X registers)
 +
$A00000 $A0FFFF Z80 memory space
 +
$A10000 $A10001 Version register
 +
$A10002 $A10003 Controller 1 data
 +
$A10004 $A10005 Controller 2 data
 +
$A10006 $A10007 Expansion port data
 +
$A10008 $A10009 Controller 1 control
 +
$A1000A $A1000B Controller 2 control
 +
$A1000C $A1000D Expansion port control
 +
$A1000E $A1000F Controller 1 serial transmit
 +
$A10010 $A10011 Controller 1 serial receive
 +
$A10012 $A10013 Controller 1 serial control
 +
$A10014 $A10015 Controller 2 serial transmit
 +
$A10016 $A10017 Controller 2 serial receive
 +
$A10018 $A10019 Controller 2 serial control
 +
$A1001A $A1001B Expansion port serial transmit
 +
$A1001C $A1001D Expansion port serial receive
 +
$A1001E $A1001F Expansion port serial control
 +
$A10020 $A10FFF Reserved
 +
$A11000 Memory mode register
 +
$A11002 $A110FF Reserved
 +
$A11100 $A11101 Z80 bus request
 +
$A11102 $A111FF Reserved
 +
$A11200 $A11201 Z80 reset
 +
$A11202 $A12FFF Reserved
 +
$A13000 $A130FF TIME registers; used to send signals to the cartridge
 +
$A130EC $A130EF "MARS" when 32X is attached
 +
$A130F1 SRAM access register
 +
$A130F3 Bank register for address $80000-$FFFFF
 +
$A130F5 Bank register for address $100000-$17FFFF
 +
$A130F7 Bank register for address $180000-$1FFFFF
 +
$A130F9 Bank register for address $200000-$27FFFF
 +
$A130FB Bank register for address $280000-$2FFFFF
 +
$A130FD Bank register for address $300000-$37FFFF
 +
$A130FF Bank register for address $380000-$3FFFFF
 +
$A14000 $A14003 TMSS "SEGA"
 +
$A14101 TMSS/cartridge register
 +
$A14102 $BFFFFF Reserved
 +
$C00000 $C00001 VDP data port
 +
$C00002 $C00003 VDP data port (mirror)
 +
$C00004 $C00005 VDP control port
 +
$C00006 $C00007 VDP control port (mirror)
 +
$C00008 $C00009 VDP H/V counter
 +
$C0000A $C0000F VDP H/V counter (mirror)
 +
$C00011 PSG output
 +
$C00013 $C00017 PSG output (mirror)
 +
$C0001C $C0001D Debug register
 +
$C0001E $C0001F Debug register (mirror)
 +
$C00020 $FEFFFF Reserved
 +
$FF0000 $FFFFFF 68000 RAM
 +
</syntaxhighlight>
 +
 +
 +
=== Startup ===
 +
From here it jumps to the CPU entry point and we need to the minimum startup here:
 +
The MegaDrive in Supervisor mode already.
 +
 +
The TMSS ROM does is place the SEGA text on screen and run a timer, then I think it just unmaps itself from the address space and does a soft reset.
 +
 +
<syntaxhighlight lang="">
 +
move.l #'SEGA', ($A14000) ; disable TMSS so that accessing the VDP won't lock up the console
 +
tst.w ($C00004)    ; test VDP CONTROL to stop the VDP, this makes it discard anything that was previously in the FIFO
 +
move.w #$2700, sr ; set IPL level 7
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
This setup should give you fully predictable state on every power cycle or reset
 +
that's just to play it safe, but getting a spurious interrupt before you even have the chance to disable interrupt processing is pretty much impossible in the real world
  
 
=== Video display ===
 
=== Video display ===
To be added.
+
So after the TMSS boot sequence you'll have a black screen but some leftover stuff in VRAM
 +
You'll have to enable display which you already need to to when setting the VDP registers to your desired configuration And no, the TMSS ROM doesn't use any interrupts
 +
It doesn't even use DMA, the 68k copies all the graphics and all.
 +
 
 +
The VDP always initializes to 320x224, to get 320x240 you have to enable V30 mode
 +
that's why sonic 1 on PAL has borders at the top and bottom they didn't care to change the video height, and PAL systems have a smaller window for 320x224.
 +
 
 +
==== VDP Setup ====
 +
VDP Access is handled by the following 3 ports and VDP Register constants:
 +
<syntaxhighlight lang="">
 +
VdpCtrl:    equ $C00004  ; VDP control port
 +
VdpData:    equ $C00000  ; VDP data port
 +
HvCounter:  equ $C00008  ; H/V counter
 +
 
 +
VDPREG_MODE1:    equ $8000  ; Mode register #1
 +
VDPREG_MODE2:    equ $8100  ; Mode register #2
 +
VDPREG_MODE3:    equ $8B00  ; Mode register #3
 +
VDPREG_MODE4:    equ $8C00  ; Mode register #4
 +
 
 +
VDPREG_PLANEA:    equ $8200  ; Plane A table address
 +
VDPREG_PLANEB:    equ $8400  ; Plane B table address
 +
VDPREG_SPRITE:    equ $8500  ; Sprite table address
 +
VDPREG_WINDOW:    equ $8300  ; Window table address
 +
VDPREG_HSCROLL:  equ $8D00  ; HScroll table address
 +
 
 +
VDPREG_SIZE:      equ $9000  ; Plane A and B size
 +
VDPREG_WINX:      equ $9100  ; Window X split position
 +
VDPREG_WINY:      equ $9200  ; Window Y split position
 +
VDPREG_INCR:      equ $8F00  ; Autoincrement
 +
VDPREG_BGCOL:    equ $8700  ; Background color
 +
VDPREG_HRATE:    equ $8A00  ; HBlank interrupt rate
  
==== VDP ====
+
VDPREG_DMALEN_L:  equ $9300  ; DMA length (low)
To be added.
+
VDPREG_DMALEN_H:  equ $9400  ; DMA length (high)
 +
VDPREG_DMASRC_L:  equ $9500  ; DMA source (low)
 +
VDPREG_DMASRC_M:  equ $9600  ; DMA source (mid)
 +
VDPREG_DMASRC_H:  equ $9700  ; DMA source (high)
 +
</syntaxhighlight>
  
 +
A somewhat limited VDP setup can look something like this:
 
<syntaxhighlight lang="">
 
<syntaxhighlight lang="">
  to be added
+
  lea    (VdpCtrl), a0
 +
    move.w #VDPREG_MODE1|$04, (a0)    ; Mode register #1
 +
    move.w  #VDPREG_MODE2|$04, (a0)    ; Mode register #2
 +
    move.w  #VDPREG_MODE3|$00, (a0)    ; Mode register #3
 +
    move.w  #VDPREG_MODE4|$81, (a0)    ; Mode register #4
 +
   
 +
    move.w  #VDPREG_PLANEA|$30, (a0)  ; Plane A address
 +
    move.w  #VDPREG_PLANEB|$07, (a0)  ; Plane B address
 +
    move.w  #VDPREG_SPRITE|$78, (a0)  ; Sprite address
 +
    move.w  #VDPREG_WINDOW|$34, (a0)  ; Window address
 +
    move.w  #VDPREG_HSCROLL|$3D, (a0)  ; HScroll address
 +
   
 +
    move.w  #VDPREG_SIZE|$01, (a0)    ; Tilemap size
 +
    move.w  #VDPREG_WINX|$00, (a0)    ; Window X split
 +
    move.w  #VDPREG_WINY|$00, (a0)    ; Window Y split
 +
    move.w  #VDPREG_INCR|$02, (a0)    ; Autoincrement
 +
    move.w  #VDPREG_BGCOL|$00, (a0)    ; Background color
 +
    move.w  #VDPREG_HRATE|$FF, (a0)    ; HBlank IRQ rate
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
 +
For more information, check out https://plutiedev.com/vdp-setup
 +
 +
==== VDP Register ====
 +
Here is a detailed explaination of the different VDP registers:
 +
https://plutiedev.com/vdp-registers
 +
  
 
==== Sprites ====
 
==== Sprites ====

Latest revision as of 17:28, 18 December 2025

SEGA MegaDrive / Genesis

The SEGA MegaDrive / Genesis is a 16-bit videogame console released by SEGA in 1989.

It features:

  • 320x240 resolution (PAL)
  • 4x 16 color palettes
  • Tile based display chip with 2 scrolling tilemaps
  • 64 Sprites (up to 4x4tiles in size each)
  • 64K of dedicated Video Memory (VRAM)
  • YM2612 Sound Chip

Setting up

The real hardware and BlastEm emulator don't require exact ROM headers, but you might want to distribute an emulator friendly version of your production as well for broader emulator compatibility.

CPU Vector table

This must be the very first thing in the ROM, since the CPU reads it from 0x0000 on bootup. The Vector table is a table of addresses that the CPU needs to know about - things like stack address, "main()" function address, vertical/horizontal interrupt addresses, etc. For any interrupts we don't want to handle, we specify INT_Null (an interrupt at the bottom of the file that doesn't do anything).

        dc.l   0x00FFE000			; Initial stack pointer value
	dc.l   CPU_EntryPoint		; Start of program
	dc.l   CPU_Exception 		; Bus error
	dc.l   CPU_Exception 		; Address error
	dc.l   CPU_Exception 		; Illegal instruction
	dc.l   CPU_Exception 		; Division by zero
	dc.l   CPU_Exception 		; CHK CPU_Exception
	dc.l   CPU_Exception 		; TRAPV CPU_Exception
	dc.l   CPU_Exception 		; Privilege violation
	dc.l   INT_Null				; TRACE exception
	dc.l   INT_Null				; Line-A emulator
	dc.l   INT_Null				; Line-F emulator
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Spurious exception
	dc.l   INT_Null				; IRQ level 1
	dc.l   INT_Null				; IRQ level 2
	dc.l   INT_Null				; IRQ level 3
	dc.l   INT_HInterrupt		; IRQ level 4 (horizontal retrace interrupt)
	dc.l   INT_Null  			; IRQ level 5
	dc.l   INT_VInterrupt		; IRQ level 6 (vertical retrace interrupt)
	dc.l   INT_Null				; IRQ level 7
	dc.l   INT_Null				; TRAP #00 exception
	dc.l   INT_Null				; TRAP #01 exception
	dc.l   INT_Null				; TRAP #02 exception
	dc.l   INT_Null				; TRAP #03 exception
	dc.l   INT_Null				; TRAP #04 exception
	dc.l   INT_Null				; TRAP #05 exception
	dc.l   INT_Null				; TRAP #06 exception
	dc.l   INT_Null				; TRAP #07 exception
	dc.l   INT_Null				; TRAP #08 exception
	dc.l   INT_Null				; TRAP #09 exception
	dc.l   INT_Null				; TRAP #10 exception
	dc.l   INT_Null				; TRAP #11 exception
	dc.l   INT_Null				; TRAP #12 exception
	dc.l   INT_Null				; TRAP #13 exception
	dc.l   INT_Null				; TRAP #14 exception
	dc.l   INT_Null				; TRAP #15 exception
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)
	dc.l   INT_Null				; Unused (reserved)

This vector table is then followed by the ROM header at 0x100

ROM Header

The ROM Header is a structure located at 0x100 that specifies some metadata about the ROM, like its name, author, version number, release date, region, and any special peripherals used.

Note that the Mega Drive console itself doesn't read any of this, it's more a convenience for the programmer, but most emulators will read the title and region. Further header information at: https://plutiedev.com/rom-header

Memory map

Start address 	End address 	Description 	32X SH-2 address
$000000 	$3FFFFF 	Cartridge ROM/RAM 	$2000000-$23FFFFF
$400000 	$7FFFFF 	Reserved (used by the Mega-CD and 32X)
$800000 	$9FFFFF 	Reserved (used by the 32X)
$840000 	$85FFFF 	32X frame buffer 	$4000000-$401FFFF
$860000 	$87FFFF 	32X frame buffer overwrite mode 	$4020000-$403FFFF
$880000 	$8FFFFF 	32X cartridge ROM (first 512kB bank only)
$900000 	$9FFFFF 	32X cartridge bankswitched ROM (any 512kB bank, controlled by 32X registers)
$A00000 	$A0FFFF 	Z80 memory space
$A10000 	$A10001 	Version register
$A10002 	$A10003 	Controller 1 data
$A10004 	$A10005 	Controller 2 data
$A10006 	$A10007 	Expansion port data
$A10008 	$A10009 	Controller 1 control
$A1000A 	$A1000B 	Controller 2 control
$A1000C 	$A1000D 	Expansion port control
$A1000E 	$A1000F 	Controller 1 serial transmit
$A10010 	$A10011 	Controller 1 serial receive
$A10012 	$A10013 	Controller 1 serial control
$A10014 	$A10015 	Controller 2 serial transmit
$A10016 	$A10017 	Controller 2 serial receive
$A10018 	$A10019 	Controller 2 serial control
$A1001A 	$A1001B 	Expansion port serial transmit
$A1001C 	$A1001D 	Expansion port serial receive
$A1001E 	$A1001F 	Expansion port serial control
$A10020 	$A10FFF 	Reserved
$A11000 	Memory mode register
$A11002 	$A110FF 	Reserved
$A11100 	$A11101 	Z80 bus request
$A11102 	$A111FF 	Reserved
$A11200 	$A11201 	Z80 reset
$A11202 	$A12FFF 	Reserved
$A13000 	$A130FF 	TIME registers; used to send signals to the cartridge
$A130EC 	$A130EF 	"MARS" when 32X is attached
$A130F1 	SRAM access register
$A130F3 	Bank register for address $80000-$FFFFF
$A130F5 	Bank register for address $100000-$17FFFF
$A130F7 	Bank register for address $180000-$1FFFFF
$A130F9 	Bank register for address $200000-$27FFFF
$A130FB 	Bank register for address $280000-$2FFFFF
$A130FD 	Bank register for address $300000-$37FFFF
$A130FF 	Bank register for address $380000-$3FFFFF
$A14000 	$A14003 	TMSS "SEGA"
$A14101 	TMSS/cartridge register
$A14102 	$BFFFFF 	Reserved
$C00000 	$C00001 	VDP data port
$C00002 	$C00003 	VDP data port (mirror)
$C00004 	$C00005 	VDP control port
$C00006 	$C00007 	VDP control port (mirror)
$C00008 	$C00009 	VDP H/V counter
$C0000A 	$C0000F 	VDP H/V counter (mirror)
$C00011 	PSG output
$C00013 	$C00017 	PSG output (mirror)
$C0001C 	$C0001D 	Debug register
$C0001E 	$C0001F 	Debug register (mirror)
$C00020 	$FEFFFF 	Reserved
$FF0000 	$FFFFFF 	68000 RAM


Startup

From here it jumps to the CPU entry point and we need to the minimum startup here: The MegaDrive in Supervisor mode already.

The TMSS ROM does is place the SEGA text on screen and run a timer, then I think it just unmaps itself from the address space and does a soft reset.

move.l #'SEGA', ($A14000) ; disable TMSS so that accessing the VDP won't lock up the console
tst.w ($C00004)    ; test VDP CONTROL to stop the VDP, this makes it discard anything that was previously in the FIFO
move.w #$2700, sr ; set IPL level 7

This setup should give you fully predictable state on every power cycle or reset that's just to play it safe, but getting a spurious interrupt before you even have the chance to disable interrupt processing is pretty much impossible in the real world

Video display

So after the TMSS boot sequence you'll have a black screen but some leftover stuff in VRAM You'll have to enable display which you already need to to when setting the VDP registers to your desired configuration And no, the TMSS ROM doesn't use any interrupts It doesn't even use DMA, the 68k copies all the graphics and all.

The VDP always initializes to 320x224, to get 320x240 you have to enable V30 mode that's why sonic 1 on PAL has borders at the top and bottom they didn't care to change the video height, and PAL systems have a smaller window for 320x224.

VDP Setup

VDP Access is handled by the following 3 ports and VDP Register constants:

VdpCtrl:    equ $C00004  ; VDP control port
VdpData:    equ $C00000  ; VDP data port
HvCounter:  equ $C00008  ; H/V counter

VDPREG_MODE1:     equ $8000  ; Mode register #1
VDPREG_MODE2:     equ $8100  ; Mode register #2
VDPREG_MODE3:     equ $8B00  ; Mode register #3
VDPREG_MODE4:     equ $8C00  ; Mode register #4

VDPREG_PLANEA:    equ $8200  ; Plane A table address
VDPREG_PLANEB:    equ $8400  ; Plane B table address
VDPREG_SPRITE:    equ $8500  ; Sprite table address
VDPREG_WINDOW:    equ $8300  ; Window table address
VDPREG_HSCROLL:   equ $8D00  ; HScroll table address

VDPREG_SIZE:      equ $9000  ; Plane A and B size
VDPREG_WINX:      equ $9100  ; Window X split position
VDPREG_WINY:      equ $9200  ; Window Y split position
VDPREG_INCR:      equ $8F00  ; Autoincrement
VDPREG_BGCOL:     equ $8700  ; Background color
VDPREG_HRATE:     equ $8A00  ; HBlank interrupt rate

VDPREG_DMALEN_L:  equ $9300  ; DMA length (low)
VDPREG_DMALEN_H:  equ $9400  ; DMA length (high)
VDPREG_DMASRC_L:  equ $9500  ; DMA source (low)
VDPREG_DMASRC_M:  equ $9600  ; DMA source (mid)
VDPREG_DMASRC_H:  equ $9700  ; DMA source (high)

A somewhat limited VDP setup can look something like this:

   lea     (VdpCtrl), a0 
    move.w  #VDPREG_MODE1|$04, (a0)    ; Mode register #1
    move.w  #VDPREG_MODE2|$04, (a0)    ; Mode register #2
    move.w  #VDPREG_MODE3|$00, (a0)    ; Mode register #3
    move.w  #VDPREG_MODE4|$81, (a0)    ; Mode register #4
    
    move.w  #VDPREG_PLANEA|$30, (a0)   ; Plane A address
    move.w  #VDPREG_PLANEB|$07, (a0)   ; Plane B address
    move.w  #VDPREG_SPRITE|$78, (a0)   ; Sprite address
    move.w  #VDPREG_WINDOW|$34, (a0)   ; Window address
    move.w  #VDPREG_HSCROLL|$3D, (a0)  ; HScroll address
    
    move.w  #VDPREG_SIZE|$01, (a0)     ; Tilemap size
    move.w  #VDPREG_WINX|$00, (a0)     ; Window X split
    move.w  #VDPREG_WINY|$00, (a0)     ; Window Y split
    move.w  #VDPREG_INCR|$02, (a0)     ; Autoincrement
    move.w  #VDPREG_BGCOL|$00, (a0)    ; Background color
    move.w  #VDPREG_HRATE|$FF, (a0)    ; HBlank IRQ rate


For more information, check out https://plutiedev.com/vdp-setup

VDP Register

Here is a detailed explaination of the different VDP registers: https://plutiedev.com/vdp-registers


Sprites

To be added

; to be added

Sound

To be added.

; to be added

Additional Resources