fs2port/port/include/chunk5Vertex.h

87 lines
3.7 KiB
C

// C translation of chunk5's 3D vertex pipeline: the vertex-emit
// family (ProcessVertex1/2, EmitPrimaryVertex), outcode classification
// (ClassifyVertex1/2), table perspective (ProjectVertex), the per-plane
// clippers (ClipVertex2ToLeft/Right/Top/Bottom, ClipVertex2ToFrustum,
// ClipBothVerticesToFrustum), the line emitter (EmitClippedLine), the
// 8-segment curve (SceneryOpEmitCurve) and the polygon fill kernel
// (PolygonScanFillSetup .. PolygonScanFillRow).
//
// All vertex state lives in the 64K RAM mirror at the chunk5 zero-page
// addresses named in chunk5Zp.h, so the routines here read and write
// the same cells the 6502 code does. The polygon working arrays
// (PrimVert*/SecVert* in chunk5) and the two auto-scale exponents are
// kept in Chunk5VertexStateT because nothing else in the image reads
// them and the FS2.1 image places them differently from the source.
//
// Rasterisation is delegated through Chunk5SinkT so the caller decides
// where pixels land (the port renders into its framebuffer).
#ifndef CHUNK5_VERTEX_H
#define CHUNK5_VERTEX_H
#include <stdbool.h>
#include <stdint.h>
#define CHUNK5_CURVE_SEGMENTS 8
typedef struct Chunk5VertexStateT {
uint8_t *ram;
} Chunk5VertexStateT;
// Rasterisation callbacks. Coordinates are chunk5 colour-pixel columns
// (0..139) and hires rows (0..191).
typedef struct Chunk5SinkT {
void (*plotColorPixel)(void *userData, int column, int row);
void (*drawColorLine)(void *userData, int col1, int row1, int col2, int row2);
void (*drawColorSpan)(void *userData, int rightColumn, int width, int row);
void (*setSpanColor)(void *userData, uint8_t sceneryCode);
void *userData;
} Chunk5SinkT;
// ClassifyVertex1 / ClassifyVertex2: outcode into $CA / $D3.
void chunk5ClassifyVertex1(uint8_t *ram);
void chunk5ClassifyVertex2(uint8_t *ram);
// ClipBothVerticesToFrustum: clip V1 against the lateral planes.
void chunk5ClipBothVerticesToFrustum(uint8_t *ram);
// ClipVertex2ToLeft/Top/Right/Bottom: move V2 onto the plane along the
// V1-V2 edge (with the overflow halve-and-retry).
void chunk5ClipVertex2ToBottom(uint8_t *ram);
void chunk5ClipVertex2ToLeft(uint8_t *ram);
void chunk5ClipVertex2ToRight(uint8_t *ram);
void chunk5ClipVertex2ToTop(uint8_t *ram);
// ClipVertex2ToFrustum: clip V2 against right/left/bottom/top planes
// in turn, reclassifying after each and stopping early when the
// segment is wholly outside.
void chunk5ClipVertex2ToFrustum(uint8_t *ram);
// SceneryOpEmitCurve body ($2B): reads both xform-B vertices at the
// scenery cursor $8B (advancing it by 9) and draws eight segments.
void chunk5EmitCurve(Chunk5VertexStateT *vs, const Chunk5SinkT *sink);
// EmitClippedLine: cull/clip/project V1->V2 and draw it, then restore
// V1 from V2 so the next segment chains.
void chunk5EmitClippedLine(uint8_t *ram, const Chunk5SinkT *sink);
// ProcessVertex1 / ProcessVertex2: transform the vertex at the scenery
// cursor into V1 / V2 (advancing the cursor) and either pool it
// (polygon mode) or classify + project it.
void chunk5ProcessVertex1(Chunk5VertexStateT *vs, bool xformA);
void chunk5ProcessVertex2(Chunk5VertexStateT *vs, bool xformA);
// ProjectVertex: table perspective divide of one camera-space vertex.
void chunk5ProjectVertex(int16_t x, int16_t y, int16_t z, uint8_t *outColumn, uint8_t *outRow);
void chunk5ProjectV1ToScreen(uint8_t *ram);
void chunk5ProjectV2ToScreen(uint8_t *ram);
// 16-bit little-endian helpers for the RAM mirror.
int16_t chunk5Read16(const uint8_t *ram, uint16_t addr);
void chunk5Write16(uint8_t *ram, uint16_t addr, int16_t value);
// Bind the vertex state to the RAM image.
void chunk5VertexStateInit(Chunk5VertexStateT *vs, uint8_t *ram);
#endif