#include "gpu.h" #include "Bus.h" #include Bus* bus; gpu::gpu() { debug = false; } void connectBus(Bus* _bus) { bus = _bus; } #define LOG #undef LOG inline void gpu::debug_printf(const char* fmt, ...) { #ifdef LOG if (debug) { std::va_list args; va_start(args, fmt); std::vprintf(fmt, args); va_end(args); } #endif } uint32_t gpu::get_status() { uint32_t status = 0b01011110100000000000000000000000; status |= page_base_x << 0; status |= page_base_y << 3; status |= texture_disable << 15; status |= interlace << 31; return status; } void gpu::InitGL() { //WriteBuffer.reserve(1024 * 512); //WriteBuffer.clear(); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO); glGenFramebuffers(1, &FBO); glBindFramebuffer(GL_FRAMEBUFFER, FBO); glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 480, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0); //glBindFramebuffer(GL_FRAMEBUFFER, oldFBO); GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, DrawBuffers); VertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(VertexShader, 1, &VertexShaderSource, NULL); glCompileShader(VertexShader); int success; char InfoLog[512]; glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(VertexShader, 512, NULL, InfoLog); std::cout << "Vertex shader compilation failed\n" << InfoLog << std::endl; } FragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(FragmentShader, 1, &FragmentShaderSource, NULL); glCompileShader(FragmentShader); glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(FragmentShader, 512, NULL, InfoLog); std::cout << "Fragment shader compilation failed\n" << InfoLog << std::endl; } ShaderProgram = glCreateProgram(); glAttachShader(ShaderProgram, VertexShader); glAttachShader(ShaderProgram, FragmentShader); glLinkProgram(ShaderProgram); glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(ShaderProgram, 512, NULL, InfoLog); std::cout << "Linking shader program failed\n" << InfoLog << std::endl; } VertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(VertexShader, 1, &TextureVertexShaderSource, NULL); glCompileShader(VertexShader); glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(VertexShader, 512, NULL, InfoLog); std::cout << "Vertex shader compilation failed\n" << InfoLog << std::endl; } FragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(FragmentShader, 1, &TextureFragmentShaderSource, NULL); glCompileShader(FragmentShader); glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(FragmentShader, 512, NULL, InfoLog); std::cout << "Fragment shader compilation failed\n" << InfoLog << std::endl; } TextureShaderProgram = glCreateProgram(); glAttachShader(TextureShaderProgram, VertexShader); glAttachShader(TextureShaderProgram, FragmentShader); glLinkProgram(TextureShaderProgram); glGetProgramiv(TextureShaderProgram, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(TextureShaderProgram, 512, NULL, InfoLog); std::cout << "Linking shader program failed\n" << InfoLog << std::endl; } glGenVertexArrays(1, &VAO); glGenVertexArrays(1, &TextureVAO); glGenBuffers(1, &VBO); glGenBuffers(1, &TextureVBO); glGenTextures(1, &VramTexture); glBindTexture(GL_TEXTURE_2D, VramTexture); //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1024 * scaling_factor, 512 * scaling_factor); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, VramTexture, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 2); glPixelStorei(GL_PACK_ALIGNMENT, 2); glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT); glGenTextures(1, &SampleVramTexture); glBindTexture(GL_TEXTURE_2D, SampleVramTexture); //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1024 * scaling_factor, 512 * scaling_factor); glGenFramebuffers(1, &tempFBO); glBindFramebuffer(GL_FRAMEBUFFER, tempFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, SampleVramTexture, 0); glBindFramebuffer(GL_FRAMEBUFFER, oldFBO); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, vram8); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, vram4); // Initialize VAO for untextured polygons glBindBuffer(GL_ARRAY_BUFFER, VBO); glBindVertexArray(VAO); glVertexAttribIPointer(0, 3, GL_INT, 3 * sizeof(uint32_t), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_UNSIGNED_INT, GL_FALSE, 3 * sizeof(uint32_t), (void*)(9 * sizeof(uint32_t))); glEnableVertexAttribArray(1); // Initialize VAO for textured polygons glBindBuffer(GL_ARRAY_BUFFER, TextureVBO); glBindVertexArray(TextureVAO); // Position attribute glVertexAttribPointer(0, 3, GL_INT, GL_FALSE, 13 * sizeof(int32_t), (void*)0); glEnableVertexAttribArray(0); // Colour attribute glVertexAttribPointer(1, 3, GL_UNSIGNED_INT, GL_FALSE, 13 * sizeof(uint32_t), (void*)(3 * sizeof(uint32_t))); glEnableVertexAttribArray(1); // texture coord attribute glVertexAttribPointer(2, 2, GL_UNSIGNED_INT, GL_FALSE, 13 * sizeof(uint32_t), (void*)(6 * sizeof(uint32_t))); glEnableVertexAttribArray(2); // texpage attribute glVertexAttribPointer(3, 2, GL_UNSIGNED_INT, GL_FALSE, 13 * sizeof(uint32_t), (void*)(8 * sizeof(uint32_t))); glEnableVertexAttribArray(3); // clut attribute glVertexAttribPointer(4, 2, GL_UNSIGNED_INT, GL_FALSE, 13 * sizeof(uint32_t), (void*)(10 * sizeof(uint32_t))); glEnableVertexAttribArray(4); // colour depth attribute glVertexAttribPointer(5, 1, GL_UNSIGNED_INT, GL_FALSE, 13 * sizeof(uint32_t), (void*)(12 * sizeof(uint32_t))); glEnableVertexAttribArray(5); } void gpu::SyncVRAM() { glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1024 * scaling_factor, 512 * scaling_factor); } void gpu::SetOpenGLState() { glViewport(0, 0, 1024 * scaling_factor, 512 * scaling_factor); glBindFramebuffer(GL_FRAMEBUFFER, FBO); glScissor(drawing_topleft_x * scaling_factor, drawing_topleft_y * scaling_factor, (drawing_bottomright_x - drawing_topleft_x) * scaling_factor, (drawing_bottomright_y - drawing_topleft_y) * scaling_factor); glEnable(GL_SCISSOR_TEST); if (DrawingTextured) { glBindBuffer(GL_ARRAY_BUFFER, TextureVBO); glBindVertexArray(TextureVAO); glUseProgram(TextureShaderProgram); } else { glBindBuffer(GL_ARRAY_BUFFER, VBO); glBindVertexArray(VAO); glUseProgram(ShaderProgram); } } void gpu::SwitchToTextured() { if (!DrawingTextured) { DrawingTextured = true; glBindBuffer(GL_ARRAY_BUFFER, TextureVBO); glBindVertexArray(TextureVAO); glUseProgram(TextureShaderProgram); } } void gpu::SwitchToUntextured() { if (DrawingTextured) { DrawingTextured = false; glBindBuffer(GL_ARRAY_BUFFER, VBO); glBindVertexArray(VAO); glUseProgram(ShaderProgram); } } void gpu::putpixel(point v1, uint32_t colour) { // TODO: OpenGL implementation uint32_t a = (colour >> 15) & 1; uint32_t b = (colour >> 10) & 0b11111; uint32_t g = (colour >> 5) & 0b11111; uint32_t r = colour & 0b11111; uint32_t rgba = ((r << 3) << 24) | ((g << 3) << 16) | ((b << 3) << 8) | 0xff; vram_rgb[(v1.y + ypos) * 1024 + (v1.x + xpos)] = rgba; } void gpu::ClearScreen() { glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); } void gpu::execute_gp0(uint32_t command) { uint8_t instr = (command >> 24) & 0xff; if (cmd_left == 0) { cmd_length = 0; switch (instr) { case 0x04: case 0x08: case 0x0c: case 0x10: case 0x14: case 0x18: case 0x1c: case 0x1d: case 0x00: // nop debug_printf("[GP0] NOP (0x%x)\n", command); break; case 0x01: { // Clear Cache SyncVRAM(); debug_printf("[GP0] Clear Cache\n"); break; } case 0x02: { // Fill rectangle in VRAM fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0x21: case 0x20: { // Monochrome three-point polygon, opaque fifo[0] = command; cmd_length++; cmd_left = 3; break; } case 0x23: case 0x22: { // Monochrome three-point polygon, semi-transparent fifo[0] = command; cmd_length++; cmd_left = 3; break; } case 0x29: case 0x28: { // Monochrome four-point polygon, opaque fifo[0] = command; cmd_length++; cmd_left = 4; break; } case 0x26: case 0x24: { // Textured three-point polygon, opaque, texture-blending fifo[0] = command; cmd_length++; cmd_left = 6; break; } case 0x25: { // Textured three-point polygon, opaque, raw-texture fifo[0] = command; cmd_length++; cmd_left = 6; break; } case 0x2B: case 0x2A: { // Monochrome four-point polygon, semi-transparent fifo[0] = command; cmd_length++; cmd_left = 4; break; } case 0x2C: { // Textured four-point polygon, opaque, texture-blending fifo[0] = command; cmd_length++; cmd_left = 8; break; } case 0x2D: { // Textured four-point polygon, opaque, raw-texture fifo[0] = command; cmd_length++; cmd_left = 8; break; } case 0x2E: { // Textured four-point polygon, semi-transparent, texture-blending cmd_length++; cmd_left = 8; break; } case 0x2F: { // Textured four-point polygon, semi-transparent, raw-texture fifo[0] = command; cmd_length++; cmd_left = 8; break; } case 0x30: { // Shaded three-point polygon, opaque fifo[0] = command; cmd_length++; cmd_left = 5; break; } case 0x33: case 0x32: { // Shaded three-point polygon, semi-transparent fifo[0] = command; cmd_length++; cmd_left = 5; break; } case 0x36: // Shaded Textured three-point polygon, semi-transparent, tex-blend case 0x34: { // Shaded Textured three-point polygon, opaque, texture-blending fifo[0] = command; cmd_length++; cmd_left = 8; break; } case 0x38: { // Shaded four-point polygon, opaque fifo[0] = command; cmd_length++; cmd_left = 7; break; } case 0x3c: { // Shaded Textured four-point polygon, opaque, texture-blending fifo[0] = command; cmd_length++; cmd_left = 11; break; } case 0x3e: { // Shaded Textured four-point polygon, semi-transparent, texture-blending fifo[0] = command; cmd_length++; cmd_left = 11; break; } //case 0x41: case 0x40: { // Monochrome line, opaque fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0x3B: case 0x3A: { // Shaded four-point polygon, semi-transparent fifo[0] = command; cmd_length++; cmd_left = 7; break; } case 0x4c: case 0x58: case 0x42: case 0x48: { // Monochrome Poly-line, opaque //abort(); fifo[0] = command; cmd_length++; cmd_left = 1; gp0_mode = 2; break; } case 0x52: { // Shaded line, semi-transparent fifo[0] = command; cmd_length++; cmd_left = 3; break; } case 0x60: { // Monochrome Rectangle (variable size) (opaque) fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0x63: case 0x62: { // Monochrome Rectangle (variable size) (semi-transparent) fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0x64: { // Textured Rectangle, variable size, opaque, texture-blending fifo[0] = command; cmd_length++; cmd_left = 3; break; } case 0x65: { // Textured Rectangle, variable size, opaque, raw-texture fifo[0] = command; cmd_length++; cmd_left = 3; break; } case 0x66: { // Textured Rectangle, variable size, semi-transp, texture-blending fifo[0] = command; cmd_length++; cmd_left = 3; break; } case 0x67: { // Textured Rectangle, variable size, semi-transp, raw-texture fifo[0] = command; cmd_length++; cmd_left = 3; break; } case 0x68: { // 1x1 Opaque Monochrome Rectangle fifo[0] = command; cmd_length++; cmd_left = 1; break; } case 0x70: { // Monochrome Rectangle (8x8) (opaque) fifo[0] = command; cmd_length++; cmd_left = 1; break; } case 0x76: case 0x74: { // Textured Rectangle, 8x8, opaque, texture-blending fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0x75: { // Textured Rectangle, 8x8, opaque, raw-texture fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0x78: { // Monochrome Rectangle (16x16) (opaque) fifo[0] = command; cmd_length++; cmd_left = 1; break; } case 0x7C: { // Textured Rectangle, 16x16, opaque, texture-blending fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0x7D: { // Textured Rectangle, 16x16, opaque, raw-texture fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0x7E: // Textured Rectangle, 16x16, semi-transparent, texture-blending case 0x7F: { // Textured Rectangle, 16x16, semi-transparent, raw-texture fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0x80: { // Copy Rectangle (VRAM to VRAM) fifo[0] = command; cmd_length++; cmd_left = 3; break; } case 0xA0: { // Copy rectangle CPU to VRAM fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0xC0: { // Copy rectangle VRAM to CPU debug_printf("[GP0] Copy Rectangle (VRAM to CPU)\n"); fifo[0] = command; cmd_length++; cmd_left = 2; break; } case 0xE1: { // Draw Mode Setting debug_printf("[GP0] Draw Mode Setting\n"); page_base_x = command & 0xf; page_base_y = (command >> 4) & 1; semi_transparency = (command >> 5) & 3; texture_depth = (command >> 7) & 3; dithering = ((command >> 9) & 1) != 0; allow_display_drawing = ((command >> 10) & 1) != 0; texpage_raw = command & 0xffff; texture_disable = (command & (1 << 11)); // rectangle x flip // rectangle y flip break; } case 0xE2: { // Set Texture Window int texWindow = command & 0xfffff; glUseProgram(TextureShaderProgram); int maskUniformLocation = glGetUniformLocation(TextureShaderProgram, "texWindow"); int texWindowX = texWindow & 0x1f; int texWindowY = (texWindow >> 5) & 0x1f; int texWindowOffsX = (texWindow >> 10) & 0x1f; int texWindowOffsY = (texWindow >> 15) & 0x1f; glUniform4i(maskUniformLocation, ~(texWindowX * 8), ~(texWindowY * 8), ((texWindowOffsX & texWindowX) * 8), ((texWindowOffsY & texWindowY) * 8)); if (!DrawingTextured) glUseProgram(ShaderProgram); debug_printf("[GP0] Set Texture Window\n"); break; } case 0xE3: { // Set Drawing Area top left drawing_topleft_x = command & 1023; drawing_topleft_y = (command >> 10) & 511; debug_printf("[GP0] Set Drawing Area top left\n"); glScissor(drawing_topleft_x * scaling_factor, drawing_topleft_y * scaling_factor, (drawing_bottomright_x - drawing_topleft_x) * scaling_factor, (drawing_bottomright_y - drawing_topleft_y) * scaling_factor); break; } case 0xE4: { // Set Drawing Area bottom right drawing_bottomright_x = command & 1023; drawing_bottomright_y = (command >> 10) & 511; debug_printf("[GP0] Set Drawing Area bottom right\n"); glScissor(drawing_topleft_x * scaling_factor, drawing_topleft_y * scaling_factor, (drawing_bottomright_x - drawing_topleft_x) * scaling_factor, (drawing_bottomright_y - drawing_topleft_y) * scaling_factor); break; } case 0xE5: { // Set Drawing Area Offset xoffset = (command & 0b1111111111); yoffset = ((command >> 11) & 0b1111111111); int offsetUniformLocation = glGetUniformLocation(ShaderProgram, "offset"); glUseProgram(ShaderProgram); glUniform3f(offsetUniformLocation, xoffset, yoffset, 0); offsetUniformLocation = glGetUniformLocation(TextureShaderProgram, "offset"); glUseProgram(TextureShaderProgram); glUniform3f(offsetUniformLocation, xoffset, yoffset, 0); if (!DrawingTextured) glUseProgram(ShaderProgram); debug_printf("[GP0] Set Drawing Area Offset\n"); break; } case 0xE6: { // Set Mask Bit Setting debug_printf("[GP0] Set Mask Bit Setting\n"); mask_bit = (command & 1) != 0; disallow_masked_pixels_drawing = (command & 2) != 0; break; } default: printf("\n[GP0] Unknown GP0 command: 0x%x (0x%x)\n", instr, command); //abort(); } } else { cmd_left--; switch (gp0_mode) { case 0: { // command mode fifo[cmd_length++] = command; if (cmd_left == 0) { // all the parameters are in, run command switch ((fifo[0] >> 24) & 0xff) { case 0x02: gpu::fill_rectangle(); break; case 0x21: case 0x20: SwitchToUntextured(); gpu::draw_untextured_tri(MONOCHROME, SOLID); break; case 0x23: case 0x22: SwitchToUntextured(); gpu::draw_untextured_tri(MONOCHROME, SEMI_TRANSPARENT); break; case 0x26: case 0x24: SwitchToTextured(); gpu::texture_blending_three_point_opaque_polygon(); break; case 0x25: SwitchToTextured(); gpu::texture_three_point_opaque_polygon(); break; case 0x29: case 0x28: SwitchToUntextured(); gpu::draw_untextured_quad(MONOCHROME, SOLID); break; case 0x2B: case 0x2A: SwitchToUntextured(); gpu::draw_untextured_quad(MONOCHROME, SEMI_TRANSPARENT); break; case 0x2C: SwitchToTextured(); gpu::texture_blending_four_point_opaque_polygon(); break; case 0x2D: SwitchToTextured(); gpu::texture_four_point_opaque_polygon(); break; case 0x2E: SwitchToTextured(); gpu::texture_blending_four_point_polygon_semi_transparent(); break; case 0x2F: SwitchToTextured(); gpu::texture_four_point_semi_transparent_polygon(); break; case 0x30: SwitchToUntextured(); gpu::draw_untextured_tri(GOURAUD, SOLID); break; case 0x33: case 0x32: SwitchToUntextured(); gpu::draw_untextured_tri(GOURAUD, SEMI_TRANSPARENT); break; case 0x36: case 0x34: SwitchToTextured(); gpu::shaded_texture_blending_three_point_opaque_polygon(); break; case 0x38: SwitchToUntextured(); gpu::draw_untextured_quad(GOURAUD, SOLID); break; case 0x3B: case 0x3A: SwitchToUntextured(); gpu::draw_untextured_quad(GOURAUD, SEMI_TRANSPARENT); break; case 0x3C: SwitchToTextured(); gpu::shaded_texture_blending_textured_four_point_opaque_polygon(); break; case 0x3E: SwitchToTextured(); gpu::shaded_texture_blending_textured_four_point_semi_transparent_polygon(); break; case 0x41: case 0x40: gpu::monochrome_line_opaque(); break; case 0x52: SwitchToUntextured(); gpu::shaded_line_semi_transparent(); break; case 0x60: SwitchToUntextured(); gpu::monochrome_rectangle_variable_size_opaque(); break; case 0x63: case 0x62: SwitchToUntextured(); gpu::monochrome_rectangle_variable_size_semi_transparent(); break; case 0x64: SwitchToTextured(); gpu::texture_blending_rectangle_variable_size_opaque(); break; case 0x65: SwitchToTextured(); gpu::texture_rectangle_variable_size_opaque(); break; case 0x66: SwitchToTextured(); gpu::texture_blending_rectangle_variable_size_semi_transparent(); break; case 0x67: SwitchToTextured(); gpu::textured_rectangle_variable_size_semi_transparent(); break; case 0x68: SwitchToUntextured(); gpu::monochrome_rectangle_dot_opaque(); break; case 0x70: SwitchToUntextured(); gpu::monochrome_rectangle_8x8_opaque(); break; case 0x76: case 0x74: SwitchToTextured(); gpu::texture_blending_rectangle_8x8_opaque(); break; case 0x75: SwitchToTextured(); gpu::texture_rectangle_8x8_opaque(); break; case 0x78: SwitchToUntextured(); gpu::monochrome_rectangle_16x16_opaque(); break; case 0x7C: SwitchToTextured(); gpu::texture_blending_rectangle_16x16_opaque(); break; case 0x7D: SwitchToTextured(); gpu::texture_rectangle_16x16_opaque(); break; case 0x7E: case 0x7F: SwitchToTextured(); gpu::texture_rectangle_16x16_semi_transparent(); break; case 0x80: gpu::vram_to_vram(); break; case 0xA0: gpu::cpu_to_vram(); break; case 0xC0: gpu::vram_to_cpu(); break; //default: printf("\n%d", fifo[0] >> 24); abort(); } } break; } case 1: { // load mode debug_printf("[CPU to VRAM transfer] Data: 0x%x\n", command); uint32_t resolution = fifo[2]; uint32_t coords = fifo[1]; auto width = resolution & 0xffff; auto height = resolution >> 16; if (width == 0) width = 1024; if (height == 0) height = 512; width &= 0x3ff; height &= 0x1ff; auto x = coords & 0xffff; auto y = coords >> 16; const auto scaled_x = x * scaling_factor; const auto scaled_y = y * scaling_factor; const auto scaled_width = width * scaling_factor; const auto scaled_height = height * scaling_factor; if (cmd_left == 0) { gp0_mode = 0; if (scaling_factor == 1) { glBindTexture(GL_TEXTURE_2D, VramTexture); } else { glBindTexture(GL_TEXTURE_2D, SampleVramTexture); } glTexSubImage2D(GL_TEXTURE_2D, 0, scaled_x, scaled_y, width, height, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, &WriteBuffer[0]); for (int i = 0; i < (1024 * 512); i++) WriteBuffer[i] = 0; //WriteBuffer.clear(); WriteBufferCnt = 0; if (scaling_factor == 1) { SyncVRAM(); } else { glDisable(GL_SCISSOR_TEST); glBindFramebuffer(GL_READ_FRAMEBUFFER, tempFBO); glBlitFramebuffer(scaled_x, scaled_y, scaled_x + width, scaled_y + height, scaled_x, scaled_y, scaled_x + scaled_width, scaled_y + scaled_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); glEnable(GL_SCISSOR_TEST); glBindFramebuffer(GL_READ_FRAMEBUFFER, FBO); SyncVRAM(); } break; } //WriteBuffer.push_back(command); WriteBuffer[WriteBufferCnt++] = command; break; } case 2: { // polyline mode if (command == 0x50005000 || command == 0x55555555) { //monochrome_polyline_opaque(); cmd_length = 0; gp0_mode = 0; cmd_left = 0; for (int i = 0; i < 12; i++) fifo[i] = 0; return; } cmd_left += 2; //fifo[cmd_length++] = command; break; } } } } void gpu::update_hres() { display_area.width = (((x2 - x1) / width_divisor) + 2) & ~3; } void gpu::update_vres() { display_area.height = y2 - y1; if (interlacing) display_area.height *= 2; } void gpu::execute_gp1(uint32_t command) { uint8_t instr = (command >> 24) & 0xff; switch (instr) { case 0x0: { // reset gpu hres1 = 1; int res_divisors[] = { 10, 8, 5, 4 }; width_divisor = res_divisors[hres1]; // NTSC: 3413 video cycles per scanline x1 = 0x200; x2 = 0x200 + 256 * 10; y1 = 0x10; y2 = 0x10 + 240; update_hres(); update_vres(); debug_printf("[GP1] Reset Gpu\n"); break; } case 0x1: // reset command buffer debug_printf("[GP1] Reset Command Buffer\n"); break; case 0x4: { // set dma direction debug_printf("[GP1] Set DMA Direction to %d\n", command & 0b11); dma_direction = command & 0b11; break; } case 0x5: { // Start of Display area frame_counter++; display_area.origin.x = command & 0x3ff; display_area.origin.y = (command >> 10) & 0x1ff; update_hres(); update_vres(); break; } case 0x6: { // Horizontal Display range x1 = command & 0xfff; x2 = (command >> 12) & 0xfff; update_hres(); break; } case 0x7: { // Vertical Display range y1 = command & 0x3ff; y2 = (command >> 10) & 0x3ff; update_vres(); break; } case 0x8: { // Display mode hres1 = command & 3; vres = (command >> 2) & 1; video_mode = (command >> 3) & 1; interlacing = (command >> 5) & 1; hres2 = (command >> 6) & 1; int res_divisors[] = { 10, 8, 5, 4 }; width_divisor = res_divisors[hres1]; // NTSC: 3413 video cycles per scanline if (hres2) width_divisor = 7; update_hres(); update_vres(); break; } default: debug_printf("[GP1] Unknown GP1 command: 0x%x\n", instr); //exit(0); } } // commands void gpu::draw_untextured_tri(int shading, int transparency) { if (shading == MONOCHROME) { point v1, v2, v3; uint32_t colour = fifo[0] & 0xffffff; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = fifo[2] & 0xffff; v2.y = fifo[2] >> 16; v3.x = fifo[3] & 0xffff; v3.y = fifo[3] >> 16; uint32_t Vertices1[]{ v1.x, v1.y, 0.0, v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } else if (shading == GOURAUD) { point v1, v2, v3; v1.c = fifo[0] & 0xffffff; v2.c = fifo[2] & 0xffffff; v3.c = fifo[4] & 0xffffff; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = fifo[3] & 0xffff; v2.y = fifo[3] >> 16; v3.x = fifo[5] & 0xffff; v3.y = fifo[5] >> 16; uint32_t Vertices[]{ v1.x, v1.y, 0.0, v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, (((v1.c) >> 0) & 0xff), (((v1.c) >> 8) & 0xff), (((v1.c) >> 16) & 0xff), (((v2.c) >> 0) & 0xff), (((v2.c) >> 8) & 0xff), (((v2.c) >> 16) & 0xff), (((v3.c) >> 0) & 0xff), (((v3.c) >> 8) & 0xff), (((v3.c) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } } void gpu::draw_untextured_quad(int shading, int transparency) { if (shading == MONOCHROME) { uint32_t colour = fifo[0] & 0xffffff; point v1, v2, v3, v4; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = fifo[2] & 0xffff; v2.y = fifo[2] >> 16; v3.x = fifo[3] & 0xffff; v3.y = fifo[3] >> 16; v4.x = fifo[4] & 0xffff; v4.y = fifo[4] >> 16; uint32_t Vertices1[]{ v1.x, v1.y, 0, v2.x, v2.y, 0, v3.x, v3.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[]{ v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, v4.x, v4.y, 0.0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } else if (shading == GOURAUD) { point v1, v2, v3, v4; v1.c = fifo[0] & 0xffffff; v2.c = fifo[2] & 0xffffff; v3.c = fifo[4] & 0xffffff; v4.c = fifo[6] & 0xffffff; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = fifo[3] & 0xffff; v2.y = fifo[3] >> 16; v3.x = fifo[5] & 0xffff; v3.y = fifo[5] >> 16; v4.x = fifo[7] & 0xffff; v4.y = fifo[7] >> 16; uint32_t Vertices1[]{ v1.x, v1.y, 0.0, v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, (((v1.c) >> 0) & 0xff), (((v1.c) >> 8) & 0xff), (((v1.c) >> 16) & 0xff), (((v2.c) >> 0) & 0xff), (((v2.c) >> 8) & 0xff), (((v2.c) >> 16) & 0xff), (((v3.c) >> 0) & 0xff), (((v3.c) >> 8) & 0xff), (((v3.c) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[]{ v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, v4.x, v4.y, 0.0, (((v2.c) >> 0) & 0xff), (((v2.c) >> 8) & 0xff), (((v2.c) >> 16) & 0xff), (((v3.c) >> 0) & 0xff), (((v3.c) >> 8) & 0xff), (((v3.c) >> 16) & 0xff), (((v4.c) >> 0) & 0xff), (((v4.c) >> 8) & 0xff), (((v4.c) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } } void gpu::texture_blending_three_point_opaque_polygon() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured three-point polygon, opaque, texture-blending (colour: 0x%x)\n", colour); point v1, v2, v3, v4; uint16_t texpage = 0; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; //printf("\nclut: 0x%x\n", clut); uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); texpage = fifo[4] >> 16; //printf("texpage: 0x%x\n", texpage); uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = fifo[3] & 0xffff; v2.y = fifo[3] >> 16; v3.x = fifo[5] & 0xffff; v3.y = fifo[5] >> 16; v4.x = fifo[7] & 0xffff; v4.y = fifo[7] >> 16; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = (fifo[4] & 0xffff) & 0xff; t2.y = ((fifo[4] & 0xffff) >> 8) & 0xff; t3.x = (fifo[6] & 0xffff) & 0xff; t3.y = ((fifo[6] & 0xffff) >> 8) & 0xff; t4.x = (fifo[8] & 0xffff) & 0xff; t4.y = ((fifo[8] & 0xffff) >> 8) & 0xff; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_three_point_opaque_polygon() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured three-point polygon, opaque, raw-texture (colour: 0x%x)\n", colour); point v1, v2, v3, v4; uint16_t texpage = 0; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; //printf("\nclut: 0x%x\n", clut); uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); texpage = fifo[4] >> 16; //printf("texpage: 0x%x\n", texpage); uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = fifo[3] & 0xffff; v2.y = fifo[3] >> 16; v3.x = fifo[5] & 0xffff; v3.y = fifo[5] >> 16; v4.x = fifo[7] & 0xffff; v4.y = fifo[7] >> 16; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = (fifo[4] & 0xffff) & 0xff; t2.y = ((fifo[4] & 0xffff) >> 8) & 0xff; t3.x = (fifo[6] & 0xffff) & 0xff; t3.y = ((fifo[6] & 0xffff) >> 8) & 0xff; t4.x = (fifo[8] & 0xffff) & 0xff; t4.y = ((fifo[8] & 0xffff) >> 8) & 0xff; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, 128, 128, 128, t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_blending_four_point_opaque_polygon() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured four-point polygon, opaque, texture blending (colour: 0x%x)\n", colour); point v1, v2, v3, v4; uint16_t texpage = 0; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; //printf("\nclut: 0x%x\n", clut); uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); texpage = fifo[4] >> 16; //printf("texpage: 0x%x\n", texpage); uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = fifo[3] & 0xffff; v2.y = fifo[3] >> 16; v3.x = fifo[5] & 0xffff; v3.y = fifo[5] >> 16; v4.x = fifo[7] & 0xffff; v4.y = fifo[7] >> 16; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = (fifo[4] & 0xffff) & 0xff; t2.y = ((fifo[4] & 0xffff) >> 8) & 0xff; t3.x = (fifo[6] & 0xffff) & 0xff; t3.y = ((fifo[6] & 0xffff) >> 8) & 0xff; t4.x = (fifo[8] & 0xffff) & 0xff; t4.y = ((fifo[8] & 0xffff) >> 8) & 0xff; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_four_point_opaque_polygon() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured four-point polygon, opaque, raw textures (colour: 0x%x)\n", colour); point v1, v2, v3, v4; uint16_t texpage = 0; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = fifo[3] & 0xffff; v2.y = fifo[3] >> 16; v3.x = fifo[5] & 0xffff; v3.y = fifo[5] >> 16; v4.x = fifo[7] & 0xffff; v4.y = fifo[7] >> 16; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = (fifo[4] & 0xffff) & 0xff; t2.y = ((fifo[4] & 0xffff) >> 8) & 0xff; t3.x = (fifo[6] & 0xffff) & 0xff; t3.y = ((fifo[6] & 0xffff) >> 8) & 0xff; t4.x = (fifo[8] & 0xffff) & 0xff; t4.y = ((fifo[8] & 0xffff) >> 8) & 0xff; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, 128, 128, 128, t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, 128, 128, 128, t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_blending_four_point_polygon_semi_transparent() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured four-point polygon, semi-transparent, texture-blending (colour: 0x%x)\n", colour); point v1, v2, v3, v4; uint16_t texpage = 0; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = fifo[3] & 0xffff; v2.y = fifo[3] >> 16; v3.x = fifo[5] & 0xffff; v3.y = fifo[5] >> 16; v4.x = fifo[7] & 0xffff; v4.y = fifo[7] >> 16; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = (fifo[4] & 0xffff) & 0xff; t2.y = ((fifo[4] & 0xffff) >> 8) & 0xff; t3.x = (fifo[6] & 0xffff) & 0xff; t3.y = ((fifo[6] & 0xffff) >> 8) & 0xff; t4.x = (fifo[8] & 0xffff) & 0xff; t4.y = ((fifo[8] & 0xffff) >> 8) & 0xff; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_four_point_semi_transparent_polygon() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured four-point polygon, semi-transparent, raw-texture\n", colour); point v1, v2, v3, v4; uint16_t texpage = 0; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = fifo[3] & 0xffff; v2.y = fifo[3] >> 16; v3.x = fifo[5] & 0xffff; v3.y = fifo[5] >> 16; v4.x = fifo[7] & 0xffff; v4.y = fifo[7] >> 16; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = (fifo[4] & 0xffff) & 0xff; t2.y = ((fifo[4] & 0xffff) >> 8) & 0xff; t3.x = (fifo[6] & 0xffff) & 0xff; t3.y = ((fifo[6] & 0xffff) >> 8) & 0xff; t4.x = (fifo[8] & 0xffff) & 0xff; t4.y = ((fifo[8] & 0xffff) >> 8) & 0xff; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, 128, 128, 128, t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, 128, 128, 128, t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::shaded_texture_blending_three_point_opaque_polygon() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured four-point polygon, opaque, raw textures (colour: 0x%x)\n", colour); point v1, v2, v3; uint16_t texpage = 0; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); texpage = fifo[5] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = fifo[4] & 0xffff; v2.y = fifo[4] >> 16; v3.x = fifo[7] & 0xffff; v3.y = fifo[7] >> 16; v1.c = fifo[0] & 0xffffff; v2.c = fifo[3] & 0xffffff; v3.c = fifo[6] & 0xffffff; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = (fifo[5] & 0xffff) & 0xff; t2.y = ((fifo[5] & 0xffff) >> 8) & 0xff; t3.x = (fifo[8] & 0xffff) & 0xff; t3.y = ((fifo[8] & 0xffff) >> 8) & 0xff; t4.x = (fifo[11] & 0xffff) & 0xff; t4.y = ((fifo[11] & 0xffff) >> 8) & 0xff; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((v1.c) >> 0) & 0xff), (((v1.c) >> 8) & 0xff), (((v1.c) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((v2.c) >> 0) & 0xff), (((v2.c) >> 8) & 0xff), (((v2.c) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((v3.c) >> 0) & 0xff), (((v3.c) >> 8) & 0xff), (((v3.c) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::shaded_texture_blending_textured_four_point_opaque_polygon() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured four-point polygon, opaque, raw textures (colour: 0x%x)\n", colour); point v1, v2, v3, v4; uint16_t texpage = 0; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); texpage = fifo[5] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = fifo[4] & 0xffff; v2.y = fifo[4] >> 16; v3.x = fifo[7] & 0xffff; v3.y = fifo[7] >> 16; v4.x = fifo[10] & 0xffff; v4.y = fifo[10] >> 16; v1.c = fifo[0] & 0xffffff; v2.c = fifo[3] & 0xffffff; v3.c = fifo[6] & 0xffffff; v4.c = fifo[9] & 0xffffff; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = (fifo[5] & 0xffff) & 0xff; t2.y = ((fifo[5] & 0xffff) >> 8) & 0xff; t3.x = (fifo[8] & 0xffff) & 0xff; t3.y = ((fifo[8] & 0xffff) >> 8) & 0xff; t4.x = (fifo[11] & 0xffff) & 0xff; t4.y = ((fifo[11] & 0xffff) >> 8) & 0xff; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((v1.c) >> 0) & 0xff), (((v1.c) >> 8) & 0xff), (((v1.c) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((v2.c) >> 0) & 0xff), (((v2.c) >> 8) & 0xff), (((v2.c) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((v3.c) >> 0) & 0xff), (((v3.c) >> 8) & 0xff), (((v3.c) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, (((v2.c) >> 0) & 0xff), (((v2.c) >> 8) & 0xff), (((v2.c) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((v3.c) >> 0) & 0xff), (((v3.c) >> 8) & 0xff), (((v3.c) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, (((v4.c) >> 0) & 0xff), (((v4.c) >> 8) & 0xff), (((v4.c) >> 16) & 0xff), t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::shaded_texture_blending_textured_four_point_semi_transparent_polygon() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured four-point polygon, opaque, raw textures (colour: 0x%x)\n", colour); point v1, v2, v3, v4; uint16_t texpage = 0; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); texpage = fifo[5] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = fifo[4] & 0xffff; v2.y = fifo[4] >> 16; v3.x = fifo[7] & 0xffff; v3.y = fifo[7] >> 16; v4.x = fifo[10] & 0xffff; v4.y = fifo[10] >> 16; v1.c = fifo[0] & 0xffffff; v2.c = fifo[3] & 0xffffff; v3.c = fifo[6] & 0xffffff; v4.c = fifo[9] & 0xffffff; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = (fifo[5] & 0xffff) & 0xff; t2.y = ((fifo[5] & 0xffff) >> 8) & 0xff; t3.x = (fifo[8] & 0xffff) & 0xff; t3.y = ((fifo[8] & 0xffff) >> 8) & 0xff; t4.x = (fifo[11] & 0xffff) & 0xff; t4.y = ((fifo[11] & 0xffff) >> 8) & 0xff; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((v1.c) >> 0) & 0xff), (((v1.c) >> 8) & 0xff), (((v1.c) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((v2.c) >> 0) & 0xff), (((v2.c) >> 8) & 0xff), (((v2.c) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((v3.c) >> 0) & 0xff), (((v3.c) >> 8) & 0xff), (((v3.c) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, (((v2.c) >> 0) & 0xff), (((v2.c) >> 8) & 0xff), (((v2.c) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((v3.c) >> 0) & 0xff), (((v3.c) >> 8) & 0xff), (((v3.c) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, (((v4.c) >> 0) & 0xff), (((v4.c) >> 8) & 0xff), (((v4.c) >> 16) & 0xff), t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::monochrome_line_opaque() { point v1, v2; uint32_t colour = fifo[0] & 0xffffff; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = fifo[2] & 0xffff; v2.y = fifo[2] >> 16; uint32_t Vertices1[]{ v1.x, v1.y, 0.0, v2.x, v2.y, 0.0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glDrawArrays(GL_LINES, 0, 2); } void gpu::shaded_line_semi_transparent() { point v1, v2; v1.c = fifo[0] & 0xffffff; v2.c = fifo[2] & 0xffffff; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = fifo[3] & 0xffff; v2.y = fifo[3] >> 16; uint32_t Vertices[]{ v1.x, v1.y, 0.0, v2.x, v2.y, 0.0, (((v1.c) >> 0) & 0xff), (((v1.c) >> 8) & 0xff), (((v1.c) >> 16) & 0xff), (((v2.c) >> 0) & 0xff), (((v2.c) >> 8) & 0xff), (((v2.c) >> 16) & 0xff), }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); glDrawArrays(GL_LINES, 0, 2); } void gpu::monochrome_polyline_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Monochrome four-point polygon, opaque (colour: 0x%x)\n", colour); point v1, v2, v3, v4, v5, v6; /*for (int i = 1; i < cmd_length; i++) { v1.x = fifo[i] & 0xffff; v1.y = fifo[i] >> 16; v2.x = fifo[i+1] & 0xffff; v2.y = fifo[i+1] >> 16; uint32_t Vertices1[]{ v1.x, v1.y, 0, v2.x, v2.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glBindVertexArray(VAO); glVertexAttribPointer(0, 2, GL_UNSIGNED_INT, GL_FALSE, 3 * sizeof(uint32_t), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_UNSIGNED_INT, GL_FALSE, 3 * sizeof(uint32_t), (void*)(6 * sizeof(uint32_t))); glEnableVertexAttribArray(1); glUseProgram(ShaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_LINE, 0, 3); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); }*/ v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = fifo[2] & 0xffff; v2.y = fifo[2] >> 16; v3.x = fifo[3] & 0xffff; v3.y = fifo[3] >> 16; v4.x = fifo[4] & 0xffff; v4.y = fifo[4] >> 16; v5.x = fifo[5] & 0xffff; v5.y = fifo[5] >> 16; //printf("%d\n", cmd_length); uint32_t Vertices1[]{ v1.x, v1.y, 0, v2.x, v2.y, 0, v3.x, v3.y, 0, v4.x, v4.y, 0, v5.x, v5.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), }; glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glBindVertexArray(VAO); glVertexAttribIPointer(0, 3, GL_INT, 3 * sizeof(uint32_t), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_UNSIGNED_INT, GL_FALSE, 3 * sizeof(uint32_t), (void*)(15 * sizeof(uint32_t))); glEnableVertexAttribArray(1); glUseProgram(ShaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_LINE_STRIP, 0, 5); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); /*uint32_t Vertices2[]{ v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, v4.x, v4.y, 0.0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glBindVertexArray(VAO); glVertexAttribPointer(0, 3, GL_UNSIGNED_INT, GL_FALSE, 3 * sizeof(uint32_t), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_UNSIGNED_INT, GL_FALSE, 3 * sizeof(uint32_t), (void*)(9 * sizeof(uint32_t))); glEnableVertexAttribArray(1); glUseProgram(ShaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_LINE_STRIP, 0, 3); glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); */ } void gpu::monochrome_rectangle_variable_size_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Monochrome Rectangle (variable size) (opaque) (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; res.x = fifo[2] & 0xffff; res.y = fifo[2] >> 16; v2.x = v1.x + res.x; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + res.y; v4.x = v1.x + res.x; v4.y = v1.y + res.y; uint32_t Vertices1[]{ v1.x, v1.y, 0, v2.x, v2.y, 0, v3.x, v3.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[]{ v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, v4.x, v4.y, 0.0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::monochrome_rectangle_variable_size_semi_transparent() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Monochrome Rectangle (variable size) (semi-transparent) (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; res.x = fifo[2] & 0xffff; res.y = fifo[2] >> 16; v2.x = v1.x + res.x; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + res.y; v4.x = v1.x + res.x; v4.y = v1.y + res.y; uint32_t Vertices1[]{ v1.x, v1.y, 0, v2.x, v2.y, 0, v3.x, v3.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[]{ v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, v4.x, v4.y, 0.0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_blending_rectangle_variable_size_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured Rectangle, variable size, opaque, texture-blending (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; uint16_t texpage = texpage_raw; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); //texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); res.x = fifo[3] & 0xffff; res.y = fifo[3] >> 16; v2.x = v1.x + res.x; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + res.y; v4.x = v1.x + res.x; v4.y = v1.y + res.y; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = t1.x + res.x; t2.y = t1.y; t3.x = t1.x; t3.y = t1.y + res.y; t4.x = t1.x + res.x; t4.y = t1.y + res.y; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_blending_rectangle_8x8_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured Rectangle, 8x8, opaque, texture-blending (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; uint16_t texpage = texpage_raw; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); //texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = v1.x + 8; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + 8; v4.x = v1.x + 8; v4.y = v1.y + 8; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = t1.x + 8; t2.y = t1.y; t3.x = t1.x; t3.y = t1.y + 8; t4.x = t1.x + 8; t4.y = t1.y + 8; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_rectangle_8x8_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured Rectangle, 8x8, opaque, raw-texture (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; uint16_t texpage = texpage_raw; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); //texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = v1.x + 8; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + 8; v4.x = v1.x + 8; v4.y = v1.y + 8; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = t1.x + 8; t2.y = t1.y; t3.x = t1.x; t3.y = t1.y + 8; t4.x = t1.x + 8; t4.y = t1.y + 8; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, 128, 128, 128, t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, 128, 128, 128, t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_blending_rectangle_16x16_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured Rectangle, 16x16, opaque, texture-blending (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; uint16_t texpage = texpage_raw; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); //texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = v1.x + 16; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + 16; v4.x = v1.x + 16; v4.y = v1.y + 16; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = t1.x + 16; t2.y = t1.y; t3.x = t1.x; t3.y = t1.y + 16; t4.x = t1.x + 16; t4.y = t1.y + 16; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_rectangle_16x16_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured Rectangle, 16x16, opaque, raw-texture (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; uint16_t texpage = texpage_raw; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); //texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = v1.x + 16; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + 16; v4.x = v1.x + 16; v4.y = v1.y + 16; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = t1.x + 16; t2.y = t1.y; t3.x = t1.x; t3.y = t1.y + 16; t4.x = t1.x + 16; t4.y = t1.y + 16; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, 128, 128, 128, t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, 128, 128, 128, t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_rectangle_16x16_semi_transparent() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured Rectangle, 16x16, semi-transparent, raw-texture (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; uint16_t texpage = texpage_raw; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); //texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); v2.x = v1.x + 16; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + 16; v4.x = v1.x + 16; v4.y = v1.y + 16; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = t1.x + 16; t2.y = t1.y; t3.x = t1.x; t3.y = t1.y + 16; t4.x = t1.x + 16; t4.y = t1.y + 16; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, 128, 128, 128, t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, 128, 128, 128, t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_rectangle_variable_size_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured Rectangle, variable size, opaque, raw-texture (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; uint16_t texpage = texpage_raw; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); //texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); res.x = fifo[3] & 0xffff; res.y = fifo[3] >> 16; v2.x = v1.x + res.x; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + res.y; v4.x = v1.x + res.x; v4.y = v1.y + res.y; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = t1.x + res.x; t2.y = t1.y; t3.x = t1.x; t3.y = t1.y + res.y; t4.x = t1.x + res.x; t4.y = t1.y + res.y; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, 128, 128, 128, t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, 128, 128, 128, t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::texture_blending_rectangle_variable_size_semi_transparent() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured Rectangle, variable size, semi-transp, texture-blending (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; uint16_t texpage = texpage_raw; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); //texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); res.x = fifo[3] & 0xffff; res.y = fifo[3] >> 16; v2.x = v1.x + res.x; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + res.y; v4.x = v1.x + res.x; v4.y = v1.y + res.y; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = t1.x + res.x; t2.y = t1.y; t3.x = t1.x; t3.y = t1.y + res.y; t4.x = t1.x + res.x; t4.y = t1.y + res.y; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::textured_rectangle_variable_size_semi_transparent() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Textured Rectangle, variable size, semi-transp, raw-texture (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; uint16_t texpage = texpage_raw; uint16_t clut = 0; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; clut = fifo[2] >> 16; uint32_t clutX = (clut & 0x3f); clutX *= 16; uint32_t clutY = (clut >> 6); //texpage = fifo[4] >> 16; uint32_t texpageX = ((texpage & 0b1111) * 64); uint32_t texpageY = (((texpage & 0b10000) >> 4) * 256); res.x = fifo[3] & 0xffff; res.y = fifo[3] >> 16; v2.x = v1.x + res.x; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + res.y; v4.x = v1.x + res.x; v4.y = v1.y + res.y; point t1, t2, t3, t4; t1.x = (fifo[2] & 0xffff) & 0xff; t1.y = ((fifo[2] & 0xffff) >> 8) & 0xff; t2.x = t1.x + res.x; t2.y = t1.y; t3.x = t1.x; t3.y = t1.y + res.y; t4.x = t1.x + res.x; t4.y = t1.y + res.y; int colourDepth = (texpage >> 7) & 3; uint32_t Vertices1[] = { // positions // colors // texture coords v1.x, v1.y, 0, 128, 128, 128, t1.x, t1.y, texpageX, texpageY, clutX, clutY, colourDepth, v2.x, v2.y, 0.0f, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBindTexture(GL_TEXTURE_2D, SampleVramTexture); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glUniform1i(colourDepthUniform, colourDepth); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[] = { // positions // colors // texture coords // texpage v2.x, v2.y, 0, 128, 128, 128, t2.x, t2.y, texpageX, texpageY, clutX, clutY, colourDepth, v3.x, v3.y, 0.0f, 128, 128, 128, t3.x, t3.y, texpageX, texpageY, clutX, clutY, colourDepth, v4.x, v4.y, 0.0f, 128, 128, 128, t4.x, t4.y, texpageX, texpageY, clutX, clutY, colourDepth //v4.x, v4.y, 0.0f, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), t4.x, t4.y // top left }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::monochrome_rectangle_dot_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Monochrome Rectangle (1x1) (opaque) (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = v1.x + 1; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + 1; v4.x = v1.x + 1; v4.y = v1.y + 1; uint32_t Vertices1[]{ v1.x, v1.y, 0, v2.x, v2.y, 0, v3.x, v3.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[]{ v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, v4.x, v4.y, 0.0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::monochrome_rectangle_8x8_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Monochrome Rectangle (8x8) (opaque) (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = v1.x + 8; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + 8; v4.x = v1.x + 8; v4.y = v1.y + 8; uint32_t Vertices1[]{ v1.x, v1.y, 0, v2.x, v2.y, 0, v3.x, v3.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[]{ v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, v4.x, v4.y, 0.0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::monochrome_rectangle_16x16_opaque() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Monochrome Rectangle (16x16) (opaque) (colour: 0x%x)\n", colour); point v1, res, v2, v3, v4; v1.x = fifo[1] & 0xffff; v1.y = fifo[1] >> 16; v2.x = v1.x + 16; v2.y = v1.y; v3.x = v1.x; v3.y = v1.y + 16; v4.x = v1.x + 16; v4.y = v1.y + 16; uint32_t Vertices1[]{ v1.x, v1.y, 0, v2.x, v2.y, 0, v3.x, v3.y, 0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices1), Vertices1, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); uint32_t Vertices2[]{ v2.x, v2.y, 0.0, v3.x, v3.y, 0.0, v4.x, v4.y, 0.0, (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff), (((colour) >> 0) & 0xff), (((colour) >> 8) & 0xff), (((colour) >> 16) & 0xff) }; glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, 3); } void gpu::fill_rectangle() { debug_printf("[GP0] Fill Rectangle\n"); glViewport(0, 0, 1024 * scaling_factor, 512 * scaling_factor); uint8_t r = (fifo[0] & 0xff); uint8_t g = ((fifo[0] >> 8) & 0xff); uint8_t b = ((fifo[0] >> 16) & 0xff); uint32_t x = fifo[1] & 0xffff; uint32_t y = fifo[1] >> 16; uint32_t width = fifo[2] & 0xffff; uint32_t height = fifo[2] >> 16; glClearColor(r / 255.f, g / 255.f, b / 255.f, 1.f); glScissor(x * scaling_factor, y * scaling_factor, width * scaling_factor, height * scaling_factor); glClear(GL_COLOR_BUFFER_BIT); glScissor(drawing_topleft_x * scaling_factor, drawing_topleft_y * scaling_factor, (drawing_bottomright_x - drawing_topleft_x) * scaling_factor, (drawing_bottomright_y - drawing_topleft_y) * scaling_factor); } void gpu::vram_to_vram() { uint32_t colour = fifo[0] & 0xffffff; debug_printf("[GP0] Copy Rectangle (VRAM to VRAM)\n", colour); uint32_t resolution = fifo[3]; uint32_t coords = fifo[1]; uint32_t dest_coords = fifo[2]; auto width = resolution & 0xffff; auto height = resolution >> 16; if (width == 0) width = 1024; if (height == 0) height = 512; auto x = coords & 0x3ff; auto y = (coords >> 16) & 0x1ff; auto dest_x = dest_coords & 0x3ff; auto dest_y = (dest_coords >> 16) & 0x1ff; //glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, ReadBuffer); glBindTexture(GL_TEXTURE_2D, VramTexture); //glTexSubImage2D(GL_TEXTURE_2D, 0, dest_x, dest_y, width, height, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, ReadBuffer); } void gpu::cpu_to_vram() { debug_printf("[GP0] Copy Rectangle (CPU to VRAM)\n"); uint32_t resolution = fifo[2]; uint32_t coords = fifo[1]; auto width = resolution & 0xffff; auto height = resolution >> 16; xpos = 0; ypos = 0; uint32_t size = width * height; size += 1; size &= ~1; cmd_left = size / 2; cmd_left++; gp0_mode = 1; } void gpu::vram_to_cpu() { uint32_t resolution = fifo[2]; uint32_t coords = fifo[1]; auto width = resolution & 0xffff; auto height = resolution >> 16; if (width == 0) width = 1024; if (height == 0) height = 512; auto x = coords & 0x3ff; auto y = (coords >> 16) & 0x1ff; width &= 0x3ff; height &= 0x1ff; uint32_t size = width * height; size += 1; size &= ~1; size /= 2; glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, ReadBuffer); ReadBufferCnt = 0; }