From: James Edward Gray II Date: 2006-08-01T04:15:24+09:00 Subject: Fwd: Please Forward: Ruby Quiz Submission (88) --Apple-Mail-2--27540162 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed Begin forwarded message: > From: afalcone@tinymonkey.net > Date: July 31, 2006 2:13:15 PM CDT > To: afalcone@tinymonkey.net > Cc: submission@rubyquiz.com > Subject: Re: Please Forward: Ruby Quiz Submission (88) > > Sorry to email you again, but there's a tiny bug in my original > program. > Please submit the one attached to this mail. > > Thanks, > -A > >> Hi James. Please forward my solution on to the board. >> >> Thanks, >> -Adrian --Apple-Mail-2--27540162 Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0666; name=chip8.rb Content-Disposition: attachment; filename=chip8.rb class UnsignedFixedWidthInt #code for this class taken from Hank Lords' solution to ruby quiz #85 #http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/199907 # #to_bin_string is mine #Direct access to @value added to assist carry and certain quicker assignments. #Kinda defeats the purpose of using this class, but I save on object creation in certain places # -AF attr_accessor :value def initialize(value, bits) raise ArgumentError.new('number of bits must be > 0') if bits <= 0 @bits = bits @value = value % 2**@bits end # operators returning a new FixedWidthInt %w{& ^ | << >> + - * / +@ -@ ~@}.each do |operator| define_method operator do |*other| self.class.new(@value.send(operator, *other), @bits) end end # methods forwarded to @value %w{== < > <=> inspect to_s to_i to_int}.each do |meth| define_method meth do |*other| @value.send(meth, *other) end end #this method was not in the original UFWI class # -AF def to_bin_string s = "" (@bits - 1).downto(0) { |i| s << @value[i].to_s } s end #modified from original because I never need Floats # -AF def coerce(other) [other, @value] end end class Integer def to_1_digit_hex #simplified to_hex method because I'll only ever need one digit raise ArgumentError, "doesn't work on negatives" if self < 0 raise ArgumentError, "#{self.to_s} is greater than 15" if self > 15 self < 10 ? self.to_s : (self - 10 + ?A).chr end end class InvalidOpCodeError < StandardError def initialize( io ) puts "Invalid Op Code starting at byte #{io.pos - 2}." end end class Chip8 def initialize( io=STDIN, carry_on_op7=1 ) raise ArgumentError, "Need an IO object" unless io.kind_of?( IO ) @code = io @v = Array.new( 16 ) { UnsignedFixedWidthInt.new( 0, 8 ) } @carry_on_op7 = carry_on_op7 end def parse hob = @code.getc lob = @code.getc raise EOFError, "File ends before opcode x0000" unless hob && lob case hob & 0xF0 when 0x00 if ( hob == 0 && lob == 0 ) @code.close rescue IOError return nil else raise InvalidOpCodeError.new( @code ) end when 0x10 @code.seek( ( ( hob & 0x0F ) << 8 ) + lob, IO::SEEK_SET ) when 0x30 @code.seek( 2, IO::SEEK_CUR ) if ( @v[ hob & 0x0F ] == lob ) when 0x60 @v[ hob & 0x0F ].value = lob when 0x70 @v[ 0 ].value = ( @carry_on_op7 && ( @v[ hob & 0x0F ].value + lob > 255 ) ) ? 1 : 0 @v[ hob & 0x0F ] += lob when 0x80 x = hob % 16 y = lob >> 4 case lob & 0x0F when 0x00 : @v[x].value = @v[y].value when 0x01 : @v[x] |= @v[y] when 0x02 : @v[x] &= @v[y] when 0x03 : @v[x] ^= @v[y] when 0x04 @v[ 0 ].value = @v[x].value + @v[y].value > 255 ? 1 : 0 @v[x] += @v[y] when 0x05 @v[ 0 ].value = @v[x].value < @v[y].value ? 1 : 0 @v[x] -= @v[y] when 0x06 if y == 0 @v[0].value = @v[x].value % 2 @v[x].value = @v[x].value >> 1 else raise InvalidOpCodeError.new( @code ) end when 0x07 @v[0].value = @v[y].value < @v[x].value ? 1 : 0 @v[x] = @v[y] - @v[x] when 0x0E if y == 0 @v[0].value = @v[x].value / 128 @v[x].value = ( @v[x].value << 1 ) % 256 else raise InvalidOpCodeError.new( @code ) end else raise InvalidOpCodeError.new( @code ) end when 0xC0 @v[ hob & 0x0F ].value = rand( 256 ) & lob else raise InvalidOpCodeError.new( @code ) end self end def dump_all 16.times { |i| puts "V#{i.to_1_digit_hex}:#{@v[i].to_bin_string}" } self end end if $0 == __FILE__ begin f=File.open( ARGV[0], "r" ) a=Chip8.new( f ) while( a.parse ) do; end a.dump_all rescue IOError puts "Please enter a valid Chip8 file name.\nExample: ruby chip8.rb Chip8Test" end end --Apple-Mail-2--27540162 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed --Apple-Mail-2--27540162--