diff --git a/CHANGELOG.md b/CHANGELOG.md index bbcc456..ad741fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [1.7.1] - 2026-10-11 + +- Fix RLC and RRC on memory writing values over a byte, which could stop the Spinel browser build + ## [1.7.0] - 2026-10-10 - Require Ruby 4.0 or higher diff --git a/Gemfile.lock b/Gemfile.lock index 9daf4e4..d4b0d31 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - rubyboy (1.7.0) + rubyboy (1.7.1) ffi (~> 1.16, >= 1.16.3) GEM diff --git a/lib/rubyboy/cpu.rb b/lib/rubyboy/cpu.rb index b0a78c5..af04b1e 100644 --- a/lib/rubyboy/cpu.rb +++ b/lib/rubyboy/cpu.rb @@ -1071,7 +1071,7 @@ def reti(cycles:) def rlc8(x, cycles:) value = get_value(x) - value = (value << 1) | (value >> 7) + value = ((value << 1) | (value >> 7)) & 0xff set_value(x, value) update_flags( z: value == 0, @@ -1085,7 +1085,7 @@ def rlc8(x, cycles:) def rrc8(x, cycles:) value = get_value(x) - value = (value >> 1) | (value << 7) + value = ((value >> 1) | (value << 7)) & 0xff set_value(x, value) update_flags( z: value == 0, diff --git a/lib/rubyboy/version.rb b/lib/rubyboy/version.rb index 4491007..7ec6611 100644 --- a/lib/rubyboy/version.rb +++ b/lib/rubyboy/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Rubyboy - VERSION = '1.7.0' + VERSION = '1.7.1' end diff --git a/spec/rubyboy/cpu_spec.rb b/spec/rubyboy/cpu_spec.rb new file mode 100644 index 0000000..04cf7e2 --- /dev/null +++ b/spec/rubyboy/cpu_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +RSpec.describe Rubyboy::Cpu do + let(:memory) { Array.new(0x10000, 0) } + let(:cpu) do + bus = instance_double(Rubyboy::Bus) + allow(bus).to receive(:read_byte) { |addr| memory[addr] } + allow(bus).to receive(:read_word) { |addr| memory[addr] | (memory[addr + 1] << 8) } + allow(bus).to receive(:write_byte) { |addr, value| memory[addr] = value } + described_class.new(bus, Rubyboy::Interrupt.new) + end + + # LD HL, 0xc000, then the CB-prefixed rotate eight times: the byte comes back. + def rotate_hl_eight_times(cb_opcode, value) + program = [0x21, 0x00, 0xc0] + ([0xcb, cb_opcode] * 8) + memory[0x0100, program.size] = program + memory[0xc000] = value + 9.times { cpu.exec } + memory[0xc000] + end + + it 'keeps RLC (HL) within a byte' do + expect(rotate_hl_eight_times(0x06, 0x81)).to eq(0x81) + end + + it 'keeps RRC (HL) within a byte' do + expect(rotate_hl_eight_times(0x0e, 0x81)).to eq(0x81) + end +end