629 lines
17 KiB
C
629 lines
17 KiB
C
#include <sys/types.h>
|
|
#include <sys/mman.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
#include <assert.h>
|
|
#include <fcntl.h>
|
|
#include <math.h>
|
|
|
|
#include "voodoo2.h"
|
|
#include "voodoo2_bits.h"
|
|
#include "voodoo2_config.h"
|
|
#include "voodoo2_config_bits.h"
|
|
#include "ics5342.h"
|
|
|
|
static inline bool _wait_graphics_busy(voodoo2_reg * voodoo2)
|
|
{
|
|
int cnt = 0;
|
|
for (int i = 0; i < 128; i++) {
|
|
if (voodoo2->status & STATUS__CHUCK_BUSY) {
|
|
//if (voodoo2->status & STATUS__PCI_FIFO_FREESPACE(0x3f)) {
|
|
cnt = 0;
|
|
} else {
|
|
cnt += 1;
|
|
}
|
|
if (cnt >= 5)
|
|
return true;
|
|
}
|
|
//fprintf(stderr, "voodoo2 status %08x\n", voodoo2->status);
|
|
//return false;
|
|
return true;
|
|
}
|
|
|
|
#define wait_graphics_busy(voodoo2) assert(_wait_graphics_busy(voodoo2));
|
|
|
|
static inline bool _wait_graphics_busy2(voodoo2_reg * voodoo2)
|
|
{
|
|
int cnt = 0;
|
|
while (true) {
|
|
if (voodoo2->status & STATUS__CHUCK_BUSY) {
|
|
cnt = 0;
|
|
} else {
|
|
cnt += 1;
|
|
}
|
|
if (cnt >= 3)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#define wait_graphics_busy2(voodoo2) assert(_wait_graphics_busy2(voodoo2));
|
|
|
|
static inline void dac_data_read(voodoo2_reg * voodoo2,
|
|
int data,
|
|
int rs)
|
|
{
|
|
voodoo2->dacData
|
|
= DACDATA__WRITE_DATA(data)
|
|
| DACDATA__ADDRESS_2_0(rs >> 0)
|
|
| DACDATA__READ_COMMAND
|
|
| DACDATA__ADDRESS_4_3(rs >> 3)
|
|
;
|
|
}
|
|
|
|
static inline void dac_data_write(voodoo2_reg * voodoo2,
|
|
int data,
|
|
int rs)
|
|
{
|
|
voodoo2->dacData
|
|
= DACDATA__WRITE_DATA(data)
|
|
| DACDATA__ADDRESS_2_0(rs >> 0)
|
|
| DACDATA__ADDRESS_4_3(rs >> 3)
|
|
;
|
|
}
|
|
|
|
static inline void dac_write_pll_8(voodoo2_reg * voodoo2,
|
|
int address,
|
|
int parameter_m)
|
|
{
|
|
dac_data_write(voodoo2, address, DAC__RS__PLL_ADDRESS_WRITE);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
dac_data_write(voodoo2, parameter_m, DAC__RS__PLL_PARAMETER);
|
|
wait_graphics_busy(voodoo2);
|
|
}
|
|
|
|
static inline void dac_write_pll_16(voodoo2_reg * voodoo2,
|
|
int address,
|
|
int parameter_m,
|
|
int parameter_n)
|
|
{
|
|
dac_data_write(voodoo2, address, DAC__RS__PLL_ADDRESS_WRITE);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
dac_data_write(voodoo2, parameter_m, DAC__RS__PLL_PARAMETER);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
dac_data_write(voodoo2, parameter_n, DAC__RS__PLL_PARAMETER);
|
|
wait_graphics_busy(voodoo2);
|
|
}
|
|
|
|
typedef struct mn {
|
|
uint8_t m;
|
|
uint8_t n;
|
|
} mn_t;
|
|
|
|
static inline mn_t dac_read_pll_16(voodoo2_reg * voodoo2,
|
|
int address)
|
|
{
|
|
dac_data_write(voodoo2, address, DAC__RS__PLL_ADDRESS_READ);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
dac_data_read(voodoo2, 0, DAC__RS__PLL_PARAMETER);
|
|
wait_graphics_busy(voodoo2);
|
|
int m = voodoo2->fbiInit2 & 0xff;
|
|
|
|
dac_data_read(voodoo2, 0, DAC__RS__PLL_PARAMETER);
|
|
wait_graphics_busy(voodoo2);
|
|
int n = voodoo2->fbiInit2 & 0xff;
|
|
|
|
return (mn_t){ m, n };
|
|
}
|
|
|
|
uint8_t read_fd_u8(int fd, uint32_t offset)
|
|
{
|
|
off_t ret = lseek(fd, offset, SEEK_SET);
|
|
assert(ret == offset);
|
|
uint8_t value;
|
|
ssize_t len = read(fd, &value, 1);
|
|
assert(len == 1);
|
|
return value;
|
|
}
|
|
|
|
uint16_t read_fd_u16(int fd, uint32_t offset)
|
|
{
|
|
off_t ret = lseek(fd, offset, SEEK_SET);
|
|
assert(ret == offset);
|
|
uint16_t value;
|
|
ssize_t len = read(fd, &value, 2);
|
|
assert(len == 2);
|
|
return value;
|
|
}
|
|
|
|
void write_fd_u8(int fd, uint32_t offset, uint8_t value)
|
|
{
|
|
off_t ret = lseek(fd, offset, SEEK_SET);
|
|
assert(ret == offset);
|
|
ssize_t len = write(fd, &value, 1);
|
|
assert(len == 1);
|
|
}
|
|
|
|
void write_fd_u32(int fd, uint32_t offset, uint32_t value)
|
|
{
|
|
off_t ret = lseek(fd, offset, SEEK_SET);
|
|
assert(ret == offset);
|
|
ssize_t len = write(fd, &value, 4);
|
|
assert(len == 4);
|
|
}
|
|
|
|
typedef struct vec3 {
|
|
float x;
|
|
float y;
|
|
float z;
|
|
} vec3;
|
|
|
|
static const vec3 cube_vertex_position[] = {
|
|
{ 1.0f, 1.0f, -1.0f },
|
|
{ 1.0f, -1.0f, -1.0f },
|
|
{ 1.0f, 1.0f, 1.0f },
|
|
{ 1.0f, -1.0f, 1.0f },
|
|
{ -1.0f, 1.0f, -1.0f },
|
|
{ -1.0f, -1.0f, -1.0f },
|
|
{ -1.0f, 1.0f, 1.0f },
|
|
{ -1.0f, -1.0f, 1.0f },
|
|
};
|
|
|
|
static const uint32_t cube_vertex_color[] = {
|
|
0xff0000, // red
|
|
0x00ff00, // green
|
|
0x0000ff, // blue
|
|
0xffff00, // yellow
|
|
0x00ffff, // cyan
|
|
0xff00ff, // magenta
|
|
0xff7f00, // orange
|
|
0x7f00ff, // violet
|
|
};
|
|
|
|
typedef struct face {
|
|
int a;
|
|
int b;
|
|
int c;
|
|
} face;
|
|
|
|
static const face cube_faces[] = {
|
|
{4, 2, 0},
|
|
{2, 7, 3},
|
|
{6, 5, 7},
|
|
{1, 7, 5},
|
|
{0, 3, 1},
|
|
{4, 1, 5},
|
|
{4, 6, 2},
|
|
{2, 6, 7},
|
|
{6, 4, 5},
|
|
{1, 3, 7},
|
|
{0, 2, 3},
|
|
{4, 0, 1},
|
|
};
|
|
static const int cube_faces_length = (sizeof (cube_faces)) / (sizeof (cube_faces[0]));
|
|
|
|
static float theta = 0;
|
|
|
|
static inline vec3 vertex_rotate(vec3 v)
|
|
{
|
|
// to make the cube's appearance more interesting, rotate the vertex on two
|
|
// axes
|
|
|
|
float x0 = v.x;
|
|
float y0 = v.y;
|
|
float z0 = v.z;
|
|
|
|
float x1 = x0 * cos(theta) - z0 * sin(theta);
|
|
float y1 = y0;
|
|
float z1 = x0 * sin(theta) + z0 * cos(theta);
|
|
|
|
float x2 = x1;
|
|
float y2 = y1 * cos(theta) - z1 * sin(theta);
|
|
float z2 = y1 * sin(theta) + z1 * cos(theta);
|
|
|
|
return (vec3){x2, y2, z2};
|
|
}
|
|
|
|
static inline vec3 vertex_perspective_divide(vec3 v)
|
|
{
|
|
float w = 1.0f / (v.z + 3.0f);
|
|
return (vec3){v.x * w, v.y * w, w};
|
|
}
|
|
|
|
static inline vec3 vertex_screen_space(vec3 v)
|
|
{
|
|
return (vec3){
|
|
v.x * 300.f + 400.f,
|
|
v.y * 300.f + 300.f,
|
|
v.z,
|
|
};
|
|
}
|
|
|
|
int main()
|
|
{
|
|
const char * config_path = "/sys/bus/pci/devices/0000:02:0a.0/config";
|
|
int config_fd = open(config_path, O_RDWR | O_SYNC);
|
|
assert(config_fd >= 0);
|
|
|
|
uint16_t vendor_id = read_fd_u16(config_fd, PCI__CONFIG__VENDOR_ID);
|
|
uint16_t device_id = read_fd_u16(config_fd, PCI__CONFIG__DEVICE_ID);
|
|
printf("Vendor ID: %04x\n", vendor_id);
|
|
printf("Device ID: %04x\n", device_id);
|
|
assert(vendor_id == 0x121a);
|
|
assert(device_id == 0x0002);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// PCI enable
|
|
////////////////////////////////////////////////////////////////////////
|
|
{
|
|
const char * enable_path = "/sys/bus/pci/devices/0000:02:0a.0/enable";
|
|
int enable_fd = open(enable_path, O_RDWR | O_SYNC);
|
|
assert(enable_fd >= 0);
|
|
|
|
if (read_fd_u8(enable_fd, 0) == '0') {
|
|
write_fd_u8(enable_fd, 0, '1'); // enable
|
|
assert(read_fd_u8(enable_fd, 0) != '0');
|
|
}
|
|
close(enable_fd);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// PCI resource0
|
|
////////////////////////////////////////////////////////////////////////
|
|
const char * resource0_path = "/sys/bus/pci/devices/0000:02:0a.0/resource0";
|
|
int resource0_fd = open(resource0_path, O_RDWR | O_SYNC);
|
|
assert(resource0_fd >= 0);
|
|
|
|
uint32_t resource0_size = 16 * 1024 * 1024;
|
|
void * resource0_base = mmap(0, resource0_size, PROT_READ | PROT_WRITE, MAP_SHARED, resource0_fd, 0);
|
|
assert(resource0_base != MAP_FAILED);
|
|
|
|
voodoo2_reg * voodoo2 = (voodoo2_reg *)resource0_base;
|
|
|
|
int init_enable;
|
|
|
|
goto draw;
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// reset
|
|
////////////////////////////////////////////////////////////////////////
|
|
init_enable
|
|
= INIT_ENABLE__ENABLE_WRITES_TO_HARDWARE_REGISTERS;
|
|
write_fd_u32(config_fd, PCI__CONFIG__INIT_ENABLE, init_enable);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->fbiInit0
|
|
= FBIINIT0__CHUCK_GRAPHICS_RESET
|
|
| FBIINIT0__CHUCK_FIFO_RESET
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->fbiInit1
|
|
= FBIINIT1__VIDEO_TIMING_RESET
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->fbiInit2
|
|
= 0; // disable DRAM refresh
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// DAC initialization
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// enable fbiInit2/dacRead remap
|
|
init_enable
|
|
= INIT_ENABLE__ENABLE_WRITES_TO_HARDWARE_REGISTERS
|
|
| INIT_ENABLE__REMAP_FBIINIT2_FBIINIT3_TO_DACREAD_VIDEOCHECKSUM;
|
|
write_fd_u32(config_fd, PCI__CONFIG__INIT_ENABLE, init_enable);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
int command = DAC__COMMAND__COLOR_MODE__16BIT_DIRECT_COLOR_WITH_BYPASS;
|
|
dac_data_write(voodoo2, command, DAC__RS__COMMAND);
|
|
wait_graphics_busy(voodoo2);
|
|
dac_data_read(voodoo2, command, DAC__RS__COMMAND);
|
|
wait_graphics_busy(voodoo2);
|
|
int command_read = voodoo2->fbiInit2 & 0xff;
|
|
printf("dac read: DAC__RS__COMMAND: m: %02x\n", command_read);
|
|
|
|
/*
|
|
pixel clock: 40MHz
|
|
graphics/memory clock: 44.6MHz
|
|
*/
|
|
|
|
int m = 54;
|
|
int n = 67;
|
|
dac_write_pll_16(voodoo2, DAC__PLL_PARAMETER__CLK0_f0_PLL, m, n);
|
|
mn_t clk0_f0_res = dac_read_pll_16(voodoo2, DAC__PLL_PARAMETER__CLK0_f0_PLL);
|
|
printf("dac read: DAC__PLL_PARAMETER__CLK0_f0_PLL: m: %02x n: %02x\n",
|
|
clk0_f0_res.m, clk0_f0_res.n);
|
|
|
|
int pll_control
|
|
= DAC__PLL_CONTROL__CLK0_SELECT(0) // f0
|
|
| DAC__PLL_CONTROL__CLK1_SELECT(0) // fA
|
|
| DAC__PLL_CONTROL__ENABLE_INTERNAL_CLOCK_SELECT;
|
|
dac_write_pll_8(voodoo2, DAC__PLL_PARAMETER__PLL_CONTROL, pll_control);
|
|
mn_t pll_control_res = dac_read_pll_16(voodoo2, DAC__PLL_PARAMETER__PLL_CONTROL);
|
|
printf("dac read: DAC__PLL_PARAMETER__PLL_CONTROL: m: %02x\n",
|
|
pll_control_res.m);
|
|
|
|
// disable fbiInit2/dacRead remap
|
|
init_enable
|
|
= INIT_ENABLE__ENABLE_WRITES_TO_HARDWARE_REGISTERS;
|
|
write_fd_u32(config_fd, PCI__CONFIG__INIT_ENABLE, init_enable);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// framebuffer initialization
|
|
////////////////////////////////////////////////////////////////////////
|
|
voodoo2->fbiInit0
|
|
= FBIINIT0__VGA_PASSTHROUGH // disable VGA passthrough
|
|
| FBIINIT0__STALL_PCI_ENABLE_FOR_HIGH_WATER_MARK
|
|
| FBIINIT0__PCI_FIFO_EMPTY_ENTRIES_LOW_WATER_MARK(0x10)
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
int x_tiles = 832 / 32;
|
|
int x_tiles_0 = (x_tiles >> 0) & 0b1;
|
|
int x_tiles_4_1 = (x_tiles >> 1) & 0b1111;
|
|
int x_tiles_5 = (x_tiles >> 5) & 0b1;
|
|
|
|
voodoo2->fbiInit1
|
|
= FBIINIT1__ENABLE_LINEAR_FRAME_BUFFER_READS
|
|
| FBIINIT1__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_4_1(x_tiles_4_1)
|
|
| FBIINIT1__DRIVE_VIDEO_TIMING_DATA_OUTPUTS
|
|
| FBIINIT1__DRIVE_VIDEO_TIMING_BLANK_OUTPUTS
|
|
| FBIINIT1__DRIVE_VIDEO_TIMING_HSYNC_VSYNC_OUTPUTS
|
|
| FBIINIT1__DRIVE_VIDEO_TIMING_DCLK_OUTPUT
|
|
| FBIINIT1__VIDEO_TIMING_VCLK_INPUT_SELECT_0(0) // vid_clk_2x
|
|
| FBIINIT1__VIDEO_TIMING_VCLK_SOURCE_SELECT__VID_CLK_2X_SEL
|
|
| FBIINIT1__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_5(x_tiles_5)
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->fbiInit2
|
|
= FBIINIT2__DRAM_BANKING_CONFIGURATION
|
|
| FBIINIT2__ENABLE_FAST_RAS_READ_CYCLES
|
|
| FBIINIT2__ENABLE_GENERATED_DRAM_OE_SIGNAL
|
|
| FBIINIT2__VIDEO_BUFFER_OFFSET(247)
|
|
| FBIINIT2__ENABLE_DRAM_READ_AHEAD_FIFO
|
|
| FBIINIT2__ENABLE_DRAM_BANKING
|
|
| FBIINIT2__REFRESH_ENABLE
|
|
| FBIINIT2__REFRESH_LOAD_VALUE(0x30)
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->fbiInit3
|
|
= FBIINIT3__DISABLE_TEXTURE_MAPPING
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->fbiInit4
|
|
= FBIINIT4__ENABLE_READ_AHEAD_LOGIC_FOR_LINEAR_FRAME_BUFFER_READS
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->fbiInit5
|
|
= FBIINIT5__VIDEO_TIMING_VCLK_INPUT_SELECT_1(0) // vid_clk_2x
|
|
| FBIINIT5__INVERT_DAC_HSYNC_OUTPUT_TO_DAC
|
|
| FBIINIT5__INVERT_DAC_VSYNC_OUTPUT_TO_DAC
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->fbiInit6
|
|
= FBIINIT6__NUMBER_OF_32X32_VIDEO_TILES_IN_HORIZONTAL_DIMENSION_0(x_tiles_0)
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// video timing initialization
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
int y_height = 600;
|
|
int x_width = 800;
|
|
|
|
int v_back_porch = 628 - 605;
|
|
int h_back_porch = 1056 - 968;
|
|
|
|
int v_sync_on = 605 - 601;
|
|
int h_sync_on = 968 - 840;
|
|
|
|
int v_sync_off = 628 - v_sync_on;
|
|
int h_sync_off = 1056 - h_sync_on;
|
|
|
|
voodoo2->hSync
|
|
= HSYNC__H_SYNC_ON(h_sync_on - 1)
|
|
| HSYNC__H_SYNC_OFF(h_sync_off)
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->vSync
|
|
= VSYNC__V_SYNC_ON(v_sync_on)
|
|
| VSYNC__V_SYNC_OFF(v_sync_off)
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->backPorch
|
|
= BACKPORCH__H_BACK_PORCH(h_back_porch - 2)
|
|
| BACKPORCH__V_BACK_PORCH(v_back_porch)
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->videoDimensions
|
|
= VIDEODIMENSIONS__X_WIDTH(x_width - 1)
|
|
| VIDEODIMENSIONS__Y_HEIGHT(y_height)
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// panda
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
init_enable
|
|
= INIT_ENABLE__ENABLE_WRITES_TO_PCI_FIFO;
|
|
write_fd_u32(config_fd, PCI__CONFIG__INIT_ENABLE, init_enable);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
if (0) {
|
|
/*
|
|
static const uint16_t panda[] __attribute__((aligned(4))) = {
|
|
#include "panda.rgb565.inc"
|
|
};
|
|
static const uint16_t bear[] __attribute__((aligned(4))) = {
|
|
#include "bear.rgb565.inc"
|
|
};
|
|
|
|
while (true) {
|
|
volatile uint16_t * framebuffer
|
|
= (volatile uint16_t * )(((ptrdiff_t)resource0_base) + 0x0400000);
|
|
|
|
printf("panda\n");
|
|
for (int y = 0; y < 600; y++) {
|
|
for (int x = 0; x < 800; x++) {
|
|
framebuffer[y * 1024 + x] = panda[y * 800 + x];
|
|
wait_graphics_busy(voodoo2);
|
|
}
|
|
}
|
|
sleep(1);
|
|
printf("bear\n");
|
|
for (int y = 0; y < 600; y++) {
|
|
for (int x = 0; x < 800; x++) {
|
|
framebuffer[y * 1024 + x] = bear[y * 800 + x];
|
|
wait_graphics_busy(voodoo2);
|
|
}
|
|
}
|
|
sleep(1);
|
|
}
|
|
*/
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// triangle
|
|
////////////////////////////////////////////////////////////////////////
|
|
draw:
|
|
voodoo2->fbzMode
|
|
= FBZMODE__DEPTH_BUFFER_FUNCTION__LESS_THAN
|
|
| FBZMODE__ENABLE_DEPTH_BUFFERING
|
|
| FBZMODE__FLOATING_POINT_DEPTH_BUFFER
|
|
| FBZMODE__RGB_BUFFER_WRITE_MASK
|
|
| FBZMODE__DEPTH_ALPHA_BUFFER_WRITE_MASK
|
|
| FBZMODE__DRAW_BUFFER__BACK_BUFFER
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->lfbMode
|
|
= LFBMODE__LINEAR_FRAME_BUFFER__WRITE_FORMAT__RGB565
|
|
| LFBMODE__LINEAR_FRAME_BUFFER__WRITE_BUFFER_SELECT__BACK_BUFFER
|
|
| LFBMODE__LINEAR_FRAME_BUFFER__READ_BUFFER_SELECT__FRONT_BUFFER
|
|
| LFBMODE__LINEAR_FRAME_BUFFER__ENABLE_PIXEL_PIPELINE_WRITES
|
|
| LFBMODE__LINEAR_FRAME_BUFFER__RGBA_LANES__ARGB
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->sSetupMode
|
|
= SSETUPMODE__SETUP_RED_GREEN_BLUE
|
|
| SSETUPMODE__SETUP_WB
|
|
;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
//
|
|
voodoo2->clipLeftRight
|
|
= CLIPLEFTRIGHT__RIGHT(800)
|
|
| CLIPLEFTRIGHT__LEFT(0);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->clipLowYHighY
|
|
= CLIPLOWYHIGHY__HIGH_Y(600)
|
|
| CLIPLOWYHIGHY__LOW_Y(0);
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->color1 = 0xff008080;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->zaColor
|
|
= ZACOLOR__DEPTH(0xffff)
|
|
| ZACOLOR__ALPHA(0xff)
|
|
;
|
|
|
|
for (int i = 0; i < 601; i++) {
|
|
/*
|
|
volatile uint16_t * framebuffer
|
|
= (volatile uint16_t * )(((ptrdiff_t)resource0_base) + 0x0400000);
|
|
|
|
for (int i = 0; i < 1024 * 800 * 2 / 2; i++) {
|
|
framebuffer[i] = 0;
|
|
}
|
|
wait_graphics_busy(voodoo2);
|
|
*/
|
|
|
|
voodoo2->fastfillCMD = 0;
|
|
wait_graphics_busy2(voodoo2);
|
|
|
|
for (int face_ix = 0; face_ix < cube_faces_length; face_ix++) {
|
|
int ia = cube_faces[face_ix].a;
|
|
int ib = cube_faces[face_ix].b;
|
|
int ic = cube_faces[face_ix].c;
|
|
|
|
vec3 va = vertex_screen_space(
|
|
vertex_perspective_divide(
|
|
vertex_rotate(cube_vertex_position[ia])));
|
|
|
|
vec3 vb = vertex_screen_space(
|
|
vertex_perspective_divide(
|
|
vertex_rotate(cube_vertex_position[ib])));
|
|
|
|
vec3 vc = vertex_screen_space(
|
|
vertex_perspective_divide(
|
|
vertex_rotate(cube_vertex_position[ic])));
|
|
|
|
uint32_t va_color = cube_vertex_color[ia];
|
|
uint32_t vb_color = cube_vertex_color[ib];
|
|
uint32_t vc_color = cube_vertex_color[ic];
|
|
|
|
voodoo2->sVx = va.x;
|
|
voodoo2->sVy = va.y;
|
|
voodoo2->sWb = va.z;
|
|
voodoo2->sARGB = va_color;
|
|
voodoo2->sBeginTriCMD = 1;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->sVx = vb.x;
|
|
voodoo2->sVy = vb.y;
|
|
voodoo2->sWb = vb.z;
|
|
voodoo2->sARGB = vb_color;
|
|
voodoo2->sDrawTriCMD = 1;
|
|
wait_graphics_busy(voodoo2);
|
|
|
|
voodoo2->sVx = vc.x;
|
|
voodoo2->sVy = vc.y;
|
|
voodoo2->sWb = vc.z;
|
|
voodoo2->sARGB = vc_color;
|
|
voodoo2->sDrawTriCMD = 1;
|
|
wait_graphics_busy(voodoo2);
|
|
}
|
|
|
|
// swap front/back buffers
|
|
voodoo2->swapbufferCMD = 1;
|
|
//wait_graphics_busy(voodoo2);
|
|
//asdf
|
|
|
|
while (voodoo2->status & STATUS__SWAP_BUFFERS_PENDING(0x7));
|
|
|
|
theta += 0.01f;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// cleanup
|
|
////////////////////////////////////////////////////////////////////////
|
|
close(config_fd);
|
|
close(resource0_fd);
|
|
|
|
return 0;
|
|
}
|