Copy Link
Add to Bookmark
Report

Sega Genesis VDP documentation

Dreamcast's profile picture
Published in 
MegaDrive
 · 6 years ago

 

Sega Genesis VDP documentation
Version 1.5f (08/10/00)

by Charles MacDonald
WWW: http://cgfm2.emuviews.com

Unpublished work Copyright 2000 Charles MacDonald


This document is very preliminary and subject to change.


Changes from the last version:

(v1.5f)
- Minor update on 68k -> VDP DMA transfers. (section 11)
(v1.5e)
- More information on VDP register sets.
- Added preliminary section numbers and table of contents.
- Revised todo list.
(v1.5d)
- Fixed sprite size byte layout.
- Listed a few games that overlap low and high priority sprites.
- Mentioned game problems regarding data port access.
(v1.5c)
- Verified DMA transfer wrapping.
- Fixed MSB/LSB mixup in DMA fill description.
- Added zero length DMA behavior.
- Mentioned results of writing during fills.
- Added VRAM address register wrapping.
(v1.5)
- Added shadow / hilight info.
- Added HV counter information.
- Added notes on odd byte access.
- Expanded register list.
- Rewrote DMA section.
- Did a little work on priority and patterns.
(v1.4)
- Described 8-bit port writes.
- Expanded VDP register programming section.
- Rewrote description of external interrupts.
- Removed 8-bit VRAM fill section.
- Added VDP pinout.
- Changed introduction and overview sections.
- Removed display size list.
- Added interrupts description.
(v1.3)
- Fixed sprite limitation count.
- Added details on blanking flags in status register.
- Added status register section.
- Added notes on VSRAM/CRAM fills.
- Added scrolling section.
- Added description of backdrop color register.
- Added description of mode set #3 register.
(v1.2)
- Completed most of the DMA section.
- Added sprite masking information.
- Verified bits 5-0 of reg 23 have no effect on VRAM fills.
- Fixed CD4 description.
(v1.1)
- Verified CD4 does not affect a 68K->VDP DMA transfer.
- Verified code and address registers retain their state after half of
a command word is written to the control port.
- Added display mode list.
- Added specific VDP RAM type info.
- Added sprite section.
- Verified register writes reset the pending flag.
- Added VDP port map.
- Verified byteswap behavior for VRAM writes.
- Verified no illegal codes allowed for CRAM writes.
- Verified A15-A7 of VSRAM address is ignored.
- Verified A0 of CRAM address is ignored.
- Verified A0 of VSRAM address is ignored.
- Verified writing to 'extra' VSRAM addresses has no effect.
- Verified ignored command word bits.
- Finalized info on palette control bit.
- Started basic control port decoding section.
- Added register #0, #1 descriptions.
- Mentioned plane A clipping in window register descriptions.
(v1.0)
- Initial draft.

Disclaimer:

If you use any information from this document, please credit me
(Charles MacDonald) and optionally provide a link to my webpage
(http://cgfm2.emuviews.com/) so interested parties can access it.

The credit text should be present in the accompanying documentation of
whatever project which used the information, or even in the program
itself (e.g. an about box)

----------------------------------------------------------------------------
Table of Contents
----------------------------------------------------------------------------

0.) Introduction
1.) Overview
2.) Display Modes
3.) VDP port map
4.) Interrupts
5.) HV Counter
6.) Status Register
7.) VDP ports
8.) VRAM
9.) CRAM
10.) VSRAM
11.) DMA
12.) Patterns
13.) Background Layers
14.) Priority
15.) Sprites
16.) Shadow / Hilight mode
17.) VDP registers
18.) VDP Pinout


----------------------------------------------------------------------------
0.) Introduction
----------------------------------------------------------------------------

This is a compilation of my notes on the Sega Genesis video display
processor.

I wanted to write this because the existing information on the VDP is
very inadequate. Many of the subtle quirks and bugs are not explained.

I'd like to thank the following people in alphabetical order for
providing information and being helpful:

Bart Trzynadlowski
Christian Schiller
Flavio Morsoletto
Omar Cornut
Stephane Dallongeville

Also thanks to Sardu and Steve Snake for genecyst and KGen98, which
were both used for devloping test programs.

I am interested in finding somebody who has a Sega Genesis copier and
would be willing to run some test programs and report the results.

----------------------------------------------------------------------------
1.) Overview
----------------------------------------------------------------------------

The Genesis VDP is derived from the Master System VDP, which in turn
was derived from the Texas Instruments TMS9918. As a result, the VDP is
programmed much like it's earlier counterparts.

Interestingly enough, none of the Sega produced VDP's are similar to the
later VDP models made by Yamaha, which were also based upon the TMS9918.

----------------------------------------------------------------------------
2.) Display Modes
----------------------------------------------------------------------------

To clarify naming conventions, here is a list of display modes used by
the various video chips mentioned:

Mode 0 - TMS9918 specific
Mode 1 - TMS9918 specific
Mode 2 - TMS9918 specific
Mode 3 - TMS9918 specific
Mode 4 - SMS mode
Mode 5 - Genesis mode

Supported mode list:

TMS9918 - Modes 0, 1, 2, 3
SMS - Modes 0, 1, 2, 3, 4
Genesis - Modes 4, 5 (possibly 0 and others as well)

If anybody has some information about how the Game Gear would fit into
this list, let me know. I assume it's identical to the SMS, but I don't
know about the TMS9918 compatability. (if any)

----------------------------------------------------------------------------
3.) VDP port map
----------------------------------------------------------------------------

The VDP occupies addresses C00000h to C0001Fh.

C00000h - Data port (8=r/w, 16=r/w)
C00002h - Data port (mirror)
C00004h - Control port (8=r/w, 16=r/w)
C00006h - Control port (mirror)
C00008h - HV counter (8/16=r/o)
C0000Ah - HV counter (mirror)
C0000Ch - HV counter (mirror)
C0000Eh - HV counter (mirror)
C00011h - SN76489 PSG (8=w/o)
C00013h - SN76489 PSG (mirror)
C00015h - SN76489 PSG (mirror)
C00017h - SN76489 PSG (mirror)

----------------------------------------------------------------------------
4.) Interrupts
----------------------------------------------------------------------------

The VDP generates all interrupts for the 68000. The only hardware
interrupts available are 2, 4, and 6.

Vertical interrupts
-------------------

If bit 5 (IE0) of register #1 is set, then a level 6 interrupt will occur
when the V counter is at line E0h, roughly at H counter cycle 08h. At this
point in time, the vertical interrupt occurance flag (bit 7) will be set
in the status register.

Line interrupts
---------------

