<span class="section">VDP</span><br><br>
Ports:<br><br>
<table cellpadding="4">
<tbody><tr><th>Address</th><th>Description</th></tr>
<tr><td>$C00000</td><td>Data port</td></tr>
<tr><td>$C00002</td><td>Data port (mirror)</td></tr>

<tr><td>$C00004</td><td>Control port</td></tr>
<tr><td>$C00006</td><td>Control port (mirror)</td></tr>
<tr><td>$C00008</td><td>HV counter</td></tr>
<tr><td>$C0000A</td><td>HV counter (mirror)</td></tr>
<tr><td>$C0000C</td><td>HV counter (mirror)</td></tr>
<tr><td>$C0000E</td><td>HV counter (mirror)</td></tr>

<tr><td>$C00011</td><td>SN76489 PSG</td></tr>
<tr><td>$C00013</td><td>SN76489 PSG (mirror)</td></tr>
<tr><td>$C00015</td><td>SN76489 PSG (mirror)</td></tr>
<tr><td>$C00017</td><td>SN76489 PSG (mirror)</td></tr>
<tr><td>$C00018</td><td>Unused</td></tr>
<tr><td>$C0001A</td><td>Unused</td></tr>

<tr><td>$C0001C</td><td>Unused</td></tr>
<tr><td>$C0001F</td><td>Unused</td></tr>
</tbody></table><br><br><br>
<span class="section">Data port</span><br><br>
Here, you write data after programming the control port.<br><br><br>

<span class="section">Control port</span><br><br>
Reading the control port returns a status word:<br><br>
<span class="offset">Bit 15</span> - Always 0<br>

<span class="offset">Bit 14</span> - Always 0<br>
<span class="offset">Bit 13</span> - Always 1<br>
<span class="offset">Bit 12</span> - Always 1<br>
<span class="offset">Bit 11</span> - Always 0<br>
<span class="offset">Bit 10</span> - Always 1<br>

<span class="offset">Bit 9</span> - FIFO empty<br>
<span class="offset">Bit 8</span> - FIFO full<br>
<span class="offset">Bit 7</span> - V blank pending<br>
<span class="offset">Bit 6</span> - Sprite overflow<br>
<span class="offset">Bit 5</span> - Sprite collision<br>

<span class="offset">Bit 4</span> - Odd frame<br>
<span class="offset">Bit 3</span> - Vertical blanking<br>
<span class="offset">Bit 2</span> - Horizontal blanking<br>
<span class="offset">Bit 1</span> - DMA in process<br>
<span class="offset">Bit 0</span> - PAL mode flag (1 for PAL, 0 for not PAL)

<br><br><br>

<span class="section">Accessing VDP RAM</span><br><br>
You can access VDP RAM writing a 32-bit command to control port then reading/writing to the data port. Here's the command:<br><br>
<pre class="68k">
    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)

</pre>

<span class="offset">A00-A15</span> - address<br>
<span class="offset">CD0-CD3</span> - code<br>

<span class="offset">CD4</span> - 1 if VRAM copy DMA mode. 0 otherwise.<br>
<span class="offset">CD5</span> - DMA operation<br><br>

Bits CD3-CD0:<br>
<span class="offset">0000</span> - VRAM read<br>
<span class="offset">0001</span> - VRAM write<br>

<span class="offset">0011</span> - CRAM write<br>
<span class="offset">0100</span> - VSRAM read<br>
<span class="offset">0101</span> - VSRAM write<br>
<span class="offset">1000</span> - CRAM read<br><br>
Example:<br><br>

<pre class="68k">	move.l	#$C0000000,($c00004).l	;program the control register
	move.w	#$0EEE,($c00000).l		;move colo(u)r EEE to CRAM
</pre>
<br>
<span class="section">Programming VDP registers</span><br><br>
VDP has 23 registers that can be programmed writing a 16-bit command to the control port:<br><br>
<pre class="68k">
     1   0   ?  R04 R03 R02 R01 R00     (D15-D8)
    D07 D06 D05 D04 D03 D02 D01 D00     (D7-D0)

</pre>
<span class="offset">R04-R00</span> - register<br>
<span class="offset">D07-D00</span> - data<br><br>

Example:<br><br>
<pre class="68k">	;set the border colo(u)r to palette $1, colo(u)r $2
	move.w	#$8712,($c00004).l
</pre>

Registers can be also set by writing a 32-bit command (2 registers at a time):<br><br>
<pre class="68k">	;set the border color to palette $1, color $2
	;and set the VDP auto increment data to $2
	move.l	#$87128F02,($c00004).l
</pre>

List of registers:<br><br>
<table cellpadding="4">
<tbody><tr><th>Register</th><th>Name</th><th>Description</th></tr>

<tr><td align="center">$00</td><td>Mode Set Register No.&nbsp;1</td><td>
<span class="offset">Bits 7-5</span> - unused<br>
<span class="offset">Bit 4</span> - H interrupts enable<br>
<span class="offset">Bit 3</span> - 1 = invalid display<br>
<span class="offset">Bit 2</span> - 1 = 8 colour mode (only bits 1, 5 and 9 of colours are displayed)<br>

<span class="offset">Bit 1</span> - 1 = HV counter latch enable<br>
<span class="offset">Bit 0</span> - 1 = disable display<br>


</td></tr>

<tr><td align="center">$01</td><td>Mode Set Register No.&nbsp;2</td><td>
<span class="offset">Bit 7</span> - TMS9918 / Genesis display select<br>

