Posted: Tue Nov 13, 2012 11:42 am
I'm going to publish my very latest timing information that I've obtained about the alignment of various digital and analog events with the HV counter. Here's the data I've sampled for horizontal scan information:
And here's my data for vertical scan information:
The samplings of the analog screen sections are mostly based on the information that's already been published here on SpritesMind by various other authors, and I haven't independently verified all of it. All the measurements about the alignment of the status register flags, sync lines, and interrupt events, have been sampled by me though, and have been confirmed to an exact SC cycle. I used a very useful fact about the VDP in order to do this, which is that for the first couple of clock cycles when a value is being read from the status register or HV counter, but before it's been latched by the M68000, the data is actually output "live" from the internal register state, meaning if the register state changes while the data is being read and its value asserted over the external bus, its value will actually immediately change. This can be observed using a logic analyser, and the exact SC cycle at which the change occurs can then be determined. I used this method to obtain these values.
Code: Select all
//Analog screen sections in relation to HCounter (H32 mode):
//-----------------------------------------------------------------
//| Screen section | HCounter |Pixel| Pixel |Serial|Serial |MCLK |
//| (PAL/NTSC H32) | value |clock| clock |clock |clock |ticks|
//| | |ticks|divider|ticks |divider| |
//|----------------|-----------|-----|-------|------|-------|-----|
//|Left border |0x00B-0x017| 13 |SCLK/2 | 26 |MCLK/5 | 130 |
//|----------------|-----------|-----|-------|------|-------|-----|
//|Active display |0x018-0x117| 256 |SCLK/2 | 512 |MCLK/5 |2560 |
//|----------------|-----------|-----|-------|------|-------|-----|
//|Right border |0x118-0x125| 14 |SCLK/2 | 28 |MCLK/5 | 140 |
//|----------------|-----------|-----|-------|------|-------|-----|
//|Back porch |0x126-0x127| 9 |SCLK/2 | 18 |MCLK/5 | 90 |
//|(Right Blanking)|0x1D2-0x1D8| | | | | |
//|----------------|-----------|-----|-------|------|-------|-----|
//|Horizontal sync |0x1D9-0x1F2| 26 |SCLK/2 | 52 |MCLK/5 | 260 |
//|----------------|-----------|-----|-------|------|-------|-----|
//|Front porch |0x1F3-0x00A| 24 |SCLK/2 | 48 |MCLK/5 | 240 |
//|(Left Blanking) | | | | | | |
//|----------------|-----------|-----|-------|------|-------|-----|
//|TOTALS | | 342 | | 684 | |3420 |
//-----------------------------------------------------------------
//Analog screen sections in relation to HCounter (H40 mode):
//--------------------------------------------------------------------
//| Screen section | HCounter |Pixel| Pixel |EDCLK| EDCLK |MCLK |
//| (PAL/NTSC H40) | value |clock| clock |ticks|divider|ticks|
//| | |ticks|divider| | | |
//|----------------|---------------|-----|-------|-----|-------|-----|
//|Left border |0x00D-0x019 | 13 |EDCLK/2| 26 |MCLK/4 | 104 |
//|----------------|---------------|-----|-------|-----|-------|-----|
//|Active display |0x01A-0x159 | 320 |EDCLK/2| 640 |MCLK/4 |2560 |
//|----------------|---------------|-----|-------|-----|-------|-----|
//|Right border |0x15A-0x167 | 14 |EDCLK/2| 28 |MCLK/4 | 112 |
//|----------------|---------------|-----|-------|-----|-------|-----|
//|Back porch |0x168-0x16C | 9 |EDCLK/2| 18 |MCLK/4 | 72 |
//|(Right Blanking)|0x1C9-0x1CC | | | | | |
//|----------------|---------------|-----|-------|-----|-------|-----|
//|Horizontal sync |0x1CD.0-0x1D4.5| 7.5 |EDCLK/2| 15 |MCLK/5 | 75 |
//| |0x1D4.5-0x1D5.5| 1 |EDCLK/2| 2 |MCLK/4 | 8 |
//| |0x1D5.5-0x1DC.0| 7.5 |EDCLK/2| 15 |MCLK/5 | 75 |
//| |0x1DD.0 | 1 |EDCLK/2| 2 |MCLK/4 | 8 |
//| |0x1DE.0-0x1E5.5| 7.5 |EDCLK/2| 15 |MCLK/5 | 75 |
//| |0x1E5.5-0x1E6.5| 1 |EDCLK/2| 2 |MCLK/4 | 8 |
//| |0x1E6.5-0x1EC.0| 6.5 |EDCLK/2| 13 |MCLK/5 | 65 |
//| |===============|=====|=======|=====|=======|=====|
//| Subtotal|0x1CD-0x1EC | (32)| | (64)| |(314)|
//|----------------|---------------|-----|-------|-----|-------|-----|
//|Front porch |0x1ED | 1 |EDCLK/2| 2 |MCLK/5 | 10 |
//|(Left Blanking) |0x1EE-0x00C | 31 |EDCLK/2| 62 |MCLK/4 | 248 |
//| |===============|=====|=======|=====|=======|=====|
//| Subtotal|0x1ED-0x00C | (32)| | (64)| |(258)|
//|----------------|---------------|-----|-------|-----|-------|-----|
//|TOTALS | | 420 | | 840 | |3420 |
//--------------------------------------------------------------------
//Digital render events in relation to HCounter:
//----------------------------------------------------
//| Video |PAL/NTSC |PAL/NTSC |
//| Mode |H32 (RSx=00) |H40 (RSx=11) |
//| |V28/V30 (M2=*) |V28/V30 (M2=*) |
//| Event |Int any (LSMx=**)|Int any (LSMx=**)|
//|--------------------------------------------------|
//|HCounter |[1]0x000-0x127 |[1]0x000-0x16C |
//|progression |[2]0x1D2-0x1FF |[2]0x1C9-0x1FF |
//|9-bit internal| | |
//|--------------------------------------------------|
//|VCounter |HCounter changes |HCounter changes |
//|increment |from 0x109 to |from 0x149 to |
//| |0x10A in [1]. |0x14A in [1]. |
//|--------------------------------------------------| //Logic analyzer tests conducted on 2012-11-03 confirm 18 SC
//|HBlank set |HCounter changes |HCounter changes | //cycles between HBlank set in status register and HSYNC
//| |from 0x125 to |from 0x165 to | //asserted in H32 mode, and 21 SC cycles in H40 mode.
//| |0x126 in [1]. |0x166 in [1]. | //Note this actually means in H40 mode, HBlank is set at 0x166.5.
//|--------------------------------------------------| //Logic analyzer tests conducted on 2012-11-03 confirm 46 SC
//|HBlank cleared|HCounter changes |HCounter changes | //cycles between HSYNC cleared and HBlank cleared in status
//| |from 0x009 to |from 0x00A to | //register in H32 mode, and 61 SC cycles in H40 mode.
//| |0x00A in [1]. |0x00B in [1]. | //Note this actually means in H40 mode, HBlank is cleared at 0x00B.5.
//|--------------------------------------------------|
//|F flag set |HCounter changes |HCounter changes | //Logic analyzer tests conducted on 2012-11-03 confirm 28 SC
//| |from 0x000 to |from 0x000 to | //cycles between HSYNC cleared and odd flag toggled in status
//| |0x001 in [1] |0x001 in [1] | //register in H32 mode, and 40 SC cycles in H40 mode.
//|--------------------------------------------------|
//|ODD flag |HCounter changes |HCounter changes | //Logic analyzer tests conducted on 2012-11-03 confirm 30 SC
//|toggled |from 0x001 to |from 0x001 to | //cycles between HSYNC cleared and odd flag toggled in status
//| |0x002 in [1] |0x002 in [1] | //register in H32 mode, and 42 SC cycles in H40 mode.
//|--------------------------------------------------|
//|HINT flagged |HCounter changes |HCounter changes | //Logic analyzer tests conducted on 2012-11-02 confirm 74 SC
//|via IPL lines |from 0x109 to |from 0x149 to | //cycles between HINT flagged in IPL lines and HSYNC
//| |0x10A in [1]. |0x14A in [1]. | //asserted in H32 mode, and 78 SC cycles in H40 mode.
//|--------------------------------------------------|
//|VINT flagged |HCounter changes |HCounter changes | //Logic analyzer tests conducted on 2012-11-02 confirm 28 SC
//|via IPL lines |from 0x000 to |from 0x000 to | //cycles between HSYNC cleared and VINT flagged in IPL lines
//| |0x001 in [1]. |0x001 in [1]. | //in H32 mode, and 40 SC cycles in H40 mode.
//|--------------------------------------------------|
//|HSYNC asserted|HCounter changes |HCounter changes |
//| |from 0x1D8 to |from 0x1CC to |
//| |0x1D9 in [2]. |0x1CD in [2]. |
//|--------------------------------------------------|
//|HSYNC negated |HCounter changes |HCounter changes |
//| |from 0x1F2 to |from 0x1EC to |
//| |0x1F3 in [2]. |0x1ED in [2]. |
//----------------------------------------------------
Code: Select all
//Analog screen sections in relation to VCounter:
//-------------------------------------------------------------------------------------------
//| Video |NTSC |NTSC |PAL |PAL |
//| Mode |H32/H40(RSx00/11)|H32/H40(RSx00/11)|H32/H40(RSx00/11)|H32/H40(RSx00/11)|
//| |V28 (M2=0) |V30 (M2=1) |V28 (M2=0) |V30 (M2=1) |
//| |Int none(LSMx=*0)|Int none(LSMx=*0)|Int none(LSMx=*0)|Int none(LSMx=*0)|
//| |------------------------------------------------------------------------
//| | VCounter |Line | VCounter |Line | VCounter |Line | VCounter |Line |
//| Screen section | value |count| value |count| value |count| value |count|
//|-----------------|-----------|-----|-----------|-----|-----------|-----|-----------|-----|
//|Active display |0x000-0x0DF| 224 |0x000-0x1FF| 240*|0x000-0x0DF| 224 |0x000-0x0EF| 240 |
//|-----------------|-----------|-----|-----------|-----|-----------|-----|-----------|-----|
//|Bottom border |0x0E0-0x0E7| 8 | | 0 |0x0E0-0x0FF| 32 |0x0F0-0x107| 24 |
//|-----------------|-----------|-----|-----------|-----|-----------|-----|-----------|-----|
//|Bottom blanking |0x0E8-0x0EA| 3 | | 0 |0x100-0x102| 3 |0x108-0x10A| 3 |
//|-----------------|-----------|-----|-----------|-----|-----------|-----|-----------|-----|
//|Vertical sync |0x1E5-0x1E7| 3 | | 0 |0x1CA-0x1CC| 3 |0x1D2-0x1D4| 3 |
//|-----------------|-----------|-----|-----------|-----|-----------|-----|-----------|-----|
//|Top blanking |0x1E8-0x1F4| 13 | | 0 |0x1CD-0x1D9| 13 |0x1D5-0x1E1| 13 |
//|-----------------|-----------|-----|-----------|-----|-----------|-----|-----------|-----|
//|Top border |0x1F5-0x1FF| 11 | | 0 |0x1DA-0x1FF| 38 |0x1E2-0x1FF| 30 |
//|-----------------|-----------|-----|-----------|-----|-----------|-----|-----------|-----|
//|TOTALS | | 262 | | 240*| | 313 | | 313 |
//-------------------------------------------------------------------------------------------
//*When V30 mode and NTSC mode are both active, no border, blanking, or retrace
//occurs. A 30-row display is setup and rendered, however, immediately following the
//end of the 30th row, the 1st row starts again. In addition, the VCounter is never
//reset, which usually happens at the beginning of vertical blanking. Instead, the
//VCounter continuously counts from 0x000-0x1FF, then wraps around back to 0x000 and
//begins again. Since there are only 240 lines output as part of the display, this
//means the actual line being rendered is desynchronized from the VCounter. Digital
//events such as vblank flags being set/cleared, VInt being triggered, the odd flag
//being toggled, and so forth, still occur at the correct VCounter positions they
//would occur in (IE, the same as PAL mode V30), however, since the VCounter has 512
//lines per cycle, this means VInt is triggered at a slower rate than normal.
//##TODO## Confirm on the hardware that the rendering row is desynchronized from the
//VCounter. This would seem unlikely, since a separate render line counter would have
//to be maintained apart from VCounter for this to occur.
//Digital render events in relation to VCounter under NTSC mode:
//#ODD - Runs only when the ODD flag is set
//----------------------------------------------------------------------------------------
//| Video |NTSC |NTSC |NTSC |NTSC |
//| Mode |H32/H40(RSx00/11)|H32/H40(RSx00/11)|H32/H40(RSx00/11)|H32/H40(RSx00/11)|
//| |V28 (M2=0) |V28 (M2=0) |V30 (M2=1) |V30 (M2=1) |
//| Event |Int none(LSMx=*0)|Int both(LSMx=*1)|Int none(LSMx=*0)|Int both(LSMx=*1)|
//|--------------------------------------------------------------------------------------|
//|VCounter |[1]0x000-0x0EA |[1]0x000-0x0EA |[1]0x000-0x1FF |[1]0x000-0x1FF |
//|progression |[2]0x1E5-0x1FF |[2]0x1E4(#ODD) | | |
//|9-bit internal| |[3]0x1E5-0x1FF | | |
//|--------------------------------------------------------------------------------------|
//|VBlank set |VCounter changes | |VCounter changes | |
//| |from 0x0DF to | <Same> |from 0x0EF to | <Same> |
//| |0x0E0 in [1]. | |0x0F0 in [1]. | |
//|--------------------------------------------------------------------------------------|
//|VBlank cleared|VCounter changes | |VCounter changes | |
//| |from 0x1FE to | <Same> |from 0x1FE to | <Same> |
//| |0x1FF in [2]. | |0x1FF in [1]. | |
//|--------------------------------------------------------------------------------------|
//|F flag set |At indicated | |At indicated | |
//| |HCounter position| |HCounter position| |
//| |while VCounter is| <Same> |while VCounter is| <Same> |
//| |set to 0x0E0 in | |set to 0x0F0 in | |
//| |[1]. | |[1]. | |
//|--------------------------------------------------------------------------------------|
//|VSYNC asserted|VCounter changes | | Never | |
//| |from 0x0E7 to | <Same> | | <Same> |
//| |0x0E8 in [1]. | | | |
//|--------------------------------------------------------------------------------------|
//|VSYNC cleared |VCounter changes | | Never | |
//| |from 0x1F4 to | <Same> | | <Same> |
//| |0x1F5 in [2]. | | | |
//|--------------------------------------------------------------------------------------|
//|ODD flag |At indicated | |At indicated | |
//|toggled |HCounter position| |HCounter position| |
//| |while VCounter is| <Same> |while VCounter is| <Same> |
//| |set to 0x0E0 in | |set to 0x0F0 in | |
//| |[1]. | |[1]. | |
//----------------------------------------------------------------------------------------
//Digital render events in relation to VCounter under PAL mode:
//#ODD - Runs only when the ODD flag is set
//----------------------------------------------------------------------------------------
//| Video |PAL |PAL |PAL |PAL |
//| Mode |H32/H40(RSx00/11)|H32/H40(RSx00/11)|H32/H40(RSx00/11)|H32/H40(RSx00/11)|
//| |V28 (M2=0) |V28 (M2=0) |V30 (M2=1) |V30 (M2=1) |
//| Event |Int none(LSMx=*0)|Int both(LSMx=*1)|Int none(LSMx=*0)|Int both(LSMx=*1)|
//|--------------------------------------------------------------------------------------|
//|VCounter |[1]0x000-0x102 |[1]0x000-0x101 |[1]0x000-0x10A |[1]0x000-0x109 |
//|progression |[2]0x1CA-0x1FF |[2]0x1C9(#ODD) |[2]0x1D2-0x1FF |[2]0x1D1(#ODD) |
//|9-bit internal| |[3]0x1CA-0x1FF | |[3]0x1D2-0x1FF |
//|--------------------------------------------------------------------------------------|
//|VBlank set |VCounter changes | |VCounter changes | |
//| |from 0x0DF to | <Same> |from 0x0EF to | <Same> |
//| |0x0E0 in [1]. | |0x0F0 in [1]. | |
//|--------------------------------------------------------------------------------------|
//|VBlank cleared|VCounter changes | |VCounter changes | |
//| |from 0x1FE to | <Same> |from 0x1FE to | <Same> |
//| |0x1FF in [2]. | |0x1FF in [2]. | |
//|--------------------------------------------------------------------------------------|
//|F flag set |At indicated | |At indicated | |
//| |HCounter position| |HCounter position| |
//| |while VCounter is| <Same> |while VCounter is| <Same> |
//| |set to 0x0E0 in | |set to 0x0F0 in | |
//| |[1]. | |[1]. | |
//|--------------------------------------------------------------------------------------|
//|VSYNC asserted|VCounter changes | |VCounter changes | |
//| |from 0x0FF to | <Same> |from 0x107 to | <Same> |
//| |0x100 in [1]. | |0x108 in [1]. | |
//|--------------------------------------------------------------------------------------|
//|VSYNC cleared |VCounter changes | |VCounter changes | |
//| |from 0x1D9 to | <Same> |from 0x1E1 to | <Same> |
//| |0x1DA in [2]. | |0x1E2 in [2]. | |
//|--------------------------------------------------------------------------------------|
//|ODD flag |At indicated | |At indicated | |
//|toggled |HCounter position| |HCounter position| |
//| |while VCounter is| <Same> |while VCounter is| <Same> |
//| |set to 0x0E0 in | |set to 0x0F0 in | |
//| |[1]. | |[1]. | |
//----------------------------------------------------------------------------------------