The VDP has a counter that is decremented on every line. When the counter
has expired, and if bit 4 (IE1) of register #0 is set, then a level 4
interrupt will occur.

The counter is loaded with the contents of register #10 in the following
situations:

- Line zero of the frame.
- When the counter has expired.
- Lines 225 through 261. (note that line 224 is not included)

The counter is *not* loaded when register #10 is written to.

Note that line interrupts are processed *before* vertical interrupts
within a scanline. If you trigger a line interrupt to occur on line E0h,
then the level 4 line interrupt will be taken by the 68000, not the
level 6 vertical interrupt.

External interrupts
-------------------

Pin 7 of each of the three I/O ports is called the TH pin. It is connected
to the VDP. When the state of TH is changed, the following events happen:

- If bit 7 of the control register for the associated I/O port is set,
and bit 3 of register #11 (IE2) is set, then the VDP will generate
a level 2 interrupt.

- If bit 1 of VDP register #0 is set, the contents of the HV counter will
be latched.

A common use for these features are in a light gun game. The light gun
can change the state of TH, which will freeze the HV counter, and then
the level 2 interrupt subroutine can read the HV counter and also
communicate with the light gun to get information like what buttons
were pressed. This is pretty much how Sega's 'Menacer' device works.
The Konami 'Justifier' light gun works on similar principles.

I don't know if the HV counter resumes normal operation after the first
read, or if the HV counter latch bit has to be cleared and set again.

Some games will enable the HV counter latch and never read the HV counter,
let alone use any special peripherals. (Shadow of the Beast II)

You cannot force an external interrupt by changing the state of TH
through software. (e.g. in the normal sequence of reading the gamepad,
TH is set and cleared - this does not cause an interrupt if interrupts
are enabled)

The data direction for TH (which corresponds to bit 6 of the data and
control registers) must be configured as an input for a peripheral
to cause an interrupt.

----------------------------------------------------------------------------
5.) HV Counter
----------------------------------------------------------------------------

The HV counter returns the vertical and horizontal position of the
television's raster beam.

Reading the HV counter will return the following data:

VC7 VC6 VC5 VC4 VC3 VC2 VC1 VC0 (D15-D08)
HC8 HC7 HC6 HC5 HC4 HC3 HC2 HC1 (D07-D00)

VCx = Vertical position in lines.
HCx = Horizontal position in pixels.

According to the manual, VC0 is replaced with VC8 when in interlace mode 2.

For 8-bit reads, the even byte (e.g. C00008h) returns the V counter, and
the odd byte (e.g. C00009h) returns the H counter.

The V counter counts up from 00h to EAh, then it jumps back to E5h and
continues counting up to FFh. This allows it to cover the entire 262 line
display.

The H counter counts up from 00h to E9h, then it jumps back to 93h and
continues counting up to FFh. This allows it to cover an entire 342 pixel
line.

The H counter description is based upon known information about the SMS
VDP's H counter. The SMS has a 256x192 display, and each line consists of
342 pixels. (that includes blanking, retrace, etc.) The description
*could* be accurate for the Genesis' 32-cell display mode. This is not
the case for the 40-cell display, where I would assume the H counter jumps
back farther at a later point in the count-up.

In terms of emulation, I have found that turning the elapsed 68000 cycle
count into a pixel offset for the current scan line seems to provide a
reasonable return value for the H counter. However, I am quite positive
a single scanline consists of more pixels than just 256 or 320, and
in addition the 'jump-back' described above is not taken into account.
In all honesty this is a hack, not a solution.

I would appreciate any additional information on the HV counter.

----------------------------------------------------------------------------
6.) Status Register
----------------------------------------------------------------------------

Reading the control port returns a 16-bit word that allows you to observe
various states of the VDP and physical display.

d15 - Always 0
d14 - Always 0
d13 - Always 1
d12 - Always 1
d11 - Always 0
d10 - Always 1
d9 - FIFO Empty
d8 - FIFO Full
d7 - Vertical interrupt pending
d6 - Sprite overflow on current scan line
d5 - Sprite collision
d4 - Odd frame
d3 - Vertical blanking
d2 - Horizontal blanking
d1 - DMA in progress
d0 - PAL mode flag

Presumably bit 0 is set when the system display is PAL; however this same
information can be read from the version register (part of the I/O
register group - not the VDP), so maybe this bit reflects the state of
having a 240-line display enabled.

Bit 1 is set for the duration of a DMA operation. This is only useful for
fills and copies, since the 68000 is frozen during 68k -> VDP transfers.

Bit 2 returns the real-time status of the horizontal blanking signal.
It is set at H counter cycle E4h and cleared at H counter cycle 08h.

Bit 3 returns the real-time status of the vertical blanking signal.
It is set on line E0h, at H counter cycle AAh, and cleared on line FFh,
at H counter cycle AAh.

(Note: For both blanking flag descriptions, the H counter values are
very likely different for 32-cell and interlaced displays; they were
taken from a test with a 40-cell screen.)

Bit 4 is set when the display is interlaced, and in the odd frame,
otherwise it is cleared in the even frame. This applies to both
interlace modes.

Bit 5 is set when any sprites have non-transparent pixels overlapping one
another. This may hold true for sprites outside of the display area too.
This bit is most likely cleared at the end of the frame.

Bit 6 is set when too many sprites are on the current scan line, meaning
when the VDP parses the 21st sprite in 40-cell mode or the 17th sprite in
32-cell mode from the sprite list.
This bit is most likely cleared at the end of the frame.

Bit 7 is set when a vertical interrupt occurs. This happens at line E0h,
roughly after H counter cycle 08h. I do not know under what conditions
it is cleared, presumably at the end of the frame. Reading the control
port does not clear this bit. (this could be incorrect)

Bit 8 and 9 (FULL and EMPTY flags, respectively) are related to the FIFO;
here's what Flavio Morsoletto has to say about their use:

"The FIFO can hold up to four 16-bit words while the VDP's busy
parsing data from VRAM. Once the 68K has written the fourth word,
FULL is raised. If the processor attempts to write one more time, it
will be frozen (/DTACK high) until the FIFO unit manages to deliver
the first stacked word to its rightful owner. EMPTY only goes 1 when
there is nothing on the stack. The intermediate state is signaled by
both of them showing 0."


This situation only occurs during the active display period, as the
data port can be written to as many times as needed during blanking.

I've noticed most emulators keep the EMPTY flag set, so it appears as
if the FIFO was always empty instead of being in the neutral state. This
is probably for games that would normally check and find the FIFO in a
neutral state, then write data and expect to poll the FULL flag afterwards.

----------------------------------------------------------------------------
7.) VDP ports
----------------------------------------------------------------------------