<span class="offset">Bit 6</span> - 1 = display enabled, 0 = fill the screen with backdrop colour (border colour)<br>
<span class="offset">Bit 5</span> - V interrupts enable<br>
<span class="offset">Bit 4</span> - DMA enable<br>
<span class="offset">Bit 3</span> - 1 = PAL (240 lines), 0 = NTSC (224 lines)<br>
<span class="offset">Bit 2</span> - SMS / Genesis display select<br>

<span class="offset">Bit 1</span> - 1 = HV counter latch enable<br>
<span class="offset">Bit 0</span> - 1 = disable display<br>


</td></tr>

<tr><td align="center">$02</td><td>VRAM Address for Scroll A</td><td>

Bits 5-3 of this register correspond to bits A15-A13 of the name table
 address for plane A.



</td></tr>

<tr><td align="center">$03</td><td>VRAM Address for Window</td><td>

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.

</td></tr>
<tr><td align="center">$04</td><td>VRAM Address for Scroll B</td><td>

Bits 2-0 of this register correspond to bits A15-A11 of the name table
 address for plane B.


</td></tr>
<tr><td align="center">$05</td><td>VRAM Address for Sprite Attributes</td><td>

 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.


</td></tr>

<tr><td align="center">$06</td><td>Unused</td><td>

(Used by Master System)

</td></tr>

<tr><td align="center">$07</td><td>Backdrop colour</td><td>

<span class="offset">Bits 5-4</span> - palette line in CRAM<br>

<span class="offset">Bits 3-0</span> - colour<br>
</td></tr>

<tr><td align="center">$08</td><td>Unused</td><td>

(Used by Master System)

</td></tr>

<tr><td align="center">$09</td><td>Unused</td><td>

(Used by Master System)

</td></tr>

<tr><td align="center">$0A</td><td>H interrupt register</td><td>

Value that will be loaded in the counter.

</td></tr>

<tr><td align="center">$0B</td><td>Mode Set Register No.&nbsp;3</td><td>
<span class="offset">Bits 7-4</span> - unused<br>

<span class="offset">Bit 3</span> - 1 = external interrupts enable<br>
<span class="offset">Bit 2</span> - 1 = 2-cell column based vertical scrolling, 0 = full screen vertical scrolling<br>
<span class="offset">Bits 1-0</span> -
<pre>  0 0    - Full screen scroll
  0 1    - Line scroll
  1 0    - Cell scroll
  1 1    - Line scroll</pre>

</td></tr>

<tr><td align="center">$0C</td><td>Mode Set Register No.&nbsp;4</td><td>
<span class="offset">Bit 6-4</span> - unused<br>
<span class="offset">Bit 3</span> - ???<br>
<span class="offset">Bits 2-1</span> - 
<pre>  0 0   - No interlace
  0 1   - Interlace (normal resolution)
  1 0   - No interlace
  1 1   - Interlace (double resolution</pre>


<span class="offset">Bits 0,7</span> -
<pre>  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</pre>

</td></tr>
<tr><td align="center">$0D</td><td>VRAM Address for Horizontal Scroll</td><td>

Bits 2-0 of this register correspond to bits A15-A11 of the name table
 address for plane B.


</td></tr>

<tr><td align="center">$0E</td><td>Unused</td><td>

---


</td></tr>

<tr><td align="center">$0F</td><td>Auto Increment Data</td><td>

Value to be added VDP address register after each read/write to the data port.

</td></tr>


<tr><td align="center">$10</td><td>Scroll Size</td><td>

<span class="offset">Bit 7-6</span> - unused<br>
<span class="offset">Bit 5-4</span> - Vertical Scroll Size (same as horizontal)<br>
<span class="offset">Bit 3-2</span> - unused<br>
<span class="offset">Bit 1-0</span> - Horizontal Scroll Size:<br>

<pre>  0 0    - 32 cells
  0 1    - 64 cells
  1 0    - invalid setting
  1 1    - 128 cells</pre>


</td></tr>

<tr><td align="center">$11</td><td>Window Horizontal Position</td><td>

Well, I don't recommend setting it to something different than $00, because I haven't cracked this register fully yet.


</td></tr>
<tr><td align="center">$12</td><td>Window Vertical Position</td><td>

Same as above


</td></tr>

<tr><td align="center">$13</td><td>DMA Length Bits 7-0</td><td>

Bits 7-0 of DMA length.


</td></tr>

<tr><td align="center">$14</td><td>DMA Length Bits 15-8</td><td>

Bits 15-8 of DMA length.


</td></tr>
<tr><td align="center">$15</td><td>DMA Source Address Bits 7-0</td><td>

Bits 7-0 of DMA source address.


</td></tr>

<tr><td align="center">$16</td><td>DMA Source Address Bits 15-8</td><td>

Bits 15-8 of DMA source address.


</td></tr>

<tr><td align="center">$17</td><td>DMA Type</td><td>

<span class="offset">Bit 7</span> - depends.<br><br>

If <span class="offset">bit 7</span> is 0:<br>
- DMA type is Memory to VRAM (68k memory to VRAM)<br>
- <span class="offset">bits 6-0</span> become bits 22-16 of DMA source address<br>
- the whole DMA source address has to be shifted to the right by one bit<br><br>

If <span class="offset">bit 7</span> is 1:<br>

- DMA type is VRAM fill (if <span class="offset">bit 6</span> = 0) or VRAM to VRAM copy (if <span class="offset">bit 6</span> = 1)<br>
- Only bits of registers $15 and $16 are taken into account, <span class="offset">bits 5-0</span> of this registers are ignored (I'm not sure, haven't tested this yet)<br>
  
</td></tr>
</tbody></table>