From f2151a0a2531785d5a30caa9f65b70b4d5726a5f Mon Sep 17 00:00:00 2001 From: Matthew Berry Date: Tue, 11 May 2021 00:47:32 -0700 Subject: [PATCH] move gb color correction to gpu, unify display logic for gb and gba --- src/crab/common/display.cr | 145 ++++++++++++++++++ src/crab/common/shaders/gb_colors.frag | 20 +++ .../{gba => common}/shaders/gba_colors.frag | 0 .../shaders/identity.vert} | 0 src/crab/gb/display.cr | 85 ---------- src/crab/gb/fifo_ppu.cr | 6 +- src/crab/gb/gb.cr | 3 +- src/crab/gb/ppu.cr | 29 +++- src/crab/gb/scanline_ppu.cr | 20 +-- src/crab/gba/display.cr | 122 --------------- src/crab/gba/gba.cr | 3 +- 11 files changed, 208 insertions(+), 225 deletions(-) create mode 100644 src/crab/common/display.cr create mode 100644 src/crab/common/shaders/gb_colors.frag rename src/crab/{gba => common}/shaders/gba_colors.frag (100%) rename src/crab/{gba/shaders/gba_colors.vert => common/shaders/identity.vert} (100%) delete mode 100644 src/crab/gb/display.cr delete mode 100644 src/crab/gba/display.cr diff --git a/src/crab/common/display.cr b/src/crab/common/display.cr new file mode 100644 index 0000000..4ae2a63 --- /dev/null +++ b/src/crab/common/display.cr @@ -0,0 +1,145 @@ +require "lib_gl" + +class Display + enum Console + GB + GBA + + def width : Int32 + case self + in GB then 160 + in GBA then 240 + end + end + + def height : Int32 + case self + in GB then 144 + in GBA then 160 + end + end + + def shader : String + case self + in GB then "gb_colors.frag" + in GBA then "gba_colors.frag" + end + end + end + + SCALE = 4 + SHADERS = "src/crab/common/shaders" + + @microseconds = 0 + @frames = 0 + @last_time = Time.utc + @seconds : Int32 = Time.utc.second + + @blend : Bool = false + + def initialize(@console : Console) + @window = SDL::Window.new(window_title(59.7), console.width * SCALE, console.height * SCALE, flags: SDL::Window::Flags::OPENGL) + setup_gl + end + + def draw(framebuffer : Slice(UInt16)) : Nil + LibGL.tex_image_2d(LibGL::TEXTURE_2D, 0, LibGL::RGB5, @console.width, @console.height, 0, LibGL::RGBA, LibGL::UNSIGNED_SHORT_1_5_5_5_REV, framebuffer) + LibGL.draw_arrays(LibGL::TRIANGLE_STRIP, 0, 4) + LibSDL.gl_swap_window(@window) + update_draw_count + end + + def toggle_blending : Nil + if @blend + LibGL.disable(LibGL::BLEND) + else + LibGL.enable(LibGL::BLEND) + end + @blend = !@blend + end + + private def window_title(fps : Float) : String + "crab - #{fps.round(1)} fps" + end + + private def update_draw_count : Nil + current_time = Time.utc + @microseconds += (current_time - @last_time).microseconds + @last_time = current_time + @frames += 1 + if current_time.second != @seconds + fps = @frames * 1_000_000 / @microseconds + @window.title = window_title(fps) + @microseconds = 0 + @frames = 0 + @seconds = current_time.second + end + end + + private def compile_shader(source : String, type : UInt32) : UInt32 + source_ptr = source.to_unsafe + shader = LibGL.create_shader(type) + LibGL.shader_source(shader, 1, pointerof(source_ptr), nil) + LibGL.compile_shader(shader) + shader_compiled = 0 + LibGL.get_shader_iv(shader, LibGL::COMPILE_STATUS, pointerof(shader_compiled)) + if shader_compiled != LibGL::TRUE + log_length = 0 + LibGL.get_shader_iv(shader, LibGL::INFO_LOG_LENGTH, pointerof(log_length)) + s = " " * log_length + LibGL.get_shader_info_log(shader, log_length, pointerof(log_length), s) if log_length > 0 + abort "Error compiling shader: #{s}" + end + shader + end + + private def setup_gl : Nil + {% if flag?(:darwin) %} + LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_FLAGS, LibSDL::GLcontextFlag::FORWARD_COMPATIBLE_FLAG) + {% end %} + LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_PROFILE_MASK, LibSDL::GLprofile::PROFILE_CORE) + LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_MAJOR_VERSION, 3) + LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_MINOR_VERSION, 3) + + {% unless flag?(:darwin) %} + # todo: proper debug messages for mac + LibGL.enable(LibGL::DEBUG_OUTPUT) + LibGL.enable(LibGL::DEBUG_OUTPUT_SYNCHRONOUS) + LibGL.debug_message_callback(->Display.callback, nil) + {% end %} + + LibSDL.gl_create_context @window + LibSDL.gl_set_swap_interval(0) # disable vsync + shader_program = LibGL.create_program + + puts "OpenGL version: #{String.new(LibGL.get_string(LibGL::VERSION))}" + puts "Shader language version: #{String.new(LibGL.get_string(LibGL::SHADING_LANGUAGE_VERSION))}" + + LibGL.blend_func(LibGL::SRC_ALPHA, LibGL::ONE_MINUS_SRC_ALPHA) + + vert_shader_id = compile_shader(File.read("#{SHADERS}/identity.vert"), LibGL::VERTEX_SHADER) + frag_shader_id = compile_shader(File.read("#{SHADERS}/#{@console.shader}"), LibGL::FRAGMENT_SHADER) + + frame_buffer = 0_u32 + LibGL.gen_textures(1, pointerof(frame_buffer)) + LibGL.active_texture(LibGL::TEXTURE0) + LibGL.bind_texture(LibGL::TEXTURE_2D, frame_buffer) + LibGL.attach_shader(shader_program, vert_shader_id) + LibGL.attach_shader(shader_program, frag_shader_id) + LibGL.link_program(shader_program) + LibGL.validate_program(shader_program) + a = [LibGL::BLUE, LibGL::GREEN, LibGL::RED, LibGL::ONE] # flip the rgba to bgra where a is always 1 + a_ptr = pointerof(a).as(Int32*) + LibGL.tex_parameter_iv(LibGL::TEXTURE_2D, LibGL::TEXTURE_SWIZZLE_RGBA, a_ptr) + LibGL.tex_parameter_i(LibGL::TEXTURE_2D, LibGL::TEXTURE_MIN_FILTER, LibGL::NEAREST) + LibGL.tex_parameter_i(LibGL::TEXTURE_2D, LibGL::TEXTURE_MAG_FILTER, LibGL::NEAREST) + LibGL.use_program(shader_program) + vao = 0_u32 # required even if not used in modern opengl + LibGL.gen_vertex_arrays(1, pointerof(vao)) + LibGL.bind_vertex_array(vao) + end + + protected def self.callback(source : UInt32, type : UInt32, id : UInt32, severity : UInt32, length : Int32, message : Pointer(UInt8), userParam : Pointer(Void)) : Nil + puts "OpenGL debug message: #{String.new message}" + end +end diff --git a/src/crab/common/shaders/gb_colors.frag b/src/crab/common/shaders/gb_colors.frag new file mode 100644 index 0000000..290e7d8 --- /dev/null +++ b/src/crab/common/shaders/gb_colors.frag @@ -0,0 +1,20 @@ +#version 330 core + +in vec2 tex_coord; +out vec4 frag_color; + +uniform sampler2D input_texture; + +mat3 m = mat3( + 26, 0, 6, + 4, 24, 4, + 2, 8, 22 +); + +void main() { + // Credits to [unknown] and Near for this color-correction algorithm. + // https://byuu.net/video/color-emulation + vec4 color = texture(input_texture, tex_coord); + frag_color.rgb = min(vec3(30), m * color.rgb / 32); + frag_color.a = 0.5; +} diff --git a/src/crab/gba/shaders/gba_colors.frag b/src/crab/common/shaders/gba_colors.frag similarity index 100% rename from src/crab/gba/shaders/gba_colors.frag rename to src/crab/common/shaders/gba_colors.frag diff --git a/src/crab/gba/shaders/gba_colors.vert b/src/crab/common/shaders/identity.vert similarity index 100% rename from src/crab/gba/shaders/gba_colors.vert rename to src/crab/common/shaders/identity.vert diff --git a/src/crab/gb/display.cr b/src/crab/gb/display.cr deleted file mode 100644 index cc4ac31..0000000 --- a/src/crab/gb/display.cr +++ /dev/null @@ -1,85 +0,0 @@ -require "stumpy_png" - -module GB - class Display - WIDTH = 160 - HEIGHT = 144 - - PIXELFORMAT_BGR5 = 357764866 - TEXTUREACCESS_STREAMING = 1 - - @window : SDL::Window - @renderer : SDL::Renderer - @texture : Pointer(LibSDL::Texture) - - @title : String - - @fps = 30 - @seconds : Int32 = Time.utc.second - - def initialize(gb : GB, headless : Bool) - @title = gb.cartridge.title - flags = headless ? SDL::Window::Flags::HIDDEN : SDL::Window::Flags::SHOWN - @window = SDL::Window.new(window_title, WIDTH * DISPLAY_SCALE, HEIGHT * DISPLAY_SCALE, flags: flags) - @renderer = SDL::Renderer.new @window - @renderer.logical_size = {WIDTH, HEIGHT} - @texture = LibSDL.create_texture @renderer, PIXELFORMAT_BGR5, TEXTUREACCESS_STREAMING, WIDTH, HEIGHT - end - - def window_title : String - "CryBoy - #{@title} - #{@fps} fps" - end - - def draw(framebuffer : Slice(UInt16)) : Nil - LibSDL.update_texture @texture, nil, framebuffer, WIDTH * sizeof(UInt16) - @renderer.clear - @renderer.copy @texture - @renderer.present - @fps += 1 - if Time.utc.second != @seconds - @window.title = window_title - @fps = 0 - @seconds = Time.utc.second - end - end - - def write_png(framebuffer : Array(RGB)) : Nil - canvas = StumpyPNG::Canvas.new WIDTH, HEIGHT - HEIGHT.times do |row| - WIDTH.times do |col| - rgb = framebuffer[row * WIDTH + col] - color = StumpyPNG::RGBA.from_rgb8(rgb.red, rgb.green, rgb.blue) - canvas[col, row] = color - end - end - StumpyPNG.write(canvas, "out.png") - end - end -end - -############################################################################### -# Method for drawing all tiles in vram - -# @all_tiles_window = SDL::Window.new("ALL TILES", 128 * scale, 192 * scale) -# @all_tiles_renderer = SDL::Renderer.new @all_tiles_window -# @all_tiles_renderer.logical_size = {128, 192} - -# # a method for showing all tiles in vram for debugging -# def draw_all_tiles(memory : Memory) -# (0...24).each do |y| -# (0...16).each do |x| -# tile_ptr = 0x8000 + (y * 16 * 16) + (x * 16) -# (0...8).each do |tile_row| -# byte_1 = memory[tile_ptr + 2 * tile_row] -# byte_2 = memory[tile_ptr + 2 * tile_row + 1] -# (0...8).each do |tile_col| -# lsb = (byte_1 >> (7 - tile_col)) & 0x1 -# msb = (byte_2 >> (7 - tile_col)) & 0x1 -# @all_tiles_renderer.draw_color = @colors[(msb << 1) | lsb] -# @all_tiles_renderer.draw_point((8 * x + tile_col), (8 * y + tile_row)) -# end -# end -# end -# end -# @all_tiles_renderer.present -# end diff --git a/src/crab/gb/fifo_ppu.cr b/src/crab/gb/fifo_ppu.cr index 289fcd5..71113cd 100644 --- a/src/crab/gb/fifo_ppu.cr +++ b/src/crab/gb/fifo_ppu.cr @@ -203,10 +203,10 @@ module GB arr = @pram end color = @cgb_ptr.value ? pixel.color : palette[pixel.color] - @framebuffer[Display::WIDTH * @ly + @lx] = arr.to_unsafe.as(UInt16*)[4 * pixel.palette + color] + @framebuffer[WIDTH * @ly + @lx] = arr.to_unsafe.as(UInt16*)[4 * pixel.palette + color] end @lx += 1 - if @lx == Display::WIDTH + if @lx == WIDTH self.mode_flag = 0 end if window_enabled? && @ly >= @wy && @lx + 7 >= @wx && !@fetching_window && @window_trigger @@ -243,7 +243,7 @@ module GB if @cycle_counter == 456 @cycle_counter = 0 @ly += 1 - if @ly == Display::HEIGHT # final row of screen complete + if @ly == HEIGHT # final row of screen complete self.mode_flag = 1 # switch to vblank @gb.interrupts.vblank_interrupt = true @gb.display.draw @framebuffer # render at vblank diff --git a/src/crab/gb/gb.cr b/src/crab/gb/gb.cr index 29c7cbc..5425941 100644 --- a/src/crab/gb/gb.cr +++ b/src/crab/gb/gb.cr @@ -2,7 +2,6 @@ require "sdl" require "./apu" require "./cartridge" require "./cpu" -require "./display" require "./interrupts" require "./joypad" require "./mbc/*" @@ -44,7 +43,7 @@ module GB @scheduler = Scheduler.new @interrupts = Interrupts.new @apu = APU.new self, @headless, @sync - @display = Display.new self, @headless + @display = Display.new Display::Console::GB @joypad = Joypad.new self @ppu = @fifo ? FifoPPU.new self : ScanlinePPU.new self @timer = Timer.new self diff --git a/src/crab/gb/ppu.cr b/src/crab/gb/ppu.cr index a1747f2..ba9e385 100644 --- a/src/crab/gb/ppu.cr +++ b/src/crab/gb/ppu.cr @@ -111,7 +111,10 @@ module GB @ran_bios : Bool # determine if colors should be adjusted for cgb @cgb_ptr : Pointer(Bool) - @framebuffer = Slice(UInt16).new Display::WIDTH * Display::HEIGHT + WIDTH = 160 + HEIGHT = 144 + + @framebuffer = Slice(UInt16).new WIDTH * HEIGHT @pram = Bytes.new 64 @palette_index : UInt8 = 0 @@ -160,6 +163,30 @@ module GB def initialize(@gb : GB) @cgb_ptr = gb.cgb_ptr + unless @cgb_ptr.value # fill default color palettes + # {% if flag? :pink %} + # @palettes[0] = @obj_palettes[0] = @obj_palettes[1] = [ + # RGB.new(0xFF, 0xF6, 0xD3), RGB.new(0xF9, 0xA8, 0x75), + # RGB.new(0xEB, 0x6B, 0x6F), RGB.new(0x7C, 0x3F, 0x58), + # ] + # {% elsif flag? :graphics_test %} + # @palettes[0] = @obj_palettes[0] = @obj_palettes[1] = [ + # RGB.new(0xFF, 0xFF, 0xFF), RGB.new(0xAA, 0xAA, 0xAA), + # RGB.new(0x55, 0x55, 0x55), RGB.new(0x00, 0x00, 0x00), + # ] + # @pram[0] = @pram[1] = @obj_pram[0] = @obj_pram[1] = 0xFF + # @pram.to_unsafe.as(UInt16*)[0] = 0x7FFF; + # {% else %} + # @palettes[0] = @obj_palettes[0] = @obj_palettes[1] = [ + # RGB.new(0xE0, 0xF8, 0xCF), RGB.new(0x86, 0xC0, 0x6C), + # RGB.new(0x30, 0x68, 0x50), RGB.new(0x07, 0x17, 0x20), + # ] + # {% end %} + @pram.to_unsafe.as(UInt16*)[0] = @obj_pram.to_unsafe.as(UInt16*)[0] = @obj_pram.to_unsafe.as(UInt16*)[4] = 0x6BDF + @pram.to_unsafe.as(UInt16*)[1] = @obj_pram.to_unsafe.as(UInt16*)[1] = @obj_pram.to_unsafe.as(UInt16*)[5] = 0x3ABF + @pram.to_unsafe.as(UInt16*)[2] = @obj_pram.to_unsafe.as(UInt16*)[2] = @obj_pram.to_unsafe.as(UInt16*)[6] = 0x35BD + @pram.to_unsafe.as(UInt16*)[3] = @obj_pram.to_unsafe.as(UInt16*)[3] = @obj_pram.to_unsafe.as(UInt16*)[7] = 0x2CEF + end @ran_bios = @cgb_ptr.value end diff --git a/src/crab/gb/scanline_ppu.cr b/src/crab/gb/scanline_ppu.cr index 5aa3f9d..18a0885 100644 --- a/src/crab/gb/scanline_ppu.cr +++ b/src/crab/gb/scanline_ppu.cr @@ -22,7 +22,7 @@ module GB end # color idx, BG-to-OAM priority bit - @scanline_color_vals = Array(Tuple(UInt8, Bool)).new Display::WIDTH, {0_u8, false} + @scanline_color_vals = Array(Tuple(UInt8, Bool)).new WIDTH, {0_u8, false} def scanline @current_window_line = 0 if @ly == 0 @@ -32,7 +32,7 @@ module GB tile_data_table = bg_window_tile_data == 0 ? 0x1000 : 0x0000 # 0x9000 : 0x8000 tile_row_window = @current_window_line & 7 tile_row = (@ly.to_u16 + @scy) & 7 - Display::WIDTH.times do |x| + WIDTH.times do |x| if window_enabled? && @ly >= @wy && x + 7 >= @wx && @window_trigger should_increment_window_line = true tile_num_addr = window_map + ((x + 7 - @wx) >> 3) + ((@current_window_line >> 3) * 32) @@ -57,9 +57,9 @@ module GB color = (msb << 1) | lsb @scanline_color_vals[x] = {color, @vram[1][tile_num_addr] & 0x80 > 0} if @cgb_ptr.value - @framebuffer[Display::WIDTH * @ly + x] = @pram.to_unsafe.as(UInt16*)[4 * (@vram[1][tile_num_addr] & 0b111) + color] + @framebuffer[WIDTH * @ly + x] = @pram.to_unsafe.as(UInt16*)[4 * (@vram[1][tile_num_addr] & 0b111) + color] else - @framebuffer[Display::WIDTH * @ly + x] = @pram.to_unsafe.as(UInt16*)[@bgp[color]] + @framebuffer[WIDTH * @ly + x] = @pram.to_unsafe.as(UInt16*)[@bgp[color]] end elsif bg_display? || @cgb_ptr.value tile_num_addr = background_map + (((x + @scx) >> 3) & 0x1F) + ((((@ly.to_u16 + @scy) >> 3) * 32) & 0x3FF) @@ -84,9 +84,9 @@ module GB color = (msb << 1) | lsb @scanline_color_vals[x] = {color, @vram[1][tile_num_addr] & 0x80 > 0} if @cgb_ptr.value - @framebuffer[Display::WIDTH * @ly + x] = @pram.to_unsafe.as(UInt16*)[4 * (@vram[1][tile_num_addr] & 0b111) + color] + @framebuffer[WIDTH * @ly + x] = @pram.to_unsafe.as(UInt16*)[4 * (@vram[1][tile_num_addr] & 0b111) + color] else - @framebuffer[Display::WIDTH * @ly + x] = @pram.to_unsafe.as(UInt16*)[@bgp[color]] + @framebuffer[WIDTH * @ly + x] = @pram.to_unsafe.as(UInt16*)[@bgp[color]] end end end @@ -97,7 +97,7 @@ module GB bytes = sprite.bytes @ly, sprite_height 8.times do |col| x = col + sprite.x - 8 - next unless 0 <= x < Display::WIDTH # only render sprites on screen + next unless 0 <= x < WIDTH # only render sprites on screen if sprite.x_flip? lsb = (@vram[@cgb_ptr.value ? sprite.bank_num : 0][bytes[0]] >> col) & 0x1 msb = (@vram[@cgb_ptr.value ? sprite.bank_num : 0][bytes[1]] >> col) & 0x1 @@ -112,12 +112,12 @@ module GB # objects are always on top of bg/window color 0 # objects are on top of bg/window colors 1-3 if bg_priority and object priority are both unset if !bg_display? || @scanline_color_vals[x][0] == 0 || (!@scanline_color_vals[x][1] && sprite.priority == 0) - @framebuffer[Display::WIDTH * @ly + x] = @obj_pram.to_unsafe.as(UInt16*)[4 * sprite.cgb_palette_number + color] + @framebuffer[WIDTH * @ly + x] = @obj_pram.to_unsafe.as(UInt16*)[4 * sprite.cgb_palette_number + color] end else if sprite.priority == 0 || @scanline_color_vals[x][0] == 0 palette = sprite.dmg_palette_number == 0 ? @obp0 : @obp1 - @framebuffer[Display::WIDTH * @ly + x] = @obj_pram.to_unsafe.as(UInt16*)[palette[color]] + @framebuffer[WIDTH * @ly + x] = @obj_pram.to_unsafe.as(UInt16*)[palette[color]] end end end @@ -146,7 +146,7 @@ module GB if @cycle_counter >= 204 # end of hblank reached @cycle_counter -= 204 # reset cycle_counter, saving extra cycles @ly += 1 - if @ly == Display::HEIGHT # final row of screen complete + if @ly == HEIGHT # final row of screen complete self.mode_flag = 1 # switch to vblank @gb.interrupts.vblank_interrupt = true @gb.display.draw @framebuffer # render at vblank diff --git a/src/crab/gba/display.cr b/src/crab/gba/display.cr deleted file mode 100644 index d8480bf..0000000 --- a/src/crab/gba/display.cr +++ /dev/null @@ -1,122 +0,0 @@ -require "lib_gl" - -module GBA - class Display - WIDTH = 240 - HEIGHT = 160 - SCALE = 4 - - @microseconds = 0 - @frames = 0 - @last_time = Time.utc - @seconds : Int32 = Time.utc.second - - @blend : Bool = false - - def initialize - @window = SDL::Window.new(window_title(59.7), WIDTH * SCALE, HEIGHT * SCALE, flags: SDL::Window::Flags::OPENGL) - setup_gl - end - - def draw(framebuffer : Slice(UInt16)) : Nil - LibGL.tex_image_2d(LibGL::TEXTURE_2D, 0, LibGL::RGB5, 240, 160, 0, LibGL::RGBA, LibGL::UNSIGNED_SHORT_1_5_5_5_REV, framebuffer) - LibGL.draw_arrays(LibGL::TRIANGLE_STRIP, 0, 4) - LibSDL.gl_swap_window(@window) - update_draw_count - end - - def toggle_blending : Nil - if @blend - LibGL.disable(LibGL::BLEND) - else - LibGL.enable(LibGL::BLEND) - end - @blend = !@blend - end - - private def window_title(fps : Float) : String - "crab - #{fps.round(1)} fps" - end - - private def update_draw_count : Nil - current_time = Time.utc - @microseconds += (current_time - @last_time).microseconds - @last_time = current_time - @frames += 1 - if current_time.second != @seconds - fps = @frames * 1_000_000 / @microseconds - @window.title = window_title(fps) - @microseconds = 0 - @frames = 0 - @seconds = current_time.second - end - end - - private def compile_shader(source : String, type : UInt32) : UInt32 - source_ptr = source.to_unsafe - shader = LibGL.create_shader(type) - LibGL.shader_source(shader, 1, pointerof(source_ptr), nil) - LibGL.compile_shader(shader) - shader_compiled = 0 - LibGL.get_shader_iv(shader, LibGL::COMPILE_STATUS, pointerof(shader_compiled)) - if shader_compiled != LibGL::TRUE - log_length = 0 - LibGL.get_shader_iv(shader, LibGL::INFO_LOG_LENGTH, pointerof(log_length)) - s = " " * log_length - LibGL.get_shader_info_log(shader, log_length, pointerof(log_length), s) if log_length > 0 - abort "Error compiling shader: #{s}" - end - shader - end - - private def setup_gl : Nil - {% if flag?(:darwin) %} - LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_FLAGS, LibSDL::GLcontextFlag::FORWARD_COMPATIBLE_FLAG) - {% end %} - LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_PROFILE_MASK, LibSDL::GLprofile::PROFILE_CORE) - LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_MAJOR_VERSION, 3) - LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_MINOR_VERSION, 3) - - {% unless flag?(:darwin) %} - # todo: proper debug messages for mac - LibGL.enable(LibGL::DEBUG_OUTPUT) - LibGL.enable(LibGL::DEBUG_OUTPUT_SYNCHRONOUS) - LibGL.debug_message_callback(->Display.callback, nil) - {% end %} - - LibSDL.gl_create_context @window - LibSDL.gl_set_swap_interval(0) # disable vsync - shader_program = LibGL.create_program - - puts "OpenGL version: #{String.new(LibGL.get_string(LibGL::VERSION))}" - puts "Shader language version: #{String.new(LibGL.get_string(LibGL::SHADING_LANGUAGE_VERSION))}" - - LibGL.blend_func(LibGL::SRC_ALPHA, LibGL::ONE_MINUS_SRC_ALPHA) - - vert_shader_id = compile_shader(File.read("src/crab/gba/shaders/gba_colors.vert"), LibGL::VERTEX_SHADER) - frag_shader_id = compile_shader(File.read("src/crab/gba/shaders/gba_colors.frag"), LibGL::FRAGMENT_SHADER) - - frame_buffer = 0_u32 - LibGL.gen_textures(1, pointerof(frame_buffer)) - LibGL.active_texture(LibGL::TEXTURE0) - LibGL.bind_texture(LibGL::TEXTURE_2D, frame_buffer) - LibGL.attach_shader(shader_program, vert_shader_id) - LibGL.attach_shader(shader_program, frag_shader_id) - LibGL.link_program(shader_program) - LibGL.validate_program(shader_program) - a = [LibGL::BLUE, LibGL::GREEN, LibGL::RED, LibGL::ONE] # flip the rgba to bgra where a is always 1 - a_ptr = pointerof(a).as(Int32*) - LibGL.tex_parameter_iv(LibGL::TEXTURE_2D, LibGL::TEXTURE_SWIZZLE_RGBA, a_ptr) - LibGL.tex_parameter_i(LibGL::TEXTURE_2D, LibGL::TEXTURE_MIN_FILTER, LibGL::NEAREST) - LibGL.tex_parameter_i(LibGL::TEXTURE_2D, LibGL::TEXTURE_MAG_FILTER, LibGL::NEAREST) - LibGL.use_program(shader_program) - vao = 0_u32 # required even if not used in modern opengl - LibGL.gen_vertex_arrays(1, pointerof(vao)) - LibGL.bind_vertex_array(vao) - end - - protected def self.callback(source : UInt32, type : UInt32, id : UInt32, severity : UInt32, length : Int32, message : Pointer(UInt8), userParam : Pointer(Void)) : Nil - puts "OpenGL debug message: #{String.new message}" - end - end -end diff --git a/src/crab/gba/gba.cr b/src/crab/gba/gba.cr index 92297bb..e7982cb 100644 --- a/src/crab/gba/gba.cr +++ b/src/crab/gba/gba.cr @@ -9,7 +9,6 @@ require "./keypad" require "./bus" require "./interrupts" require "./cpu" -require "./display" require "./ppu" require "./apu" require "./dma" @@ -50,7 +49,7 @@ module GBA @bus = Bus.new self, @bios_path @interrupts = Interrupts.new self @cpu = CPU.new self - @display = Display.new + @display = Display.new Display::Console::GBA @ppu = PPU.new self @apu = APU.new self @dma = DMA.new self