The VDP is programmed entirely through the control and data ports.
Data written to the control port is formatted, so the VDP will know
how to interpret the data it recieves.

You can divide control port data into two categories; 16-bit register sets
and 32-bit command words.

Programming VDP registers
-------------------------

Any one of the 23 VDP registers can be programmed by writing 16 bits of
data to the control port. The data written has the following format:

1 0 ? R04 R03 R02 R01 R00 (D15-D8)
D07 D06 D05 D04 D03 D02 D01 D00 (D7-D0)

Rxx = VDP register select (00-1F)
Dxx = VDP register data (00-FF)

Writing to non-existant VDP registers has no effect.

Bits 15 and 14 must be set to 1 and 0 respectively, otherwise the write
will be treated as the first half of a command word. The state of bit 13
does not matter.

Here's an example of programming one register:

; Set border color to palette $3, index $F
move.w #$873F, $00C00004

Since the 68000 treats 32-bit memory access as two 16-bit operations,
you can program two registers at once:

; Set split point bits for both window registers
move.w #$91809280, $00C00004

Accessing VDP RAM
-----------------

You can access VRAM, CRAM, or VSRAM by writing a 32-bit command word to
the control port. The data written has the following format:

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)

CDx = VDP code (0-3F)
Axx = VDP address (00-FFFF)

The state of D15 through D8, D3, and D2 are ignored.

The VDP has an address and code register. They are used in conjunction to
handle data port accesses. The address register provides an offset into
VDP RAM to write or read data from. The code register specifies if
data port accesses will be reads or writes, and the kind of VDP RAM
to perform these operations on.

In order for the VDP to know if the first or second 16-bit half of the
command word has been written to the control port, it maintains an internal
write-pending flag. This flag is updated when these conditions are met:

- It is set when the first half of the command word is written.
- It is cleared when the second half of the command word is written.
- It is cleared when the data port is written to or read from.
- It is cleared when the control port is read.

It is perfectly valid to write the first half of the command word only.
In this case, _only_ A13-A00 and CD1-CD0 are updated to reflect the new
values, while the remaining address and code bits _retain_ their former
value.

You cannot write to a VDP register if the pending flag is set to one,
since the VDP is expecting the 2nd half of a command word.

Writing to a VDP register will clear the code register. Games that rely
on this are Golden Axe II (will display missing SEGA logo) and Sonic 3D.
(will show intro movie in wrong colors for a few frames) It is not known
if the address register is cleared as well, but the TMS9918 manual
indicates that this is so, perhaps it applies to the Genesis as well.

Here is a table of code register settings:

Bits CD3-CD0
0000b : VRAM read
1000b : CRAM read
0100b : VSRAM read
0001b : VRAM write
0011b : CRAM write
0101b : VSRAM write

You cannot write data after setting up a read operation, or read data
after setting up a write operation. The write or read is ignored.

CD4 is only set for the the VRAM copy DMA mode.
For data port accesses and 68k to VDP DMA, the state of CD4 is ignored.

Setting CD5 will trigger a DMA operation.

8-bit port access
-----------------

Doing an 8-bit write to the control or data port is interpreted by
the VDP as a 16-bit word, with the data written used for both halfs
of the word.

For instance, the following code writes 87h to VDP register #7:

; VDP sees data as 8787h
move.b #$87, $00C00004

This also applies to the data port. The following code sets CRAM entry
zero to pink:

; VDP sees data as 0E0Eh
move.l #$C0000000, $00C00004
move.b #$0E, $00C00000

It's important to realize that a distinction between 8-bit and 16-bit VRAM
fills do not exist. There is only one type of fill, and depending on how
you write to the data port will determine the kind of data used in the fill.

Odd addresses (e.g. C00007h, C00001h) function identically to even addresses
in the case of 8-bit writes. For instance, writing data to anywhere within
C00004h-C00007h would go to the control port.

Miscellaneous
-------------

I've found that some games will write VDP register data to the data port,
after the code and address registers have been set to zero. I've confirmed
that this is simply a bug on the programmer's behalf, you cannot program
the VDP registers in this way.

Games that do this include Alien Soldier and Eternal Champions.

Some games also set up VRAM reads and try to write to VRAM; this is
also pointless as data written after a VRAM read command is issued
is ignored by the VDP. The unlicensed version of Populous does
this, along with Golden Axe II.

----------------------------------------------------------------------------
8.) VRAM
----------------------------------------------------------------------------

The VDP is connected to 64K of video RAM. It is accessed as 65535 8-bit
bytes or 32768 16-bit words through the data port.

VRAM is multipurpose; it can store pattern data, horizontal scroll data,
sprite tables, and background name tables.

When writing 16-bit data to VRAM, having address bit 0 set will swap
the upper and lower bytes of the data written.

The address register wraps past address FFFFh.

----------------------------------------------------------------------------
9.) CRAM
----------------------------------------------------------------------------

The VDP has 64x9 bits of on-chip color RAM. It is accessed as 64 16-bit
words through the data port. Each word has the following format:

----bbb-ggg-rrr-

r = Red component (0-7)
g = Green component (0-7)
b = Blue component (0-7)

This allows for a total of 512 possible colors, with 64 colors stored
in CRAM at any given time.

When accessing CRAM, only address bits 6 through 1 are valid. The high-order
address bits are ignored. Since CRAM is word-wide, address bit zero has
no effect.

The address register wraps past address 7Fh.

----------------------------------------------------------------------------
10.) VSRAM
----------------------------------------------------------------------------

The VDP has 40x10 bits of on-chip vertical scroll RAM. It is accessed as
40 16-bit words through the data port. Each word has the following format:

------yyyyyyyyyy

y = Vertical scroll factor (0-3FFh)

When accessing VSRAM, only address bits 6 through 1 are valid.
The high-order address bits are ignored. Since VSRAM is word-wide, address
bit zero has no effect.

Even though there are 40 words of VSRAM, the address register will wrap
when it passes 7Fh. Writes to the addresses beyond 50h are ignored.

----------------------------------------------------------------------------
11.) DMA
----------------------------------------------------------------------------

The VDP can be programmed to move data into, copy, and fill sections of
VDP RAM, meaning VRAM, CRAM, and VSRAM. These functions are referred to
as Direct Memory Access. (DMA)

Overview
--------

Bits 7 and 6 of register #23 select the type of DMA operation:

D7 D6
0 ? : 68K -> VDP RAM transfer (D6 is bit 24 of source address)
1 0 : VRAM fill
1 1 : VRAM copy

Bit 4 of register #1 will enable DMA operations when set.

Some games will attempt to do DMA when it is disabled, including Phelios
and Rocket Knight Adventures.

