diff --git a/spec/gb/cpu_spec.cr b/spec/gb/cpu_spec.cr new file mode 100644 index 0000000..2633633 --- /dev/null +++ b/spec/gb/cpu_spec.cr @@ -0,0 +1,772 @@ +require "./spec_helper" + +describe CPU do + describe "registers" do + it "do computations correctly across registers" do + cpu = new_cpu [] of UInt8 + cpu.b = 0x00 + cpu.c = 0x00 + cpu.bc.should eq 0x0000 + cpu.c += 0x01 + cpu.b.should eq 0x00 + cpu.c.should eq 0x01 + cpu.bc.should eq 0x0001 + cpu.bc += 0x4320 + cpu.b.should eq 0x43 + cpu.c.should eq 0x21 + cpu.bc.should eq 0x4321 + end + end + + describe "unprefixed opcode" do + describe "0x00" do + it "does nothing" do + cpu = new_cpu [0x00] + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + end + end + + describe "0x01" do + it "loads bc with d16" do + d16 = 0x1234 + cpu = new_cpu [0x01, d16 & 0xFF, d16 >> 8] + cpu.tick + + cpu.pc.should eq 3 + cpu.sp.should eq 0xFFFE + cpu.bc.should eq d16 + end + end + + describe "0x02" do + it "loads (bc) with a" do + cpu = new_cpu [0x02] + cpu.a = 0x34 + cpu.bc = 0xA000 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.memory[0xA000].should eq 0x34 + end + end + + describe "0x03" do + it "increments bc" do + cpu = new_cpu [0x03] + cpu.bc = 0x1234 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.bc.should eq 0x1235 + end + end + + describe "0x04" do + it "increments b" do + cpu = new_cpu [0x04] + cpu.b = 0x12 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.b.should eq 0x13 + end + end + + describe "0x05" do + it "decrements b" do + cpu = new_cpu [0x05] + cpu.b = 0x12 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.b.should eq 0x11 + end + end + + describe "0x06" do + it "loads b with d8" do + d8 = 0x12 + cpu = new_cpu [0x06, d8] + cpu.tick + + cpu.pc.should eq 2 + cpu.sp.should eq 0xFFFE + cpu.b.should eq d8 + end + end + + describe "0x07" do + it "rotates accumulator left w/o carry" do + cpu = new_cpu [0x07] + cpu.a = 0b01011010 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.a.should eq 0b10110100 + cpu.f_c.should eq false + end + + it "rotates accumulator left w/ carry" do + cpu = new_cpu [0x07] + cpu.a = 0b10100101 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.a.should eq 0b01001011 + cpu.f_c.should eq true + end + end + + describe "0x08" do + it "loads (d16) with sp" do + d16 = 0xA000 + cpu = new_cpu [0x08, d16 & 0xFF, d16 >> 8] + cpu.tick + + cpu.pc.should eq 3 + cpu.sp.should eq 0xFFFE + cpu.memory[0xA000] = 0xFFFE + end + end + + describe "0x09" do + it "adds bc to hl" do + cpu = new_cpu [0x09] + cpu.hl = 0x1010 + cpu.bc = 0x1111 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.hl.should eq 0x2121 + cpu.bc.should eq 0x1111 + end + end + + describe "0x0A" do + it "loads a with (bc)" do + cpu = new_cpu [0x0A, 0x12] + cpu.bc = 0x0001_u8 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.bc.should eq 0x0001 + cpu.memory[0x01].should eq 0x12 + end + end + + describe "0x0B" do + it "decrememnts bc" do + cpu = new_cpu [0x0B] + cpu.bc = 0x1234 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.bc.should eq 0x1233 + end + end + + describe "0x0C" do + it "increments c" do + cpu = new_cpu [0x0C] + cpu.c = 0x12 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.c.should eq 0x13 + end + end + + describe "0x0D" do + it "decrements c" do + cpu = new_cpu [0x0D] + cpu.c = 0x12 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.c.should eq 0x11 + end + end + + describe "0x0E" do + it "loads c with d8" do + cpu = new_cpu [0x0E, 0x12] + cpu.tick + + cpu.pc.should eq 2 + cpu.sp.should eq 0xFFFE + cpu.c.should eq 0x12 + end + end + + describe "0x0F" do + it "rotates accumulator right w/o carry" do + cpu = new_cpu [0x0F] + cpu.a = 0b01011010 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.a.should eq 0b00101101 + cpu.f_c.should eq false + end + + it "rotates accumulator right w/ carry" do + cpu = new_cpu [0x0F] + cpu.a = 0b10100101 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.a.should eq 0b11010010 + cpu.f_c.should eq true + end + end + + describe "0x10" do + it "stops execution" do + # todo: implement and test + end + end + + describe "0x11" do + it "loads de with d16" do + d16 = 0x1234 + cpu = new_cpu [0x11, d16 & 0xFF, d16 >> 8] + cpu.tick + + cpu.pc.should eq 3 + cpu.sp.should eq 0xFFFE + cpu.de.should eq d16 + end + end + + describe "0x12" do + it "loads (de) with a" do + cpu = new_cpu [0x12] + cpu.a = 0x34 + cpu.de = 0xA000 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.memory[0xA000].should eq 0x34 + end + end + + describe "0x13" do + it "increments de" do + cpu = new_cpu [0x13] + cpu.de = 0x1234 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.de.should eq 0x1235 + end + end + + describe "0x14" do + it "increments d" do + cpu = new_cpu [0x14] + cpu.d = 0x12 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.d.should eq 0x13 + end + end + + describe "0x15" do + it "decrements d" do + cpu = new_cpu [0x15] + cpu.d = 0x12 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.d.should eq 0x11 + end + end + + describe "0x16" do + it "loads d with d8" do + d8 = 0x12 + cpu = new_cpu [0x16, d8] + cpu.tick + + cpu.pc.should eq 2 + cpu.sp.should eq 0xFFFE + cpu.d.should eq d8 + end + end + + describe "0x17" do + it "rotates accumulator left through carry w/o carry" do + cpu = new_cpu [0x17] + cpu.a = 0b01011010 + cpu.f_c = true + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.a.should eq 0b10110101 + cpu.f_c.should eq false + end + + it "rotates accumulator left through carry w/ carry" do + cpu = new_cpu [0x17] + cpu.a = 0b10100101 + cpu.f_c = false + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.a.should eq 0b01001010 + cpu.f_c.should eq true + end + end + + # todo codes here + + describe "0x21" do + it "loads hl with d16" do + d16 = 0x1234 + cpu = new_cpu [0x21, d16 & 0xFF, d16 >> 8] + cpu.tick + + cpu.pc.should eq 3 + cpu.sp.should eq 0xFFFE + cpu.hl.should eq d16 + end + end + + describe "0x22" do + it "loads (hl+) with a" do + cpu = new_cpu [0x22] + cpu.a = 0x34 + cpu.hl = 0xA000 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.memory[0xA000].should eq 0x34 + cpu.hl.should eq 0xA001 + end + end + + describe "0x23" do + it "increments hl" do + cpu = new_cpu [0x23] + cpu.hl = 0x1234 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.hl.should eq 0x1235 + end + end + + describe "0x24" do + it "increments h" do + cpu = new_cpu [0x24] + cpu.h = 0x12 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.h.should eq 0x13 + end + end + + describe "0x25" do + it "decrements h" do + cpu = new_cpu [0x25] + cpu.h = 0x12 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.h.should eq 0x11 + end + end + + describe "0x26" do + it "loads h with d8" do + d8 = 0x12 + cpu = new_cpu [0x26, d8] + cpu.tick + + cpu.pc.should eq 2 + cpu.sp.should eq 0xFFFE + cpu.h.should eq d8 + end + end + + # todo codes here + + describe "0x31" do + it "loads sp with d16" do + d16 = 0x1234 + cpu = new_cpu [0x31, d16 & 0xFF, d16 >> 8] + cpu.tick + + cpu.pc.should eq 3 + cpu.sp.should eq d16 + end + end + + describe "0x32" do + it "loads (hl-) with a" do + cpu = new_cpu [0x32] + cpu.a = 0x34 + cpu.hl = 0xA000 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.memory[0xA000].should eq 0x34 + cpu.hl.should eq 0x9FFF + end + end + + describe "0x33" do + it "increments sp" do + cpu = new_cpu [0x33] + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFF + end + end + + describe "0x34" do + it "increments (hl)" do + cpu = new_cpu [0x34] + cpu.memory[0xA000] = 0x12_u8 + cpu.hl = 0xA000 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.memory[0xA000].should eq 0x13 + end + end + + describe "0x35" do + it "decrements (hl)" do + cpu = new_cpu [0x35] + cpu.memory[0xA000] = 0x12_u8 + cpu.hl = 0xA000 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + cpu.memory[0xA000].should eq 0x11 + end + end + + describe "0x36" do + it "loads (hl) with d8" do + d8 = 0x12 + cpu = new_cpu [0x36, d8] + cpu.hl = 0xA000 + cpu.tick + + cpu.pc.should eq 2 + cpu.sp.should eq 0xFFFE + cpu.memory[0xA000].should eq d8 + end + end + + # todo codes here + + describe "0xC0" do + it "returns if nz" do + cpu = new_cpu [0xC0] + cpu.sp = 0xFFF0_u16 + cpu.memory[0xFFF0] = 0x1234_u16 + cpu.f_z = false + cpu.tick + + cpu.pc.should eq 0x1234 + cpu.sp.should eq 0xFFF2 + end + + it "doesn't return if not nz" do + cpu = new_cpu [0xC0] + cpu.f_z = true + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + end + end + + describe "0xC1" do + it "pops bc" do + cpu = new_cpu [0xC1] + cpu.sp = 0xFFF0_u16 + cpu.memory[0xFFF0_u16] = 0x1234 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFF2 + cpu.bc.should eq 0x1234 + end + end + + describe "0xC2" do + it "jumps to a16 if nz" do + a16 = 0xA000 + cpu = new_cpu [0xC2, a16 & 0xFF, a16 >> 8] + cpu.f_z = false + cpu.tick + + cpu.pc.should eq a16 + cpu.sp.should eq 0xFFFE + end + + it "doesn't jump to a16 if not nz" do + a16 = 0xA000 + cpu = new_cpu [0xC2, a16 & 0xFF, a16 >> 8] + cpu.f_z = true + cpu.tick + + cpu.pc.should eq 3 + cpu.sp.should eq 0xFFFE + end + end + + describe "0xC3" do + it "jumps to a16" do + a16 = 0xA000 + cpu = new_cpu [0xC3, a16 & 0xFF, a16 >> 8] + cpu.tick + + cpu.pc.should eq 0xA000 + cpu.sp.should eq 0xFFFE + end + + it "jumps to a16 regardless of nz" do + a16 = 0xAC00 + cpu = new_cpu [0xC3, a16 & 0xFF, a16 >> 8] + cpu.f_z = false + cpu.tick + cpu.pc.should eq a16 + cpu = new_cpu [0xC3, a16 & 0xFF, a16 >> 8] + cpu.f_z = true + cpu.tick + cpu.pc.should eq a16 + end + end + + describe "0xC4" do + it "calls a16 if nz" do + a16 = 0xAC00 + cpu = new_cpu [0xC4, a16 & 0xFF, a16 >> 8] + cpu.f_z = false + cpu.tick + + cpu.pc.should eq 0xAC00 + cpu.sp.should eq 0xFFFC + cpu.memory[0xFFFD].should eq 0x00 + cpu.memory[0xFFFC].should eq 0x03 + end + + it "doesn't call a16 if not nz" do + a16 = 0xAC00 + cpu = new_cpu [0xC4, a16 & 0xFF, a16 >> 8] + cpu.f_z = true + cpu.tick + + cpu.pc.should eq 3 + cpu.sp.should eq 0xFFFE + end + end + + describe "0xC5" do + it "pushes bc" do + cpu = new_cpu [0xC5] + cpu.bc = 0x1234_u16 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFC + cpu.memory[0xFFFD].should eq 0x12 + cpu.memory[0xFFFC].should eq 0x34 + end + end + + describe "0xC6" do + it "adds d8 to a" do + d8 = 0x01 + cpu = new_cpu [0xC6, d8] + cpu.a = 0xFF + cpu.tick + + cpu.pc.should eq 2 + cpu.sp.should eq 0xFFFE + cpu.a.should eq 0x00 + cpu.f_z.should eq true + cpu.f_n.should eq false + cpu.f_h.should eq true + cpu.f_c.should eq true + end + end + + # todo codes here + + describe "0xD0" do + it "returns if nc" do + cpu = new_cpu [0xD0] + cpu.sp = 0xFFF0_u16 + cpu.memory[0xFFF0] = 0x1234_u16 + cpu.f_c = false + cpu.tick + + cpu.pc.should eq 0x1234 + cpu.sp.should eq 0xFFF2 + end + + it "doesn't return if not nc" do + cpu = new_cpu [0xD0] + cpu.f_c = true + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFE + end + end + + describe "0xD1" do + it "pops de" do + cpu = new_cpu [0xD1] + cpu.sp = 0xFFF0_u16 + cpu.memory[0xFFF0_u16] = 0x1234 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFF2 + cpu.de.should eq 0x1234 + end + end + + describe "0xD2" do + it "jumps to a16 if nc" do + a16 = 0xA000 + cpu = new_cpu [0xD2, a16 & 0xFF, a16 >> 8] + cpu.f_c = false + cpu.tick + + cpu.pc.should eq a16 + cpu.sp.should eq 0xFFFE + end + + it "doesn't jump to a16 if not nc" do + a16 = 0xA000 + cpu = new_cpu [0xD2, a16 & 0xFF, a16 >> 8] + cpu.f_c = true + cpu.tick + + cpu.pc.should eq 3 + cpu.sp.should eq 0xFFFE + end + end + + describe "0xD3" do + # unused opcode + end + + describe "0xD4" do + it "calls a16 if nc" do + a16 = 0xAC00 + cpu = new_cpu [0xD4, a16 & 0xFF, a16 >> 8] + cpu.f_c = false + cpu.tick + + cpu.pc.should eq 0xAC00 + cpu.sp.should eq 0xFFFC + cpu.memory[0xFFFD].should eq 0x00 + cpu.memory[0xFFFC].should eq 0x03 + end + + it "doesn't call a16 if not nc" do + a16 = 0xAC00 + cpu = new_cpu [0xD4, a16 & 0xFF, a16 >> 8] + cpu.f_c = true + cpu.tick + + cpu.pc.should eq 3 + cpu.sp.should eq 0xFFFE + end + end + + describe "0xD5" do + it "pushes de" do + cpu = new_cpu [0xD5] + cpu.de = 0x1234_u16 + cpu.tick + + cpu.pc.should eq 1 + cpu.sp.should eq 0xFFFC + cpu.memory[0xFFFD].should eq 0x12 + cpu.memory[0xFFFC].should eq 0x34 + end + end + + describe "0xD6" do + it "subs d8 from a" do + d8 = 0x01 + cpu = new_cpu [0xD6, d8] + cpu.a = 0x10 + cpu.tick + + cpu.pc.should eq 2 + cpu.sp.should eq 0xFFFE + cpu.a.should eq 0x0F + cpu.f_z.should eq false + cpu.f_n.should eq true + cpu.f_h.should eq true + cpu.f_c.should eq false + end + end + + # todo codes here + end + + describe "prefixed opcode" do + # todo codes here + + describe "0x40" do + it "tests bit 0 of b" do + cpu = new_cpu [0xCB, 0x40] + cpu.b = 0b01010101 + cpu.tick + + cpu.pc.should eq 2 + cpu.sp.should eq 0xFFFE + cpu.b.should eq 0b01010101 + cpu.f_z.should eq false + cpu.f_c.should eq false + cpu.f_h.should eq true + end + end + + # todo codes here + end +end diff --git a/spec/gb/cryboy_spec.cr b/spec/gb/cryboy_spec.cr new file mode 100644 index 0000000..db95d13 --- /dev/null +++ b/spec/gb/cryboy_spec.cr @@ -0,0 +1,4 @@ +require "./spec_helper" + +describe Crab do +end diff --git a/spec/gb/joypad_spec.cr b/spec/gb/joypad_spec.cr new file mode 100644 index 0000000..2abc4c9 --- /dev/null +++ b/spec/gb/joypad_spec.cr @@ -0,0 +1,54 @@ +describe Joypad do + it "defaults to buttons not pressed" do + joypad = Joypad.new + joypad.read.should eq 0b00111111 + end + + it "toggles button select" do + joypad = Joypad.new + joypad.write 0b00011111 + joypad.read.should eq 0b00011111 + joypad.write 0b00111111 + joypad.read.should eq 0b00111111 + end + + it "toggles direction select" do + joypad = Joypad.new + joypad.write 0b00101111 + joypad.read.should eq 0b00101111 + joypad.write 0b00111111 + joypad.read.should eq 0b00111111 + end + + it "only allows writing to selection keys" do + joypad = Joypad.new + joypad.write 0b00000000 + joypad.read.should eq 0b00001111 + joypad.write 0b11111111 + joypad.read.should eq 0b00111111 + end + + it "sets correct bits for one key down" do + joypad = Joypad.new + joypad.down = true + joypad.write 0b00100000 + joypad.read.should eq 0b00100111 + end + + it "sets correct bits for two different keys down" do + joypad = Joypad.new + joypad.down = true + joypad.b = true + joypad.write 0b00000000 + joypad.read.should eq 0b00000101 + end + + it "sets correct bits for two parallel keys down" do + joypad = Joypad.new + joypad.up = true + joypad.select = true + joypad.button_keys = true + joypad.direction_keys = true + joypad.read.should eq 0b00001011 + end +end diff --git a/spec/gb/memory_spec.cr b/spec/gb/memory_spec.cr new file mode 100644 index 0000000..404a40a --- /dev/null +++ b/spec/gb/memory_spec.cr @@ -0,0 +1,31 @@ +require "./spec_helper" + +describe GB::Memory do + it "can't write over rom" do + bytes = Array.new 0x8000, 0 + bytes[0] = 0x01 + bytes[1] = 0x02 + bytes[2] = 0x03 + memory = new_memory bytes + memory[0x0000] = 0x05_u8 + memory[0x0001] = 0x06_u8 + memory[0x3FFF] = 0x07_u8 + memory[0x4000] = 0x07_u8 + memory[0x7FFF] = 0x08_u8 + + memory[0x0000].should eq 0x01 + memory[0x0001].should eq 0x02 + memory[0x0002].should eq 0x03 + memory[0x3FFF].should eq 0x00 + memory[0x4000].should eq 0x00 + memory[0x7FFF].should eq 0x00 + end + + it "writes to external ram simple" do + memory = new_memory [0x00] + memory[0xA000] = 0x12.to_u8 + memory[0xBFFF] = 0x34.to_u8 + memory[0xA000].should eq 0x12 + memory[0xBFFF].should eq 0x34 + end +end diff --git a/spec/gb/run_test_roms.cr b/spec/gb/run_test_roms.cr new file mode 100644 index 0000000..6d76026 --- /dev/null +++ b/spec/gb/run_test_roms.cr @@ -0,0 +1,109 @@ +require "option_parser" + +TEST_RESULTS_DIR = "spec/gb/test_results" +SCREENSHOT_DIR = "#{TEST_RESULTS_DIR}/screenshots" +README_FILE = "#{TEST_RESULTS_DIR}/README.md" + +# kill process after given number of seconds +def kill(process : Process, after : Number = 5) : Nil + spawn do + sleep after + process.signal Signal::KILL if process.exists? + end +end + +def get_test_name(dir : String, test : String) : String + test.rpartition('.')[0][dir.size + 1, test.size] +end + +alias TestResult = NamedTuple(test: String, pass: Bool) +alias TestSuite = NamedTuple(suite: String, results: Array(TestResult)) + +test_results : Array(TestSuite) = [] of TestSuite + +acid_dir = "" +blargg_dir = "" +mealybug_dir = "" +mooneye_dir = "" + +OptionParser.parse do |parser| + parser.on("--acid PATH", "Path to directory with acid tests") { |path| acid_dir = path } + parser.on("--blargg PATH", "Path to directory with blargg tests") { |path| blargg = path } + parser.on("--mealybug PATH", "Path to directory with mealybug tests") { |path| mealybug_dir = path } + parser.on("--mooneye PATH", "Path to directory with mooneye tests") { |path| mooneye_dir = path } + parser.invalid_option { abort parser } +end + +system "shards build -Dgraphics_test > /dev/null" + +unless acid_dir == "" + [true, false].each do |fifo| + test_results << {suite: "Acid#{" Fifo" if fifo}", results: [] of TestResult} + puts "Acid #{"Fifo " if fifo}Tests" + Dir.glob("#{acid_dir}/*acid2.gb*").sort.each do |path| + test_name = get_test_name acid_dir, path + Process.run "bin/crab", [path, "--headless"] + (fifo ? ["--fifo"] : [] of String) do |process| + kill process, after: 1 + end + system %[touch out.png] # touch image in case something went wrong + system %[mv out.png #{SCREENSHOT_DIR}/#{test_name}#{"_fifo" if fifo}.png] + system %[compare -metric AE #{SCREENSHOT_DIR}/#{test_name}#{"_fifo" if fifo}.png #{SCREENSHOT_DIR}/expected/#{test_name}.png /tmp/crab_diff 2>/dev/null] + passed = $?.exit_status == 0 + test_results[test_results.size - 1][:results] << {test: test_name, pass: passed} + print passed ? "." : "F" + end + print "\n" + end +end + +unless mealybug_dir == "" + test_results << {suite: "Mealybug Fifo", results: [] of TestResult} + puts "Mealybug Fifo Tests" + Dir.glob("#{mealybug_dir}/**/*.gb").sort.each do |path| + test_name = get_test_name mealybug_dir, path + Process.run "bin/crab", [path, "--headless", "--fifo"] do |process| + kill process, after: 1 + end + system %[touch out.png] # touch image in case something went wrong + system %[mv out.png #{SCREENSHOT_DIR}/#{test_name}.png] + system %[compare -metric AE #{SCREENSHOT_DIR}/#{test_name}.png #{SCREENSHOT_DIR}/expected/#{test_name}.png /tmp/crab_diff 2>/dev/null] + passed = $?.exit_status == 0 + test_results[test_results.size - 1][:results] << {test: test_name, pass: passed} + print passed ? "." : "F" + end + print "\n" +end + +system "shards build --release -Dprint_serial > /dev/null" + +unless mooneye_dir == "" + test_results << {suite: "Mooneye", results: [] of TestResult} + puts "Mooneye Tests" + fib_string = "358132134" + Dir.glob("#{mooneye_dir}/**/*.gb").sort.each do |path| + next if path.includes?("util") || path.includes?("manual-only") || path.includes?("dmg") || path.includes?("mgb") || path.includes?("sgb") + test_name = get_test_name mooneye_dir, path + passed = false + Process.run("bin/crab", [path, "--headless"]) do |process| + kill process, after: 10 # seconds + result = process.output.gets 9 + process.terminate if process.exists? + passed = result == fib_string + end + test_results[test_results.size - 1][:results] << {test: test_name, pass: passed} + print passed ? "." : "F" + end + print "\n" +end + +File.open README_FILE, "w" do |file| + file.puts "# Test Results" + test_results.each do |test_suite| + file.puts "## #{test_suite[:suite]} Tests" + file.puts "| Result | Test Name |" + file.puts "|--------|-----------|" + test_suite[:results].each do |test_result| + file.puts "| #{test_result[:pass] ? "👌" : "👀"} | #{test_result[:test]} |" + end + end +end diff --git a/spec/gb/spec_helper.cr b/spec/gb/spec_helper.cr new file mode 100644 index 0000000..eacae48 --- /dev/null +++ b/spec/gb/spec_helper.cr @@ -0,0 +1,28 @@ +# define a new CPU with the given bytes as rom +def new_cpu(bytes : Array(Int), cgb_enabled = true, boot = false) + interrupts = Interrupts.new + display = Display.new + ppu = PPU.new display, interrupts, pointerof(cgb_enabled) + apu = APU.new + timer = Timer.new interrupts + + cpu = CPU.new new_memory(bytes), interrupts, ppu, apu, timer, boot + cpu.sp = 0xFFFE_u16 + cpu +end + +# define a new Memory with the given bytes as rom +def new_memory(bytes : Array(Int), cgb_enabled = true, bootrom = nil) + rom = Bytes.new 0x8000 + bytes.each_with_index do |byte, i| + rom[i] = byte.to_u8! + end + cartridge = GB::Cartridge.new rom + interrupts = GB::Interrupts.new + display = GB::Display.new + ppu = GB::PPU.new display, interrupts, pointerof(cgb_enabled) + apu = GB::APU.new + timer = GB::Timer.new interrupts + joypad = GB::Joypad.new + GB::Memory.new cartridge, interrupts, ppu, apu, timer, joypad, pointerof(cgb_enabled), bootrom +end diff --git a/spec/gb/test_results/README.md b/spec/gb/test_results/README.md new file mode 100644 index 0000000..15d50ef --- /dev/null +++ b/spec/gb/test_results/README.md @@ -0,0 +1,149 @@ +# Test Results +## Acid Fifo Tests +| Result | Test Name | +|--------|-----------| +| 👌 | cgb-acid2 | +| 👌 | dmg-acid2 | +## Acid Tests +| Result | Test Name | +|--------|-----------| +| 👌 | cgb-acid2 | +| 👌 | dmg-acid2 | +## Mealybug Fifo Tests +| Result | Test Name | +|--------|-----------| +| 👀 | m2_win_en_toggle | +| 👀 | m3_bgp_change | +| 👀 | m3_bgp_change_sprites | +| 👀 | m3_lcdc_bg_en_change | +| 👀 | m3_lcdc_bg_en_change2 | +| 👀 | m3_lcdc_bg_map_change | +| 👀 | m3_lcdc_bg_map_change2 | +| 👀 | m3_lcdc_obj_en_change | +| 👀 | m3_lcdc_obj_en_change_variant | +| 👀 | m3_lcdc_obj_size_change | +| 👀 | m3_lcdc_obj_size_change_scx | +| 👀 | m3_lcdc_tile_sel_change | +| 👀 | m3_lcdc_tile_sel_change2 | +| 👀 | m3_lcdc_tile_sel_win_change | +| 👀 | m3_lcdc_tile_sel_win_change2 | +| 👀 | m3_lcdc_win_en_change_multiple | +| 👀 | m3_lcdc_win_en_change_multiple_wx | +| 👀 | m3_lcdc_win_map_change | +| 👀 | m3_lcdc_win_map_change2 | +| 👀 | m3_obp0_change | +| 👀 | m3_scx_high_5_bits | +| 👀 | m3_scx_high_5_bits_change2 | +| 👌 | m3_scx_low_3_bits | +| 👀 | m3_scy_change | +| 👀 | m3_scy_change2 | +| 👀 | m3_window_timing | +| 👀 | m3_window_timing_wx_0 | +| 👀 | m3_wx_4_change | +| 👀 | m3_wx_4_change_sprites | +| 👀 | m3_wx_5_change | +| 👀 | m3_wx_6_change | +## Mooneye Tests +| Result | Test Name | +|--------|-----------| +| 👌 | acceptance/add_sp_e_timing | +| 👌 | acceptance/bits/mem_oam | +| 👌 | acceptance/bits/reg_f | +| 👀 | acceptance/bits/unused_hwio-GS | +| 👀 | acceptance/boot_div-S | +| 👀 | acceptance/boot_div2-S | +| 👀 | acceptance/boot_hwio-S | +| 👌 | acceptance/call_cc_timing | +| 👌 | acceptance/call_cc_timing2 | +| 👌 | acceptance/call_timing | +| 👌 | acceptance/call_timing2 | +| 👌 | acceptance/di_timing-GS | +| 👌 | acceptance/div_timing | +| 👌 | acceptance/ei_sequence | +| 👌 | acceptance/ei_timing | +| 👌 | acceptance/halt_ime0_ei | +| 👌 | acceptance/halt_ime0_nointr_timing | +| 👌 | acceptance/halt_ime1_timing | +| 👌 | acceptance/halt_ime1_timing2-GS | +| 👌 | acceptance/if_ie_registers | +| 👌 | acceptance/instr/daa | +| 👌 | acceptance/interrupts/ie_push | +| 👌 | acceptance/intr_timing | +| 👌 | acceptance/jp_cc_timing | +| 👌 | acceptance/jp_timing | +| 👌 | acceptance/ld_hl_sp_e_timing | +| 👌 | acceptance/oam_dma/basic | +| 👌 | acceptance/oam_dma/reg_read | +| 👀 | acceptance/oam_dma/sources-GS | +| 👌 | acceptance/oam_dma_restart | +| 👌 | acceptance/oam_dma_start | +| 👌 | acceptance/oam_dma_timing | +| 👌 | acceptance/pop_timing | +| 👀 | acceptance/ppu/hblank_ly_scx_timing-GS | +| 👌 | acceptance/ppu/intr_1_2_timing-GS | +| 👌 | acceptance/ppu/intr_2_0_timing | +| 👀 | acceptance/ppu/intr_2_mode0_timing | +| 👀 | acceptance/ppu/intr_2_mode0_timing_sprites | +| 👀 | acceptance/ppu/intr_2_mode3_timing | +| 👀 | acceptance/ppu/intr_2_oam_ok_timing | +| 👀 | acceptance/ppu/lcdon_timing-GS | +| 👀 | acceptance/ppu/lcdon_write_timing-GS | +| 👌 | acceptance/ppu/stat_irq_blocking | +| 👀 | acceptance/ppu/stat_lyc_onoff | +| 👀 | acceptance/ppu/vblank_stat_intr-GS | +| 👌 | acceptance/push_timing | +| 👌 | acceptance/rapid_di_ei | +| 👌 | acceptance/ret_cc_timing | +| 👌 | acceptance/ret_timing | +| 👌 | acceptance/reti_intr_timing | +| 👌 | acceptance/reti_timing | +| 👌 | acceptance/rst_timing | +| 👌 | acceptance/timer/div_write | +| 👌 | acceptance/timer/rapid_toggle | +| 👌 | acceptance/timer/tim00 | +| 👌 | acceptance/timer/tim00_div_trigger | +| 👌 | acceptance/timer/tim01 | +| 👌 | acceptance/timer/tim01_div_trigger | +| 👌 | acceptance/timer/tim10 | +| 👌 | acceptance/timer/tim10_div_trigger | +| 👌 | acceptance/timer/tim11 | +| 👌 | acceptance/timer/tim11_div_trigger | +| 👌 | acceptance/timer/tima_reload | +| 👌 | acceptance/timer/tima_write_reloading | +| 👌 | acceptance/timer/tma_write_reloading | +| 👌 | emulator-only/mbc1/bits_bank1 | +| 👌 | emulator-only/mbc1/bits_bank2 | +| 👌 | emulator-only/mbc1/bits_mode | +| 👌 | emulator-only/mbc1/bits_ramg | +| 👀 | emulator-only/mbc1/multicart_rom_8Mb | +| 👌 | emulator-only/mbc1/ram_256kb | +| 👌 | emulator-only/mbc1/ram_64kb | +| 👌 | emulator-only/mbc1/rom_16Mb | +| 👌 | emulator-only/mbc1/rom_1Mb | +| 👌 | emulator-only/mbc1/rom_2Mb | +| 👌 | emulator-only/mbc1/rom_4Mb | +| 👌 | emulator-only/mbc1/rom_512kb | +| 👌 | emulator-only/mbc1/rom_8Mb | +| 👌 | emulator-only/mbc2/bits_ramg | +| 👌 | emulator-only/mbc2/bits_romb | +| 👌 | emulator-only/mbc2/bits_unused | +| 👌 | emulator-only/mbc2/ram | +| 👌 | emulator-only/mbc2/rom_1Mb | +| 👌 | emulator-only/mbc2/rom_2Mb | +| 👌 | emulator-only/mbc2/rom_512kb | +| 👌 | emulator-only/mbc5/rom_16Mb | +| 👌 | emulator-only/mbc5/rom_1Mb | +| 👌 | emulator-only/mbc5/rom_2Mb | +| 👌 | emulator-only/mbc5/rom_32Mb | +| 👌 | emulator-only/mbc5/rom_4Mb | +| 👌 | emulator-only/mbc5/rom_512kb | +| 👌 | emulator-only/mbc5/rom_64Mb | +| 👌 | emulator-only/mbc5/rom_8Mb | +| 👌 | misc/bits/unused_hwio-C | +| 👀 | misc/boot_div-A | +| 👀 | misc/boot_div-cgb0 | +| 👌 | misc/boot_div-cgbABCDE | +| 👀 | misc/boot_hwio-C | +| 👀 | misc/boot_regs-A | +| 👌 | misc/boot_regs-cgb | +| 👀 | misc/ppu/vblank_stat_intr-C | diff --git a/spec/gb/test_results/readme.md b/spec/gb/test_results/readme.md new file mode 100644 index 0000000..15d50ef --- /dev/null +++ b/spec/gb/test_results/readme.md @@ -0,0 +1,149 @@ +# Test Results +## Acid Fifo Tests +| Result | Test Name | +|--------|-----------| +| 👌 | cgb-acid2 | +| 👌 | dmg-acid2 | +## Acid Tests +| Result | Test Name | +|--------|-----------| +| 👌 | cgb-acid2 | +| 👌 | dmg-acid2 | +## Mealybug Fifo Tests +| Result | Test Name | +|--------|-----------| +| 👀 | m2_win_en_toggle | +| 👀 | m3_bgp_change | +| 👀 | m3_bgp_change_sprites | +| 👀 | m3_lcdc_bg_en_change | +| 👀 | m3_lcdc_bg_en_change2 | +| 👀 | m3_lcdc_bg_map_change | +| 👀 | m3_lcdc_bg_map_change2 | +| 👀 | m3_lcdc_obj_en_change | +| 👀 | m3_lcdc_obj_en_change_variant | +| 👀 | m3_lcdc_obj_size_change | +| 👀 | m3_lcdc_obj_size_change_scx | +| 👀 | m3_lcdc_tile_sel_change | +| 👀 | m3_lcdc_tile_sel_change2 | +| 👀 | m3_lcdc_tile_sel_win_change | +| 👀 | m3_lcdc_tile_sel_win_change2 | +| 👀 | m3_lcdc_win_en_change_multiple | +| 👀 | m3_lcdc_win_en_change_multiple_wx | +| 👀 | m3_lcdc_win_map_change | +| 👀 | m3_lcdc_win_map_change2 | +| 👀 | m3_obp0_change | +| 👀 | m3_scx_high_5_bits | +| 👀 | m3_scx_high_5_bits_change2 | +| 👌 | m3_scx_low_3_bits | +| 👀 | m3_scy_change | +| 👀 | m3_scy_change2 | +| 👀 | m3_window_timing | +| 👀 | m3_window_timing_wx_0 | +| 👀 | m3_wx_4_change | +| 👀 | m3_wx_4_change_sprites | +| 👀 | m3_wx_5_change | +| 👀 | m3_wx_6_change | +## Mooneye Tests +| Result | Test Name | +|--------|-----------| +| 👌 | acceptance/add_sp_e_timing | +| 👌 | acceptance/bits/mem_oam | +| 👌 | acceptance/bits/reg_f | +| 👀 | acceptance/bits/unused_hwio-GS | +| 👀 | acceptance/boot_div-S | +| 👀 | acceptance/boot_div2-S | +| 👀 | acceptance/boot_hwio-S | +| 👌 | acceptance/call_cc_timing | +| 👌 | acceptance/call_cc_timing2 | +| 👌 | acceptance/call_timing | +| 👌 | acceptance/call_timing2 | +| 👌 | acceptance/di_timing-GS | +| 👌 | acceptance/div_timing | +| 👌 | acceptance/ei_sequence | +| 👌 | acceptance/ei_timing | +| 👌 | acceptance/halt_ime0_ei | +| 👌 | acceptance/halt_ime0_nointr_timing | +| 👌 | acceptance/halt_ime1_timing | +| 👌 | acceptance/halt_ime1_timing2-GS | +| 👌 | acceptance/if_ie_registers | +| 👌 | acceptance/instr/daa | +| 👌 | acceptance/interrupts/ie_push | +| 👌 | acceptance/intr_timing | +| 👌 | acceptance/jp_cc_timing | +| 👌 | acceptance/jp_timing | +| 👌 | acceptance/ld_hl_sp_e_timing | +| 👌 | acceptance/oam_dma/basic | +| 👌 | acceptance/oam_dma/reg_read | +| 👀 | acceptance/oam_dma/sources-GS | +| 👌 | acceptance/oam_dma_restart | +| 👌 | acceptance/oam_dma_start | +| 👌 | acceptance/oam_dma_timing | +| 👌 | acceptance/pop_timing | +| 👀 | acceptance/ppu/hblank_ly_scx_timing-GS | +| 👌 | acceptance/ppu/intr_1_2_timing-GS | +| 👌 | acceptance/ppu/intr_2_0_timing | +| 👀 | acceptance/ppu/intr_2_mode0_timing | +| 👀 | acceptance/ppu/intr_2_mode0_timing_sprites | +| 👀 | acceptance/ppu/intr_2_mode3_timing | +| 👀 | acceptance/ppu/intr_2_oam_ok_timing | +| 👀 | acceptance/ppu/lcdon_timing-GS | +| 👀 | acceptance/ppu/lcdon_write_timing-GS | +| 👌 | acceptance/ppu/stat_irq_blocking | +| 👀 | acceptance/ppu/stat_lyc_onoff | +| 👀 | acceptance/ppu/vblank_stat_intr-GS | +| 👌 | acceptance/push_timing | +| 👌 | acceptance/rapid_di_ei | +| 👌 | acceptance/ret_cc_timing | +| 👌 | acceptance/ret_timing | +| 👌 | acceptance/reti_intr_timing | +| 👌 | acceptance/reti_timing | +| 👌 | acceptance/rst_timing | +| 👌 | acceptance/timer/div_write | +| 👌 | acceptance/timer/rapid_toggle | +| 👌 | acceptance/timer/tim00 | +| 👌 | acceptance/timer/tim00_div_trigger | +| 👌 | acceptance/timer/tim01 | +| 👌 | acceptance/timer/tim01_div_trigger | +| 👌 | acceptance/timer/tim10 | +| 👌 | acceptance/timer/tim10_div_trigger | +| 👌 | acceptance/timer/tim11 | +| 👌 | acceptance/timer/tim11_div_trigger | +| 👌 | acceptance/timer/tima_reload | +| 👌 | acceptance/timer/tima_write_reloading | +| 👌 | acceptance/timer/tma_write_reloading | +| 👌 | emulator-only/mbc1/bits_bank1 | +| 👌 | emulator-only/mbc1/bits_bank2 | +| 👌 | emulator-only/mbc1/bits_mode | +| 👌 | emulator-only/mbc1/bits_ramg | +| 👀 | emulator-only/mbc1/multicart_rom_8Mb | +| 👌 | emulator-only/mbc1/ram_256kb | +| 👌 | emulator-only/mbc1/ram_64kb | +| 👌 | emulator-only/mbc1/rom_16Mb | +| 👌 | emulator-only/mbc1/rom_1Mb | +| 👌 | emulator-only/mbc1/rom_2Mb | +| 👌 | emulator-only/mbc1/rom_4Mb | +| 👌 | emulator-only/mbc1/rom_512kb | +| 👌 | emulator-only/mbc1/rom_8Mb | +| 👌 | emulator-only/mbc2/bits_ramg | +| 👌 | emulator-only/mbc2/bits_romb | +| 👌 | emulator-only/mbc2/bits_unused | +| 👌 | emulator-only/mbc2/ram | +| 👌 | emulator-only/mbc2/rom_1Mb | +| 👌 | emulator-only/mbc2/rom_2Mb | +| 👌 | emulator-only/mbc2/rom_512kb | +| 👌 | emulator-only/mbc5/rom_16Mb | +| 👌 | emulator-only/mbc5/rom_1Mb | +| 👌 | emulator-only/mbc5/rom_2Mb | +| 👌 | emulator-only/mbc5/rom_32Mb | +| 👌 | emulator-only/mbc5/rom_4Mb | +| 👌 | emulator-only/mbc5/rom_512kb | +| 👌 | emulator-only/mbc5/rom_64Mb | +| 👌 | emulator-only/mbc5/rom_8Mb | +| 👌 | misc/bits/unused_hwio-C | +| 👀 | misc/boot_div-A | +| 👀 | misc/boot_div-cgb0 | +| 👌 | misc/boot_div-cgbABCDE | +| 👀 | misc/boot_hwio-C | +| 👀 | misc/boot_regs-A | +| 👌 | misc/boot_regs-cgb | +| 👀 | misc/ppu/vblank_stat_intr-C | diff --git a/spec/gb/test_results/screenshots/cgb-acid2.png b/spec/gb/test_results/screenshots/cgb-acid2.png new file mode 100644 index 0000000..e227dfe Binary files /dev/null and b/spec/gb/test_results/screenshots/cgb-acid2.png differ diff --git a/spec/gb/test_results/screenshots/cgb-acid2_fifo.png b/spec/gb/test_results/screenshots/cgb-acid2_fifo.png new file mode 100644 index 0000000..e227dfe Binary files /dev/null and b/spec/gb/test_results/screenshots/cgb-acid2_fifo.png differ diff --git a/spec/gb/test_results/screenshots/dmg-acid2.png b/spec/gb/test_results/screenshots/dmg-acid2.png new file mode 100644 index 0000000..ebdd4a9 Binary files /dev/null and b/spec/gb/test_results/screenshots/dmg-acid2.png differ diff --git a/spec/gb/test_results/screenshots/dmg-acid2_fifo.png b/spec/gb/test_results/screenshots/dmg-acid2_fifo.png new file mode 100644 index 0000000..ebdd4a9 Binary files /dev/null and b/spec/gb/test_results/screenshots/dmg-acid2_fifo.png differ diff --git a/spec/gb/test_results/screenshots/expected/cgb-acid2.png b/spec/gb/test_results/screenshots/expected/cgb-acid2.png new file mode 100644 index 0000000..92e9c09 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/cgb-acid2.png differ diff --git a/spec/gb/test_results/screenshots/expected/dmg-acid2.png b/spec/gb/test_results/screenshots/expected/dmg-acid2.png new file mode 100644 index 0000000..345a6c4 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/dmg-acid2.png differ diff --git a/spec/gb/test_results/screenshots/expected/m2_win_en_toggle.png b/spec/gb/test_results/screenshots/expected/m2_win_en_toggle.png new file mode 100644 index 0000000..66da948 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m2_win_en_toggle.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_bgp_change.png b/spec/gb/test_results/screenshots/expected/m3_bgp_change.png new file mode 100644 index 0000000..1eaed2c Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_bgp_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_bgp_change_sprites.png b/spec/gb/test_results/screenshots/expected/m3_bgp_change_sprites.png new file mode 100644 index 0000000..8dd4269 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_bgp_change_sprites.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_en_change.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_en_change.png new file mode 100644 index 0000000..5107eb5 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_en_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_en_change2.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_en_change2.png new file mode 100644 index 0000000..d042a80 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_en_change2.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_map_change.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_map_change.png new file mode 100644 index 0000000..8d47a3c Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_map_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_map_change2.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_map_change2.png new file mode 100644 index 0000000..c84b45b Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_bg_map_change2.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_en_change.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_en_change.png new file mode 100644 index 0000000..2fe28ea Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_en_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_en_change_variant.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_en_change_variant.png new file mode 100644 index 0000000..8f35f76 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_en_change_variant.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_size_change.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_size_change.png new file mode 100644 index 0000000..2692919 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_size_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_size_change_scx.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_size_change_scx.png new file mode 100644 index 0000000..05b542d Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_obj_size_change_scx.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_change.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_change.png new file mode 100644 index 0000000..bbe6e5c Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_change2.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_change2.png new file mode 100644 index 0000000..a809321 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_change2.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_win_change.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_win_change.png new file mode 100644 index 0000000..9ae708f Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_win_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_win_change2.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_win_change2.png new file mode 100644 index 0000000..efd7a09 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_tile_sel_win_change2.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_win_en_change_multiple.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_win_en_change_multiple.png new file mode 100644 index 0000000..fa89ec2 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_win_en_change_multiple.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_win_en_change_multiple_wx.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_win_en_change_multiple_wx.png new file mode 100644 index 0000000..6477623 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_win_en_change_multiple_wx.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_win_map_change.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_win_map_change.png new file mode 100644 index 0000000..4e81b8a Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_win_map_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_lcdc_win_map_change2.png b/spec/gb/test_results/screenshots/expected/m3_lcdc_win_map_change2.png new file mode 100644 index 0000000..dacf86b Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_lcdc_win_map_change2.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_obp0_change.png b/spec/gb/test_results/screenshots/expected/m3_obp0_change.png new file mode 100644 index 0000000..065e2fe Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_obp0_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_scx_high_5_bits.png b/spec/gb/test_results/screenshots/expected/m3_scx_high_5_bits.png new file mode 100644 index 0000000..d7e25b5 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_scx_high_5_bits.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_scx_high_5_bits_change2.png b/spec/gb/test_results/screenshots/expected/m3_scx_high_5_bits_change2.png new file mode 100644 index 0000000..2e64918 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_scx_high_5_bits_change2.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_scx_low_3_bits.png b/spec/gb/test_results/screenshots/expected/m3_scx_low_3_bits.png new file mode 100644 index 0000000..bd7db2f Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_scx_low_3_bits.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_scy_change.png b/spec/gb/test_results/screenshots/expected/m3_scy_change.png new file mode 100644 index 0000000..2468d22 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_scy_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_scy_change2.png b/spec/gb/test_results/screenshots/expected/m3_scy_change2.png new file mode 100644 index 0000000..ab60b58 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_scy_change2.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_window_timing.png b/spec/gb/test_results/screenshots/expected/m3_window_timing.png new file mode 100644 index 0000000..30c9fa7 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_window_timing.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_window_timing_wx_0.png b/spec/gb/test_results/screenshots/expected/m3_window_timing_wx_0.png new file mode 100644 index 0000000..de5d3f0 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_window_timing_wx_0.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_wx_4_change.png b/spec/gb/test_results/screenshots/expected/m3_wx_4_change.png new file mode 100644 index 0000000..edf7e28 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_wx_4_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_wx_4_change_sprites.png b/spec/gb/test_results/screenshots/expected/m3_wx_4_change_sprites.png new file mode 100644 index 0000000..9620fe9 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_wx_4_change_sprites.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_wx_5_change.png b/spec/gb/test_results/screenshots/expected/m3_wx_5_change.png new file mode 100644 index 0000000..1d0d058 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_wx_5_change.png differ diff --git a/spec/gb/test_results/screenshots/expected/m3_wx_6_change.png b/spec/gb/test_results/screenshots/expected/m3_wx_6_change.png new file mode 100644 index 0000000..daaca82 Binary files /dev/null and b/spec/gb/test_results/screenshots/expected/m3_wx_6_change.png differ diff --git a/spec/gb/test_results/screenshots/m2_win_en_toggle.png b/spec/gb/test_results/screenshots/m2_win_en_toggle.png new file mode 100644 index 0000000..c2e3994 Binary files /dev/null and b/spec/gb/test_results/screenshots/m2_win_en_toggle.png differ diff --git a/spec/gb/test_results/screenshots/m3_bgp_change.png b/spec/gb/test_results/screenshots/m3_bgp_change.png new file mode 100644 index 0000000..5c7b948 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_bgp_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_bgp_change_sprites.png b/spec/gb/test_results/screenshots/m3_bgp_change_sprites.png new file mode 100644 index 0000000..f64a99a Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_bgp_change_sprites.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_bg_en_change.png b/spec/gb/test_results/screenshots/m3_lcdc_bg_en_change.png new file mode 100644 index 0000000..0d04855 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_bg_en_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_bg_en_change2.png b/spec/gb/test_results/screenshots/m3_lcdc_bg_en_change2.png new file mode 100644 index 0000000..4027b9c Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_bg_en_change2.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_bg_map_change.png b/spec/gb/test_results/screenshots/m3_lcdc_bg_map_change.png new file mode 100644 index 0000000..648ee9e Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_bg_map_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_bg_map_change2.png b/spec/gb/test_results/screenshots/m3_lcdc_bg_map_change2.png new file mode 100644 index 0000000..4027b9c Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_bg_map_change2.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_obj_en_change.png b/spec/gb/test_results/screenshots/m3_lcdc_obj_en_change.png new file mode 100644 index 0000000..07c7952 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_obj_en_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_obj_en_change_variant.png b/spec/gb/test_results/screenshots/m3_lcdc_obj_en_change_variant.png new file mode 100644 index 0000000..07c7952 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_obj_en_change_variant.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_obj_size_change.png b/spec/gb/test_results/screenshots/m3_lcdc_obj_size_change.png new file mode 100644 index 0000000..74d7831 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_obj_size_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_obj_size_change_scx.png b/spec/gb/test_results/screenshots/m3_lcdc_obj_size_change_scx.png new file mode 100644 index 0000000..b56e5be Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_obj_size_change_scx.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_change.png b/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_change.png new file mode 100644 index 0000000..495fb74 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_change2.png b/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_change2.png new file mode 100644 index 0000000..b50492a Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_change2.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_win_change.png b/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_win_change.png new file mode 100644 index 0000000..495fb74 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_win_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_win_change2.png b/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_win_change2.png new file mode 100644 index 0000000..bbc2592 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_tile_sel_win_change2.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_win_en_change_multiple.png b/spec/gb/test_results/screenshots/m3_lcdc_win_en_change_multiple.png new file mode 100644 index 0000000..145bd1b Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_win_en_change_multiple.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_win_en_change_multiple_wx.png b/spec/gb/test_results/screenshots/m3_lcdc_win_en_change_multiple_wx.png new file mode 100644 index 0000000..bdfd6dd Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_win_en_change_multiple_wx.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_win_map_change.png b/spec/gb/test_results/screenshots/m3_lcdc_win_map_change.png new file mode 100644 index 0000000..648ee9e Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_win_map_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_lcdc_win_map_change2.png b/spec/gb/test_results/screenshots/m3_lcdc_win_map_change2.png new file mode 100644 index 0000000..ff3ab9e Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_lcdc_win_map_change2.png differ diff --git a/spec/gb/test_results/screenshots/m3_obp0_change.png b/spec/gb/test_results/screenshots/m3_obp0_change.png new file mode 100644 index 0000000..ecd80c8 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_obp0_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_scx_high_5_bits.png b/spec/gb/test_results/screenshots/m3_scx_high_5_bits.png new file mode 100644 index 0000000..43d5472 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_scx_high_5_bits.png differ diff --git a/spec/gb/test_results/screenshots/m3_scx_high_5_bits_change2.png b/spec/gb/test_results/screenshots/m3_scx_high_5_bits_change2.png new file mode 100644 index 0000000..3d8983a Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_scx_high_5_bits_change2.png differ diff --git a/spec/gb/test_results/screenshots/m3_scx_low_3_bits.png b/spec/gb/test_results/screenshots/m3_scx_low_3_bits.png new file mode 100644 index 0000000..ee7912c Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_scx_low_3_bits.png differ diff --git a/spec/gb/test_results/screenshots/m3_scy_change.png b/spec/gb/test_results/screenshots/m3_scy_change.png new file mode 100644 index 0000000..25b2dbd Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_scy_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_scy_change2.png b/spec/gb/test_results/screenshots/m3_scy_change2.png new file mode 100644 index 0000000..7827425 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_scy_change2.png differ diff --git a/spec/gb/test_results/screenshots/m3_window_timing.png b/spec/gb/test_results/screenshots/m3_window_timing.png new file mode 100644 index 0000000..5a9f562 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_window_timing.png differ diff --git a/spec/gb/test_results/screenshots/m3_window_timing_wx_0.png b/spec/gb/test_results/screenshots/m3_window_timing_wx_0.png new file mode 100644 index 0000000..ac67458 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_window_timing_wx_0.png differ diff --git a/spec/gb/test_results/screenshots/m3_wx_4_change.png b/spec/gb/test_results/screenshots/m3_wx_4_change.png new file mode 100644 index 0000000..d121867 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_wx_4_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_wx_4_change_sprites.png b/spec/gb/test_results/screenshots/m3_wx_4_change_sprites.png new file mode 100644 index 0000000..7f1e589 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_wx_4_change_sprites.png differ diff --git a/spec/gb/test_results/screenshots/m3_wx_5_change.png b/spec/gb/test_results/screenshots/m3_wx_5_change.png new file mode 100644 index 0000000..8d68a49 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_wx_5_change.png differ diff --git a/spec/gb/test_results/screenshots/m3_wx_6_change.png b/spec/gb/test_results/screenshots/m3_wx_6_change.png new file mode 100644 index 0000000..6061817 Binary files /dev/null and b/spec/gb/test_results/screenshots/m3_wx_6_change.png differ diff --git a/spec/gb/util_spec.cr b/spec/gb/util_spec.cr new file mode 100644 index 0000000..18f6996 --- /dev/null +++ b/spec/gb/util_spec.cr @@ -0,0 +1,17 @@ +require "./spec_helper" + +describe "util" do + describe "array_to_uint8" do + it "converts array to uint8" do + res = array_to_uint8 [false, true, 0, 1, 0_u8, 1_u8, -0, -1] + res.should eq 0b01010101_u8 + end + end + + describe "array_to_uint16" do + it "converts array to uint16" do + res = array_to_uint16 [false, true, 0, 1, 0_u8, 1_u8, -0, -1, false, true, 0, 1, 0_u8, 1_u8, -0, -1] + res.should eq 0b0101010101010101_u16 + end + end +end