Class: PSX::Display
- Inherits:
-
Object
- Object
- PSX::Display
- Defined in:
- lib/psx/display.rb
Constant Summary collapse
- WIDTH =
320- HEIGHT =
240- SCALE =
640x480 window
2
Instance Method Summary collapse
- #close ⇒ Object
- #controller_state ⇒ Object
-
#initialize(title: "PSX-Ruby") ⇒ Display
constructor
A new instance of Display.
- #poll_events ⇒ Object
- #quit_requested? ⇒ Boolean
- #update(framebuffer) ⇒ Object
Constructor Details
#initialize(title: "PSX-Ruby") ⇒ Display
Returns a new instance of Display.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/psx/display.rb', line 11 def initialize(title: "PSX-Ruby") SDL2.init(SDL2::INIT_VIDEO) @window = SDL2::Window.create( title, SDL2::Window::POS_CENTERED, SDL2::Window::POS_CENTERED, WIDTH * SCALE, HEIGHT * SCALE, 0 ) @renderer = @window.create_renderer(-1, SDL2::Renderer::Flags::ACCELERATED) # Input state @quit_requested = false @controller_state = 0xFFFF # All buttons released (active low) # Performance tracking @frame_count = 0 @last_fps_time = Time.now @fps = 0 # Cache texture reference @texture = nil # Pre-allocated RGBA buffer (320x240x4 = 307,200 bytes) @rgba_buffer = "\x00".b * (WIDTH * HEIGHT * 4) @rgba_buffer_size = WIDTH * HEIGHT * 4 # Track if we've seen real content @has_rendered_content = false end |
Instance Method Details
#close ⇒ Object
139 140 141 142 143 |
# File 'lib/psx/display.rb', line 139 def close @texture&.destroy @renderer.destroy @window.destroy end |
#controller_state ⇒ Object
135 136 137 |
# File 'lib/psx/display.rb', line 135 def controller_state @controller_state end |
#poll_events ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/psx/display.rb', line 118 def poll_events while (event = SDL2::Event.poll) case event when SDL2::Event::Quit @quit_requested = true when SDL2::Event::KeyDown handle_key(event.scancode, true) when SDL2::Event::KeyUp handle_key(event.scancode, false) end end end |
#quit_requested? ⇒ Boolean
131 132 133 |
# File 'lib/psx/display.rb', line 131 def quit_requested? @quit_requested end |
#update(framebuffer) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/psx/display.rb', line 45 def update(framebuffer) width = framebuffer[:width] height = framebuffer[:height] # GPU now provides pre-packed RGBA string rgba = framebuffer[:rgba] # Check if framebuffer has any non-zero content (only until first content seen) if rgba && !@has_rendered_content # Quick check: sample a few bytes instead of iterating all has_content = rgba.getbyte(0) != 0 || rgba.getbyte(rgba.bytesize / 2) != 0 @has_rendered_content = true if has_content end if rgba && @has_rendered_content @rgba_buffer = rgba else # Use cached loading screen if size matches buffer_size = width * height * 4 if @loading_screen_size != buffer_size # Generate loading screen pattern once rgba_arr = [] height.times do |y| width.times do |x| if (x % 32 < 2) || (y % 32 < 2) rgba_arr.push(40, 40, 80, 255) # Grid lines else rgba_arr.push(0, 0, 40, 255) # Dark blue end end end @loading_screen = rgba_arr.pack("C*") @loading_screen_size = buffer_size end @rgba_buffer = @loading_screen end # Create SDL surface from RGBA data surface = SDL2::Surface.from_string( @rgba_buffer, width, height, 32, # depth (bits per pixel) width * 4, # pitch (bytes per row) 0x000000FF, # R mask 0x0000FF00, # G mask 0x00FF0000, # B mask 0xFF000000 # A mask ) # Create texture from surface @texture&.destroy @texture = @renderer.create_texture_from(surface) surface.destroy # Render (stretch to window size) @renderer.copy(@texture, nil, nil) @renderer.present # Update FPS counter @frame_count += 1 @total_frames = (@total_frames || 0) + 1 now = Time.now elapsed = now - @last_fps_time if elapsed >= 1.0 @fps = (@frame_count / elapsed).round(1) status = has_content ? "RENDERING" : "Loading..." @window.title = "PSX-Ruby - #{@fps} FPS - Frame #{@total_frames} - #{status}" @frame_count = 0 @last_fps_time = now end end |