require 'spec_helper'

describe Waterfoul::MBC::MBC1 do
  let(:program) { double :program }
  subject { Waterfoul::MBC::MBC1.new program }

  describe '#[]' do
    context 'when reading at 0x0001' do
      it 'reads byte from bank 0' do
        expect(program).to receive(:[]).with(0x0001)
        subject[0x0001]
      end
    end

    context 'when reading at 0x4001' do
      it 'reads from bank 1' do
        expect(program).to receive(:[]).with(0x4001)
        subject[0x4001]
      end
    end
  end

  describe '#[]=' do
    context 'when writing to 0x1' do
      it 'enables the external ram' do
        subject[0x1] = 0xA
        expect(subject.ram_enabled).to eq true
      end
    end

    context 'when writing to 4001' do
      it 'sets rom bank from 5 bits' do
        subject[0x2000] = 0xFF
        expect(subject.rom_bank).to eq 0x1F
      end
    end

    context 'when writing to 0x4000' do
      context 'with mode set to 1' do
        before { subject[0x6000] = 0x1 }
        it 'sets ram bank' do
          subject[0x4000] = 0x3
          expect(subject.ram_bank).to eq 0x3
        end
      end

      context 'with mode set to 0' do
        before { subject[0x6000] = 0x0 }
        before { subject[0x2000] = 0x1F }
        it 'sets upper 3 bits of rom bank' do
          subject[0x4000] = 0x3
          expect(subject.rom_bank).to eq 0x7F
        end
      end
    end

    context 'when writing to 0xA001' do
      context 'when RAM is enabled' do
        before { subject[0x1] = 0xA }
        it 'saves the value to external memory' do
          subject[0xA001] = 0x1
          expect(subject[0xA001]).to eq 0x1
        end
      end

      context 'when ram is disabled' do
        it 'does not store value into ram' do
          subject[0xA001] = 0x1
          expect(subject[0xA001]).to eq 0xFF
        end
      end
    end

    context 'writing to 0x6001' do
      it 'sets the ROM mode to 1' do
        subject[0x6001] = 0x1
        expect(subject.mode).to eq 1
      end
    end
  end
end
