Commit the RDP demo before I mess it up.
authorTyler J. Stachecki <stachecki.tyler@gmail.com>
Sat, 30 Dec 2017 23:30:15 +0000 (18:30 -0500)
committerTyler J. Stachecki <stachecki.tyler@gmail.com>
Sun, 31 Dec 2017 14:05:46 +0000 (09:05 -0500)
Signed-off-by: Tyler J. Stachecki <stachecki.tyler@gmail.com>
libgfx/include/libgfx/init.h
libgfx/include/libgfx/rdp.h [new file with mode: 0644]
libgfx/ucodes/gfx.rsp
libn64/ucodes/init.rsp
rdpdemo/Makefile [new file with mode: 0644]
rdpdemo/src/3d.c [new file with mode: 0644]
rdpdemo/src/3dscene.c [new file with mode: 0644]
rdpdemo/src/main.c [new file with mode: 0644]

index 533bc25..7ee4dea 100644 (file)
@@ -21,7 +21,6 @@ void libgfx_init(void);
 static inline void libgfx_run(void) {
   libn64_rsp_set_pc(0x04001000);
   libn64_rsp_set_status(RSP_STATUS_CLEAR_HALT | RSP_STATUS_CLEAR_BROKE);
-  while ((libn64_rsp_get_status() & 0x3) != 0x3);
 }
 
 #endif
diff --git a/libgfx/include/libgfx/rdp.h b/libgfx/include/libgfx/rdp.h
new file mode 100644 (file)
index 0000000..cf8e3b9
--- /dev/null
@@ -0,0 +1,166 @@
+//
+// libgfx/include/libgfx/rdpcmd.h: RDP commands.
+//
+// n64chain: A (free) open-source N64 development toolchain.
+// Copyright 2014-16 Tyler J. Stachecki <stachecki.tyler@gmail.com>
+//
+// This file is subject to the terms and conditions defined in
+// 'LICENSE', which is part of this source code package.
+//
+
+#ifndef LIBGFX_INCLUDE_LIBGFX_RDPCMD_H
+#define LIBGFX_INCLUDE_LIBGFX_RDPCMD_H
+
+#include <libgfx/rspbuf.h>
+#include <stdint.h>
+
+// This file provides a bunch of functions which pack RAW RDP fields.
+// An interface that is a bit more intelligent about cramming values
+// should come later...
+#define COLOR_ELEMENT_4B          0
+#define COLOR_ELEMENT_8B          1
+#define COLOR_ELEMENT_16B         2
+#define COLOR_ELEMENT_32B         3
+
+#define CYCLE_TYPE_1CYCLE         (0ULL << 52)
+#define CYCLE_TYPE_2CYCLE         (1ULL << 52)
+#define CYCLE_TYPE_COP            (2ULL << 52)
+#define CYCLE_TYPE_FILL           (3ULL << 52)
+
+#define FORMAT_RGBA               0
+#define FORMAT_YUV                1
+#define FORMAT_COLOR_INDEX        2
+#define FORMAT_IA                 3
+#define FORMAT_I                  4
+
+#define SCISSOR_NO_INTERLACED     0
+#define SCISSOR_INTERLACED        1
+#define SCISSOR_DONTCARE          0
+#define SCISSOR_KEEPEVEN          0
+#define SCISSOR_KEEPODD           1
+
+static inline uint32_t rdp_rgba16(
+    uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
+  uint16_t rgba16 = (r << 8) | ((g & 0xF8) << 3) | ((b & 0xF8) >> 2) | (a >> 7);
+  return (rgba16 << 16) | rgba16;
+}
+
+static inline uint32_t rdp_rgba32(
+    uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
+  return (r << 24) | (g << 16) | (b << 8) | a;
+}
+
+static inline void rsp_finalize(struct libgfx_rspbuf *rspbuf) {
+  libgfx_rspbuf_append(rspbuf, 0x00000000);
+}
+
+// The commands that follow are uCode commands. uCode commands can
+// be quickly identified because they are always signed number (i.e.,
+// bit 31 is signed).
+
+// RSP Draw Triangle (given three vertex cache indexes)
+static inline void rsp_draw_triangle(struct libgfx_rspbuf *rspbuf,
+    unsigned vert1, unsigned vert2, unsigned vert3) {
+
+  libgfx_rspbuf_append(rspbuf, 0xF000000F |
+      (vert1 << 20) | (vert2 << 12) | (vert3 << 4));
+}
+
+// The commands that follow are RDP commands. An interface which is
+// a bit more intelligent about packing them should come in the future...
+
+// RDP Fill Rectangle
+static inline void rdp_fill_rectangle(struct libgfx_rspbuf *rspbuf,
+    float xh, float yh, float xl, float yl) {
+
+  uint16_t xhsc = xh * 4;
+  uint16_t yhsc = yh * 4;
+  uint16_t xlsc = xl * 4;
+  uint16_t ylsc = yl * 4;
+
+  libgfx_rspbuf_append(rspbuf, 0x36000000 |
+      ((xlsc & 0xFFF) << 12) | (ylsc & 0xFFF));
+
+  libgfx_rspbuf_append(rspbuf,
+      ((xhsc & 0xFFF) << 12) | (yhsc & 0xFFF));
+}
+
+// RDP Set Blend Color
+static inline void rdp_set_blend_color(struct libgfx_rspbuf *rspbuf,
+    uint32_t rgba32) {
+
+  libgfx_rspbuf_append(rspbuf, 0x39000000);
+  libgfx_rspbuf_append(rspbuf, rgba32);
+}
+
+// RDP Set Color Image
+static inline void rdp_set_color_image(struct libgfx_rspbuf *rspbuf,
+    unsigned format, unsigned size, unsigned width, uint32_t fb_origin) {
+
+  libgfx_rspbuf_append(rspbuf, 0x3F000000 |
+      (format << 21) | (size << 19) | width);
+
+  libgfx_rspbuf_append(rspbuf, fb_origin);
+}
+
+// RDP Set Fill Color
+static inline void rdp_set_fill_color(struct libgfx_rspbuf *rspbuf,
+    uint32_t rgba) {
+
+  libgfx_rspbuf_append(rspbuf, 0x37000000);
+  libgfx_rspbuf_append(rspbuf, rgba);
+}
+
+// RDP Set Other Modes
+static inline void rdp_set_other_modes(struct libgfx_rspbuf *rspbuf,
+    uint64_t bits) {
+
+  uint32_t bits_hi = bits >> 32;
+  uint32_t bits_lo = bits;
+
+  libgfx_rspbuf_append(rspbuf, 0x2F000000 | bits_hi);
+  libgfx_rspbuf_append(rspbuf, bits_lo);
+}
+
+// RDP Set Scissor
+static inline void rdp_set_scissor(struct libgfx_rspbuf *rspbuf,
+    float xh, float yh, float xl, float yl, unsigned f, unsigned o) {
+
+  uint16_t xhsc = xh * 4;
+  uint16_t yhsc = yh * 4;
+  uint16_t xlsc = xl * 4;
+  uint16_t ylsc = yl * 4;
+
+  libgfx_rspbuf_append(rspbuf, 0x2D000000 |
+      ((xhsc & 0xFFF) << 12) | (yhsc & 0xFFF));
+
+  libgfx_rspbuf_append(rspbuf, (f << 25) | (o << 24) |
+      ((xlsc & 0xFFF) << 12) | (ylsc & 0xFFF));
+}
+
+// RDP Sync Full
+static inline void rdp_sync_full(struct libgfx_rspbuf *rspbuf) {
+  libgfx_rspbuf_append(rspbuf, 0x29000000);
+  libgfx_rspbuf_append(rspbuf, 0x00000000);
+}
+
+// RDP Sync Load
+static inline void rdp_sync_load(struct libgfx_rspbuf *rspbuf) {
+  libgfx_rspbuf_append(rspbuf, 0x26000000);
+  libgfx_rspbuf_append(rspbuf, 0x00000000);
+}
+
+// RDP Sync Pipe
+static inline void rdp_sync_pipe(struct libgfx_rspbuf *rspbuf) {
+  libgfx_rspbuf_append(rspbuf, 0x27000000);
+  libgfx_rspbuf_append(rspbuf, 0x00000000);
+}
+
+// RDP Sync Tile
+static inline void rdp_sync_tile(struct libgfx_rspbuf *rspbuf) {
+  libgfx_rspbuf_append(rspbuf, 0x28000000);
+  libgfx_rspbuf_append(rspbuf, 0x00000000);
+}
+
+#endif
+
index a8ad251..58b9ce4 100644 (file)
@@ -8,7 +8,7 @@
 .text
   addiu $30, $0, VERTEX_CACHE_OFFSET
   addiu COMMAND_POINTER, $0, 0x10
-  addiu OUTPUT_POINTER, $0, 0x100
+  addiu OUTPUT_POINTER, $0, 0x400
 
 loop:
   ; Check if command is RSP processing command.
@@ -30,7 +30,7 @@ loop:
 
 finish:
   lui $at, 0x0400
-  ori $at, $at, 0x100
+  ori $at, $at, 0x400
   mtc0 $at, CMD_START
 
   lui $at, 0x0400
index c02cf29..192f541 100644 (file)
@@ -1,5 +1,10 @@
 #include "defs.h"
 
+.data
+.half 0x0000 ; 0
+.half 0x4000 ; 1/4
+.half 0x0008 ; 8
+
 .text
 
 ; Initialize the RSP (configure CP0, load constants, etc.)
@@ -12,6 +17,9 @@ init_rdp:
   addiu $at, $0, (SET_XBUS_DMEM_DMA | CLEAR_FREEZE | CLEAR_FLUSH)
   mtc0 $at, CMD_STATUS
 
+; Load the magical constant vector register.
+  lqv $v31, 0x0($0)
+
 ; Raise an interrupt - we are done.
   break
   nop
