diff --git a/Makefile b/Makefile index 34b7699..12c1583 100644 --- a/Makefile +++ b/Makefile @@ -5,4 +5,4 @@ python gen/rgb_txt.py $< > $@ main: main.c bear.rgb565.inc panda.rgb565.inc - gcc -g -Og -std=c23 $< -o $@ + gcc -g -Og -lm -std=gnu23 $< -o $@ diff --git a/main.c b/main.c index b55e125..20bbb2d 100644 --- a/main.c +++ b/main.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "voodoo2.h" #include "voodoo2_bits.h" @@ -16,7 +17,27 @@ static inline bool _wait_graphics_busy(voodoo2_reg * voodoo2) { int cnt = 0; - for (int i = 0; i < 4096; i++) { + 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 { @@ -28,7 +49,7 @@ static inline bool _wait_graphics_busy(voodoo2_reg * voodoo2) return false; } -#define wait_graphics_busy(voodoo2) assert(_wait_graphics_busy(voodoo2)); +#define wait_graphics_busy2(voodoo2) assert(_wait_graphics_busy2(voodoo2)); static inline void dac_data_read(voodoo2_reg * voodoo2, int data, @@ -137,6 +158,93 @@ void write_fd_u32(int fd, uint32_t offset, uint32_t value) 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"; @@ -180,6 +288,8 @@ int main() int init_enable; + goto draw; + //////////////////////////////////////////////////////////////////////// // reset //////////////////////////////////////////////////////////////////////// @@ -283,6 +393,7 @@ int main() | 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) ; @@ -360,6 +471,7 @@ int main() wait_graphics_busy(voodoo2); if (0) { + /* static const uint16_t panda[] __attribute__((aligned(4))) = { #include "panda.rgb565.inc" }; @@ -388,23 +500,123 @@ int main() } 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) ; - voodoo2->sBeginTriCMD = 1; + for (int i = 0; i < 601; i++) { + /* + volatile uint16_t * framebuffer + = (volatile uint16_t * )(((ptrdiff_t)resource0_base) + 0x0400000); - voodoo2->sVx = 10; - voodoo2->sVy = 10; - voodoo2->sVy = 10; + for (int i = 0; i < 1024 * 800 * 2 / 2; i++) { + framebuffer[i] = 0; + } + wait_graphics_busy(voodoo2); + */ - voodoo2->sDrawTriCMD = 1; + 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