Research / Megadrive Programming / VDP
VDP
Ports:
Address | Description |
$C00000 | Data port |
$C00002 | Data port (mirror) |
$C00004 | Control port |
$C00006 | Control port (mirror) |
$C00008 | HV counter |
$C0000A | HV counter (mirror) |
$C0000C | HV counter (mirror) |
$C0000E | HV counter (mirror) |
$C00011 | SN76489 PSG |
$C00013 | SN76489 PSG (mirror) |
$C00015 | SN76489 PSG (mirror) |
$C00017 | SN76489 PSG (mirror) |
$C00018 | Unused |
$C0001A | Unused |
$C0001C | Unused |
$C0001F | Unused |
Data port
Here, you write data after programming the control port.
Control port
Reading the control port returns a status word:
Bit 15 - Always 0
Bit 14 - Always 0
Bit 13 - Always 1
Bit 12 - Always 1
Bit 11 - Always 0
Bit 10 - Always 1
Bit 9 - FIFO empty
Bit 8 - FIFO full
Bit 7 - V blank pending
Bit 6 - Sprite overflow
Bit 5 - Sprite collision
Bit 4 - Odd frame
Bit 3 - Vertical blanking
Bit 2 - Horizontal blanking
Bit 1 - DMA in process
Bit 0 - PAL mode flag (1 for PAL, 0 for not PAL)
Accessing VDP RAM
You can access VDP RAM writing a 32-bit command to control port then reading/writing to the data port. Here's the command:
CD1 CD0 A13 A12 A11 A10 A09 A08 (D31-D24)
A07 A06 A05 A04 A03 A02 A01 A00 (D23-D16)
? ? ? ? ? ? ? ? (D15-D8)
CD5 CD4 CD3 CD2 ? ? A15 A14 (D7-D0)
A00-A15 - address
CD0-CD3 - code
CD4 - 1 if VRAM copy DMA mode. 0 otherwise.
CD5 - DMA operation
Bits CD3-CD0:
0000 - VRAM read
0001 - VRAM write
0011 - CRAM write
0100 - VSRAM read
0101 - VSRAM write
1000 - CRAM read
Example:
move.l #$C0000000,($c00004).l ;program the control register
move.w #$0EEE,($c00000).l ;move colo(u)r EEE to CRAM
Programming VDP registers
VDP has 23 registers that can be programmed writing a 16-bit command to the control port:
1 0 ? R04 R03 R02 R01 R00 (D15-D8)
D07 D06 D05 D04 D03 D02 D01 D00 (D7-D0)
R04-R00 - register
D07-D00 - data
Example:
;set the border colo(u)r to palette $1, colo(u)r $2
move.w #$8712,($c00004).l
Registers can be also set by writing a 32-bit command (2 registers at a time):
;set the border color to palette $1, color $2
;and set the VDP auto increment data to $2
move.l #$87128F02,($c00004).l
List of registers:
Register | Name | Description |
$00 | Mode Set Register No. 1 |
Bits 7-5 - unused
Bit 4 - H interrupts enable
Bit 3 - 1 = invalid display
Bit 2 - 1 = 8 colour mode (only bits 1, 5 and 9 of colours are displayed)
Bit 1 - 1 = HV counter latch enable
Bit 0 - 1 = disable display
|
$01 | Mode Set Register No. 2 |
Bit 7 - TMS9918 / Genesis display select
Bit 6 - 1 = display enabled, 0 = fill the screen with backdrop colour (border colour)
Bit 5 - V interrupts enable
Bit 4 - DMA enable
Bit 3 - 1 = PAL (240 lines), 0 = NTSC (224 lines)
Bit 2 - SMS / Genesis display select
Bit 1 - 1 = HV counter latch enable
Bit 0 - 1 = disable display
|
$02 | VRAM Address for Scroll A |
Bits 5-3 of this register correspond to bits A15-A13 of the name table
address for plane A.
|
$03 | VRAM Address for Window |
Bits 5-1 of this register correspond to bits A15-A11 of the name table
address for the window.
In 40-cell mode, A11 is always forced to zero.
|
$04 | VRAM Address for Scroll B |
Bits 2-0 of this register correspond to bits A15-A11 of the name table
address for plane B.
|
$05 | VRAM Address for Sprite Attributes |
Bits 6-0 of this register correspond to bits A15-A09 of the sprite
attribute table.
In 40-cell mode, A09 is always forced to zero.
|
$06 | Unused |
(Used by Master System)
|
$07 | Backdrop colour |
Bits 5-4 - palette line in CRAM
Bits 3-0 - colour
|
$08 | Unused |
(Used by Master System)
|
$09 | Unused |
(Used by Master System)
|
$0A | H interrupt register |
Value that will be loaded in the counter.
|
$0B | Mode Set Register No. 3 |
Bits 7-4 - unused
Bit 3 - 1 = external interrupts enable
Bit 2 - 1 = 2-cell column based vertical scrolling, 0 = full screen vertical scrolling
Bits 1-0 -
0 0 - Full screen scroll
0 1 - Line scroll
1 0 - Cell scroll
1 1 - Line scroll
|
$0C | Mode Set Register No. 4 |
Bit 6-4 - unused
Bit 3 - ???
Bits 2-1 -
0 0 - No interlace
0 1 - Interlace (normal resolution)
1 0 - No interlace
1 1 - Interlace (double resolution
Bits 0,7 -
0 0 - 32 cells display
0 1 - 40 cells display (the display is weird a bit)
1 0 - invalid setting
1 1 - 40 cells display
|
$0D | VRAM Address for Horizontal Scroll |
Bits 2-0 of this register correspond to bits A15-A11 of the name table
address for plane B.
|
$0E | Unused |
---
|
$0F | Auto Increment Data |
Value to be added VDP address register after each read/write to the data port.
|
$10 | Scroll Size |
Bit 7-6 - unused
Bit 5-4 - Vertical Scroll Size (same as horizontal)
Bit 3-2 - unused
Bit 1-0 - Horizontal Scroll Size:
0 0 - 32 cells
0 1 - 64 cells
1 0 - invalid setting
1 1 - 128 cells
|
$11 | Window Horizontal Position |
Well, I don't recommend setting it to something different than $00, because I haven't cracked this register fully yet.
|
$12 | Window Vertical Position |
Same as above
|
$13 | DMA Length Bits 7-0 |
Bits 7-0 of DMA length.
|
$14 | DMA Length Bits 15-8 |
Bits 15-8 of DMA length.
|
$15 | DMA Source Address Bits 7-0 |
Bits 7-0 of DMA source address.
|
$16 | DMA Source Address Bits 15-8 |
Bits 15-8 of DMA source address.
|
$17 | DMA Type |
Bit 7 - depends.
If bit 7 is 0:
- DMA type is Memory to VRAM (68k memory to VRAM)
- bits 6-0 become bits 22-16 of DMA source address
- the whole DMA source address has to be shifted to the right by one bit
If bit 7 is 1:
- DMA type is VRAM fill (if bit 6 = 0) or VRAM to VRAM copy (if bit 6 = 1)
- Only bits of registers $15 and $16 are taken into account, bits 5-0 of this registers are ignored (I'm not sure, haven't tested this yet)
|
Back | Printer friendly << 4. I/O ports | 6. DMA >>
|