When doing 68K -> VDP RAM transfers, the 68000 is frozen. For VRAM fills
and copies, the 68000 runs normally, but you can only read the control
port, HV counter, and write to the PSG register.

Writing to the control or data port during a VRAM fill seems to corrupt
the VDP registers and VRAM.

When the length field is set to zero, the length is treated as FFFFh.

68000 to VDP RAM
----------------

This is used to transfer data out of the 68000's address space into VRAM,
CRAM, or VSRAM.

Registers 19, 20, specify how many 16-bit words to transfer:

#19: L07 L06 L05 L04 L03 L02 L01 L00
#20: L15 L14 L13 L12 L11 L10 L08 L08

Note that a length of 7FFFh equals FFFFh bytes transferred, and a length
of FFFFh = 1FFFF bytes transferred.

Registers 21, 22, 23 specify the source address on the 68000 side:

#21: S08 S07 S06 S05 S04 S03 S02 S01
#22: S16 S15 S14 S13 S12 S11 S10 S09
#23: 0 S23 S22 S21 S20 S19 S18 S17

If the source address goes past FFFFFFh, it wraps to FF0000h.
(Actually, it probably wraps at E00000h, but there's no way to tell as
the two addresses are functionally equivelant)

When doing a transfer to CRAM, the operation is aborted once the address
register is larger than 7Fh. The only known game that requires this is
Batman & Robin, which will have palette corruption in levels 1 and 3
otherwise. This rule may possibly apply to VSRAM transfers as well.

A transfer is started when the following command word is written:

CD1 CD0 A13 A12 A11 A10 A09 A08 (D31-D24)
A07 A06 A05 A04 A03 A02 A01 A00 (D23-D16)
? ? ? ? ? ? ? ? (D15-D8)
1 0 0 CD2 ? ? A15 A14 (D7-D0)

CD2-CD0 specify the type of VDP RAM to write to:

001b - VRAM
011b - CRAM
101b - VSRAM

The following events occur after the command word is written:

- 68000 is frozen.
- VDP reads a word from source address.
- Source address is incremented by 2.
- VDP writes word to VRAM, CRAM, or VSRAM.
(For VRAM, the data is byteswapped if the address register has bit 0 set)
- Address register is incremented by the value in register #15.
- Repeat until length counter has expired.
- 68000 resumes operation.

When a transfer is done out of the ROM area ($000000-3FFFFF), the machine
will lock up unless the write that triggers the DMA operation is done
using RAM.

Usually this means putting the command word or the latter half of the
command word in RAM and moving that into the control port, putting
the command word on the stack and moving that into the control port,
or having the instruction that moves the command word into the control
port execute out of RAM.

VRAM fill
---------

VRAM fills are used to repeatedly write a given data value to multiple
sequential addresses in VRAM.

Registers 19, 20, specify how many 8-bit bytes to fill:

#19: L07 L06 L05 L04 L03 L02 L01 L00
#20: L15 L14 L13 L12 L11 L10 L08 L08

The address bits in registers 21, 22, 23 are ignored:

#21: ? ? ? ? ? ? ? ?
#22: ? ? ? ? ? ? ? ?
#23: 1 0 ? ? ? ? ? ?

A VRAM fill is started when the following command word is written:

0 1 A13 A12 A11 A10 A09 A08 (D31-D24)
A07 A06 A05 A04 A03 A02 A01 A00 (D23-D16)
? ? ? ? ? ? ? ? (D15-D8)
1 0 0 0 ? ? A15 A14 (D7-D0)

Any write to the data port will then start a VRAM fill. The LSB of the
data is written to the address specified, then the MSB is written to
the adjacent address. The address register is incremented by the value
in VDP register 15, and the upper 8 bits are written again to the next
adjacent address, and so on.

Here is some "C" pseudocode to illustrate a VRAM fill:

void vram_fill(int data)
{
/ * Write lower byte to address specified * /
vram[address] = (data >> 0) & 0xFF;

do {
/ * Write upper byte to adjacent address * /
vram[address ^ 1] = (data >> 8) & 0xFF;

/ * Increment address register * /
address += vdp_reg[15];
} while(--length)
}

Games that require accurate VRAM fill emulation include Thunder Force IV,
Contra Hard Corps, Revenge of Shinobi, Taiga Drama, and Sword of Vermillion.

VRAM copy
---------

VRAM copies are used to copy blocks of VRAM data.

Registers 19, 20, specify how many 8-bit bytes to copy:

#19: L07 L06 L05 L04 L03 L02 L01 L00
#20: L15 L14 L13 L12 L11 L10 L08 L08

The address bits in register 23 are ignored.
Registers 21, 22 specify the source address in VRAM:

#21: S07 S06 S05 S04 S03 S02 S01 S00
#22: S15 S14 S13 S12 S11 S10 S09 S08
#23: 1 1 ? ? ? ? ? ?

A VRAM copy is started when the following command word is written:

0 0 A13 A12 A11 A10 A09 A08 (D31-D24)
A07 A06 A05 A04 A03 A02 A01 A00 (D23-D16)
? ? ? ? ? ? ? ? (D15-D8)
1 1 0 0 ? ? A15 A14 (D7-D0)

The VDP will read a byte from the source address which is then incremented
by one. The data will then be written to the destination address, which
is incremented by register #15.

Games that use VRAM copies include Aleste, Bad Omen, and Viewpoint.

Transfer capacity
-----------------

The VDP can access memory a certain number of times on each line of the
display. This is severely limited during the active display period, since
the VDP also needs to update the screen, leaving less memory accesses
left for DMA.

According to the manual, here's a table that describes the transfer
rates of each of the three DMA types:

DMA Mode Width Display Transfer Count
-----------------------------------------------------
68K > VDP 32-cell Active 16
Blanking 167
40-cell Active 18
Blanking 205
VRAM Fill 32-cell Active 15
Blanking 166
40-cell Active 17
Blanking 204
VRAM Copy 32-cell Active 8
Blanking 83
40-cell Active 9
Blanking 102

'Active' is the active display period, 'Blanking' is either the vertical
blanking period or when the display is forcibly blanked via register #1.

The above transfer counts are all in bytes, unless the destination is
CRAM or VSRAM for a 68K > VDP transfer, in which case it is in words.

Miscellaneous
-------------

I don't know if the source address register and length counter are actually
updated during a DMA operation. I doubt it, but in theory you could have
a sequence like this:

move.l #$94109300, $00C00004 ; length = 4k words
move.l #$96009500, $00C00004
move.l #$97708F02, $00C00004 ; src = E00000h, inc = 02h
move.w #$40000003, $00C00004 ; VRAM write to C000h
; 8k is transferred to VRAM C000h from RAM E00000h