diff --git a/rdpdemo/Makefile b/rdpdemo/Makefile
new file mode 100644 (file)
index 0000000..76435a4
--- /dev/null
@@ -0,0 +1,125 @@
+#
+# Makefile for n64chain ROMs.
+#
+# n64chain: A (free) open-source N64 development toolchain.
+# Copyright 2014-16 Tyler J. Stachecki <stachecki.tyler@gmail.com>
+#
+# This file is subject to the terms and conditions defined in
+# 'LICENSE', which is part of this source code package.
+#
+
+ifdef SystemRoot
+FIXPATH = $(subst /,\,$1)
+RM = del /Q
+else
+FIXPATH = $1
+RM = rm -f
+endif
+
+ROM_NAME = $(notdir $(CURDIR))
+
+AS = $(call FIXPATH,$(CURDIR)/../tools/bin/mips64-elf-as)
+AR = $(call FIXPATH,$(CURDIR)/../tools/bin/mips64-elf-gcc-ar)
+CC = $(call FIXPATH,$(CURDIR)/../tools/bin/mips64-elf-gcc)
+CPP = $(call FIXPATH,$(CURDIR)/../tools/bin/mips64-elf-cpp)
+MAKE = $(call FIXPATH,$(CURDIR)/../tools/bin/make)
+MKFS = $(call FIXPATH,$(CURDIR)/../tools/bin/mkfs)
+OBJCOPY = $(call FIXPATH,$(CURDIR)/../tools/bin/mips64-elf-objcopy)
+
+CHECKSUM = $(call FIXPATH,$(CURDIR)/../tools/bin/checksum)
+RSPASM = $(call FIXPATH,$(CURDIR)/../tools/bin/rspasm)
+
+# priv_include is not "advertised", but this is just a demo...
+CFLAGS = -Wall -Wextra -pedantic -std=c99 -Wno-main \
+       -I../libn64/include -I../libgfx/include -I../libn64/priv_include -I.
+
+OPTFLAGS = -Os -march=vr4300 -mtune=vr4300 -mabi=eabi -mgp32 -mlong32 \
+       -flto -ffat-lto-objects -ffunction-sections -fdata-sections \
+       -G4 -mno-extern-sdata -mgpopt -mfix4300 -mbranch-likely \
+       -mno-check-zero-division
+
+ASMFILES = $(call FIXPATH,\
+)
+
+CFILES = $(call FIXPATH,\
+       src/main.c \
+)
+
+UCODES = $(call FIXPATH,\
+       $(wildcard ucodes/*.rsp) \
+)
+
+OBJFILES = \
+       $(ASMFILES:.S=.o) \
+       $(CFILES:.c=.o)
+
+UCODETSKS = $(foreach ucode, $(UCODES),\
+       filesystem/$(basename $(notdir $(ucode))).tsk)
+
+DEPFILES = $(OBJFILES:.o=.d)
+
+#
+# Primary targets.
+#
+all: $(ROM_NAME).z64
+
+$(ROM_NAME).z64: $(ROM_NAME).elf
+       @echo $(call FIXPATH,"Building: $(ROM_NAME)/$@")
+       @$(OBJCOPY) -O binary $< $@
+       @$(CHECKSUM) $(call FIXPATH,../libn64/header.bin) $@
+
+$(ROM_NAME).elf: libn64 libgfx $(OBJFILES) filesystem.obj
+       @echo $(call FIXPATH,"Building: $(ROM_NAME)/$@")
+       @$(CC) $(CFLAGS) $(OPTFLAGS) -Wl,-Map=$(ROM_NAME).map -nostdlib \
+               -T$(call FIXPATH,../libn64/rom.ld) -o $@ $(OBJFILES) filesystem.obj \
+               -L$(call FIXPATH,../libn64) -ln64 -L$(call FIXPATH,../libgfx) -lgfx
+
+#
+# Filesystem build target.
+#
+filesystem.obj: filesystem.h
+       @echo $(call FIXPATH,"Building: $(ROM_NAME)/$@")
+       @$(OBJCOPY) -I binary -O elf32-bigmips -B mips filesystem.bin $@
+
+filesystem.h: $(wildcard filesystem/*) $(UCODETSKS)
+       @echo $(call FIXPATH,"Generate: $(ROM_NAME)/$@")
+       @$(MKFS) filesystem.bin filesystem.h filesystem
+
+#
+# Generic compilation/assembly targets.
+#
+%.o: %.S filesystem.h
+       @echo $(call FIXPATH,"Assembling: $(ROM_NAME)/$<")
+       @$(CC) $(CFLAGS) $(OPTFLAGS) -MMD -c $< -o $@
+
+%.o: %.c filesystem.h
+       @echo $(call FIXPATH,"Compiling: $(ROM_NAME)/$<")
+       @$(CC) $(CFLAGS) $(OPTFLAGS) -MMD -c $< -o $@
+
+filesystem/%.tsk: ucodes/%.rsp
+       @echo $(call FIXPATH,"Assembling: $(ROM_NAME)/$@")
+       @$(CPP) -E -I../libn64/ucodes -Iucodes $< | $(RSPASM) -o $@ -
+
+.PHONY: libn64
+libn64:
+       @$(MAKE) -sC $(call FIXPATH,../libn64)
+
+.PHONY: libgfx
+libgfx:
+       @$(MAKE) -sC $(call FIXPATH,../libgfx)
+
+#
+# Clean project target.
+#
+.PHONY: clean
+clean:
+       @echo "Cleaning $(ROM_NAME)..."
+       @$(RM) $(ROM_NAME).map $(ROM_NAME).elf $(ROM_NAME).z64 \
+               $(DEPFILES) $(OBJFILES) $(UCODEBINS) filesystem.obj \
+               filesystem.bin filesystem.h
+
+#
+# Use computed dependencies.
+#
+-include $(DEPFILES)
+
diff --git a/rdpdemo/src/3d.c b/rdpdemo/src/3d.c
new file mode 100644 (file)
index 0000000..8801c2c
--- /dev/null
@@ -0,0 +1,1255 @@
+#include <libgfx/rdp.h>\r
+#include <libgfx/rspbuf.h>\r
+\r
+// 3D Defines\r
+#define CULL_NONE 0  // Culling Option: No Polygon Culling\r
+#define CULL_BACK 1  // Culling Option: Back Face Polygon Culling\r
+#define CULL_FRONT 2 // Culling Option: Front Face Polygon Culling\r
+\r
+// 3D Functions\r
+typedef struct { float x, y, z; } XYZResult;\r
+typedef struct { float x, y; } XYResult;\r
+\r
+// Matrix 3D Data\r
+static float Matrix3D[12] = {\r
+//  X,   Y,   Z,   T\r
+  1.0, 0.0, 0.0, 0.0, // X\r
+  0.0, 1.0, 0.0, 0.0, // Y\r
+  0.0, 0.0, 1.0, 0.0, // Z\r
+};\r
+\r
+// Reset Matrix To Identity\r
+void matrix_identity( float matrix[] )\r
+{\r
+  matrix[0] = 1.0;\r
+  matrix[1] = 0.0;\r
+  matrix[2] = 0.0;\r
+  matrix[3] = 0.0;\r
+  matrix[4] = 0.0;\r
+  matrix[5] = 1.0;\r
+  matrix[6] = 0.0;\r
+  matrix[7] = 0.0;\r
+  matrix[8] = 0.0;\r
+  matrix[9] = 0.0;\r
+  matrix[10] = 1.0;\r
+  matrix[11] = 0.0;\r
+}\r
+\r
+// Calculate 3D: X,Y,Z\r
+XYZResult calc_3d( float matrix[], float x, float y, float z )\r
+{\r
+  XYZResult res;\r
+  res.x = (matrix[0] * x) + (matrix[1] * y) + (matrix[2] * z) + matrix[3];\r
+  res.y = (matrix[4] * x) + (matrix[5] * y) + (matrix[6] * z) + matrix[7];\r
+  res.z = (matrix[8] * x) + (matrix[9] * y) + (matrix[10] * z) + matrix[11];\r
+  return res;\r
+}\r
+\r
+// Calculate 2D: X,Y\r
+XYResult calc_2d( float x, float y, float z )\r
+{\r
+  XYResult res;\r
+  if (z > 0.0) { // Do Not Divide By Zero\r
+    z /= 240.0; // Z = Z / FOV\r
+    res.x = (float)(int)((x / z) + 160.0); // round(X = (X / Z) + (Screen X / 2))\r
+    res.y = (float)(int)(120.0 - (y / z)); // round(Y = (Screen Y / 2) - (Y / Z))\r
+  }\r
+  else {\r
+    res.x = 0.0;\r
+    res.y = 0.0;\r
+  }\r
+  return res;\r
+}\r
+\r
+// Test Polygon Winding Direction (IF Triangle Winding > 0.0: Clockwise ELSE: Anti-Clockwise)\r
+float poly_winding( float x1, float y1, float x2, float y2, float x3, float y3 )\r
+{\r
+  return (x1*y2 - x2*y1) + (x2*y3 - x3*y2) + (x3*y1 - x1*y3);\r
+}\r
+\r
+// Fill Triangle Array: Vert Array, Color Array, Culling, Base, Length\r
+void fill_triangle_array( struct libgfx_rspbuf *rspbuf, float vert[], uint8_t col[], uint8_t cull, uint32_t base, uint32_t length )\r
+{\r
+  for(uint32_t v = base, c = (base / 9) << 2; v < (base + length); v += 9, c += 4) {\r
+    // Calculate 3D Points\r
+    XYZResult xyz1 = calc_3d(Matrix3D, vert[v], vert[v + 1], vert[v + 2]);\r
+    XYZResult xyz2 = calc_3d(Matrix3D, vert[v + 3], vert[v + 4], vert[v + 5]);\r
+    XYZResult xyz3 = calc_3d(Matrix3D, vert[v + 6], vert[v + 7], vert[v + 8]);\r
+\r
+    // Calculate 2D Points\r
+    XYResult xy1 = calc_2d(xyz1.x, xyz1.y, xyz1.z);\r
+    XYResult xy2 = calc_2d(xyz2.x, xyz2.y, xyz2.z);\r
+    XYResult xy3 = calc_2d(xyz3.x, xyz3.y, xyz3.z);\r
+\r
+    // Test Polygon Winding Direction (IF Triangle Winding > 0.0: Clockwise ELSE: Anti-Clockwise)\r
+    float winding = poly_winding(xy1.x,xy1.y, xy2.x,xy2.y, xy3.x,xy3.y);\r
+\r
+    if((cull == CULL_NONE) || ((winding > 0.0) && (cull == CULL_BACK)) || ((winding <= 0.0) && (cull == CULL_FRONT))) {\r
+      rdp_set_blend_color(rspbuf, rdp_rgba32(col[c], col[c + 1], col[c + 2], col[c + 3])); // Set Blend Color: R,G,B,A\r
+\r
+#if 0\r
+      rdp_draw_fill_triangle( rspbuf, xy1.x,xy1.y, xy2.x,xy2.y, xy3.x,xy3.y ); // Draw Fill Triangle: X1,Y1, X2,Y2, X3,Y3\r
+#else\r
+      struct libgfx_vertex *verts = rspbuf->vertices;\r
+\r
+      libgfx_vertex_init(verts + next_free_vert);\r
+      libgfx_vertex_init(verts + next_free_vert + 1);\r
+      libgfx_vertex_init(verts + next_free_vert + 2);\r
+\r
+      // screen coordinates (10.2)\r
+      verts[next_free_vert].x = xy1.x * 4;\r
+      verts[next_free_vert].y = xy1.y * 4;\r
+      verts[next_free_vert+1].x = xy2.x * 4;\r
+      verts[next_free_vert+1].y = xy2.y * 4;\r
+      verts[next_free_vert+2].x = xy3.x * 4;\r
+      verts[next_free_vert+2].y = xy3.y * 4;\r
+\r
+      rsp_draw_triangle(rspbuf, next_free_vert, next_free_vert + 1, next_free_vert + 2);\r
+      next_free_vert += 3;\r
+      //return;\r
+#endif\r
+\r
+      rdp_sync_pipe(rspbuf); // Stall Pipeline, Until Preceeding Primitives Completely Finish\r
+    }\r
+  }\r
+}\r
+\r
+// Translate: Matrix, X\r
+void translate_x( float matrix[], float x )\r
+{\r
+  matrix[3] = x;\r
+}\r
+\r
+// Translate: Matrix, Y\r
+void translate_y( float matrix[], float y )\r
+{\r
+  matrix[7] = y;\r
+}\r
+\r
+// Translate: Matrix, Z\r
+void translate_z( float matrix[], float z )\r
+{\r
+  matrix[11] = z;\r
+}\r
+\r
+// Translate: Matrix, X, Y, Z\r
+void translate_xyz( float matrix[], float x, float y, float z )\r
+{\r
+  matrix[3] = x;\r
+  matrix[7] = y;\r
+  matrix[11] = z;\r
+}\r
+\r
+// Rotate: Matrix, Precalc Table, X\r
+void rotate_x( float matrix[], float precalc[], uint16_t x )\r
+{\r
+  matrix[5] = precalc[(x + 256) & 1023]; // XC\r
+  matrix[6] = -precalc[x]; // -XS\r
+  matrix[9] = -matrix[6]; // XS\r
+  matrix[10] = matrix[5]; // XC\r
+}\r
+\r
+// Rotate: Matrix, Precalc Table, Y\r
+void rotate_y( float matrix[], float precalc[], uint16_t y )\r
+{\r
+  matrix[0] = precalc[(y + 256) & 1023]; // YC\r
+  matrix[8] = -precalc[y]; // -YS\r
+  matrix[2] = -matrix[8]; // YS\r
+  matrix[10] = matrix[0]; // YC\r
+}\r
+\r
+// Rotate: Matrix, Precalc Table, Z\r
+void rotate_z( float matrix[], float precalc[], uint16_t z )\r
+{\r
+  matrix[0] = precalc[(z + 256) & 1023]; // ZC\r
+  matrix[1] = -precalc[z]; // -ZS\r
+  matrix[4] = -matrix[1]; // ZS\r
+  matrix[5] = matrix[0]; // ZC\r
+}\r
+\r
+// Rotate: Matrix, Precalc Table, X, Y\r
+void rotate_xy( float matrix[], float precalc[], uint16_t x, uint16_t y )\r
+{\r
+  matrix[5] = precalc[(x + 256) & 1023]; // XC\r
+  matrix[6] = precalc[x]; // XS\r
+  matrix[0] = precalc[(y + 256) & 1023]; // YC\r
+  matrix[8] = precalc[y]; // YS\r
+  matrix[1] = matrix[6] * matrix[8]; // XS * YS\r
+  matrix[2] = -matrix[5] * matrix[8]; // -XC * YS\r
+  matrix[9] = -matrix[6] * matrix[0]; // -XS * YC\r
+  matrix[10] = matrix[5] * matrix[0]; // XC * YC\r
+}\r
+\r
+// Rotate: Matrix, Precalc Table, X, Z\r
+void rotate_xz( float matrix[], float precalc[], uint16_t x, uint16_t z )\r
+{\r
+  matrix[10] = precalc[(x + 256) & 1023]; // XC\r
+  matrix[6] = precalc[x]; // XS\r
+  matrix[0] = precalc[(z + 256) & 1023]; // ZC\r
+  matrix[1] = precalc[z]; // ZS\r
+  matrix[4] = matrix[10] * -matrix[1]; // XC * -ZS\r
+  matrix[5] = matrix[10] * matrix[0]; // XC * ZC\r
+  matrix[8] = matrix[6] * matrix[1]; // XS * ZS\r
+  matrix[9] = matrix[6] * -matrix[0]; // XS * -ZC\r
+}\r
+\r
+// Rotate: Matrix, Precalc Table, Y, Z\r
+void rotate_yz( float matrix[], float precalc[], uint16_t y, uint16_t z )\r
+{\r
+  matrix[10] = precalc[(y + 256) & 1023]; // YC\r
+  matrix[8] = precalc[y]; // YS\r
+  matrix[5] = precalc[(z + 256) & 1023]; // ZC\r
+  matrix[1] = precalc[z]; // ZS\r
+  matrix[0] = matrix[10] * matrix[5]; // YC * ZC\r
+  matrix[2] = matrix[8] * -matrix[5]; // YS * -ZC\r
+  matrix[4] = matrix[10] * -matrix[1]; // YC * -ZS\r
+  matrix[6] = matrix[8] * matrix[1]; // YS * ZS\r
+}\r
+\r
+// Rotate: Matrix, Precalc Table, X, Y, Z\r
+void rotate_xyz( float matrix[], float precalc[], uint16_t x, uint16_t y, uint16_t z )\r
+{\r
+  matrix[1] = precalc[(x + 256) & 1023]; // XC\r
+  matrix[6] = precalc[x]; // XS\r
+  matrix[10] = precalc[(y + 256) & 1023]; // YC\r
+  matrix[2] = precalc[y]; // YS\r
+  matrix[8] = precalc[(z + 256) & 1023]; // ZC\r
+  matrix[9] = precalc[z]; // ZS\r
+  matrix[5] = -matrix[6] * matrix[10]; // -XS * YC\r
+  matrix[4] = (matrix[5] * matrix[8]) - (matrix[1] * matrix[9]); // (-XS * YC * ZC) - (XC * ZS)\r
+  matrix[5] = (matrix[5] * matrix[9]) + (matrix[1] * matrix[8]); // (-XS * YC * ZS) + (XC * ZC)\r
+  matrix[1] = matrix[1] * matrix[10]; // XC * YC\r
+  matrix[0] = (matrix[1] * matrix[8]) - (matrix[6] * matrix[9]); // (XC * YC * ZC) - (XS * ZS)\r
+  matrix[1] = (matrix[1] * matrix[9]) + (matrix[6] * matrix[8]); // (XC * YC * ZS) + (XS * ZC)\r
+  matrix[6] *= matrix[2]; // XS * YS\r
+  matrix[8] *= matrix[2]; // ZC * YS\r
+  matrix[9] *= matrix[2]; // ZS * YS\r
+  matrix[2] *= -precalc[(x + 256) & 1023]; // -XC * YS\r
+}\r
+\r
+static float Sin1024[1024] = { // 1024 Rotations (Sin)\r
+  0.000000000000000000,\r
+  0.006135884649154475,\r
+  0.012271538285719925,\r
+  0.01840672990580482,\r
+  0.024541228522912288,\r
+  0.030674803176636626,\r
+  0.03680722294135883,\r
+  0.04293825693494082,\r
+  0.049067674327418015,\r
+  0.05519524434968994,\r
+  0.06132073630220858,\r
+  0.06744391956366405,\r
+  0.07356456359966743,\r
+  0.07968243797143013,\r
+  0.0857973123444399,\r
+  0.09190895649713272,\r
+  0.0980171403295606,\r
+  0.10412163387205459,\r
+  0.11022220729388306,\r
+  0.11631863091190475,\r
+  0.1224106751992162,\r
+  0.12849811079379317,\r
+  0.13458070850712617,\r
+  0.1406582393328492,\r
+  0.14673047445536175,\r
+  0.15279718525844344,\r
+  0.15885814333386145,\r
+  0.16491312048996992,\r
+  0.17096188876030122,\r
+  0.17700422041214875,\r
+  0.18303988795514095,\r
+  0.1890686641498062,\r
+  0.19509032201612825,\r
+  0.2011046348420919,\r
+  0.20711137619221856,\r
+  0.21311031991609136,\r
+  0.2191012401568698,\r
+  0.22508391135979283,\r
+  0.2310581082806711,\r
+  0.2370236059943672,\r
+  0.24298017990326387,\r
+  0.24892760574572015,\r
+  0.25486565960451457,\r
+  0.2607941179152755,\r
+  0.26671275747489837,\r
+  0.272621355449949,\r
+  0.27851968938505306,\r
+  0.2844075372112719,\r
+  0.29028467725446233,\r
+  0.2961508882436238,\r
+  0.3020059493192281,\r
+  0.30784964004153487,\r
+  0.3136817403988915,\r
+  0.3195020308160157,\r
+  0.3253102921622629,\r
+  0.33110630575987643,\r
+  0.33688985339222005,\r
+  0.3426607173119944,\r
+  0.34841868024943456,\r
+  0.35416352542049034,\r
+  0.3598950365349881,\r
+  0.36561299780477385,\r
+  0.3713171939518375,\r
+  0.37700741021641826,\r
+  0.3826834323650898,\r
+  0.38834504669882625,\r
+  0.3939920400610481,\r
+  0.3996241998456468,\r
+  0.40524131400498986,\r
+  0.4108431710579039,\r
+  0.41642956009763715,\r
+  0.4220002707997997,\r
+  0.4275550934302821,\r
+  0.43309381885315196,\r
+  0.43861623853852766,\r
+  0.4441221445704292,\r
+  0.44961132965460654,\r
+  0.45508358712634384,\r
+  0.46053871095824,\r
+  0.4659764957679662,\r
+  0.47139673682599764,\r
+  0.4767992300633221,\r
+  0.4821837720791227,\r
+  0.487550160148436,\r
+  0.49289819222978404,\r
+  0.4982276669727818,\r
+  0.5035383837257176,\r
+  0.508830142543107,\r
+  0.5141027441932217,\r
+  0.5193559901655896,\r
+  0.524589682678469,\r
+  0.5298036246862946,\r
+  0.5349976198870972,\r
+  0.5401714727298929,\r
+  0.5453249884220465,\r
+  0.5504579729366048,\r
+  0.5555702330196022,\r
+  0.560661576197336,\r
+  0.5657318107836131,\r
+  0.5707807458869673,\r
+  0.5758081914178453,\r
+  0.5808139580957645,\r
+  0.5857978574564389,\r
+  0.5907597018588742,\r
+  0.5956993044924334,\r
+  0.600616479383869,\r
+  0.6055110414043255,\r
+  0.6103828062763095,\r
+  0.6152315905806268,\r
+  0.6200572117632891,\r
+  0.6248594881423863,\r
+  0.629638238914927,\r
+  0.6343932841636455,\r
+  0.6391244448637757,\r
+  0.6438315428897914,\r
+  0.6485144010221124,\r
+  0.6531728429537768,\r
+  0.6578066932970786,\r
+  0.6624157775901718,\r
+  0.6669999223036375,\r
+  0.6715589548470183,\r
+  0.6760927035753159,\r
+  0.680600997795453,\r
+  0.6850836677727004,\r
+  0.6895405447370668,\r
+  0.6939714608896539,\r
+  0.6983762494089729,\r
+  0.7027547444572253,\r
+  0.7071067811865475,\r
+  0.7114321957452164,\r
+  0.7157308252838186,\r
+  0.7200025079613817,\r
+  0.7242470829514669,\r
+  0.7284643904482252,\r
+  0.7326542716724128,\r
+  0.7368165688773698,\r
+  0.7409511253549591,\r
+  0.745057785441466,\r
+  0.7491363945234593,\r
+  0.7531867990436125,\r
+  0.7572088465064846,\r
+  0.7612023854842618,\r
+  0.765167265622459,\r
+  0.7691033376455796,\r
+  0.7730104533627369,\r
+  0.7768884656732324,\r
+  0.7807372285720944,\r
+  0.7845565971555752,\r
+  0.7883464276266062,\r
+  0.7921065773002123,\r
+  0.7958369046088836,\r
+  0.799537269107905,\r
+  0.8032075314806448,\r
+  0.8068475535437992,\r
+  0.8104571982525948,\r
+  0.8140363297059483,\r
+  0.8175848131515837,\r
+  0.8211025149911046,\r
+  0.8245893027850253,\r
+  0.8280450452577558,\r
+  0.8314696123025452,\r
+  0.83486287498638,\r
+  0.838224705554838,\r
+  0.8415549774368983,\r
+  0.844853565249707,\r
+  0.8481203448032971,\r
+  0.8513551931052652,\r
+  0.8545579883654005,\r
+  0.8577286100002721,\r
+  0.8608669386377673,\r
+  0.8639728561215867,\r
+  0.8670462455156926,\r
+  0.8700869911087113,\r
+  0.8730949784182901,\r
+  0.8760700941954066,\r
+  0.8790122264286334,\r
+  0.8819212643483549,\r
+  0.8847970984309378,\r
+  0.8876396204028539,\r
+  0.8904487232447579,\r
+  0.8932243011955153,\r
+  0.8959662497561851,\r
+  0.8986744656939538,\r
+  0.901348847046022,\r
+  0.9039892931234433,\r
+  0.9065957045149153,\r
+  0.9091679830905224,\r
+  0.9117060320054299,\r
+  0.9142097557035307,\r
+  0.9166790599210427,\r
+  0.9191138516900578,\r
+  0.9215140393420419,\r
+  0.9238795325112867,\r
+  0.9262102421383114,\r
+  0.9285060804732156,\r
+  0.9307669610789837,\r
+  0.9329927988347388,\r
+  0.9351835099389475,\r
+  0.937339011912575,\r
+  0.9394592236021899,\r
+  0.9415440651830208,\r
+  0.9435934581619604,\r
+  0.9456073253805213,\r
+  0.9475855910177411,\r
+  0.9495281805930367,\r
+  0.9514350209690083,\r
+  0.9533060403541938,\r
+  0.9551411683057707,\r
+  0.9569403357322089,\r
+  0.9587034748958716,\r
+  0.9604305194155658,\r
+  0.9621214042690416,\r
+  0.9637760657954398,\r
+  0.9653944416976894,\r
+  0.9669764710448521,\r
+  0.9685220942744173,\r
+  0.970031253194544,\r
+  0.9715038909862518,\r
+  0.9729399522055601,\r
+  0.9743393827855759,\r
+  0.9757021300385286,\r
+  0.9770281426577544,\r
+  0.9783173707196277,\r
+  0.9795697656854405,\r
+  0.9807852804032304,\r
+  0.9819638691095552,\r
+  0.9831054874312163,\r
+  0.984210092386929,\r
+  0.9852776423889412,\r
+  0.9863080972445987,\r
+  0.9873014181578584,\r
+  0.9882575677307495,\r
+  0.989176509964781,\r
+  0.9900582102622971,\r
+  0.99090263542778,\r
+  0.9917097536690995,\r
+  0.99247953459871,\r
+  0.9932119492347945,\r
+  0.9939069700023561,\r
+  0.9945645707342554,\r
+  0.9951847266721968,\r
+  0.9957674144676598,\r
+  0.996312612182778,\r
+  0.9968202992911657,\r
+  0.9972904566786902,\r
+  0.9977230666441916,\r
+  0.9981181129001492,\r
+  0.9984755805732948,\r
+  0.9987954562051724,\r
+  0.9990777277526454,\r
+  0.9993223845883495,\r
+  0.9995294175010931,\r
+  0.9996988186962042,\r
+  0.9998305817958234,\r
+  0.9999247018391445,\r
+  0.9999811752826011,\r
+  1.0000000000000000,\r
+  0.9999811752826011,\r
+  0.9999247018391445,\r
+  0.9998305817958234,\r
+  0.9996988186962042,\r
+  0.9995294175010931,\r
+  0.9993223845883495,\r
+  0.9990777277526454,\r
+  0.9987954562051724,\r
+  0.9984755805732948,\r
+  0.9981181129001492,\r
+  0.9977230666441916,\r
+  0.9972904566786902,\r
+  0.9968202992911658,\r
+  0.996312612182778,\r
+  0.9957674144676598,\r
+  0.9951847266721969,\r
+  0.9945645707342554,\r
+  0.9939069700023561,\r
+  0.9932119492347945,\r
+  0.99247953459871,\r
+  0.9917097536690995,\r
+  0.99090263542778,\r
+  0.9900582102622971,\r
+  0.989176509964781,\r
+  0.9882575677307495,\r
+  0.9873014181578584,\r
+  0.9863080972445987,\r
+  0.9852776423889412,\r
+  0.984210092386929,\r
+  0.9831054874312163,\r
+  0.9819638691095552,\r
+  0.9807852804032304,\r
+  0.9795697656854405,\r
+  0.9783173707196277,\r
+  0.9770281426577544,\r
+  0.9757021300385286,\r
+  0.9743393827855759,\r
+  0.9729399522055602,\r
+  0.9715038909862518,\r
+  0.970031253194544,\r
+  0.9685220942744173,\r
+  0.9669764710448521,\r
+  0.9653944416976894,\r
+  0.9637760657954398,\r
+  0.9621214042690416,\r
+  0.9604305194155659,\r
+  0.9587034748958716,\r
+  0.9569403357322089,\r
+  0.9551411683057707,\r
+  0.9533060403541939,\r
+  0.9514350209690083,\r
+  0.9495281805930367,\r
+  0.9475855910177412,\r
+  0.9456073253805214,\r
+  0.9435934581619604,\r
+  0.9415440651830208,\r
+  0.9394592236021899,\r
+  0.937339011912575,\r
+  0.9351835099389476,\r
+  0.9329927988347388,\r
+  0.9307669610789837,\r
+  0.9285060804732156,\r
+  0.9262102421383114,\r
+  0.9238795325112867,\r
+  0.921514039342042,\r
+  0.9191138516900578,\r
+  0.9166790599210427,\r
+  0.9142097557035307,\r
+  0.9117060320054299,\r
+  0.9091679830905225,\r
+  0.9065957045149153,\r
+  0.9039892931234434,\r
+  0.901348847046022,\r
+  0.8986744656939539,\r
+  0.8959662497561852,\r
+  0.8932243011955152,\r
+  0.890448723244758,\r
+  0.8876396204028539,\r
+  0.8847970984309379,\r
+  0.881921264348355,\r
+  0.8790122264286335,\r
+  0.8760700941954066,\r
+  0.8730949784182902,\r
+  0.8700869911087115,\r
+  0.8670462455156928,\r
+  0.8639728561215868,\r
+  0.8608669386377672,\r
+  0.8577286100002721,\r
+  0.8545579883654005,\r
+  0.8513551931052652,\r
+  0.8481203448032972,\r
+  0.8448535652497072,\r
+  0.8415549774368984,\r
+  0.8382247055548382,\r
+  0.8348628749863801,\r
+  0.8314696123025453,\r
+  0.8280450452577558,\r
+  0.8245893027850252,\r
+  0.8211025149911048,\r
+  0.8175848131515837,\r
+  0.8140363297059485,\r
+  0.8104571982525948,\r
+  0.8068475535437994,\r
+  0.8032075314806449,\r
+  0.7995372691079052,\r
+  0.7958369046088836,\r
+  0.7921065773002123,\r
+  0.7883464276266063,\r
+  0.7845565971555751,\r
+  0.7807372285720946,\r
+  0.7768884656732324,\r
+  0.7730104533627371,\r
+  0.7691033376455796,\r
+  0.7651672656224591,\r
+  0.7612023854842619,\r
+  0.7572088465064847,\r
+  0.7531867990436125,\r
+  0.7491363945234593,\r
+  0.7450577854414661,\r
+  0.740951125354959,\r
+  0.73681656887737,\r
+  0.7326542716724128,\r
+  0.7284643904482253,\r
+  0.7242470829514669,\r
+  0.7200025079613818,\r
+  0.7157308252838187,\r
+  0.7114321957452167,\r
+  0.7071067811865476,\r
+  0.7027547444572252,\r
+  0.6983762494089729,\r
+  0.6939714608896539,\r
+  0.689540544737067,\r
+  0.6850836677727004,\r
+  0.6806009977954532,\r
+  0.6760927035753159,\r
+  0.6715589548470186,\r
+  0.6669999223036376,\r
+  0.662415777590172,\r
+  0.6578066932970787,\r
+  0.6531728429537766,\r
+  0.6485144010221126,\r
+  0.6438315428897914,\r
+  0.6391244448637758,\r
+  0.6343932841636455,\r
+  0.6296382389149272,\r
+  0.6248594881423863,\r
+  0.6200572117632894,\r
+  0.6152315905806269,\r
+  0.6103828062763097,\r
+  0.6055110414043255,\r
+  0.6006164793838689,\r
+  0.5956993044924335,\r
+  0.5907597018588742,\r
+  0.585797857456439,\r
+  0.5808139580957645,\r
+  0.5758081914178454,\r
+  0.5707807458869673,\r
+  0.5657318107836135,\r
+  0.5606615761973361,\r
+  0.5555702330196022,\r
+  0.5504579729366049,\r
+  0.5453249884220464,\r
+  0.540171472729893,\r
+  0.5349976198870972,\r
+  0.5298036246862948,\r
+  0.524589682678469,\r
+  0.5193559901655898,\r
+  0.5141027441932218,\r
+  0.5088301425431073,\r
+  0.5035383837257177,\r
+  0.49822766697278176,\r
+  0.49289819222978415,\r
+  0.4875501601484359,\r
+  0.4821837720791229,\r
+  0.4767992300633221,\r
+  0.47139673682599786,\r
+  0.4659764957679662,\r
+  0.4605387109582402,\r
+  0.4550835871263439,\r
+  0.4496113296546069,\r
+  0.4441221445704293,\r
+  0.43861623853852755,\r
+  0.43309381885315207,\r
+  0.42755509343028203,\r
+  0.42200027079979985,\r
+  0.41642956009763715,\r
+  0.41084317105790413,\r
+  0.4052413140049899,\r
+  0.39962419984564707,\r
+  0.39399204006104815,\r
+  0.3883450466988266,\r
+  0.3826834323650899,\r
+  0.37700741021641815,\r
+  0.3713171939518377,\r
+  0.3656129978047738,\r
+  0.35989503653498833,\r
+  0.3541635254204904,\r
+  0.3484186802494348,\r
+  0.34266071731199443,\r
+  0.33688985339222033,\r
+  0.3311063057598765,\r
+  0.32531029216226326,\r
+  0.3195020308160158,\r
+  0.3136817403988914,\r
+  0.30784964004153503,\r
+  0.30200594931922803,\r
+  0.296150888243624,\r
+  0.2902846772544624,\r
+  0.2844075372112721,\r
+  0.27851968938505317,\r
+  0.27262135544994925,\r
+  0.2667127574748985,\r
+  0.26079411791527585,\r
+  0.2548656596045147,\r
+  0.2489276057457201,\r
+  0.24298017990326407,\r
+  0.23702360599436717,\r
+  0.23105810828067133,\r
+  0.22508391135979283,\r
+  0.21910124015687005,\r
+  0.21311031991609142,\r
+  0.20711137619221884,\r
+  0.201104634842092,\r
+  0.1950903220161286,\r
+  0.18906866414980636,\r
+  0.1830398879551409,\r
+  0.17700422041214894,\r
+  0.17096188876030122,\r
+  0.16491312048997014,\r
+  0.15885814333386147,\r
+  0.15279718525844369,\r
+  0.1467304744553618,\r
+  0.14065823933284954,\r
+  0.13458070850712628,\r
+  0.12849811079379309,\r
+  0.12241067519921635,\r
+  0.11631863091190471,\r
+  0.11022220729388324,\r
+  0.10412163387205457,\r
+  0.09801714032956083,\r
+  0.09190895649713275,\r
+  0.08579731234444016,\r
+  0.0796824379714302,\r
+  0.07356456359966773,\r
+  0.06744391956366418,\r
+  0.06132073630220849,\r
+  0.055195244349690094,\r
+  0.049067674327417966,\r
+  0.04293825693494102,\r
+  0.03680722294135883,\r
+  0.030674803176636865,\r
+  0.024541228522912326,\r
+  0.0184067299058051,\r
+  0.012271538285720007,\r
+  0.006135884649154799,\r
+  0.000000000000000000,\r
+  -0.006135884649154554,\r
+  -0.012271538285719762,\r
+  -0.01840672990580486,\r
+  -0.02454122852291208,\r
+  -0.03067480317663662,\r
+  -0.03680722294135858,\r
+  -0.04293825693494078,\r
+  -0.049067674327417724,\r
+  -0.05519524434968985,\r
+  -0.061320736302208245,\r
+  -0.06744391956366393,\r
+  -0.0735645635996675,\r
+  -0.07968243797142995,\r
+  -0.08579731234443992,\r
+  -0.09190895649713252,\r
+  -0.09801714032956059,\r
+  -0.10412163387205432,\r
+  -0.110222207293883,\r
+  -0.11631863091190447,\r
+  -0.1224106751992161,\r
+  -0.12849811079379284,\r
+  -0.13458070850712606,\r
+  -0.1406582393328493,\r
+  -0.14673047445536158,\r
+  -0.15279718525844344,\r
+  -0.15885814333386122,\r
+  -0.1649131204899699,\r
+  -0.17096188876030097,\r
+  -0.1770042204121487,\r
+  -0.18303988795514065,\r
+  -0.1890686641498061,\r
+  -0.19509032201612836,\r
+  -0.20110463484209176,\r
+  -0.2071113761922186,\r
+  -0.2131103199160912,\r
+  -0.2191012401568698,\r
+  -0.2250839113597926,\r
+  -0.23105810828067108,\r
+  -0.23702360599436695,\r
+  -0.24298017990326382,\r
+  -0.24892760574571987,\r
+  -0.25486565960451446,\r
+  -0.2607941179152756,\r
+  -0.26671275747489825,\r
+  -0.27262135544994903,\r
+  -0.2785196893850529,\r
+  -0.2844075372112718,\r
+  -0.2902846772544621,\r
+  -0.2961508882436238,\r
+  -0.3020059493192278,\r
+  -0.3078496400415348,\r
+  -0.3136817403988912,\r
+  -0.3195020308160156,\r
+  -0.325310292162263,\r
+  -0.33110630575987626,\r
+  -0.33688985339222005,\r
+  -0.3426607173119942,\r
+  -0.34841868024943456,\r
+  -0.3541635254204901,\r
+  -0.3598950365349881,\r
+  -0.3656129978047736,\r
+  -0.37131719395183743,\r
+  -0.3770074102164179,\r
+  -0.38268343236508967,\r
+  -0.38834504669882636,\r
+  -0.39399204006104793,\r
+  -0.39962419984564684,\r
+  -0.4052413140049897,\r
+  -0.4108431710579039,\r
+  -0.41642956009763693,\r
+  -0.4220002707997996,\r
+  -0.4275550934302818,\r
+  -0.43309381885315185,\r
+  -0.4386162385385273,\r
+  -0.4441221445704291,\r
+  -0.44961132965460665,\r
+  -0.45508358712634367,\r
+  -0.46053871095824006,\r
+  -0.46597649576796596,\r
+  -0.47139673682599764,\r
+  -0.4767992300633219,\r
+  -0.48218377207912266,\r
+  -0.48755016014843566,\r
+  -0.4928981922297839,\r
+  -0.49822766697278154,\r
+  -0.5035383837257175,\r
+  -0.5088301425431071,\r
+  -0.5141027441932216,\r
+  -0.5193559901655895,\r
+  -0.5245896826784687,\r
+  -0.5298036246862946,\r
+  -0.5349976198870969,\r
+  -0.5401714727298929,\r
+  -0.5453249884220461,\r
+  -0.5504579729366047,\r
+  -0.555570233019602,\r
+  -0.5606615761973359,\r
+  -0.5657318107836132,\r
+  -0.5707807458869671,\r
+  -0.5758081914178453,\r
+  -0.5808139580957643,\r
+  -0.5857978574564389,\r
+  -0.5907597018588739,\r
+  -0.5956993044924332,\r
+  -0.6006164793838686,\r
+  -0.6055110414043254,\r
+  -0.6103828062763095,\r
+  -0.6152315905806267,\r
+  -0.6200572117632892,\r
+  -0.6248594881423862,\r
+  -0.629638238914927,\r
+  -0.6343932841636453,\r
+  -0.6391244448637757,\r
+  -0.6438315428897913,\r
+  -0.6485144010221123,\r
+  -0.6531728429537765,\r
+  -0.6578066932970785,\r
+  -0.6624157775901718,\r
+  -0.6669999223036374,\r
+  -0.6715589548470184,\r
+  -0.6760927035753158,\r
+  -0.680600997795453,\r
+  -0.6850836677727001,\r
+  -0.6895405447370668,\r
+  -0.6939714608896538,\r
+  -0.6983762494089728,\r
+  -0.7027547444572251,\r
+  -0.7071067811865475,\r
+  -0.7114321957452164,\r
+  -0.7157308252838185,\r
+  -0.7200025079613817,\r
+  -0.7242470829514668,\r
+  -0.7284643904482252,\r
+  -0.7326542716724127,\r
+  -0.7368165688773698,\r
+  -0.7409511253549589,\r
+  -0.7450577854414658,\r
+  -0.749136394523459,\r
+  -0.7531867990436124,\r
+  -0.7572088465064842,\r
+  -0.761202385484262,\r
+  -0.765167265622459,\r
+  -0.7691033376455795,\r
+  -0.7730104533627367,\r
+  -0.7768884656732326,\r
+  -0.7807372285720944,\r
+  -0.784556597155575,\r
+  -0.7883464276266059,\r
+  -0.7921065773002124,\r
+  -0.7958369046088835,\r
+  -0.7995372691079048,\r
+  -0.803207531480645,\r
+  -0.8068475535437992,\r
+  -0.8104571982525947,\r
+  -0.8140363297059481,\r
+  -0.8175848131515838,\r
+  -0.8211025149911046,\r
+  -0.8245893027850251,\r
+  -0.8280450452577555,\r
+  -0.8314696123025452,\r
+  -0.8348628749863799,\r
+  -0.8382247055548379,\r
+  -0.8415549774368986,\r
+  -0.8448535652497071,\r
+  -0.8481203448032971,\r
+  -0.8513551931052649,\r
+  -0.8545579883654005,\r
+  -0.857728610000272,\r
+  -0.8608669386377671,\r
+  -0.8639728561215865,\r
+  -0.8670462455156926,\r
+  -0.8700869911087113,\r
+  -0.8730949784182899,\r
+  -0.8760700941954067,\r
+  -0.8790122264286334,\r
+  -0.8819212643483549,\r
+  -0.8847970984309376,\r
+  -0.887639620402854,\r
+  -0.8904487232447579,\r
+  -0.8932243011955152,\r
+  -0.8959662497561849,\r
+  -0.8986744656939538,\r
+  -0.9013488470460219,\r
+  -0.9039892931234431,\r
+  -0.9065957045149154,\r
+  -0.9091679830905224,\r
+  -0.9117060320054298,\r
+  -0.9142097557035305,\r
+  -0.9166790599210427,\r
+  -0.9191138516900577,\r
+  -0.9215140393420418,\r
+  -0.9238795325112865,\r
+  -0.9262102421383114,\r
+  -0.9285060804732155,\r
+  -0.9307669610789836,\r
+  -0.932992798834739,\r
+  -0.9351835099389476,\r
+  -0.9373390119125748,\r
+  -0.9394592236021897,\r
+  -0.9415440651830208,\r
+  -0.9435934581619603,\r
+  -0.9456073253805212,\r
+  -0.9475855910177412,\r
+  -0.9495281805930367,\r
+  -0.9514350209690083,\r
+  -0.9533060403541938,\r
+  -0.9551411683057708,\r
+  -0.9569403357322088,\r
+  -0.9587034748958715,\r
+  -0.9604305194155657,\r
+  -0.9621214042690416,\r
+  -0.9637760657954398,\r
+  -0.9653944416976893,\r
+  -0.9669764710448522,\r
+  -0.9685220942744173,\r
+  -0.970031253194544,\r
+  -0.9715038909862517,\r
+  -0.9729399522055602,\r
+  -0.9743393827855759,\r
+  -0.9757021300385285,\r
+  -0.9770281426577543,\r
+  -0.9783173707196277,\r
+  -0.9795697656854405,\r
+  -0.9807852804032303,\r
+  -0.9819638691095554,\r
+  -0.9831054874312163,\r
+  -0.984210092386929,\r
+  -0.9852776423889411,\r
+  -0.9863080972445987,\r
+  -0.9873014181578583,\r
+  -0.9882575677307495,\r
+  -0.9891765099647809,\r
+  -0.9900582102622971,\r
+  -0.99090263542778,\r
+  -0.9917097536690995,\r
+  -0.9924795345987101,\r
+  -0.9932119492347945,\r
+  -0.9939069700023561,\r
+  -0.9945645707342554,\r
+  -0.9951847266721969,\r
+  -0.9957674144676598,\r
+  -0.996312612182778,\r
+  -0.9968202992911657,\r
+  -0.9972904566786902,\r
+  -0.9977230666441916,\r
+  -0.9981181129001492,\r
+  -0.9984755805732948,\r
+  -0.9987954562051724,\r
+  -0.9990777277526454,\r
+  -0.9993223845883494,\r
+  -0.9995294175010931,\r
+  -0.9996988186962042,\r
+  -0.9998305817958234,\r
+  -0.9999247018391445,\r
+  -0.9999811752826011,\r
+  -1.0000000000000000,\r
+  -0.9999811752826011,\r
+  -0.9999247018391445,\r
+  -0.9998305817958234,\r
+  -0.9996988186962042,\r
+  -0.9995294175010931,\r
+  -0.9993223845883495,\r
+  -0.9990777277526454,\r
+  -0.9987954562051724,\r
+  -0.9984755805732948,\r
+  -0.9981181129001492,\r
+  -0.9977230666441916,\r
+  -0.9972904566786902,\r
+  -0.9968202992911657,\r
+  -0.996312612182778,\r
+  -0.9957674144676598,\r
+  -0.9951847266721969,\r
+  -0.9945645707342554,\r
+  -0.9939069700023561,\r
+  -0.9932119492347946,\r
+  -0.9924795345987101,\r
+  -0.9917097536690995,\r
+  -0.99090263542778,\r
+  -0.9900582102622971,\r
+  -0.9891765099647809,\r
+  -0.9882575677307495,\r
+  -0.9873014181578584,\r
+  -0.9863080972445988,\r
+  -0.9852776423889412,\r
+  -0.9842100923869291,\r
+  -0.9831054874312164,\r
+  -0.9819638691095554,\r
+  -0.9807852804032304,\r
+  -0.9795697656854405,\r
+  -0.9783173707196278,\r
+  -0.9770281426577543,\r
+  -0.9757021300385286,\r
+  -0.974339382785576,\r
+  -0.9729399522055603,\r
+  -0.9715038909862518,\r
+  -0.970031253194544,\r
+  -0.9685220942744174,\r
+  -0.9669764710448523,\r
+  -0.9653944416976894,\r
+  -0.96377606579544,\r
+  -0.9621214042690417,\r
+  -0.9604305194155658,\r
+  -0.9587034748958716,\r
+  -0.9569403357322089,\r
+  -0.9551411683057709,\r
+  -0.9533060403541938,\r
+  -0.9514350209690084,\r
+  -0.9495281805930368,\r
+  -0.9475855910177413,\r
+  -0.9456073253805213,\r
+  -0.9435934581619604,\r
+  -0.9415440651830209,\r
+  -0.9394592236021898,\r
+  -0.937339011912575,\r
+  -0.9351835099389477,\r
+  -0.9329927988347391,\r
+  -0.9307669610789837,\r
+  -0.9285060804732156,\r
+  -0.9262102421383115,\r
+  -0.9238795325112866,\r
+  -0.9215140393420419,\r
+  -0.9191138516900579,\r
+  -0.9166790599210428,\r
+  -0.9142097557035306,\r
+  -0.9117060320054299,\r
+  -0.9091679830905225,\r
+  -0.9065957045149156,\r
+  -0.9039892931234433,\r
+  -0.901348847046022,\r
+  -0.898674465693954,\r
+  -0.895966249756185,\r
+  -0.8932243011955153,\r
+  -0.890448723244758,\r
+  -0.8876396204028542,\r
+  -0.8847970984309377,\r
+  -0.881921264348355,\r
+  -0.8790122264286336,\r
+  -0.8760700941954069,\r
+  -0.8730949784182901,\r
+  -0.8700869911087115,\r
+  -0.8670462455156929,\r
+  -0.8639728561215866,\r
+  -0.8608669386377673,\r
+  -0.8577286100002722,\r
+  -0.8545579883654008,\r
+  -0.8513551931052651,\r
+  -0.8481203448032973,\r
+  -0.8448535652497072,\r
+  -0.8415549774368988,\r
+  -0.838224705554838,\r
+  -0.8348628749863801,\r
+  -0.8314696123025455,\r
+  -0.8280450452577557,\r
+  -0.8245893027850253,\r
+  -0.8211025149911049,\r
+  -0.8175848131515839,\r
+  -0.8140363297059483,\r
+  -0.8104571982525949,\r
+  -0.8068475535437994,\r
+  -0.8032075314806453,\r
+  -0.799537269107905,\r
+  -0.7958369046088837,\r
+  -0.7921065773002126,\r
+  -0.7883464276266061,\r
+  -0.7845565971555752,\r
+  -0.7807372285720947,\r
+  -0.7768884656732328,\r
+  -0.7730104533627369,\r
+  -0.7691033376455797,\r
+  -0.7651672656224592,\r
+  -0.7612023854842622,\r
+  -0.7572088465064846,\r
+  -0.7531867990436126,\r
+  -0.7491363945234597,\r
+  -0.7450577854414658,\r
+  -0.7409511253549591,\r
+  -0.73681656887737,\r
+  -0.7326542716724131,\r
+  -0.7284643904482251,\r
+  -0.724247082951467,\r
+  -0.7200025079613819,\r
+  -0.715730825283819,\r
+  -0.7114321957452164,\r
+  -0.7071067811865477,\r
+  -0.7027547444572256,\r
+  -0.6983762494089727,\r
+  -0.693971460889654,\r
+  -0.6895405447370672,\r
+  -0.6850836677727008,\r
+  -0.680600997795453,\r
+  -0.676092703575316,\r
+  -0.6715589548470187,\r
+  -0.666999922303638,\r
+  -0.6624157775901718,\r
+  -0.6578066932970789,\r
+  -0.6531728429537771,\r
+  -0.6485144010221123,\r
+  -0.6438315428897915,\r
+  -0.639124444863776,\r
+  -0.6343932841636459,\r
+  -0.629638238914927,\r
+  -0.6248594881423865,\r
+  -0.6200572117632894,\r
+  -0.6152315905806274,\r
+  -0.6103828062763095,\r
+  -0.6055110414043257,\r
+  -0.6006164793838693,\r
+  -0.5956993044924332,\r
+  -0.5907597018588743,\r
+  -0.5857978574564391,\r
+  -0.580813958095765,\r
+  -0.5758081914178452,\r
+  -0.5707807458869674,\r
+  -0.5657318107836136,\r
+  -0.5606615761973366,\r
+  -0.5555702330196022,\r
+  -0.550457972936605,\r
+  -0.5453249884220468,\r
+  -0.5401714727298927,\r
+  -0.5349976198870973,\r
+  -0.5298036246862949,\r
+  -0.5245896826784694,\r
+  -0.5193559901655895,\r
+  -0.5141027441932219,\r
+  -0.5088301425431074,\r
+  -0.5035383837257181,\r
+  -0.49822766697278187,\r
+  -0.49289819222978426,\r
+  -0.4875501601484364,\r
+  -0.4821837720791226,\r
+  -0.4767992300633222,\r
+  -0.4713967368259979,\r
+  -0.4659764957679667,\r
+  -0.46053871095823995,\r
+  -0.455083587126344,\r
+  -0.449611329654607,\r
+  -0.4441221445704298,\r
+  -0.43861623853852766,\r
+  -0.43309381885315223,\r
+  -0.42755509343028253,\r
+  -0.42200027079979957,\r
+  -0.41642956009763726,\r
+  -0.41084317105790424,\r
+  -0.4052413140049904,\r
+  -0.3996241998456468,\r
+  -0.39399204006104827,\r
+  -0.3883450466988267,\r
+  -0.3826834323650904,\r
+  -0.37700741021641826,\r
+  -0.3713171939518378,\r
+  -0.36561299780477435,\r
+  -0.359895036534988,\r
+  -0.3541635254204905,\r
+  -0.3484186802494349,\r
+  -0.34266071731199493,\r
+  -0.33688985339222,\r
+  -0.3311063057598766,\r
+  -0.32531029216226337,\r
+  -0.31950203081601547,\r
+  -0.3136817403988915,\r
+  -0.30784964004153514,\r
+  -0.3020059493192286,\r
+  -0.29615088824362373,\r
+  -0.2902846772544625,\r
+  -0.2844075372112722,\r
+  -0.27851968938505367,\r
+  -0.2726213554499489,\r
+  -0.2667127574748986,\r
+  -0.26079411791527596,\r
+  -0.2548656596045144,\r
+  -0.2489276057457202,\r
+  -0.24298017990326418,\r
+  -0.23702360599436773,\r
+  -0.231058108280671,\r
+  -0.22508391135979297,\r
+  -0.21910124015687016,\r
+  -0.21311031991609197,\r
+  -0.20711137619221853,\r
+  -0.20110463484209212,\r
+  -0.19509032201612872,\r
+  -0.18906866414980603,\r
+  -0.183039887955141,\r
+  -0.17700422041214905,\r
+  -0.17096188876030177,\r
+  -0.1649131204899698,\r
+  -0.15885814333386158,\r
+  -0.1527971852584438,\r
+  -0.1467304744553624,\r
+  -0.1406582393328492,\r
+  -0.13458070850712642,\r
+  -0.12849811079379364,\r
+  -0.12241067519921603,\r
+  -0.11631863091190484,\r
+  -0.11022220729388336,\r
+  -0.10412163387205513,\r
+  -0.0980171403295605,\r
+  -0.09190895649713288,\r
+  -0.08579731234444028,\r
+  -0.07968243797143075,\r
+  -0.07356456359966741,\r
+  -0.06744391956366429,\r
+  -0.06132073630220906,\r
+  -0.055195244349689775,\r
+  -0.04906767432741809,\r
+  -0.04293825693494114,\r
+  -0.036807222941359394,\r
+  -0.030674803176636543,\r
+  -0.024541228522912448,\r
+  -0.018406729905805226,\r
+  -0.012271538285720572,\r
+  -0.006135884649154477,\r
+};\r
diff --git a/rdpdemo/src/3dscene.c b/rdpdemo/src/3dscene.c
new file mode 100644 (file)
index 0000000..8e74fe8
--- /dev/null
@@ -0,0 +1,220 @@
+// Object Triangle Vertices: X, Y, Z (Clockwise Winding)\r
+static float CubeTri[108] = {\r
+  // Cube Front Face\r
+  -10.0,  10.0, -10.0, // Triangle 1 Top Left\r
+   10.0,  10.0, -10.0, // Triangle 1 Top Right\r
+  -10.0, -10.0, -10.0, // Triangle 1 Bottom Left\r
+   10.0,  10.0, -10.0, // Triangle 2 Top Right\r
+   10.0, -10.0, -10.0, // Triangle 2 Bottom Right\r
+  -10.0, -10.0, -10.0, // Triangle 2 Bottom Left\r
+\r
+  // Cube Back Face\r
+   10.0,  10.0,  10.0, // Triangle 3 Top Right\r
+  -10.0,  10.0,  10.0, // Triangle 3 Top Left\r
+   10.0, -10.0,  10.0, // Triangle 3 Bottom Right\r
+  -10.0,  10.0,  10.0, // Triangle 4 Top Left\r
+  -10.0, -10.0,  10.0, // Triangle 4 Bottom Left\r
+   10.0, -10.0,  10.0, // Triangle 4 Bottom Right\r
+\r
+  // Cube Left Face\r
+  -10.0,  10.0,  10.0, // Triangle 5 Top Left\r
+  -10.0,  10.0, -10.0, // Triangle 5 Top Right\r
+  -10.0, -10.0,  10.0, // Triangle 5 Bottom Left\r
+  -10.0,  10.0, -10.0, // Triangle 6 Top Right\r
+  -10.0, -10.0, -10.0, // Triangle 6 Bottom Right\r
+  -10.0, -10.0,  10.0, // Triangle 6 Bottom Left\r
+\r
+  // Cube Right Face\r
+   10.0,  10.0, -10.0, // Triangle 7 Top Left\r
+   10.0,  10.0,  10.0, // Triangle 7 Top Right\r
+   10.0, -10.0, -10.0, // Triangle 7 Bottom Left\r
+   10.0,  10.0,  10.0, // Triangle 8 Top Right\r
+   10.0, -10.0,  10.0, // Triangle 8 Bottom Right\r
+   10.0, -10.0, -10.0, // Triangle 8 Bottom Left\r
+\r
+  // Cube Top Face\r
+   10.0,  10.0, -10.0, // Triangle 9 Top Right\r
+  -10.0,  10.0, -10.0, // Triangle 9 Top Left\r
+  -10.0,  10.0,  10.0, // Triangle 9 Bottom Left\r
+   10.0,  10.0, -10.0, // Triangle 10 Top Right\r
+  -10.0,  10.0,  10.0, // Triangle 10 Bottom Left\r
+   10.0,  10.0,  10.0, // Triangle 10 Bottom Right\r
+\r
+  // Bottom Face\r
+  -10.0, -10.0, -10.0, // Triangle 11 Top Left\r
+   10.0, -10.0, -10.0, // Triangle 11 Top Right\r
+   10.0, -10.0,  10.0, // Triangle 11 Bottom Right\r
+  -10.0, -10.0, -10.0, // Triangle 12 Top Left\r
+   10.0, -10.0,  10.0, // Triangle 12 Bottom Right\r
+  -10.0, -10.0,  10.0, // Triangle 12 Bottom Left\r
+};\r
+\r
+// Object Triangle Colors: R, G, B, A\r
+static uint8_t CubeRedCol[48] = {\r
+  // Cube Front Face\r
+  255,0,0,255, // Triangle 1 Color\r
+  255,0,0,255, // Triangle 2 Color\r
+\r
+  // Cube Back Face\r
+  120,0,0,255, // Triangle 3 Color\r
+  120,0,0,255, // Triangle 4 Color\r
+\r
+  // Cube Left Face\r
+  140,0,0,255, // Triangle 5 Color\r
+  140,0,0,255, // Triangle 6 Color\r
+\r
+  // Cube Right Face\r
+  160,0,0,255, // Triangle 7 Color\r
+  160,0,0,255, // Triangle 8 Color\r
+\r
+  // Cube Top Face\r
+  180,0,0,255, // Triangle 9 Color\r
+  180,0,0,255, // Triangle 10 Color\r
+\r
+  // Cube Bottom Face\r
+  100,0,0,255, // Triangle 11 Color\r
+  100,0,0,255, // Triangle 12 Color\r
+};\r
+\r
+// Object Triangle Colors: R, G, B, A\r
+static uint8_t CubeGreenCol[48] = {\r
+  // Cube Front Face\r
+  0,255,0,255, // Triangle 1 Color\r
+  0,255,0,255, // Triangle 2 Color\r
+\r
+  // Cube Back Face\r
+  0,120,0,255, // Triangle 3 Color\r
+  0,120,0,255, // Triangle 4 Color\r
+\r
+  // Cube Left Face\r
+  0,140,0,255, // Triangle 5 Color\r
+  0,140,0,255, // Triangle 6 Color\r
+\r
+  // Cube Right Face\r
+  0,160,0,255, // Triangle 7 Color\r
+  0,160,0,255, // Triangle 8 Color\r
+\r
+  // Cube Top Face\r
+  0,180,0,255, // Triangle 9 Color\r
+  0,180,0,255, // Triangle 10 Color\r
+\r
+  // Cube Bottom Face\r
+  0,100,0,255, // Triangle 11 Color\r
+  0,100,0,255, // Triangle 12 Color\r
+};\r
+\r
+// Object Triangle Colors: R, G, B, A\r
+static uint8_t CubeBlueCol[48] = {\r
+  // Cube Front Face\r
+  0,0,255,255, // Triangle 1 Color\r
+  0,0,255,255, // Triangle 2 Color\r
+\r
+  // Cube Back Face\r
+  0,0,120,255, // Triangle 3 Color\r
+  0,0,120,255, // Triangle 4 Color\r
+\r
+  // Cube Left Face\r
+  0,0,140,255, // Triangle 5 Color\r
+  0,0,140,255, // Triangle 6 Color\r
+\r
+  // Cube Right Face\r
+  0,0,160,255, // Triangle 7 Color\r
+  0,0,160,255, // Triangle 8 Color\r
+\r
+  // Cube Top Face\r
+  0,0,180,255, // Triangle 9 Color\r
+  0,0,180,255, // Triangle 10 Color\r
+\r
+  // Cube Bottom Face\r
+  0,0,100,255, // Triangle 11 Color\r
+  0,0,100,255, // Triangle 12 Color\r
+};\r
+\r
+// Object Triangle Colors: R, G, B, A\r
+static uint8_t CubeYellowCol[48] = {\r
+  // Cube Front Face\r
+  255,255,0,255, // Triangle 1 Color\r
+  255,255,0,255, // Triangle 2 Color\r
+\r
+  // Cube Back Face\r
+  120,120,0,255, // Triangle 3 Color\r
+  120,120,0,255, // Triangle 4 Color\r
+\r
+  // Cube Left Face\r
+  140,140,0,255, // Triangle 5 Color\r
+  140,140,0,255, // Triangle 6 Color\r
+\r
+  // Cube Right Face\r
+  160,160,0,255, // Triangle 7 Color\r
+  160,160,0,255, // Triangle 8 Color\r
+\r
+  // Cube Top Face\r
+  180,180,0,255, // Triangle 9 Color\r
+  180,180,0,255, // Triangle 10 Color\r
+\r
+  // Cube Bottom Face\r
+  100,100,0,255, // Triangle 11 Color\r
+  100,100,0,255, // Triangle 12 Color\r
+};\r
+\r
+// Object Triangle Colors: R, G, B, A\r
+static uint8_t CubePurpleCol[48] = {\r
+  // Cube Front Face\r
+  255,0,255,255, // Triangle 1 Color\r
+  255,0,255,255, // Triangle 2 Color\r
+\r
+  // Cube Back Face\r
+  120,0,120,255, // Triangle 3 Color\r
+  120,0,120,255, // Triangle 4 Color\r
+\r
+  // Cube Left Face\r
+  140,0,140,255, // Triangle 5 Color\r
+  140,0,140,255, // Triangle 6 Color\r
+\r
+  // Cube Right Face\r
+  160,0,160,255, // Triangle 7 Color\r
+  160,0,160,255, // Triangle 8 Color\r
+\r
+  // Cube Top Face\r
+  180,0,180,255, // Triangle 9 Color\r
+  180,0,180,255, // Triangle 10 Color\r
+\r
+  // Cube Bottom Face\r
+  100,0,100,255, // Triangle 11 Color\r
+  100,0,100,255, // Triangle 12 Color\r
+};\r
+\r
+// Object Triangle Colors: R, G, B, A\r
+static uint8_t CubeCyanCol[48] = {\r
+  // Cube Front Face\r
+  0,255,255,255, // Triangle 1 Color\r
+  0,255,255,255, // Triangle 2 Color\r
+\r
+  // Cube Back Face\r
+  0,120,120,255, // Triangle 3 Color\r
+  0,120,120,255, // Triangle 4 Color\r
+\r
+  // Cube Left Face\r
+  0,140,140,255, // Triangle 5 Color\r
+  0,140,140,255, // Triangle 6 Color\r
+\r
+  // Cube Right Face\r
+  0,160,160,255, // Triangle 7 Color\r
+  0,160,160,255, // Triangle 8 Color\r
+\r
+  // Cube Top Face\r
+  0,180,180,255, // Triangle 9 Color\r
+  0,180,180,255, // Triangle 10 Color\r
+\r
+  // Cube Bottom Face\r
+  0,100,100,255, // Triangle 11 Color\r
+  0,100,100,255, // Triangle 12 Color\r
+};\r
+\r
+// Scene Object Position Data: Translation X, Y, Z\r
+static float CubeRedPos[3] = { -35.0, 20.0, 90.0 }; // Object Position: X, Y, Z\r
+static float CubeGreenPos[3] = { 0.0, 20.0, 90.0 }; // Object Position: X, Y, Z\r
+static float CubeBluePos[3] = { 35.0, 20.0, 90.0 }; // Object Position: X, Y, Z\r
+static float CubeYellowPos[3] = {-35.0, -20.0, 90.0 }; // Object Position: X, Y, Z\r
+static float CubePurplePos[3] = { 0.0, -20.0, 90.0 }; // Object Position: X, Y, Z\r
+static float CubeCyanPos[3] = { 35.0, -20.0, 90.0 }; // Object Position: X, Y, Z
\ No newline at end of file
diff --git a/rdpdemo/src/main.c b/rdpdemo/src/main.c
new file mode 100644 (file)
index 0000000..bee1df4
--- /dev/null
@@ -0,0 +1,211 @@
+//
+// rdpdemo/src/main.c: RDP demo (entry point).
+//
+// n64chain: A (free) open-source N64 development toolchain.
+// Copyright 2014-16 Tyler J. Stachecki <stachecki.tyler@gmail.com>
+//
+// This file is subject to the terms and conditions defined in
+// 'LICENSE', which is part of this source code package.
+//
+
+#include <os/fbtext.h>
+#include <libgfx/init.h>
+#include <libgfx/rdp.h>
+#include <libgfx/rspbuf.h>
+#include <rcp/vi.h>
+#include <stdint.h>
+
+// These pre-defined values are suitable for NTSC.
+// TODO: Add support for PAL and PAL-M televisions.
+static vi_state_t vi_state = {
+  0x0000324E, // status
+  0x00200000, // origin
+  0x00000140, // width
+  0x00000002, // intr
+  0x00000000, // current
+  0x03E52239, // burst
+  0x0000020D, // v_sync
+  0x00000C15, // h_sync
+  0x0C150C15, // leap
+  0x006C02EC, // h_start
+  0x002501FF, // v_start
+  0x000E0204, // v_burst
+  0x00000200, // x_scale
+  0x00000400, // y_scale
+};
+
+static uint32_t fb_origin;
+
+// krom's 3d library.
+static unsigned next_free_vert;
+#include "3d.c"
+#include "3dscene.c"
+
+#define SAMPLE_TYPE 0x00200000000000ULL // Set_Other_Modes b: Determines How Textures Are Sampled: 0=1x1 (Point Sample), 1=2x2. Note That Copy (Point Sample 4 Horizontally Adjacent Texels) Mode Is Indicated By CYCLE_TYPE (Bit 45)
+#define BI_LERP_0 0x00080000000000ULL // Set_Other_Modes Z: 1=BI_LERP, 0=Color Convert Operation In Texture Filter. Used In Cycle 0 (Bit 43)
+#define RGB_DITHER_SEL_NO_DITHER 0x0000C000000000ULL             // Set_Other_Modes V2: RGB Dither Selection No Dither (Bit 38..39)
+#define ALPHA_DITHER_SEL_NO_DITHER 0x00003000000000ULL // Set_Other_Modes V1: Alpha Dither Selection No Dither (Bit 36..37)
+#define B_M1A_0_2 0x00000080000000ULL // Set_Other_Modes V: Blend Modeword, Multiply 1a Input Select 2, Cycle 0 (Bit 30..31)
+
+// Set Combine Mode
+static inline void rdp_set_combine_mode( struct libgfx_rspbuf *rspbuf, uint8_t sub_a_r0, uint8_t mul_r0, uint8_t sub_a_a0, uint8_t mul_a0, uint8_t sub_a_r1, uint8_t mul_r1, uint8_t sub_b_r0, uint8_t sub_b_r1, uint8_t sub_a_a1, uint8_t mul_a1, uint8_t add_r0, uint8_t sub_b_a0, uint8_t add_a0, uint8_t add_r1, uint8_t sub_b_a1, uint8_t add_a1 )
+{
+    libgfx_rspbuf_append( rspbuf, 0x3C000000 | sub_a_r0 << 20 | mul_r0 << 15 | sub_a_a0 << 12 | mul_a0 << 9 | sub_a_r1 << 5 | mul_r1 );
+    libgfx_rspbuf_append( rspbuf, sub_b_r0 << 28 | sub_b_r1 << 24 | sub_a_a1 << 21 | mul_a1 << 18 | add_r0 << 15 | sub_b_a0 << 12 | add_a0 << 9 | add_r1 << 6 | sub_b_a1 << 3 | add_a1);
+}
+
+void main(void *unused __attribute__((unused))) {
+  struct libgfx_rspbuf *rspbuf = libgfx_rspbuf_create();
+  struct libn64_fbtext_context context;
+  
+  // Setup the OS's private/hidden text rendering engine.
+  // The 0 and ~0 are just fill colors (black and white).
+  libn64_fbtext_init(&context, 0x80000000 | vi_state.origin,
+      ~0, 0, 320, LIBN64_FBTEXT_16BPP);
+         
+  libgfx_init();
+
+  // Register DP/VI interrupts on this thread. When registering a thread
+  // w/ interrupts, it causes the threads message queue to get populated
+  // w/ a message each time an interrupt fires.
+  libn64_thread_reg_intr(libn64_thread_self(), LIBN64_INTERRUPT_DP);
+
+  // Initialize the RDP by building and issuing a display list.
+  rdp_set_color_image(rspbuf, FORMAT_RGBA, COLOR_ELEMENT_16B,
+      vi_state.width - 1, vi_state.origin);
+
+  rdp_set_scissor(rspbuf, 0, 0, 320, 240,
+      SCISSOR_NO_INTERLACED, SCISSOR_DONTCARE);
+
+  rdp_set_other_modes(rspbuf, CYCLE_TYPE_FILL);
+  rdp_set_fill_color(rspbuf, rdp_rgba16(24, 128, 212, 255));
+  rdp_fill_rectangle(rspbuf, 0, 0, 319, 239);
+  rdp_sync_pipe(rspbuf);
+  rdp_sync_full(rspbuf);
+
+  rsp_finalize(rspbuf);
+  libgfx_rspbuf_flush(rspbuf);
+  libgfx_run();
+  libn64_recvt_message();
+  vi_flush_state(&vi_state);
+
+  //libn64_thread_reg_intr(libn64_thread_self(), LIBN64_INTERRUPT_VI);
+  //libn64_thread_unreg_intr(libn64_thread_self(), LIBN64_INTERRUPT_DP);
+
+  // For each frame...
+  uint16_t fps_tick=0;
+  uint16_t fps_sec=0;
+  uint32_t last_sec=0;
+
+  uint16_t XRot = 0; // X Rotation Value (0..1023)
+  uint16_t YRot = 0; // Y Rotation Value (0..1023)
+  uint16_t ZRot = 0; // Z Rotation Value (0..1023)
+
+  while (1) {
+    rdp_set_other_modes(rspbuf, CYCLE_TYPE_FILL);
+    rdp_set_fill_color(rspbuf, rdp_rgba16(24, 128, 212, 255));
+    rdp_fill_rectangle(rspbuf, 0, 0, 319, 239);
+    rdp_sync_pipe(rspbuf);
+
+    rdp_set_other_modes(rspbuf, SAMPLE_TYPE|BI_LERP_0|RGB_DITHER_SEL_NO_DITHER|ALPHA_DITHER_SEL_NO_DITHER|B_M1A_0_2); // Set Other Modes
+    rdp_set_combine_mode(rspbuf, 0x0,0x00, 0,0, 0x6,0x01, 0x0,0xF, 1,0, 0,0,0, 7,7,7); // Set Combine Mode: SubA RGB0,MulRGB0, SubA Alpha0,MulAlpha0, SubA RGB1,MulRGB1, SubB RGB0,SubB RGB1, SubA Alpha1,MulAlpha1, AddRGB0,SubB Alpha0,AddAlpha0, AddRGB1,SubB Alpha1,AddAlpha1
+    matrix_identity(Matrix3D); // Reset Matrix To Identity
+    translate_xyz(Matrix3D, CubeRedPos[0], CubeRedPos[1], CubeRedPos[2]); // Translate: Matrix, X, Y, Z
+    rotate_x(Matrix3D, Sin1024, XRot); // Rotate: Matrix, Precalc Table, X
+    fill_triangle_array(rspbuf, CubeTri, CubeRedCol, CULL_BACK, 0, 108); // Fill Triangle Array: Vert Array, Color Array, RDP Buffer, Culling, Base, Length
+
+    matrix_identity(Matrix3D); // Reset Matrix To Identity
+    translate_xyz(Matrix3D, CubeGreenPos[0], CubeGreenPos[1], CubeGreenPos[2]); // Translate: Matrix, X, Y, Z
+    rotate_y(Matrix3D, Sin1024, YRot); // Rotate: Matrix, Precalc Table, Y
+    fill_triangle_array(rspbuf, CubeTri, CubeGreenCol, CULL_BACK, 0, 108); // Fill Triangle Array: Vert Array, Color Array, RDP Buffer, Culling, Base, Length
+
+    matrix_identity(Matrix3D); // Reset Matrix To Identity
+    translate_xyz(Matrix3D, CubeBluePos[0], CubeBluePos[1], CubeBluePos[2]); // Translate: Matrix, X, Y, Z
+    rotate_z(Matrix3D, Sin1024, ZRot); // Rotate: Matrix, Precalc Table, Z
+    fill_triangle_array(rspbuf, CubeTri, CubeBlueCol, CULL_BACK, 0, 108); // Fill Triangle Array: Vert Array, Color Array, RDP Buffer, Culling, Base, Length
+
+    rdp_sync_full(rspbuf);
+    rsp_finalize(rspbuf);
+    libgfx_rspbuf_flush(rspbuf);
+    libgfx_rspbuf_flush_vertices(rspbuf);
+    libgfx_run();
+
+    // We blow out the vertex cache if we do this without flushing...
+    next_free_vert = 0;
+
+    matrix_identity(Matrix3D); // Reset Matrix To Identity
+    translate_xyz(Matrix3D, CubeYellowPos[0], CubeYellowPos[1], CubeYellowPos[2]); // Translate: Matrix, X, Y, Z
+    rotate_xy(Matrix3D, Sin1024, XRot, YRot); // Rotate: Matrix, Precalc Table, X, Y
+    fill_triangle_array(rspbuf, CubeTri, CubeYellowCol, CULL_BACK, 0, 108); // Fill Triangle Array: Vert Array, Color Array, RDP Buffer, Culling, Base, Length
+
+    matrix_identity(Matrix3D); // Reset Matrix To Identity
+    translate_xyz(Matrix3D, CubePurplePos[0], CubePurplePos[1], CubePurplePos[2]); // Translate: Matrix, X, Y, Z
+    rotate_xz(Matrix3D, Sin1024, XRot, ZRot); // Rotate: Matrix, Precalc Table, X, Z
+    fill_triangle_array(rspbuf, CubeTri, CubePurpleCol, CULL_BACK, 0, 108); // Fill Triangle Array: Vert Array, Color Array, RDP Buffer, Culling, Base, Length
+
+    matrix_identity(Matrix3D); // Reset Matrix To Identity
+    translate_xyz(Matrix3D, CubeCyanPos[0], CubeCyanPos[1], CubeCyanPos[2]); // Translate: Matrix, X, Y, Z
+    rotate_xyz(Matrix3D, Sin1024, XRot, YRot, ZRot); // Rotate: Matrix, Precalc Table, X, Y, Z
+    fill_triangle_array(rspbuf, CubeTri, CubeCyanCol, CULL_BACK, 0, 108); // Fill Triangle Array: Vert Array, Color Array, RDP Buffer, Culling, Base, Length
+
+    rdp_sync_full(rspbuf);
+    rsp_finalize(rspbuf);
+
+    // Wait for the last RDP DL to finish before issuing anew.
+    libn64_recvt_message();
+    libgfx_rspbuf_flush(rspbuf);
+    libgfx_rspbuf_flush_vertices(rspbuf);
+    libgfx_run();
+
+#if 0
+    // Point to VI to the last fb, swap the front and back fbs.
+    vi_flush_state(&vi_state);
+    vi_state.origin ^= 0x100000; // 1MB
+
+    // Wipe the back-buffer to black.
+    for (i = 0; i < 320 * 240 * 2; i += 16) {
+      __asm__ __volatile__(
+        ".set gp=64\n\t"
+        "cache 0xD, 0x0(%0)\n\t"
+        "sd $zero, 0x0(%0)\n\t"
+        "sd $zero, 0x8(%0)\n\t"
+        "cache 0x19, 0x0(%0)\n\t"
+        ".set gp=default\n\t"
+
+        :: "r" (0x80000000 | (vi_state.origin + i))
+        : "memory"
+      );
+    }
+
+#endif
+    // All vertices were flushed and can be reused.
+    next_free_vert = 0;
+
+    // Update triangle rotation variables
+    XRot = (XRot + 1) & 1023;
+    YRot = (YRot + 1) & 1023;
+    ZRot = (ZRot + 1) & 1023;
+
+    // Set the position of the cursor. If your string
+    // contains \n, it will automatically advance it.
+    // The text also wraps around, but it won't scroll.
+    context.x = 1;
+    context.y = 1;
+
+         struct timeval timer = libn64_time();
+       
+    if(timer.tv_sec!=last_sec)
+    {
+        fps_sec=fps_tick;
+        fps_tick=0;
+        last_sec=timer.tv_sec;
+    }  
+    fps_tick++;
+
+    libn64_fbtext_putu32(&context, fps_sec);   
+       
+    // Block until the next VI interrupt comes in.
+    libn64_recvt_message();
+  }
+}
+