[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Fwd: Please Forward: Ruby Quiz Submission

James Gray

7/30/2006 6:59:00 PM

Begin forwarded message:

> From: Daniel Martin <martin@snowplow.org>
> Date: July 29, 2006 10:16:17 PM CDT
> To: submission@rubyquiz.com
> Subject: Please Forward: Ruby Quiz Submission
>
> #! /usr/bin/env ruby
> # Here's my entry for the Chip8 quiz question - I expect to be far
> # away from net access when the time limit expires. I implemented
> # a few of the operations not in the quiz because they were very
> # easy to add, and I thought that they would be useful in writing
> # some of my own Chip-8 programs, but I ran out of time before
> vacation
> # and so never wrote my Chip-8 division program. Doing a full
> simulator
> # of Chip-8 with ASCII-art graphics sounds a bit interesting, and I
> # might do it at some point, depending on my desire for serious retro
> # computing.
> #
> # My program runs the file given as the first argument, or, if given
> # no arguments runs the test program from the quiz. The second and
> # subsequent arguments should be of the form <reg>=<value>, with
> # both <reg> and <value> written in hex.
> #
> # Only the registers whose values are changed (including those
> initialized
> # from the command line) are dumped when the program exits.
>
> class Chip8
> def initialize(memblock)
> @ip = 0
> @memblock = memblock
> @registers = Array.new(16){nil}
> end
>
> # These are the pieces of the current operation
> def op; (@memblock[@ip]||0)/16; end
> def x; (@memblock[@ip]||0)%16; end
> def y; (@memblock[@ip+1]||0)/16; end
> def k; (@memblock[@ip+1]||0); end
> def n; 256*x + k; end
> def op2;(@memblock[@ip+1]||0)%16; end
>
> # Some convenient accessor functions
> def [](r); @registers[r]; end
> def []=(r,v); @registers[r]=v; end
> def vx; self[x]; end
> def vy; self[y]; end
>
> # Used to implement both addition and subtraction
> def add(a,b)
> ret1 = a + b
> ret = ret1 & 0xff
> self[0xF] = (ret1!=ret)?1:0
> ret
> end
>
> def do_instruction
> case op
> when 0
> return false if [x,k] == [0,0]
> raise "bad/unknown opcode #{@memblock[@ip,2].unpack('H4')}"
> when 1; @ip=n; return true
> when 3; @ip += 2 if vx == k
> when 4; @ip += 2 if vx != k
> when 5; @ip += 2 if vx == vy
> when 6; self[x] = k
> when 7; self[x] = add(vx,k)
> when 8
> case op2
> when 0; self[x] = vy
> when 1; self[x] |= vy
> when 2; self[x] &= vy
> when 3; self[x] ^= vy
> when 4; self[x] = add(vx,vy)
> when 5; self[x] = add(vx,256-vy)
> when 7; self[x] = add(256-vx,vy)
> when 6; self[0xF] = vx & 1; self[x] >>= 1
> when 0xE; self[0xF] = vx >> 7; self[x] <<= 1
> else
> raise "bad opcode #{@memblock[@ip,2].unpack('H4')}"
> end
> when 12; self[x] = k & rand(256)
> else
> raise "bad opcode #{@memblock[@ip,2].unpack('H4')}"
> end
> @ip += 2
> return true
> end
>
> def run
> 1 while do_instruction
> end
>
> def dump
> contents = @registers.map {|a| a ? [a].pack('C').unpack("B8") :
> nil}
> @registers.each_index { |i|
> printf("V%X:%s (%d)\n",i,contents[i],@registers[i]) if
> contents[i]
> }
> end
>
> def Chip8.run(memblock, init={})
> a = Chip8.new(memblock)
> init.each{|h,k| a[h] = k}
> a.run
> a.dump
> end
> end
>
> if __FILE__ == $0
> if ARGV.empty?
> # test program from the quiz spec
> Chip8.run(%w{ 61 77 62 45 71 01 83 20 81 21 81 22
> 82 33 81 34 82 35 81 06 83 27 83 0e 64 ff c4 11
> 32 bb 10 00 00 00 }.map{|b| [b].pack("H2")}.join)
> else
> init = {}
> buff = ""
> if ARGV[1] and ARGV[1] =~ /^\d+$/
> buff = "\0" * ARGV[1].to_i
> end
> File.open(ARGV[0], "rb") {|f| buff += f.read}
> ARGV[1..-1].each {|s| r,v = s.split(/=/); init[r.hex]=v.hex}
> Chip8.run(buff, init)
> end
> end


1 Answer

Daniel Martin

7/31/2006 11:56:00 AM

0

> # Here's my entry for the Chip8 quiz question - I expect to be far
> # away from net access when the time limit expires. I implemented

Well who knew they'd have easily accessible wireless within spitting
distance of Rocky Mountain National Park?

Here's my solution again, but this time without > marks that prevent
people from trying it, and hopefully without mangled lines:

______________
#! /usr/bin/env ruby
# Here's my entry for the Chip8 quiz question - I expect to be far
# away from net access when the time limit expires. I implemented
# a few of the operations not in the quiz because they were very
# easy to add, and I thought that they would be useful in writing
# some of my own Chip-8 programs, but I ran out of time before vacation
# and so never wrote my Chip-8 division program. Doing a full simulator
# of Chip-8 with ASCII-art graphics sounds a bit interesting, and I
# might do it at some point, depending on my desire for serious retro
# computing.
#
# My program runs the file given as the first argument, or, if given
# no arguments runs the test program from the quiz. The second and
# subsequent arguments should be of the form <reg>=<value>, with
# both <reg> and <value> written in hex.
#
# Only the registers whose values are changed (including those initialized
# from the command line) are dumped when the program exits.

class Chip8
def initialize(memblock)
@ip = 0
@memblock = memblock
@registers = Array.new(16){nil}
end

# These are the pieces of the current operation
def op; (@memblock[@ip]||0)/16; end
def x; (@memblock[@ip]||0)%16; end
def y; (@memblock[@ip+1]||0)/16; end
def k; (@memblock[@ip+1]||0); end
def n; 256*x + k; end
def op2;(@memblock[@ip+1]||0)%16; end

# Some convenient accessor functions
def [](r); @registers[r]; end
def []=(r,v); @registers[r]=v; end
def vx; self[x]; end
def vy; self[y]; end

# Used to implement both addition and subtraction
def add(a,b)
ret1 = a + b
ret = ret1 & 0xff
self[0xF] = (ret1!=ret)?1:0
ret
end

def do_instruction
case op
when 0
return false if [x,k] == [0,0]
raise "bad/unknown opcode #{@memblock[@ip,2].unpack('H4')}"
when 1; @ip=n; return true
when 3; @ip += 2 if vx == k
when 4; @ip += 2 if vx != k
when 5; @ip += 2 if vx == vy
when 6; self[x] = k
when 7; self[x] = add(vx,k)
when 8
case op2
when 0; self[x] = vy
when 1; self[x] |= vy
when 2; self[x] &= vy
when 3; self[x] ^= vy
when 4; self[x] = add(vx,vy)
when 5; self[x] = add(vx,256-vy)
when 7; self[x] = add(256-vx,vy)
when 6; self[0xF] = vx & 1; self[x] >>= 1
when 0xE; self[0xF] = vx >> 7; self[x] <<= 1
else
raise "bad opcode #{@memblock[@ip,2].unpack('H4')}"
end
when 12; self[x] = k & rand(256)
else
raise "bad opcode #{@memblock[@ip,2].unpack('H4')}"
end
@ip += 2
return true
end

def run
1 while do_instruction
end

def dump
contents = @registers.map {|a| a ? [a].pack('C').unpack("B8") : nil}
@registers.each_index { |i|
printf("V%X:%s (%d)\n",i,contents[i],@registers[i]) if contents[i]
}
end

def Chip8.run(memblock, init={})
a = Chip8.new(memblock)
init.each{|h,k| a[h] = k}
a.run
a.dump
end
end

if __FILE__ == $0
if ARGV.empty?
# test program from the quiz spec
Chip8.run(%w{ 61 77 62 45 71 01 83 20 81 21 81 22
82 33 81 34 82 35 81 06 83 27 83 0e 64 ff c4 11
32 bb 10 00 00 00 }.map{|b| [b].pack("H2")}.join)
else
init = {}
buff = ""
if ARGV[1] and ARGV[1] =~ /^\d+$/
buff = "\0" * ARGV[1].to_i
end
File.open(ARGV[0], "rb") {|f| buff += f.read}
ARGV[1..-1].each {|s| r,v = s.split(/=/); init[r.hex]=v.hex}
Chip8.run(buff, init)
end
end

__END__