move.w #$60000003, $00C00004 ; VRAM write to E000h
; 8k is transferred to VRAM E000h from RAM E02000h

You can make VRAM fills affect CRAM or VSRAM by changing the CD2-CD0 bits
to the appropriate RAM type, just like how 68K -> VDP transfers work.
Due to the limited way this was tested, I can't say how exactly the fill
data is written; CRAM and VSRAM are word-wide, while VRAM is byte-wide,
to there's bound to be some differences. I'd assume the results are
the same as normal byte-wide data port access, where both the LSB and
MSB of each word are set to the same 8-bit data written.

In the case of a VRAM fill, the CD2-CD0 bits are set to the same value
required for a VRAM write. In the same vein, VRAM copies have the code
bits set to the same setting as a VRAM read. Maybe changing the code
register would allow copies within CRAM and VSRAM? Or perhaps the code
bits only select the source address? (Not that a CRAM > VRAM copy is
particularly useful, but there you go.)

----------------------------------------------------------------------------
12.) Patterns
----------------------------------------------------------------------------

All background and sprite graphics are made up of patterns. A pattern is
an 8x8 or 8x16 (interlace mode 2 only) pixel block that is made up of
fifteen colors.

Patterns are stored in VRAM. Each pixel is represented by four bits,
meaning there are four bytes (4 bits * 8 pixels = 4 bytes) per line of
the pattern, and 32 or 64 bytes per pattern, depending if the pattern
is 8x8 or 8x16.

Unlike other VRAM data that is stored in a specific table, patterns can
be placed anywhere. Even in the parts of other tables that aren't being
used, like a name table or sprite attribute table.

A pixel within a pattern that uses value zero isn't shown. It acts as a
transparency indicator.

----------------------------------------------------------------------------
13.) Background Layers
----------------------------------------------------------------------------

The VDP manages two background layers, called plane A and plane B.

Name Tables
-----------

There are three tables stored in video RAM that define the layout for
planes A, B, and W.

Each table is a matrix of 16-bit words. Each word has the following format:

pccvhnnnnnnnnnnn

p = Priority flag
c = Palette select
v = Vertical flip
h = Horizontal flip
n = Pattern name

The pattern name is the upper 11 bits of the physical address of pattern
in video RAM. Bit zero of the name is ignored in interlace mode 2.

The vertical and horizontal flip flags tell the VDP to draw the pattern
flipped in either direction.

The palette select allows the pattern to be shown in one of four
16-color palettes.

The priority flag is described later.

The name tables for plane A and B share the same dimensions. The name
table size cannot exceed 8192 bytes, so while a 64x64 or 128x32 name
table is allowed, a size of 128x128 or 64x128 is invalid.

The name table for plane W is 32x32 in 32-cell mode, and 64x32 in 40-cell
mode. This size is fixed and is entirely dependant on the display width.

Window
------

The window plane operates differently from plane A or B. It can be thought
of a 'replacement' for plane A which is used under certain conditions.
That said, plane A cannot be displayed in any area where plane W is
located, it is impossible for them to overlap.

Registers 17 and 18 define an area which the window is restricted to.

In terms of priority and intensity calculation for shadow / hilight mode,
plane W is treated _exactly_ the same as plane A.

Horizontal Scrolling
--------------------

The horizontal scroll table holds the scroll value for every line of
both planes A and B, that can be positioned anywhere within video RAM.

Each entry of the scroll table is a 16-bit word. It has the following
format:

------xxxxxxxxxx

x = Horizontal scroll value (0-3FFh)

Bits D15 through D10 are ignored by the VDP.

The lower three bits of the scroll value provide a pixel offset into each
column comprised of one pattern. The upper seven bits provide an offset
into each column of the name table (0-127).

When the scroll value is larger than the width of the playfield, the
display wraps horizontally.

Scroll values for planes A and B are stored in an interleaved fashion.
Entry #0 of the table is for plane A, entry #1 is for plane B, and this
repeats for the entire length of the table.

The manual says the scroll table is 960 bytes in size,
and this seems like an accurate figure, considering the scroll table
address bits suggest the table can be 1024 bytes.

However, I do not know what happens in double-resolution interlace
mode. To provide a scroll entry for both planes on every line, a total
of 1920 bytes would be needed. (480 lines x 2 planes x 2 bytes per line)

Here is some "C" pseudocode to illustrate how the VDP reads the scroll
table depnding on the settings of bits 0 and 1 of register #11:

void get_scroll(int line, int *scroll_a, int *scroll_b)
{
switch(vdp_reg[11] & 3)
{
case 0x00: / * Full screen * /
*scroll_a = *(word *)vram[hscb + 0];
*scroll_b = *(word *)vram[hscb + 2];
break;

case 0x01: / * First eight lines * /
*scroll_a = *(word *)vram[hscb + ((line & 7) * 2) + 0];
*scroll_b = *(word *)vram[hscb + ((line & 7) * 2) + 2];
break;

case 0x02: / * Every row * /
*scroll_a = *(word *)vram[hscb + ((line & ~7) * 2) + 0];
*scroll_b = *(word *)vram[hscb + ((line & ~7) * 2) + 2];
break;

case 0x03: / * Every line * /
*scroll_a = *(word *)vram[hscb + (line * 2) + 0];
*scroll_b = *(word *)vram[hscb + (line * 2) + 2];
break;
}
}

A scroll mode setting of 01b is not valid; however the unlicensed version
of Populous uses it. This mode is identical to per-line scrolling, however
the VDP will only read the first sixteen entries in the scroll table for
every line of the display.

----------------------------------------------------------------------------
14.) Priority
----------------------------------------------------------------------------

The VDP manages a fairly complex system of priorities between the two
background layers and sprites. The basic ordering is:


(back) (front)
A > B > C > D > E' > F' > G'

' = Denotes high priority
A = Backdrop color
B = Low priority plane B
C = Low priority plane A
D = Low priority sprites
E = High priority plane B
F = High priority plane A
G = High priority sprites

The sprite priority bit does not affect inter-sprite priority, only the
relation between background data. Low priority sprites *can* overlap high
priority sprites. Games that do this to mask other sprites include
Castlevania Bloodlines, Raiden Trad, and Alien Soldier.

----------------------------------------------------------------------------
15.) Sprites
----------------------------------------------------------------------------

The Genesis can display a total of eighty 32x32 15-color sprites.
There are of course various restrictions on the display capacity, based
on current configuration of the VDP.

Sprite Attribute Table
----------------------

All sprite data is stored in a region of VRAM called sprite attribute table.
The table is 640 bytes in size. Each 8-byte entry has the following format:

Index + 0 : ------yy yyyyyyyy
Index + 2 : ----hhvv
Index + 3 : -lllllll
Index + 4 : pccvhnnn nnnnnnnn
Index + 6 : ------xx xxxxxxxx

y = Vertical coordinate of sprite
h = Horizontal size in cells (00b=1 cell, 11b=4 cells)
v = Vertical size in cells (00b=1 cell, 11b=4 cells)
l = Link field
p = Priority
c = Color palette
v = Vertical flip
h = Horizontal flip
n = Sprite pattern start index
x = Horizontal coordinate of sprite

Linking
-------

The VDP draws sprites in a front-to-back order, starting with sprite zero.
The 7-bit link field in each list entry is an index to the next entry of
the sprite that will be drawn. If the link field is zero, then no more
sprites will be drawn after the current sprite. Here's an example:

Sprite #00 has a link field of 2
Sprite #01 has a link field of 7
Sprite #02 has a link field of 4
Sprite #03 has a link field of 0
Sprite #04 has a link field of 3
Sprite #05 has a link field of 2

In this case, sprites #00, #02, #04, #03 will be drawn, in that order.

Coordinate System
-----------------

Sprites are positioned in a virtual 512x512 space. The display starts at
coordinate 128, 128, and takes up a space equal to the size of the physical
display. (usually 256x224 or 320x224) This system is convenient for
programmers; unwanted sprites can easily be hidden off screen, and sprites
can be shown partially at the top and left screen edges.

Sprite masking, mode 1
----------------------

If a sprite has an X coordinate of zero, and has a Y coordinate that
is within range of the display, then all sprites of lower priority
will not be displayed on the lines which the sprite takes up.

The height of the sprite is determined by the vertical size bits in
the sprite attributes; other factors like horizontal size, pattern data
used, priority bit, and color palette have no effect.

For instance, an 8x32 sprite at coordinates 0, 128, that was sprite #4
in the list would stop all sprites onwards for lines zero to 31 from
being shown. However, sprites #0 through #3 could still be displayed
in this area.

Sprite masking, mode 2
----------------------

If a sprite has an X coordinate of one, the former rule is invalid. Low
priority sprites will only be masked if a sprite with an X coordinate of
zero _also_ has a sprite with an X coordinate of one on the _same_ line.

This 'mode' is enabled when the VDP first parses a sprite with an X
coordinate of one. It is reset at the end of the frame.

To my knowledge, the only game which uses this masking mode is Galaxy
Force II. Because of this, I cannot ensure my description is accurate for
other games which may use it.

Sprite Drawing Limitations
--------------------------

The VDP will stop drawing sprites under the following conditions:

- The 80th sprite has been drawn in 40-cell mode.
- The 64th sprite has been drawn in 32-cell mode.
- Twenty sprites on the same scanline have been drawn in 40 cell mode.
- Sixteen sprites on the same scanline have been drawn in 32 cell mode.
- 320 pixels worth of sprite data has been drawn on the same scanline
in 40 cell mode.
- 256 pixels worth of sprite data has been drawn on the same scanline
in 32 cell mode.
- The currently drawn sprite has a link field of zero.

Sprites that are outside of the physical display area are still taken
into account.

Link settings that create an 'infinite loop' or that have self-referencing
will not cause any unforseen problem, these kinds of loops will be broken
out of when the above sprite limitations are eventually reached.

Because so many sprites can be shown on a single line, some games will
fill the entire display with sprites for a 'fake' third background layer.
Games that do this include 'Red Zone' by Zyrinx.

----------------------------------------------------------------------------
16.) Shadow / Hilight mode
----------------------------------------------------------------------------

Shadow / hilight mode allows more colors to be displayed on screen.

These additional colors are selected based upon the priority settings
for a background tile or sprite, and when certain kinds of sprite pixels
overlap background pixels.

Background
----------

Background tiles are shown at half intensity, or at normal intensity
if their priority bit is set.

In the latter case, this affects all other graphics elements in the
region (usually 8x8) that the tile takes up, regardless of the tile
containing opaque pixels or not. Meaning that the backdrop color, other
background plane, and sprites will be forcibly shown at normal intensity
in a given area if a background tile has it's priority bit set.

For instance, Ranger-X has both background layers and all sprites set
to low priority. A column in plane A uses high priority transparent
tiles. The result is that any sprites passing within that column, as
well as the plane B tiles that scroll behind it, are all shown at
normal intensity.

Sprites
-------

Depending on the priority setting, sprites are shown at normal or half
intensity just like background tiles.

Colors 0Eh, 1Eh, 2Eh, are always shown at normal intensity regardless of
priority. I'd say this a bug rather than a feature.

Any pixel in a sprite that uses colors 3Eh or 3Fh is treated specially:

Pixels with color 3Eh are not drawn. Instead, the underlying pixel
(from the backdrop or background) will be shown at half intensity.

If the pixel to be overwritten is already at half intensity, then
nothing will happen.

Pixels with color 3Fh are not drawn. Instead, the underlying pixel
(from the backdrop or background) will be shown at double intensity.

Backdrop
--------

The backdrop is shown at half intensity, while the overscan region outside
of the display area is always shown at normal intensity.

If a background tile has high priority, then the corresponding 8x8 block
of the backdrop color will be shown at normal intensity. It does not matter
if the background tile is fully opaque or not.

Operator sprites will affect the backdrop color as well.

Details
-------

It isn't known exactly how the colors are generated in shadow / hilight
mode. Currently all emulators make the half and double intensity colors
exactly half and double brightness of the current palette.

This is not correct. At least the double intensity palette is actually
not much brighter than the normal palette. You can see a good example
of this by running any game using hilight sprites in an emulator
side-by-side to the same game running on a real Genesis.

However, I haven't been able to figure out the colors exactly. In
particular, the introduction screen for Sonic 3D will only look correct
if the colors are exactly half and double, while this is certainly wrong
for other games.

I've verified that the contents of CRAM entries 3Eh and 3Fh do not
affect the intensity of shadow and hilight pixels used in sprites.

Any information on the colors used in shadow / hilight mode would be
appreciated.

----------------------------------------------------------------------------
17.) VDP registers
----------------------------------------------------------------------------

All the register names are taken from the manual.

$00 - Mode Set Register No. 1
-----------------------------

d7 - No effect
d6 - No effect
d5 - No effect
d4 - IE1 (Horizontal interrupt enable)
d3 - 1= Invalid display setting
d2 - Palette select
d1 - M3 (HV counter latch enable)
d0 - Display disable

Bit 4 will enable horizontal interrupts when set.

When bit 2 is cleared, only bits 1, 5, and 9 are taken into account
when the VDP generates color data from each word of CRAM. (meaning
the LSB of each RGB component is the only bit used) This reduces the
available color palette from 512 to 8 colors.

