Class: MicroCisc::Vm::Video

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(proc_count, mem_size, rom, debug = false) ⇒ Video

Returns a new instance of Video.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/micro_cisc/vm/video.rb', line 5

def initialize(proc_count, mem_size, rom, debug = false)
  @bytes_per_pixel = 2
  @w = 640
  @h = 480
  @refresh = 24
  @page_count = (@w * @h * @bytes_per_pixel + 511) / 512
  @enabled = 1

  # Initialize the control section of main memory
  config_mem = [@enabled, @w, @h, @bytes_per_pixel, @refresh]
  config_mem = config_mem + Array.new(256 - config_mem.size).map { 0 }
  @config_page = 16
  @start_page = 17
  @end_page = @config_page + @page_count

  @reader, @writer = IO.pipe

  fork do
    @reader.close
    system = System.new(proc_count, mem_size, rom, self, debug)
    system.write_page(@config_page, config_mem)
    system.run
  end

  @writer.close
  # Initialize the video memory space
  @memory = [config_mem] + Array.new(@page_count).map { Array.new(256).map { 0 } }
  launch
end

Instance Attribute Details

#config_pageObject (readonly)

Returns the value of attribute config_page.



4
5
6
# File 'lib/micro_cisc/vm/video.rb', line 4

def config_page
  @config_page
end

#end_pageObject (readonly)

Returns the value of attribute end_page.



4
5
6
# File 'lib/micro_cisc/vm/video.rb', line 4

def end_page
  @end_page
end

#page_countObject (readonly)

Returns the value of attribute page_count.



4
5
6
# File 'lib/micro_cisc/vm/video.rb', line 4

def page_count
  @page_count
end

#start_pageObject (readonly)

Returns the value of attribute start_page.



4
5
6
# File 'lib/micro_cisc/vm/video.rb', line 4

def start_page
  @start_page
end

Instance Method Details

#do_updateObject



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
117
118
119
120
121
122
123
124
125
# File 'lib/micro_cisc/vm/video.rb', line 74

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

  while(@reader.ready?) do
    msg = Message.read_from_stream(@reader)
    if msg.write?
      changed = true
      page = msg.local_page
      data = msg.data
      data = data[0...256] if data.size > 256
      @memory[page] = data

     if msg.local_page == 0
        @config_page = data
        @enabled, @w, @h, @bytes_per_pixel, @refresh = @config_page[0...4]
        @window.resize(@w, @h)
      else
        update_page(page)
      end
    else
      exit(0)
    end
  end

  if changed
    pixel_buffer = GdkPixbuf::Pixbuf.new(
      data: @image_data.pack("C*"),
      colorspace: GdkPixbuf::Colorspace::RGB,
      has_alpha: false,
      bits_per_sample: 8,
      width: 640,
      height: 480
    )
    new_image = Gtk::Image.new(pixel_buffer)
    @window.remove(@image)
    @window.add(new_image)
    new_image.show
    @window.show
    @image = new_image
  end
 
  @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

#launchObject



41
42
43
44
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
# File 'lib/micro_cisc/vm/video.rb', line 41

def launch
  require 'gtk2'
  
  Gtk.init

  @image_data = Array.new(@w * @h * 3).map { 0 }
  pixel_buffer = GdkPixbuf::Pixbuf.new(
    data: @image_data.pack("C*"),
    colorspace: GdkPixbuf::Colorspace::RGB,
    has_alpha: false,
    bits_per_sample: 8,
    width: 640,
    height: 480
  )
  @image = Gtk::Image.new(pixel_buffer)

  @window = Gtk::Window.new.set_default_size(640, 480)
  @window.set_title("uCISC Virtual Machine")
  @window.set_resizable(false)
  @window.add(@image)
  @image.show
  @window.signal_connect("destroy") do
    Gtk.main_quit
  end
  GLib::Timeout.add(15) do
    do_update
    true
  end
  @window.show

  Gtk.main
end

#send_page_update(main_page, data) ⇒ Object



35
36
37
38
39
# File 'lib/micro_cisc/vm/video.rb', line 35

def send_page_update(main_page, data)
  msg = Message.new
  msg.write(main_page, main_page - @config_page, data)
  msg.write_to_stream(@writer)
end

#update_page(page) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/micro_cisc/vm/video.rb', line 127

def update_page(page)
  word_offset = (page - 1) * 256
  finish = word_offset + 256
  row_words = @bytes_per_pixel * @w / 2
  pixel_x = word_offset % row_words
  pixel_y = (word_offset / row_words)

  while word_offset < finish
    word = @memory[page][word_offset % 256]
    pixel_offset = (pixel_y * @w + pixel_x) * 3
    @image_data[pixel_offset] = ((word & 0xF800) >> 8) + 7
    @image_data[pixel_offset + 1] = ((word & 0x07E0) >> 3) + 3
    @image_data[pixel_offset + 2] = ((word & 0x001F) << 3) + 7

    word_offset += 1
    pixel_x += 1
    if pixel_x % @w == 0
      pixel_x = 0
      pixel_y += 1
    end
  end
end