Class: MicroCisc::Vm::ColorLcdDisplay

Inherits:
Device
  • Object
show all
Defined in:
lib/micro_cisc/vm/color_lcd_display.rb

Constant Summary collapse

COLOR_MODE_12BIT =
1
COLOR_MODE_16BIT =
2
COLOR_MODES =
[COLOR_MODE_16BIT, COLOR_MODE_12BIT].freeze

Constants inherited from Device

Device::TYPE_BLOCK_IO, Device::TYPE_BLOCK_MEMORY, Device::TYPE_HID, Device::TYPE_INVALID, Device::TYPE_PROCESSOR, Device::TYPE_SERIAL, Device::TYPE_TERMINAL

Instance Attribute Summary

Attributes inherited from Device

#id

Instance Method Summary collapse

Methods inherited from Device

#bank_index=, #banked?, #devices=, #handle_control_read, #handle_control_update, #read_control, #read_mem, #write_control, #write_mem

Constructor Details

#initialize(device_id, mem_blocks, width, height, bit_mode) ⇒ ColorLcdDisplay

Returns a new instance of ColorLcdDisplay.



10
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
44
45
46
47
48
# File 'lib/micro_cisc/vm/color_lcd_display.rb', line 10

def initialize(device_id, mem_blocks, width, height, bit_mode)
  super(device_id, Device::TYPE_BLOCK_MEMORY, mem_blocks)
  @w = width
  @h = height
  @bit_mode = COLOR_MODES.include?(bit_mode) ? bit_mode : COLOR_MODES.first
  @image_data = Array.new(@w * @h * 3).map { 0 }
  @scale =
    if @w <= 320
      4
    elsif @w <= 640
      2
    else
      1
    end
  @control_mem[6] = @w
  @control_mem[7] = @h
  @privileged_read = @privileged_read | 0x0C0

  Gtk.init

  @window = Gtk::Window.new.set_default_size(@w * @scale, @h * @scale)
  @window.set_title("uCISC Virtual Machine")
  @window.set_resizable(false)

  update_screen

  @window.signal_connect("destroy") do
    Gtk.main_quit
  end
  GLib::Timeout.add(5) do
    do_update
    true
  end
  @window.show

  @window_thread = Thread.new do
    Gtk.main
  end
end

Instance Method Details

#do_updateObject



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/micro_cisc/vm/color_lcd_display.rb', line 72

def do_update
  @t0 ||= Time.now
  @tcount ||= 0

  update_image_data
  update_screen
 
  @tcount += 1
  if @tcount == 60
    delta = Time.now - @t0
    #puts "60 frames in #{delta}s (#{60 / delta} fps)"
    @t0 = Time.now
    @tcount = 0
  end
rescue Interrupt
end

#joinObject



50
51
52
# File 'lib/micro_cisc/vm/color_lcd_display.rb', line 50

def join
  @window_thread.join
end

#update_image_dataObject



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/micro_cisc/vm/color_lcd_display.rb', line 89

def update_image_data
  (0...@w).each do |x|
    (0...@h).each do |y|
      word_offset = y * @w + x
      pixel_offset = word_offset * 3
      word = read_mem(@id, word_offset, true)
      if (@bit_mode == COLOR_MODE_16BIT)
        r = (word & 0x0F00) >> 8
        @image_data[pixel_offset] = r + (r >> 5)
        g = (word & 0x07E0) >> 3
        @image_data[pixel_offset + 1] = g + (g >> 5)
        b = (word & 0x001F) << 3
        @image_data[pixel_offset + 2] = b + (b >> 5)
      elsif (@bit_mode == COLOR_MODE_12BIT)
        r = (word & 0x0F00) >> 4
        @image_data[pixel_offset] = r + (r >> 4)
        g = word & 0x00F0
        @image_data[pixel_offset + 1] = g + (g >> 4)
        b = (word & 0x000F) << 4
        @image_data[pixel_offset + 2] = b + (b >> 4)
      end
    end
  end
end

#update_screenObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/micro_cisc/vm/color_lcd_display.rb', line 54

def update_screen
  pixel_buffer = GdkPixbuf::Pixbuf.new(
    data: @image_data.pack("C*"),
    colorspace: GdkPixbuf::Colorspace::RGB,
    has_alpha: false,
    bits_per_sample: 8,
    width: @w,
    height: @h
  )
  pixel_buffer = pixel_buffer.scale_simple(@w * @scale, @h * @scale, 0)
  new_image = Gtk::Image.new(pixel_buffer)
  @window.remove(@image) if @image
  @window.add(new_image)
  new_image.show
  @window.show
  @image = new_image
end