Bit 1 will cause the HV counter to be latched when a level 2 interrupt
is generated. The HV counter will resume normal operation when this bit
is cleared. (untested, need more info)

Setting bit 0 actually turns off all display generation, as opposed to the
screen blanking feature which simply shows the backdrop color.

$01 - Mode Set Register No. 2
-----------------------------

d7 - TMS9918 / Genesis display select
d6 - DISP (Display Enable)
d5 - IE0 (Vertical Interrupt Enable)
d4 - M1 (DMA Enable)
d3 - M2 (PAL / NTSC)
d2 - SMS / Genesis display select
d1 - 0 (No effect)
d0 - 0 (See notes)

Bit 7 seemingly puts the display in a TMS9918-like state when set, similar
to one of it's text display modes. Each 8x8 block is filled with a solid
color from the palette, and has no pattern data. The sprites seem to be
active. I couldn't select any of the other TMS9918 modes through the
usual TMS9918 mode bits. It would appear all the colors are actually
affected by CRAM, instead of using a fixed color set.

Bit 6 will blank the display when cleared. Any line that is blanked is
filled with the backdrop color. During this time, you can freely access
VDP memory with no limitations on the number of writes per line.

Bit 5 will enable vertical blanking interrupts when set.

Bit 4 will enable DMA operations when set. Otherwise, nothing will happen
when a DMA command is sent to the VDP.

Bit 3 will select between a PAL (240) and NTSC (224 lines) display.

