====== Set Up a Triangle ======
[[tools:risc#example-triangle|Open this program in the workbench]].
Draw a flat opaque red triangle with vertices ''(16,16)'', ''(48,32)'', ''(16,48)''. The destination is a 64×64 ARGB8888 surface at local byte address ''0x00100000'', with 256 bytes per row.
Local memory and the RISC are already configured. All drawing engines are idle on entry, the surface occupies reserved memory through ''0x00103FFF'', and the program enters from V1000 compatibility mode.
===== Pixel State =====
^ spr index ^ Register ^ Value ^ Meaning ^
| 1 | SrcMode | ''0x00000000'' | No texture or specular add; SwapUV clear |
| 2 | SrcMask | ''0x00000000'' | U/V masks zero; unused coordinates are zero |
| 3 | Stride | ''0x00000100'' | DstStride0 = 1, DstStride1 = 0: 256 bytes |
| 4 | DstBase | ''0x00100000'' | Word-aligned surface base |
| 5 | DstMode | ''0x0000000C'' | ALU source replace; no blend, Z write, fog, dither or alpha rejection |
| 6 | DstFmt | ''0x0000000C'' | 32-bit ARGB8888 |
| 7 | PMask | ''0xFFFFFFFF'' | All planes writable |
| 12 | PatMode | ''0x00000000'' | Pattern disabled |
| 14, 15 | ScissorX, ScissorY | ''0x00000040'' | Half-open range 0..64 |
Stride code 1 means a shift of eight, not a one-byte row. DstStride0 occupies bits 10:8, so its operand value is ''1 << 8''. The source and Z stride fields are zero because those reads are unused.
Sources: [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=28|Technical Spec, p.28]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=29|Technical Spec, p.29]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=30|Technical Spec, p.30]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=31|Technical Spec, p.31]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=33|Technical Spec, p.33]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=34|Technical Spec, p.34]]
===== Start Values and Edge Gradients =====
DrawCtl is ''0x000B'': triangle shadowing enabled, mono clear and all parameter iteration enables clear. XTop, YTop and XMid still iterate. Constant color comes from the shadowed R/A/G/B start values.
^ Parameter ^ Register ^ Word ^
| XTop, YTop | a0/%128, a1/%129 | ''0x00100000'', ''0x00100000'' |
| XMid, YMid | a16/%144, a17/%145 | ''0x00300000'', ''0x00200000'' |
| YBot | q1/%161 | ''0x00300000'' |
| dXLong/dy | a14/%142 | ''0x00000000'' |
| dXTop/dy | a30/%158 | ''0x00020000'' |
| dXBot/dy | q14/%174 | ''0xFFFE0000'' |
| dX | q0/%160 | ''0x00000000'': triangle, long edge on left, increasing edge walk |
| R, A | a4/%132, a5/%133 | ''0x00FF0000'', ''0x00FF0000'' |
| G, B | a6/%134, a7/%135 | Zero |
| Z | a2/%130 | Zero |
| Q | a3/%131 | ''0x00800000'' (0.5 in 0I.24F); perspective iteration disabled |
| R2, F, G2, B2, U, V | a8..a13/%136..%141 | Zero |
Coordinates, colors and X edge gradients use 16I.16F. The edge slopes follow directly from these vertices:
dXLong/dy = (16 - 16) / (48 - 16) = 0
dXTop/dy = (48 - 16) / (32 - 16) = +2
dXBot/dy = (16 - 48) / (48 - 32) = -2
The long edge is vertical at X=16 and lies on the left. For example, at Y=20 the right edge is X=24 and the half-open span covers X=16..23. Fractional coordinates are zero, so the initial Y subpixel correction is zero. No color, Z or texture gradients are needed when their iteration classes are disabled.
Sources: [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=12|Technical Spec, p.12]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=16|Technical Spec, p.16]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=17|Technical Spec, p.17]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=18|Technical Spec, p.18]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=19|Technical Spec, p.19]]
===== Assembly and Ordering =====
; Flat red triangle, vertices (16,16), (48,32), (16,48).
; Local memory configured; all engines idle; entering compatibility mode.
; Clobbers DrawCtl, listed shadow registers, %200, and listed Pixel state.
; Pixel Engine state. No shadow destinations have been written yet.
spri 1, %0 ; SrcMode: no texture, no specular, SwapUV = 0.
spri 2, %0 ; SrcMask: zero; unused coordinates stay zero.
li %200, 0x0100
spri 3, %200 ; Stride: DstStride0 = 1 => 256 bytes/row.
lui %200, 0x0010
spri 4, %200 ; DstBase = 0x00100000, word aligned.
li %200, 0x000C
spri 5, %200 ; DstMode: ALU replace, no Z/blend/fog/dither.
spri 6, %200 ; DstFmt = 0xC, ARGB8888.
spri 7, %16 ; PMask = 0xFFFFFFFF.
spri 12, %0 ; Pattern disabled.
li %200, 64
spri 14, %200 ; ScissorX: 0 <= X < 64.
spri 15, %200 ; ScissorY: 0 <= Y < 64.
; Enable shadowing before loading start values. Mono = 0.
li %40, 0x000B ; No parameter classes iterated.
lui %128, 0x0010 ; a0: XTop = 16.0.
lui %129, 0x0010 ; a1: YTop = 16.0.
or %130, %0, %0 ; a2: Z = 0.
lui %131, 0x0080 ; a3: Q = 0.5 in 0I.24F; Q disabled.
lui %132, 0x00FF ; a4: R = 255.0.
lui %133, 0x00FF ; a5: A = 255.0.
or %134, %0, %0 ; a6: G = 0.
or %135, %0, %0 ; a7: B = 0.
or %136, %0, %0 ; a8: R2 = 0; specular disabled.
or %137, %0, %0 ; a9: F = 0; fog disabled.
or %138, %0, %0 ; a10: G2 = 0.
or %139, %0, %0 ; a11: B2 = 0.
or %140, %0, %0 ; a12: U = 0.
or %141, %0, %0 ; a13: V = 0.
or %142, %0, %0 ; a14: dXLong/dy = 0.
lui %144, 0x0030 ; a16: XMid = 48.0.
lui %145, 0x0020 ; a17: YMid = 32.0.
lui %158, 0x0002 ; a30: dXTop/dy = +2.0.
or %160, %0, %0 ; q0: dX = 0, triangle, increasing edge walk.
lui %161, 0x0030 ; q1: YBot = 48.0.
lui %174, 0xFFFE ; q14: dXBot/dy = -2.0.
tri %128, %128, %0 ; XY + zero pair; word 0xFE808000.
add %0, %0, %0 ; tri -> fill separating instruction 1.
add %0, %0, %0 ; Separating instruction 2.
add %0, %0, %0 ; Separating instruction 3.
li %40, 0x0000 ; Stalls until Triangle idle, then disables shadowing.
add %0, %0, %0 ; DrawCtl -> compatibility draw gap 1.
add %0, %0, %0 ; Gap 2.
add %0, %0, %0 ; Gap 3.
halt 0
Pixel state is written first. DrawCtl then enables shadowing **before** the start values are loaded, with mono set before color writes. No spr follows a shadow-register write, so the two-instruction shadow-destination→spr hazard is avoided by this order.
''tri %128,%128,%0'' adds the zero pair ''%0/%1'' to XY, leaves XY unchanged and launches the triangle. Its word is ''0xFE808000''. Launch takes one cycle; the source gives total engine time as ''4 + scanlines + pixels'', excluding memory stalls.
Three ordinary instructions separate ''tri'' from possible Fill Engine use. The final DrawCtl write stalls until the triangle is idle, then disables shadowing. Three further instructions satisfy the DrawCtl hazard before a later compatibility draw. Every iterated start value must be loaded again before another triangle.
Sources: [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=7|Technical Spec, p.7]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=9|Technical Spec, p.9]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=13|Technical Spec, p.13]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=16|Technical Spec, p.16]], [[https://verite.3d32.org/_media/source/v2200spec.pdf#page=17|Technical Spec, p.17]]
[[drawing:triangle|Triangle reference]] · [[registers:risc-shadow-views:start|Shadow register map]] · [[registers:risc-special:risc_40|DrawCtl]] · [[risc:hazards|Hazards]] · [[examples:start|Examples]]