From: Mitchell Koch Date: 2006-07-31T15:01:31+09:00 Subject: Re: [QUIZ] Chip-8 (#88) --oyUTqETQ0mS9luUI Content-Type: text/plain; charset=us-ascii Content-Disposition: inline My solution for managing binary numbers was to make a new class BitArray. It seems like I'm repeating myself and being awfully wordy in the main loop. Mitchell Koch --oyUTqETQ0mS9luUI Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="chip8.rb" #!/usr/bin/env ruby # Chip-8 emulator class Chip8 # Load program def initialize(prog) # split program into 16 bit opcodes (4 hex digits) @prog = prog.unpack('S'*(prog.size/2)).inject([]) do |prog,i| prog << BitArray.new(i,16) end # initialize registers V0..VF to random 8 bit values @regs = (0x0..0xF).inject([]){|m,i| m< size raise "Cannot fit #{val} into #{size} bits." else @size = size end end # Initialize a bit array with a random value <= size def BitArray.rand(size) val = Kernel.rand(eval('0b'+'1'*size)) BitArray.new(val, size) end def hex "%x" % @val end # Make a new BitArray based on the digits of another def digits(digits) digits = [digits] unless digits.is_a? Enumerable hexnum = digits.inject(''){|m,i| m << hex[i].chr} numval = eval('0x'+hexnum) numsize = hexnum.size * 4 BitArray.new(numval, numsize) end def &(other) BitArray.new((val & other.val), size) end def |(other) BitArray.new((val | other.val), size) end def ^(other) BitArray.new((val ^ other.val), size) end def +(other) newval = val + other.val binval = '%b' % newval if binval.size > size [ BitArray.new(eval('0b'+binval[binval.size-size..-1]), size), BitArray.new(1, 8) ] else BitArray.new(newval, size) end end def -(other) if val >= other.val [ BitArray.new(val-other.val, size), BitArray.new(1, 8) ] else binval = '%b' % val borrowed = eval('0b1' + '0'*(size-binval.size) + binval) [ BitArray.new(borrowed-other.val, size), BitArray.new(0, 8) ] end end def rshift if val % 2 == 0 [BitArray.new(val/2,size), BitArray.new(0,8)] else [BitArray.new(val/2,size), BitArray.new(1,8)] end end def lshift binval = '%b' % val binval = '0'*(size-binval.size) + binval [ BitArray.new(eval('0b' + binval[1..-1] + '0'), size), BitArray.new(binval[0].chr.to_i, 8) ] end def ==(other) (val == other.val) && (size == other.size) end end if __FILE__ == $0 ARGV.each {|f| puts Chip8.new(File.read(f)).run} end --oyUTqETQ0mS9luUI--