Bit 2 toggles between the Master System (mode 4) and Genesis (mode 5)
display modes. While in mode 4, none of the registers which normally
affect the Genesis work; and the unused registers (8, 9 - can't test 6) now
function. The mode bits which select TMS9918 modes on a real SMS have
no function here. (This is why the SMS game F16 Fighter will not work
with a Power Base Converter, it uses some of the TMS9918 modes in-game)

The one exception is register $0C. You can set up a 320x192 display,
but the leftmost eight columns read 'garbage' data for the name table
attributes. Enabling interlace makes the display unstable. (and this
is partially true for a 320x192 picture, which shakes slightly) I'd
advise you set $0C to zero to enable a 256x192 display, which is the
normal SMS resolution. The Genesis always generates a 224 line picture;
the 192 lines in SMS mode are centered in the middle of the screen.

I could not get the top row or right column lock features to work while
in SMS mode. Apart from this bit, the M3 pin on the cartridge connector
also puts the machine into SMS mode, which may fully enable all video
features.

Bit 0 has an interesting effect; horizontal scrolling is disabled, and
it would almost seem like the horizontal scroll value modifies the
horizontal retrace / blanking / sync start and end positions around; the
middle of the display is blanked out, and will scroll left or right.
(note the blanked area scrolls - not the background) Moving too far in
one direction, so the blanked area is offscreen, totally corrupts the
display.

Combining bits 7 (TMS9918 mode) and 2 (SMS mode) have no effect.

$02 - Pattern Name Table Address for Scroll A
---------------------------------------------

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

$03 - Pattern Name Table 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 - Pattern Name Table Address for Scroll B
---------------------------------------------

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

$05 - Sprite Attribute Table Base Address
-----------------------------------------

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.

$07 - Backdrop Color
--------------------

Bits 5-0 of this register select a palette entry to be used as the
backdrop color.

The backdrop color is displayed in the following places:

- The overscan area around the physical display
- Any line where the display enable bit has been cleared

You can think of the display being filled with the backdrop color, and
then everything else being drawn over it. Any gaps where no pixels were
drawn will show the backdrop color.

Even though palette entries 00h, 10h, 20h, and 30h cannot be used by
any patterns, these entries can be used for the backdrop color.

$0A - H Interrupt Register
--------------------------

Bits 7-0 specify the value to be loaded in the counter; for complete
details see the "Interrupts" section.

$0B - Mode Set Register No. 3
-----------------------------

d7 - 0 (No effect)
d6 - 0 (No effect)
d5 - 0 (No effect)
d4 - 0 (No effect)
d3 - IE2
d2 - VSCR
d1 - HSCR
d0 - LSCR

Bit 3 will enable external interrupts, caused by the TH pin being set
to input mode and having the TH interrupt enable bit set. (Both of these
are controlled by the Genesis' I/O registers)

Bit 2 selects between full screen vertical scrolling when clear, and
2-cell column based vertical scrolling when set.

Bits 1 and 0 determine how the VDP will parse the horizontal scroll table
when it is rendering display lines:

HSCR LSCR
0 0 - Full screen scroll
0 1 - Line scroll
1 0 - Cell scroll
1 1 - Line scroll

$0C - Mode Set Register No. 4
-----------------------------

d7 - RS0
d6 - 0 (No effect)
d5 - ? (See notes)
d4 - 0 (No effect)
d3 - S/TE
d2 - LSM1
d1 - LSM0
d0 - RS1

LSMx table:
00 : No interlace
01 : Interlace (Normal resolution)
10 : No interlace
11 : Interlace (Double resolution)

RSx table:
00 : Display is 32 cells wide
01 : Display is 40 cells wide
10 : Invalid display setting
11 : Display is 40 cells wide

Changes made to LSM0, LSM1 do not take effect until the display is no
longer in the active scan period.

All other bits can be modified with changes taking effect immediately at
any point in the display frame.

You should normally set the RSx bits to 00b or 11b. The unlicensed version
of Populous sets up a 40 cell display with a setting of 01b - technically
valid, but the display is distorted a bit.

Bit 5 seems to affect the display when used in conjunction with RS0, but
only in the same way as the display appears when using a setting of 01b.
I've tried every combination of bit 6 along with the RSx bits, and the
physical width of the display was never different from 32 or 40 cells.

$0D - H Scroll Data Table Base Address
--------------------------------------

Bits 5-0 of this register correspond to bits A15-A10 of the horizontal
scroll data table address.

$0F - Auto Increment Data
-------------------------

Bits 7-0 specify the value to be added to the VDP's address register
after every read or write to the data port.

A setting of zero means the address register is not incremented.

$10 - Scroll Size
-----------------

d7 - 0 (No effect)
d6 - 0 (No effect)
d5 - VSZ1
d4 - VSZ0
d3 - 0 (No effect)
d2 - 0 (No effect)
d1 - HSZ1
d0 - HSZ0

This register defines the size of the name tables for planes A and B.
Both fields can be set to the following values:

0 0 32 cells
0 1 64 cells
1 0 Invalid
1 1 128 cells

If the HSZ bits are set to 10b (invalid), then the first row of the name
table is shown for every line of the display.


$11 - Window H Position
-----------------------

d7 - RIGT
d6 - 0 (No effect)
d5 - 0 (No effect)
d4 - WHP5
d3 - WHP4
d2 - WHP3
d1 - WHP2
d0 - WHP1

This register will affect the window shown on the current line, if
the current line does not fall into the vertical range specified by
register $12.

The WHP field defines the horizontal range of the window, in units
of two cells. (16 pixels)

Setting the WHP field to zero disables the window.
Any nonzero value indicates how many 2-cell columns wide the window
plane is. (0=no window, 1=2 cells, 2=4 cells, 3=6 cells, etc.)

When RIGT=0, the window is shown from column zero to the column
specified by the WHP field.

For instance, if RIGT=0 and WHP=4, the window is displayed on columns
zero up to (and including) column seven.

When RIGHT=1, the window is shown from the column specified in the WHP
field up to the last column in the display meaning column 31 or 39
depending on the screen width setting.

For instance, if RIGT=1 and WHP=4, the window is displayed on columns
eight up to (and including) column 31 or 39.

Having WHP set to zero and RIGHT=1 is a legal setting; it means the
window is shown from column zero up to the last column in the display,
meaning the entire line is taken up by the window plane.

There is a bug in the window processing. This occurs when the window is
showing partially on the left side of the screen, specifically when
the VDP is drawing the 2-cell column from plane A that immediately proceeds
the last column the window was drawn on. (i.e. WHP+1)

If the lower four bits of the horizontal scroll value for the current
scan line are zero, then the name table attribute data for the current
column are fetched correctly.

If the lower four bits of the horizontal scroll value for the current
scan line are nonzero, the name table attribute data are fetched from
next column. (WHP+2)

In effect, you'll have N columns of the window plane, 1 column that has
identical patterns as the next column, then the remainder of the display
is drawn correctly.

Here's a diagram to illustrate this:
w = window tiles
abc = tile columns

D3-D0 of scroll value == 0
wwwwwwwwwwwwwwwwaabbccddeeffgghh

D3-D0 of scroll value != 0
wwwwwwwwwwwwwwwwbbbbccddeeffgghh

This register can be modified with changes taking effect immediately at
any point in the display frame.

Plane A is not shown in any column where plane W is shown; they cannot
overlap.

$12 - Window V Position
-----------------------

d7 - DOWN
d6 - 0 (No effect)
d5 - 0 (No effect)
d4 - WVP4
d3 - WVP3
d2 - WVP2
d1 - WVP1
d0 - WVP0

If the current scanline does not fall within the range specified by
register $12, then register $11 determines where the window is shown
for the remainder of the display.

The WVP field defines the vertical range of the window, in units
of eight lines.

Setting the WVP field to zero disables the window.
Any nonzero value indicates a vertical range for the window to appear
in. (0=no window, 1=lines 0-$7, 2= lines 0-$F, 3= lines 0-$17, etc.)

When DOWN=0, the window is shown from line zero to the line specified
by the WVP field.

For instance, if DOWN=0 and WVP=4, the window is displayed on lines
zero up to (and including) line $1F.

When DOWN=1, the window is shown from the line specified in the WVP
field up to the last line in the display.

For instance, if DOWN=1 and WVP=4, the window is displayed on lines $1F
up to (and including) the last line in the display.

Having WVP set to zero and DOWN=1 is a legal setting; it means the
window is shown from line zero up to the last line in the display,
meaning the entire screen is taken up by the window plane.

Plane A is not shown in any line where plane W is shown; they cannot
overlap.

----------------------------------------------------------------------------
18.) VDP Pinout
----------------------------------------------------------------------------

This is applicable to the 315-5313 chip used in the early versions of
the original Genesis model.

1-8 - SD0-SD7 (VRAM data bus)
10 - SE0 (VRAM)
11 - SC (VRAM)
12 - RAS (VRAM)
13 - CAS (VRAM)
15 - WE0 (VRAM)
16 - OE (VRAM)
17 - GND
26 - AGC
27 - R (Red video output)
28 - G (Green video output)
29 - B (Blue video output)
30 - AVC
31-38 - AD0-AD7 (VRAM address bus)
39 - YS
40 - SPA/8
41 - VSYNC (Vertical sync)
42 - C-SYNC (Composite sync)
43 - HSYNC (Horizontal sync)
44 - HL (from control port HL pin)
45 - SEL0 (from M3 on cartridge connector - forces mode 4 graphics)
46 - PAL (PAL / NTSC select)
47 - RESET (68000)
49 - CLK1 (68000)
48 - SEL1 (?)
50 - SBCR
51 - CLK0
52 - MCLK (53.64165 MHz)
53 - EDCLK
54 - VDD
54-70 - CD0-CD15 (68000 data bus)
71-93 - CA0-CA22 (68000 address bus (A23-A1))
94 - AVS
95 - PSG (SN76489 PSG sound output)
97 - GND
98 - INT
99 - BR
100 - BGAK
101 - BG
102 - MRE0
103 - INTAK
104 - IPL1 (68000)
105 - IPL2 (68000)
106 - IREQ
107 - RD (68000)
108 - WR (68000)
109 - MI
110 - AS (68000)
111 - UDS (68000)
112 - LDS (68000)
113 - R/W
114 - DTAK (68000)
115 - UWR (68000)
116 - LWR (68000)
118 - CAS0 (VRAM)
117 - OE0 (VRAM)
119 - RAS0 (VRAM)
128 - VDD

============================================================================

To-do test list

- Last column wrapping (40 cell mode only?)
- Columns being offset by the horizontal scroll value (d3-d0)
- How line scrolling is managed in interlace mode 2
- How sprite Y positions and VSRAM values are used in interlace mode 2
- Vertical interrupt supression via line interrupts
- Reverse sprite stage in CV
- Mid frame sprite table changes (can't be done I think; sprite table
changes aren't seen by VDP, though changing the sprite table address
will cause a switch)
- Large sprite pattern overflow
- Result of copy and fill operations overflowing
- Result of copy operations overlapping
- Use of HV counter latch in the 6-in-1 pak.
- Source and length registers being updated during DMA
- Confirm invalid code use
- Default status flag settings
- Sprite collisions and overflows outside of the physical display area
- How many times a sprite collision and overflow can occur (per line/frame?)

And for timing, based on the HV counter:

- Vertical counter increment
- Horizontal blanking flag clear and set
- Vertical blank flag clear and set
- Horizontal interrupt occurance
- Vertical interrupt occurance
- Invalid periods for vertical counter
- Invalid periods for horizontal counter (test with 6-in-1 pak)
- Start/stop of physical display (use sprite collision on either edge)

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT