summaryrefslogtreecommitdiff
path: root/lib/nes/mapper.hh
blob: f2873a63d82167a60df7d06d51a7ce1f13bc171c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#pragma once

#include "nes/util/address.hh"

namespace nes
{
	class cartridge;

	class mapper
	{
		using read_cpu_func = std::uint8_t(mapper::*)(address);
		using write_cpu_func = void(mapper::*)(address, std::uint8_t);
		using read_ppu_func = std::uint8_t(mapper::*)(address, std::uint8_t const* vram);
		using write_ppu_func = void(mapper::*)(address, std::uint8_t* vram, std::uint8_t);

		cartridge& cartridge_;
		read_cpu_func read_cpu_;
		write_cpu_func write_cpu_;
		read_ppu_func read_ppu_;
		write_ppu_func write_ppu_;

	public:
		static auto select(cartridge&) -> mapper;

		mapper(mapper const&) = delete;
		mapper(mapper&&) = delete;
		auto operator=(mapper const&) -> mapper& = delete;
		auto operator=(mapper&&) -> mapper& = delete;

		auto read_cpu(address const addr) -> std::uint8_t
		{
			return (this->*read_cpu_)(addr);
		}

		auto write_cpu(address const addr, std::uint8_t const value) -> void
		{
			(this->*write_cpu_)(addr, value);
		}

		auto read_ppu(address const addr, std::uint8_t const* vram) -> std::uint8_t
		{
			return (this->*read_ppu_)(addr, vram);
		}

		auto write_ppu(address const addr, std::uint8_t* vram, std::uint8_t const value) -> void
		{
			(this->*write_ppu_)(addr, vram, value);
		}

	private:
		explicit mapper(
			cartridge& cartridge,
			read_cpu_func read_cpu, write_cpu_func write_cpu,
			read_ppu_func read_ppu, write_ppu_func write_ppu);

		// Implementations

		auto nrom_read_cpu(address) -> std::uint8_t;
		auto nrom_write_cpu(address, std::uint8_t) -> void;
		auto nrom_read_ppu(address, std::uint8_t const* vram) -> std::uint8_t;
		auto nrom_write_ppu(address, std::uint8_t* vram, std::uint8_t) -> void;
		auto nrom_mirrored_vram_address(address) const -> unsigned;
	};
} // namespace nes