diff --git a/GNUmakefile b/GNUmakefile index 232b7fcf..eba1f35f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -7,8 +7,6 @@ gba := gba profile := accuracy target := tomoko - -# arch := x86 # console := true # compiler @@ -28,16 +26,12 @@ endif # platform ifeq ($(platform),windows) - ifeq ($(arch),x86) - flags += -m32 - link += -m32 - endif ifeq ($(console),true) link += -mconsole else link += -mwindows endif - link += -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 -lws2_32 + link += -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 link += -Wl,-enable-auto-import link += -Wl,-enable-runtime-pseudo-reloc else ifeq ($(platform),macosx) @@ -46,7 +40,7 @@ else ifeq ($(platform),linux) flags += -march=native -fopenmp link += -fopenmp link += -Wl,-export-dynamic - link += -lX11 -lXext -ldl + link += -lX11 -lXext else ifeq ($(platform),bsd) flags += -march=native -fopenmp link += -fopenmp diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index d78825ab..6090a003 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -7,7 +7,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "095.08"; + static const string Version = "095.09"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/fc/apu/apu.cpp b/fc/apu/apu.cpp index 9c38b39b..38c9d71e 100644 --- a/fc/apu/apu.cpp +++ b/fc/apu/apu.cpp @@ -11,38 +11,40 @@ namespace Famicom { #include "serialization.cpp" APU apu; -const uint8 APU::length_counter_table[32] = { - 0x0a, 0xfe, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06, 0xa0, 0x08, 0x3c, 0x0a, 0x0e, 0x0c, 0x1a, 0x0e, - 0x0c, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16, 0xc0, 0x18, 0x48, 0x1a, 0x10, 0x1c, 0x20, 0x1e, -}; +APU::APU() { + for(uint amp : range(32)) { + if(amp == 0) { + pulse_dac[amp] = 0; + } else { + pulse_dac[amp] = 16384.0 * 95.88 / (8128.0 / amp + 100.0); + } + } -const uint16 APU::ntsc_noise_period_table[16] = { - 4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068, -}; + for(uint dmc_amp : range(128)) { + for(uint triangle_amp : range(16)) { + for(uint noise_amp : range(16)) { + if(dmc_amp == 0 && triangle_amp == 0 && noise_amp == 0) { + dmc_triangle_noise_dac[dmc_amp][triangle_amp][noise_amp] = 0; + } else { + dmc_triangle_noise_dac[dmc_amp][triangle_amp][noise_amp] + = 16384.0 * 159.79 / (100.0 + 1.0 / (triangle_amp / 8227.0 + noise_amp / 12241.0 + dmc_amp / 22638.0)); + } + } + } + } +} -const uint16 APU::pal_noise_period_table[16] = { - 4, 7, 14, 30, 60, 88, 118, 148, 188, 236, 354, 472, 708, 944, 1890, 3778, -}; - -const uint16 APU::ntsc_dmc_period_table[16] = { - 428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 84, 72, 54, -}; - -const uint16 APU::pal_dmc_period_table[16] = { - 398, 354, 316, 298, 276, 236, 210, 198, 176, 148, 132, 118, 98, 78, 66, 50, -}; - -void APU::Main() { +auto APU::Main() -> void { apu.main(); } -void APU::main() { +auto APU::main() -> void { while(true) { if(scheduler.sync == Scheduler::SynchronizeMode::All) { scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); } - unsigned pulse_output, triangle_output, noise_output, dmc_output; + uint pulse_output, triangle_output, noise_output, dmc_output; pulse_output = pulse[0].clock(); pulse_output += pulse[1].clock(); @@ -52,7 +54,7 @@ void APU::main() { clock_frame_counter_divider(); - signed output = pulse_dac[pulse_output] + dmc_triangle_noise_dac[dmc_output][triangle_output][noise_output]; + int output = pulse_dac[pulse_output] + dmc_triangle_noise_dac[dmc_output][triangle_output][noise_output]; output = filter.run_hipass_strong(output); output += cartridge_sample; @@ -66,20 +68,20 @@ void APU::main() { } } -void APU::tick() { +auto APU::tick() -> void { clock += 12; if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); } -void APU::set_irq_line() { +auto APU::set_irq_line() -> void { cpu.set_irq_apu_line(frame.irq_pending || dmc.irq_pending); } -void APU::set_sample(int16 sample) { +auto APU::set_sample(int16 sample) -> void { cartridge_sample = sample; } -void APU::power() { +auto APU::power() -> void { filter.hipass_strong = 0; filter.hipass_weak = 0; filter.lopass = 0; @@ -91,7 +93,7 @@ void APU::power() { dmc.power(); } -void APU::reset() { +auto APU::reset() -> void { create(APU::Main, 21477272); pulse[0].reset(); @@ -112,7 +114,7 @@ void APU::reset() { set_irq_line(); } -uint8 APU::read(uint16 addr) { +auto APU::read(uint16 addr) -> uint8 { if(addr == 0x4015) { uint8 result = 0x00; result |= pulse[0].length_counter ? 0x01 : 0; @@ -132,8 +134,8 @@ uint8 APU::read(uint16 addr) { return cpu.mdr(); } -void APU::write(uint16 addr, uint8 data) { - const unsigned n = (addr >> 2) & 1; //pulse# +auto APU::write(uint16 addr, uint8 data) -> void { + const uint n = (addr >> 2) & 1; //pulse# switch(addr) { case 0x4000: case 0x4004: @@ -254,22 +256,22 @@ void APU::write(uint16 addr, uint8 data) { } } -signed APU::Filter::run_hipass_strong(signed sample) { +auto APU::Filter::run_hipass_strong(int sample) -> int { hipass_strong += ((((int64)sample << 16) - (hipass_strong >> 16)) * HiPassStrong) >> 16; return sample - (hipass_strong >> 32); } -signed APU::Filter::run_hipass_weak(signed sample) { +auto APU::Filter::run_hipass_weak(int sample) -> int { hipass_weak += ((((int64)sample << 16) - (hipass_weak >> 16)) * HiPassWeak) >> 16; return sample - (hipass_weak >> 32); } -signed APU::Filter::run_lopass(signed sample) { +auto APU::Filter::run_lopass(int sample) -> int { lopass += ((((int64)sample << 16) - (lopass >> 16)) * LoPass) >> 16; return (lopass >> 32); } -void APU::clock_frame_counter() { +auto APU::clock_frame_counter() -> void { frame.counter++; if(frame.counter & 1) { @@ -295,7 +297,7 @@ void APU::clock_frame_counter() { } } -void APU::clock_frame_counter_divider() { +auto APU::clock_frame_counter_divider() -> void { frame.divider -= 2; if(frame.divider <= 0) { clock_frame_counter(); @@ -303,27 +305,25 @@ void APU::clock_frame_counter_divider() { } } -APU::APU() { - for(unsigned amp = 0; amp < 32; amp++) { - if(amp == 0) { - pulse_dac[amp] = 0; - } else { - pulse_dac[amp] = 16384.0 * 95.88 / (8128.0 / amp + 100.0); - } - } +const uint8 APU::length_counter_table[32] = { + 0x0a, 0xfe, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06, 0xa0, 0x08, 0x3c, 0x0a, 0x0e, 0x0c, 0x1a, 0x0e, + 0x0c, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16, 0xc0, 0x18, 0x48, 0x1a, 0x10, 0x1c, 0x20, 0x1e, +}; - for(unsigned dmc_amp = 0; dmc_amp < 128; dmc_amp++) { - for(unsigned triangle_amp = 0; triangle_amp < 16; triangle_amp++) { - for(unsigned noise_amp = 0; noise_amp < 16; noise_amp++) { - if(dmc_amp == 0 && triangle_amp == 0 && noise_amp == 0) { - dmc_triangle_noise_dac[dmc_amp][triangle_amp][noise_amp] = 0; - } else { - dmc_triangle_noise_dac[dmc_amp][triangle_amp][noise_amp] - = 16384.0 * 159.79 / (100.0 + 1.0 / (triangle_amp / 8227.0 + noise_amp / 12241.0 + dmc_amp / 22638.0)); - } - } - } - } -} +const uint16 APU::ntsc_noise_period_table[16] = { + 4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068, +}; + +const uint16 APU::pal_noise_period_table[16] = { + 4, 7, 14, 30, 60, 88, 118, 148, 188, 236, 354, 472, 708, 944, 1890, 3778, +}; + +const uint16 APU::ntsc_dmc_period_table[16] = { + 428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 84, 72, 54, +}; + +const uint16 APU::pal_dmc_period_table[16] = { + 398, 354, 316, 298, 276, 236, 210, 198, 176, 148, 132, 118, 98, 78, 66, 50, +}; } diff --git a/fc/apu/apu.hpp b/fc/apu/apu.hpp index a0ea1282..6928d866 100644 --- a/fc/apu/apu.hpp +++ b/fc/apu/apu.hpp @@ -1,31 +1,33 @@ struct APU : Thread { - static void Main(); - void main(); - void tick(); - void set_irq_line(); - void set_sample(int16 sample); - - void power(); - void reset(); - - uint8 read(uint16 addr); - void write(uint16 addr, uint8 data); - - void serialize(serializer&); APU(); + static auto Main() -> void; + auto main() -> void; + auto tick() -> void; + auto set_irq_line() -> void; + auto set_sample(int16 sample) -> void; + + auto power() -> void; + auto reset() -> void; + + auto read(uint16 addr) -> uint8; + auto write(uint16 addr, uint8 data) -> void; + + auto serialize(serializer&) -> void; + struct Filter { - enum : signed { HiPassStrong = 225574, HiPassWeak = 57593, LoPass = 86322413 }; + auto run_hipass_strong(int sample) -> int; + auto run_hipass_weak(int sample) -> int; + auto run_lopass(int sample) -> int; + + auto serialize(serializer&) -> void; + + enum : int { HiPassStrong = 225574, HiPassWeak = 57593, LoPass = 86322413 }; int64 hipass_strong; int64 hipass_weak; int64 lopass; - - signed run_hipass_strong(signed sample); - signed run_hipass_weak(signed sample); - signed run_lopass(signed sample); - void serialize(serializer&); - } filter; + }; #include "envelope.hpp" #include "sweep.hpp" @@ -35,19 +37,22 @@ struct APU : Thread { #include "dmc.hpp" struct FrameCounter { - enum : unsigned { NtscPeriod = 14915 }; //~(21.477MHz / 6 / 240hz) + auto serialize(serializer&) -> void; + + enum : uint { NtscPeriod = 14915 }; //~(21.477MHz / 6 / 240hz) bool irq_pending; uint2 mode; uint2 counter; - signed divider; + int divider; + }; - void serialize(serializer&); - } frame; + auto clock_frame_counter() -> void; + auto clock_frame_counter_divider() -> void; - void clock_frame_counter(); - void clock_frame_counter_divider(); + Filter filter; + FrameCounter frame; uint8 enabled_channels; int16 cartridge_sample; diff --git a/fc/apu/dmc.cpp b/fc/apu/dmc.cpp index ffe221f8..aaf24552 100644 --- a/fc/apu/dmc.cpp +++ b/fc/apu/dmc.cpp @@ -1,18 +1,18 @@ -void APU::DMC::start() { +auto APU::DMC::start() -> void { if(length_counter == 0) { read_addr = 0x4000 + (addr_latch << 6); length_counter = (length_latch << 4) + 1; } } -void APU::DMC::stop() { +auto APU::DMC::stop() -> void { length_counter = 0; dma_delay_counter = 0; cpu.set_rdy_line(1); cpu.set_rdy_addr(false); } -uint8 APU::DMC::clock() { +auto APU::DMC::clock() -> uint8 { uint8 result = dac_latch; if(dma_delay_counter > 0) { @@ -42,8 +42,8 @@ uint8 APU::DMC::clock() { if(--period_counter == 0) { if(have_sample) { - signed delta = (((sample >> bit_counter) & 1) << 2) - 2; - unsigned data = dac_latch + delta; + int delta = (((sample >> bit_counter) & 1) << 2) - 2; + uint data = dac_latch + delta; if((data & 0x80) == 0) dac_latch = data; } @@ -68,10 +68,10 @@ uint8 APU::DMC::clock() { return result; } -void APU::DMC::power() { +auto APU::DMC::power() -> void { } -void APU::DMC::reset() { +auto APU::DMC::reset() -> void { length_counter = 0; irq_pending = 0; @@ -91,7 +91,7 @@ void APU::DMC::reset() { sample = 0; } -void APU::DMC::serialize(serializer& s) { +auto APU::DMC::serialize(serializer& s) -> void { s.integer(length_counter); s.integer(irq_pending); diff --git a/fc/apu/dmc.hpp b/fc/apu/dmc.hpp index 5fcce929..a77252eb 100644 --- a/fc/apu/dmc.hpp +++ b/fc/apu/dmc.hpp @@ -1,9 +1,18 @@ struct DMC { - unsigned length_counter; + auto start() -> void; + auto stop() -> void; + auto clock() -> uint8; + + auto power() -> void; + auto reset() -> void; + + auto serialize(serializer&) -> void; + + uint length_counter; bool irq_pending; uint4 period; - unsigned period_counter; + uint period_counter; bool irq_enable; bool loop_mode; @@ -13,7 +22,7 @@ struct DMC { uint8 length_latch; uint15 read_addr; - unsigned dma_delay_counter; + uint dma_delay_counter; uint3 bit_counter; bool have_dma_buffer; @@ -21,12 +30,4 @@ struct DMC { bool have_sample; uint8 sample; - - void start(); - void stop(); - uint8 clock(); - - void power(); - void reset(); - void serialize(serializer&); } dmc; diff --git a/fc/apu/envelope.cpp b/fc/apu/envelope.cpp index 8d0dbc7d..719f916d 100644 --- a/fc/apu/envelope.cpp +++ b/fc/apu/envelope.cpp @@ -1,8 +1,8 @@ -unsigned APU::Envelope::volume() const { +auto APU::Envelope::volume() const -> uint { return use_speed_as_volume ? speed : decay_volume; } -void APU::Envelope::clock() { +auto APU::Envelope::clock() -> void { if(reload_decay) { reload_decay = false; decay_volume = 0x0f; @@ -16,10 +16,10 @@ void APU::Envelope::clock() { } } -void APU::Envelope::power() { +auto APU::Envelope::power() -> void { } -void APU::Envelope::reset() { +auto APU::Envelope::reset() -> void { speed = 0; use_speed_as_volume = 0; loop_mode = 0; @@ -28,7 +28,7 @@ void APU::Envelope::reset() { decay_volume = 0; } -void APU::Envelope::serialize(serializer& s) { +auto APU::Envelope::serialize(serializer& s) -> void { s.integer(speed); s.integer(use_speed_as_volume); s.integer(loop_mode); diff --git a/fc/apu/envelope.hpp b/fc/apu/envelope.hpp index 054d2fef..457631c3 100644 --- a/fc/apu/envelope.hpp +++ b/fc/apu/envelope.hpp @@ -1,4 +1,12 @@ struct Envelope { + auto volume() const -> uint; + auto clock() -> void; + + auto power() -> void; + auto reset() -> void; + + auto serialize(serializer&) -> void; + uint4 speed; bool use_speed_as_volume; bool loop_mode; @@ -6,11 +14,4 @@ struct Envelope { bool reload_decay; uint8 decay_counter; uint4 decay_volume; - - unsigned volume() const; - void clock(); - - void power(); - void reset(); - void serialize(serializer&); }; diff --git a/fc/apu/noise.cpp b/fc/apu/noise.cpp index 65eee58d..fac0190d 100644 --- a/fc/apu/noise.cpp +++ b/fc/apu/noise.cpp @@ -1,16 +1,16 @@ -void APU::Noise::clock_length() { +auto APU::Noise::clock_length() -> void { if(envelope.loop_mode == 0) { if(length_counter > 0) length_counter--; } } -uint8 APU::Noise::clock() { +auto APU::Noise::clock() -> uint8 { if(length_counter == 0) return 0; uint8 result = (lfsr & 1) ? envelope.volume() : 0; if(--period_counter == 0) { - unsigned feedback; + uint feedback; if(short_mode) { feedback = ((lfsr >> 0) & 1) ^ ((lfsr >> 6) & 1); @@ -25,10 +25,10 @@ uint8 APU::Noise::clock() { return result; } -void APU::Noise::power() { +auto APU::Noise::power() -> void { } -void APU::Noise::reset() { +auto APU::Noise::reset() -> void { length_counter = 0; envelope.speed = 0; @@ -44,7 +44,7 @@ void APU::Noise::reset() { lfsr = 1; } -void APU::Noise::serialize(serializer& s) { +auto APU::Noise::serialize(serializer& s) -> void { s.integer(length_counter); envelope.serialize(s); diff --git a/fc/apu/noise.hpp b/fc/apu/noise.hpp index 6684893a..f4eed0a3 100644 --- a/fc/apu/noise.hpp +++ b/fc/apu/noise.hpp @@ -1,18 +1,19 @@ struct Noise { - unsigned length_counter; + auto clock_length() -> void; + auto clock() -> uint8; + + auto power() -> void; + auto reset() -> void; + + auto serialize(serializer&) -> void; + + uint length_counter; Envelope envelope; uint4 period; - unsigned period_counter; + uint period_counter; bool short_mode; uint15 lfsr; - - void clock_length(); - uint8 clock(); - - void power(); - void reset(); - void serialize(serializer&); } noise; diff --git a/fc/apu/pulse.cpp b/fc/apu/pulse.cpp index 5f8abbcd..44ba034d 100644 --- a/fc/apu/pulse.cpp +++ b/fc/apu/pulse.cpp @@ -1,14 +1,14 @@ -void APU::Pulse::clock_length() { +auto APU::Pulse::clock_length() -> void { if(envelope.loop_mode == 0) { if(length_counter) length_counter--; } } -uint8 APU::Pulse::clock() { +auto APU::Pulse::clock() -> uint8 { if(sweep.check_period() == false) return 0; if(length_counter == 0) return 0; - static const unsigned duty_table[] = {1, 2, 4, 6}; + static const uint duty_table[] = {1, 2, 4, 6}; uint8 result = (duty_counter < duty_table[duty]) ? envelope.volume() : 0; if(sweep.pulse_period < 0x008) result = 0; @@ -20,12 +20,12 @@ uint8 APU::Pulse::clock() { return result; } -void APU::Pulse::power() { +auto APU::Pulse::power() -> void { envelope.power(); sweep.power(); } -void APU::Pulse::reset() { +auto APU::Pulse::reset() -> void { envelope.reset(); sweep.reset(); @@ -37,7 +37,7 @@ void APU::Pulse::reset() { period_counter = 1; } -void APU::Pulse::serialize(serializer& s) { +auto APU::Pulse::serialize(serializer& s) -> void { s.integer(length_counter); envelope.serialize(s); diff --git a/fc/apu/pulse.hpp b/fc/apu/pulse.hpp index 6c41cea4..222a0190 100644 --- a/fc/apu/pulse.hpp +++ b/fc/apu/pulse.hpp @@ -1,5 +1,14 @@ struct Pulse { - unsigned length_counter; + auto clock_length() -> void; + auto check_period() -> bool; + auto clock() -> uint8; + + auto power() -> void; + auto reset() -> void; + + auto serialize(serializer&) -> void; + + uint length_counter; Envelope envelope; Sweep sweep; @@ -8,13 +17,5 @@ struct Pulse { uint3 duty_counter; uint11 period; - unsigned period_counter; - - void clock_length(); - bool check_period(); - uint8 clock(); - - void power(); - void reset(); - void serialize(serializer&); + uint period_counter; } pulse[2]; diff --git a/fc/apu/serialization.cpp b/fc/apu/serialization.cpp index 5968a9c2..d53cee01 100644 --- a/fc/apu/serialization.cpp +++ b/fc/apu/serialization.cpp @@ -1,4 +1,4 @@ -void APU::serialize(serializer& s) { +auto APU::serialize(serializer& s) -> void { Thread::serialize(s); filter.serialize(s); @@ -13,13 +13,13 @@ void APU::serialize(serializer& s) { s.integer(cartridge_sample); } -void APU::Filter::serialize(serializer& s) { +auto APU::Filter::serialize(serializer& s) -> void { s.integer(hipass_strong); s.integer(hipass_weak); s.integer(lopass); } -void APU::FrameCounter::serialize(serializer& s) { +auto APU::FrameCounter::serialize(serializer& s) -> void { s.integer(irq_pending); s.integer(mode); diff --git a/fc/apu/sweep.cpp b/fc/apu/sweep.cpp index 333ccae0..25e3dc0e 100644 --- a/fc/apu/sweep.cpp +++ b/fc/apu/sweep.cpp @@ -1,4 +1,4 @@ -bool APU::Sweep::check_period() { +auto APU::Sweep::check_period() -> bool { if(pulse_period > 0x7ff) return false; if(decrement == 0) { @@ -8,11 +8,11 @@ bool APU::Sweep::check_period() { return true; } -void APU::Sweep::clock(unsigned channel) { +auto APU::Sweep::clock(uint channel) -> void { if(--counter == 0) { counter = period + 1; if(enable && shift && pulse_period > 8) { - signed delta = pulse_period >> shift; + int delta = pulse_period >> shift; if(decrement) { pulse_period -= delta; @@ -29,7 +29,7 @@ void APU::Sweep::clock(unsigned channel) { } } -void APU::Sweep::power() { +auto APU::Sweep::power() -> void { shift = 0; decrement = 0; period = 0; @@ -39,10 +39,10 @@ void APU::Sweep::power() { pulse_period = 0; } -void APU::Sweep::reset() { +auto APU::Sweep::reset() -> void { } -void APU::Sweep::serialize(serializer& s) { +auto APU::Sweep::serialize(serializer& s) -> void { s.integer(shift); s.integer(decrement); s.integer(period); diff --git a/fc/apu/sweep.hpp b/fc/apu/sweep.hpp index 69137b5b..1da1d5e9 100644 --- a/fc/apu/sweep.hpp +++ b/fc/apu/sweep.hpp @@ -1,4 +1,12 @@ struct Sweep { + auto check_period() -> bool; + auto clock(uint channel) -> void; + + auto power() -> void; + auto reset() -> void; + + auto serialize(serializer&) -> void; + uint8 shift; bool decrement; uint3 period; @@ -6,11 +14,4 @@ struct Sweep { bool enable; bool reload; uint11 pulse_period; - - bool check_period(); - void clock(unsigned channel); - - void power(); - void reset(); - void serialize(serializer&); }; diff --git a/fc/apu/triangle.cpp b/fc/apu/triangle.cpp index 1249b384..573fd2d5 100644 --- a/fc/apu/triangle.cpp +++ b/fc/apu/triangle.cpp @@ -1,10 +1,10 @@ -void APU::Triangle::clock_length() { +auto APU::Triangle::clock_length() -> void { if(halt_length_counter == 0) { if(length_counter > 0) length_counter--; } } -void APU::Triangle::clock_linear_length() { +auto APU::Triangle::clock_linear_length() -> void { if(reload_linear) { linear_length_counter = linear_length; } else if(linear_length_counter) { @@ -14,7 +14,7 @@ void APU::Triangle::clock_linear_length() { if(halt_length_counter == 0) reload_linear = false; } -uint8 APU::Triangle::clock() { +auto APU::Triangle::clock() -> uint8 { uint8 result = step_counter & 0x0f; if((step_counter & 0x10) == 0) result ^= 0x0f; if(length_counter == 0 || linear_length_counter == 0) return result; @@ -27,11 +27,11 @@ uint8 APU::Triangle::clock() { return result; } -void APU::Triangle::power() { +auto APU::Triangle::power() -> void { reset(); } -void APU::Triangle::reset() { +auto APU::Triangle::reset() -> void { length_counter = 0; linear_length = 0; @@ -43,7 +43,7 @@ void APU::Triangle::reset() { reload_linear = 0; } -void APU::Triangle::serialize(serializer& s) { +auto APU::Triangle::serialize(serializer& s) -> void { s.integer(length_counter); s.integer(linear_length); diff --git a/fc/apu/triangle.hpp b/fc/apu/triangle.hpp index ef88a5ca..48b057b9 100644 --- a/fc/apu/triangle.hpp +++ b/fc/apu/triangle.hpp @@ -1,21 +1,22 @@ struct Triangle { - unsigned length_counter; + auto clock_length() -> void; + auto clock_linear_length() -> void; + auto clock() -> uint8; + + auto power() -> void; + auto reset() -> void; + + auto serialize(serializer&) -> void; + + uint length_counter; uint8 linear_length; bool halt_length_counter; uint11 period; - unsigned period_counter; + uint period_counter; uint5 step_counter; uint8 linear_length_counter; bool reload_linear; - - void clock_length(); - void clock_linear_length(); - uint8 clock(); - - void power(); - void reset(); - void serialize(serializer&); } triangle; diff --git a/fc/cartridge/board/bandai-fcg.cpp b/fc/cartridge/board/bandai-fcg.cpp index a23ad2a4..12ebe9bd 100644 --- a/fc/cartridge/board/bandai-fcg.cpp +++ b/fc/cartridge/board/bandai-fcg.cpp @@ -1,117 +1,115 @@ //BANDAI-FCG struct BandaiFCG : Board { + BandaiFCG(Markup::Node& document) : Board(document) { + } -uint8 chr_bank[8]; -uint8 prg_bank; -uint2 mirror; -bool irq_counter_enable; -uint16 irq_counter; -uint16 irq_latch; + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + if(irq_counter_enable) { + if(--irq_counter == 0xffff) { + cpu.set_irq_line(1); + irq_counter_enable = false; + } + } + + tick(); } + } - if(irq_counter_enable) { - if(--irq_counter == 0xffff) { - cpu.set_irq_line(1); - irq_counter_enable = false; + auto ciram_addr(uint addr) const -> uint { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); + case 2: return 0x0000 | (addr & 0x03ff); + case 3: return 0x0400 | (addr & 0x03ff); + } + } + + auto prg_read(uint addr) -> uint8 { + if(addr & 0x8000) { + bool region = addr & 0x4000; + uint bank = (region == 0 ? prg_bank : 0x0f); + return prgrom.read((bank << 14) | (addr & 0x3fff)); + } + return cpu.mdr(); + } + + auto prg_write(uint addr, uint8 data) -> void { + if(addr >= 0x6000) { + switch(addr & 15) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + chr_bank[addr & 7] = data; + break; + case 0x08: + prg_bank = data & 0x0f; + break; + case 0x09: + mirror = data & 0x03; + break; + case 0x0a: + cpu.set_irq_line(0); + irq_counter_enable = data & 0x01; + irq_counter = irq_latch; + break; + case 0x0b: + irq_latch = (irq_latch & 0xff00) | (data << 0); + break; + case 0x0c: + irq_latch = (irq_latch & 0x00ff) | (data << 8); + break; + case 0x0d: + //TODO: serial EEPROM support + break; } } - - tick(); } -} -unsigned ciram_addr(unsigned addr) const { - switch(mirror) { - case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); - case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); - case 2: return 0x0000 | (addr & 0x03ff); - case 3: return 0x0400 | (addr & 0x03ff); + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(ciram_addr(addr)); + addr = (chr_bank[addr >> 10] << 10) | (addr & 0x03ff); + return Board::chr_read(addr); } -} -uint8 prg_read(unsigned addr) { - if(addr & 0x8000) { - bool region = addr & 0x4000; - unsigned bank = (region == 0 ? prg_bank : 0x0f); - return prgrom.read((bank << 14) | (addr & 0x3fff)); + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(ciram_addr(addr), data); + addr = (chr_bank[addr >> 10] << 10) | (addr & 0x03ff); + return Board::chr_write(addr, data); } - return cpu.mdr(); -} -void prg_write(unsigned addr, uint8 data) { - if(addr >= 0x6000) { - switch(addr & 15) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - chr_bank[addr & 7] = data; - break; - case 0x08: - prg_bank = data & 0x0f; - break; - case 0x09: - mirror = data & 0x03; - break; - case 0x0a: - cpu.set_irq_line(0); - irq_counter_enable = data & 0x01; - irq_counter = irq_latch; - break; - case 0x0b: - irq_latch = (irq_latch & 0xff00) | (data << 0); - break; - case 0x0c: - irq_latch = (irq_latch & 0x00ff) | (data << 8); - break; - case 0x0d: - //TODO: serial EEPROM support - break; - } + auto power() -> void { + reset(); } -} -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(ciram_addr(addr)); - addr = (chr_bank[addr >> 10] << 10) | (addr & 0x03ff); - return Board::chr_read(addr); -} + auto reset() -> void { + for(auto &n : chr_bank) n = 0; + prg_bank = 0; + mirror = 0; + irq_counter_enable = 0; + irq_counter = 0; + irq_latch = 0; + } -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(ciram_addr(addr), data); - addr = (chr_bank[addr >> 10] << 10) | (addr & 0x03ff); - return Board::chr_write(addr, data); -} + auto serialize(serializer& s) -> void { + Board::serialize(s); -void power() { - reset(); -} - -void reset() { - for(auto &n : chr_bank) n = 0; - prg_bank = 0; - mirror = 0; - irq_counter_enable = 0; - irq_counter = 0; - irq_latch = 0; -} - -void serialize(serializer& s) { - Board::serialize(s); - - s.array(chr_bank); - s.integer(prg_bank); - s.integer(mirror); - s.integer(irq_counter_enable); - s.integer(irq_counter); - s.integer(irq_latch); -} - -BandaiFCG(Markup::Node& document) : Board(document) { -} + s.array(chr_bank); + s.integer(prg_bank); + s.integer(mirror); + s.integer(irq_counter_enable); + s.integer(irq_counter); + s.integer(irq_latch); + } + uint8 chr_bank[8]; + uint8 prg_bank; + uint2 mirror; + bool irq_counter_enable; + uint16 irq_counter; + uint16 irq_latch; }; diff --git a/fc/cartridge/board/board.cpp b/fc/cartridge/board/board.cpp index 3354bb60..517c1172 100644 --- a/fc/cartridge/board/board.cpp +++ b/fc/cartridge/board/board.cpp @@ -19,69 +19,6 @@ #include "nes-uxrom.cpp" #include "sunsoft-5b.cpp" -uint8 Board::Memory::read(unsigned addr) const { - return data[mirror(addr, size)]; -} - -void Board::Memory::write(unsigned addr, uint8 byte) { - if(writable) data[mirror(addr, size)] = byte; -} - -unsigned Board::mirror(unsigned addr, unsigned size) { - unsigned base = 0; - if(size) { - unsigned mask = 1 << 23; - while(addr >= size) { - while(!(addr & mask)) mask >>= 1; - addr -= mask; - if(size > mask) { - size -= mask; - base += mask; - } - mask >>= 1; - } - base += addr; - } - return base; -} - -void Board::main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - cartridge.clock += 12 * 4095; - tick(); - } -} - -void Board::tick() { - cartridge.clock += 12; - if(cartridge.clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); -} - -uint8 Board::chr_read(unsigned addr) { - if(chrram.size) return chrram.data[mirror(addr, chrram.size)]; - if(chrrom.size) return chrrom.data[mirror(addr, chrrom.size)]; - return 0u; -} - -void Board::chr_write(unsigned addr, uint8 data) { - if(chrram.size) chrram.data[mirror(addr, chrram.size)] = data; -} - -void Board::power() { -} - -void Board::reset() { -} - -void Board::serialize(serializer& s) { - if(prgram.size) s.array(prgram.data, prgram.size); - if(chrram.size) s.array(chrram.data, chrram.size); -} - Board::Board(Markup::Node& document) { cartridge.board = this; auto cartridge = document["cartridge"]; @@ -116,10 +53,70 @@ Board::Board(Markup::Node& document) { chrram.writable = true; } -Board::~Board() { +auto Board::Memory::read(uint addr) const -> uint8 { + return data[mirror(addr, size)]; } -Board* Board::load(string manifest) { +auto Board::Memory::write(uint addr, uint8 byte) -> void { + if(writable) data[mirror(addr, size)] = byte; +} + +auto Board::mirror(uint addr, uint size) -> uint { + uint base = 0; + if(size) { + uint mask = 1 << 23; + while(addr >= size) { + while(!(addr & mask)) mask >>= 1; + addr -= mask; + if(size > mask) { + size -= mask; + base += mask; + } + mask >>= 1; + } + base += addr; + } + return base; +} + +auto Board::main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } + + cartridge.clock += 12 * 4095; + tick(); + } +} + +auto Board::tick() -> void { + cartridge.clock += 12; + if(cartridge.clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); +} + +auto Board::chr_read(uint addr) -> uint8 { + if(chrram.size) return chrram.data[mirror(addr, chrram.size)]; + if(chrrom.size) return chrrom.data[mirror(addr, chrrom.size)]; + return 0u; +} + +auto Board::chr_write(uint addr, uint8 data) -> void { + if(chrram.size) chrram.data[mirror(addr, chrram.size)] = data; +} + +auto Board::power() -> void { +} + +auto Board::reset() -> void { +} + +auto Board::serialize(serializer& s) -> void { + if(prgram.size) s.array(prgram.data, prgram.size); + if(chrram.size) s.array(chrram.data, chrram.size); +} + +auto Board::load(string manifest) -> Board* { auto document = BML::unserialize(manifest); cartridge.information.title = document["information/title"].text(); diff --git a/fc/cartridge/board/board.hpp b/fc/cartridge/board/board.hpp index 89106319..be6e2f0b 100644 --- a/fc/cartridge/board/board.hpp +++ b/fc/cartridge/board/board.hpp @@ -1,38 +1,39 @@ struct Board { struct Memory { - uint8_t* data; - unsigned size; - bool writable; - - inline uint8 read(unsigned addr) const; - inline void write(unsigned addr, uint8 data); - - inline Memory(uint8_t* data, unsigned size) : data(data), size(size) {} + inline Memory(uint8_t* data, uint size) : data(data), size(size) {} inline Memory() : data(nullptr), size(0u), writable(false) {} inline ~Memory() { if(data) delete[] data; } + + inline auto read(uint addr) const -> uint8; + inline auto write(uint addr, uint8 data) -> void; + + uint8_t* data; + uint size; + bool writable; }; - static unsigned mirror(unsigned addr, unsigned size); - - virtual void main(); - virtual void tick(); - - virtual uint8 prg_read(unsigned addr) = 0; - virtual void prg_write(unsigned addr, uint8 data) = 0; - - virtual uint8 chr_read(unsigned addr); - virtual void chr_write(unsigned addr, uint8 data); - - virtual inline void scanline(unsigned y) {} - - virtual void power(); - virtual void reset(); - - virtual void serialize(serializer&); Board(Markup::Node& document); - virtual ~Board(); + virtual ~Board() = default; - static Board* load(string manifest); + static auto mirror(uint addr, uint size) -> uint; + + virtual auto main() -> void; + virtual auto tick() -> void; + + virtual auto prg_read(uint addr) -> uint8 = 0; + virtual auto prg_write(uint addr, uint8 data) -> void = 0; + + virtual auto chr_read(uint addr) -> uint8; + virtual auto chr_write(uint addr, uint8 data) -> void; + + virtual inline auto scanline(uint y) -> void {} + + virtual auto power() -> void; + virtual auto reset() -> void; + + virtual auto serialize(serializer&) -> void; + + static auto load(string manifest) -> Board*; struct Information { string type; diff --git a/fc/cartridge/board/konami-vrc1.cpp b/fc/cartridge/board/konami-vrc1.cpp index b91c2d8a..ff10d8cc 100644 --- a/fc/cartridge/board/konami-vrc1.cpp +++ b/fc/cartridge/board/konami-vrc1.cpp @@ -1,40 +1,38 @@ struct KonamiVRC1 : Board { + KonamiVRC1(Markup::Node& document) : Board(document), vrc1(*this) { + } -VRC1 vrc1; + auto prg_read(uint addr) -> uint8 { + if(addr & 0x8000) return prgrom.read(vrc1.prg_addr(addr)); + return cpu.mdr(); + } -uint8 prg_read(unsigned addr) { - if(addr & 0x8000) return prgrom.read(vrc1.prg_addr(addr)); - return cpu.mdr(); -} + auto prg_write(uint addr, uint8 data) -> void { + if(addr & 0x8000) return vrc1.reg_write(addr, data); + } -void prg_write(unsigned addr, uint8 data) { - if(addr & 0x8000) return vrc1.reg_write(addr, data); -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(vrc1.ciram_addr(addr)); + return Board::chr_read(vrc1.chr_addr(addr)); + } -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(vrc1.ciram_addr(addr)); - return Board::chr_read(vrc1.chr_addr(addr)); -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(vrc1.ciram_addr(addr), data); + return Board::chr_write(vrc1.chr_addr(addr), data); + } -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(vrc1.ciram_addr(addr), data); - return Board::chr_write(vrc1.chr_addr(addr), data); -} + auto power() -> void { + vrc1.power(); + } -void power() { - vrc1.power(); -} + auto reset() -> void { + vrc1.reset(); + } -void reset() { - vrc1.reset(); -} - -void serialize(serializer& s) { - Board::serialize(s); - vrc1.serialize(s); -} - -KonamiVRC1(Markup::Node& document) : Board(document), vrc1(*this) { -} + auto serialize(serializer& s) -> void { + Board::serialize(s); + vrc1.serialize(s); + } + VRC1 vrc1; }; diff --git a/fc/cartridge/board/konami-vrc2.cpp b/fc/cartridge/board/konami-vrc2.cpp index ea86d714..01011890 100644 --- a/fc/cartridge/board/konami-vrc2.cpp +++ b/fc/cartridge/board/konami-vrc2.cpp @@ -1,57 +1,55 @@ struct KonamiVRC2 : Board { + KonamiVRC2(Markup::Node& document) : Board(document), vrc2(*this) { + settings.pinout.a0 = 1 << document["cartridge/chip/pinout/a0"].natural(); + settings.pinout.a1 = 1 << document["cartridge/chip/pinout/a1"].natural(); + } -struct Settings { - struct Pinout { - unsigned a0; - unsigned a1; - } pinout; -} settings; + auto prg_read(uint addr) -> uint8 { + if(addr < 0x6000) return cpu.mdr(); + if(addr < 0x8000) return vrc2.ram_read(addr); + return prgrom.read(vrc2.prg_addr(addr)); + } -VRC2 vrc2; + auto prg_write(uint addr, uint8 data) -> void { + if(addr < 0x6000) return; + if(addr < 0x8000) return vrc2.ram_write(addr, data); -uint8 prg_read(unsigned addr) { - if(addr < 0x6000) return cpu.mdr(); - if(addr < 0x8000) return vrc2.ram_read(addr); - return prgrom.read(vrc2.prg_addr(addr)); -} + bool a0 = (addr & settings.pinout.a0); + bool a1 = (addr & settings.pinout.a1); + addr &= 0xfff0; + addr |= (a0 << 0) | (a1 << 1); + return vrc2.reg_write(addr, data); + } -void prg_write(unsigned addr, uint8 data) { - if(addr < 0x6000) return; - if(addr < 0x8000) return vrc2.ram_write(addr, data); + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(vrc2.ciram_addr(addr)); + return Board::chr_read(vrc2.chr_addr(addr)); + } - bool a0 = (addr & settings.pinout.a0); - bool a1 = (addr & settings.pinout.a1); - addr &= 0xfff0; - addr |= (a0 << 0) | (a1 << 1); - return vrc2.reg_write(addr, data); -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(vrc2.ciram_addr(addr), data); + return Board::chr_write(vrc2.chr_addr(addr), data); + } -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(vrc2.ciram_addr(addr)); - return Board::chr_read(vrc2.chr_addr(addr)); -} + auto power() -> void { + vrc2.power(); + } -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(vrc2.ciram_addr(addr), data); - return Board::chr_write(vrc2.chr_addr(addr), data); -} + auto reset() -> void { + vrc2.reset(); + } -void power() { - vrc2.power(); -} + auto serialize(serializer& s) -> void { + Board::serialize(s); + vrc2.serialize(s); + } -void reset() { - vrc2.reset(); -} - -void serialize(serializer& s) { - Board::serialize(s); - vrc2.serialize(s); -} - -KonamiVRC2(Markup::Node& document) : Board(document), vrc2(*this) { - settings.pinout.a0 = 1 << document["cartridge/chip/pinout/a0"].natural(); - settings.pinout.a1 = 1 << document["cartridge/chip/pinout/a1"].natural(); -} + struct Settings { + struct Pinout { + uint a0; + uint a1; + } pinout; + } settings; + VRC2 vrc2; }; diff --git a/fc/cartridge/board/konami-vrc3.cpp b/fc/cartridge/board/konami-vrc3.cpp index 11685a43..baa00525 100644 --- a/fc/cartridge/board/konami-vrc3.cpp +++ b/fc/cartridge/board/konami-vrc3.cpp @@ -1,57 +1,55 @@ struct KonamiVRC3 : Board { - -struct Settings { - bool mirror; //0 = horizontal, 1 = vertical -} settings; - -VRC3 vrc3; - -void main() { - vrc3.main(); -} - -uint8 prg_read(unsigned addr) { - if((addr & 0xe000) == 0x6000) return prgram.read(addr & 0x1fff); - if(addr & 0x8000) return prgrom.read(vrc3.prg_addr(addr)); - return cpu.mdr(); -} - -void prg_write(unsigned addr, uint8 data) { - if((addr & 0xe000) == 0x6000) return prgram.write(addr & 0x1fff, data); - if(addr & 0x8000) return vrc3.reg_write(addr, data); -} - -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_read(addr & 0x07ff); + KonamiVRC3(Markup::Node& document) : Board(document), vrc3(*this) { + settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; } - return chrram.read(addr); -} -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_write(addr & 0x07ff, data); + auto main() -> void { + vrc3.main(); } - return chrram.write(addr, data); -} -void power() { - vrc3.power(); -} + auto prg_read(uint addr) -> uint8 { + if((addr & 0xe000) == 0x6000) return prgram.read(addr & 0x1fff); + if(addr & 0x8000) return prgrom.read(vrc3.prg_addr(addr)); + return cpu.mdr(); + } -void reset() { - vrc3.reset(); -} + auto prg_write(uint addr, uint8 data) -> void { + if((addr & 0xe000) == 0x6000) return prgram.write(addr & 0x1fff, data); + if(addr & 0x8000) return vrc3.reg_write(addr, data); + } -void serialize(serializer& s) { - Board::serialize(s); - vrc3.serialize(s); -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_read(addr & 0x07ff); + } + return chrram.read(addr); + } -KonamiVRC3(Markup::Node& document) : Board(document), vrc3(*this) { - settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr & 0x07ff, data); + } + return chrram.write(addr, data); + } + auto power() -> void { + vrc3.power(); + } + + auto reset() -> void { + vrc3.reset(); + } + + auto serialize(serializer& s) -> void { + Board::serialize(s); + vrc3.serialize(s); + } + + struct Settings { + bool mirror; //0 = horizontal, 1 = vertical + } settings; + + VRC3 vrc3; }; diff --git a/fc/cartridge/board/konami-vrc4.cpp b/fc/cartridge/board/konami-vrc4.cpp index 835d396c..ca7b0c14 100644 --- a/fc/cartridge/board/konami-vrc4.cpp +++ b/fc/cartridge/board/konami-vrc4.cpp @@ -1,61 +1,59 @@ struct KonamiVRC4 : Board { + KonamiVRC4(Markup::Node& document) : Board(document), vrc4(*this) { + settings.pinout.a0 = 1 << document["cartridge/chip/pinout/a0"].natural(); + settings.pinout.a1 = 1 << document["cartridge/chip/pinout/a1"].natural(); + } -struct Settings { - struct Pinout { - unsigned a0; - unsigned a1; - } pinout; -} settings; + auto main() -> void { + return vrc4.main(); + } -VRC4 vrc4; + auto prg_read(uint addr) -> uint8 { + if(addr < 0x6000) return cpu.mdr(); + if(addr < 0x8000) return prgram.read(addr); + return prgrom.read(vrc4.prg_addr(addr)); + } -void main() { - return vrc4.main(); -} + auto prg_write(uint addr, uint8 data) -> void { + if(addr < 0x6000) return; + if(addr < 0x8000) return prgram.write(addr, data); -uint8 prg_read(unsigned addr) { - if(addr < 0x6000) return cpu.mdr(); - if(addr < 0x8000) return prgram.read(addr); - return prgrom.read(vrc4.prg_addr(addr)); -} + bool a0 = (addr & settings.pinout.a0); + bool a1 = (addr & settings.pinout.a1); + addr &= 0xfff0; + addr |= (a1 << 1) | (a0 << 0); + return vrc4.reg_write(addr, data); + } -void prg_write(unsigned addr, uint8 data) { - if(addr < 0x6000) return; - if(addr < 0x8000) return prgram.write(addr, data); + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(vrc4.ciram_addr(addr)); + return Board::chr_read(vrc4.chr_addr(addr)); + } - bool a0 = (addr & settings.pinout.a0); - bool a1 = (addr & settings.pinout.a1); - addr &= 0xfff0; - addr |= (a1 << 1) | (a0 << 0); - return vrc4.reg_write(addr, data); -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(vrc4.ciram_addr(addr), data); + return Board::chr_write(vrc4.chr_addr(addr), data); + } -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(vrc4.ciram_addr(addr)); - return Board::chr_read(vrc4.chr_addr(addr)); -} + auto power() -> void { + vrc4.power(); + } -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(vrc4.ciram_addr(addr), data); - return Board::chr_write(vrc4.chr_addr(addr), data); -} + auto reset() -> void { + vrc4.reset(); + } -void power() { - vrc4.power(); -} + auto serialize(serializer& s) -> void { + Board::serialize(s); + vrc4.serialize(s); + } -void reset() { - vrc4.reset(); -} - -void serialize(serializer& s) { - Board::serialize(s); - vrc4.serialize(s); -} - -KonamiVRC4(Markup::Node& document) : Board(document), vrc4(*this) { - settings.pinout.a0 = 1 << document["cartridge/chip/pinout/a0"].natural(); - settings.pinout.a1 = 1 << document["cartridge/chip/pinout/a1"].natural(); -} + struct Settings { + struct Pinout { + uint a0; + uint a1; + } pinout; + } settings; + VRC4 vrc4; }; diff --git a/fc/cartridge/board/konami-vrc6.cpp b/fc/cartridge/board/konami-vrc6.cpp index f4e5e95b..3f34f2ae 100644 --- a/fc/cartridge/board/konami-vrc6.cpp +++ b/fc/cartridge/board/konami-vrc6.cpp @@ -1,42 +1,40 @@ struct KonamiVRC6 : Board { - -VRC6 vrc6; - -uint8 prg_read(unsigned addr) { - if((addr & 0xe000) == 0x6000) return vrc6.ram_read(addr); - if(addr & 0x8000) return prgrom.read(vrc6.prg_addr(addr)); - return cpu.mdr(); -} - -void prg_write(unsigned addr, uint8 data) { - if((addr & 0xe000) == 0x6000) return vrc6.ram_write(addr, data); - if(addr & 0x8000) { - addr = (addr & 0xf003); - if(prgram.size) addr = (addr & ~3) | ((addr & 2) >> 1) | ((addr & 1) << 1); - return vrc6.reg_write(addr, data); + KonamiVRC6(Markup::Node& document) : Board(document), vrc6(*this) { } -} -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(vrc6.ciram_addr(addr)); - return Board::chr_read(vrc6.chr_addr(addr)); -} + auto prg_read(uint addr) -> uint8{ + if((addr & 0xe000) == 0x6000) return vrc6.ram_read(addr); + if(addr & 0x8000) return prgrom.read(vrc6.prg_addr(addr)); + return cpu.mdr(); + } -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(vrc6.ciram_addr(addr), data); - return Board::chr_write(vrc6.chr_addr(addr), data); -} + auto prg_write(uint addr, uint8 data) -> void { + if((addr & 0xe000) == 0x6000) return vrc6.ram_write(addr, data); + if(addr & 0x8000) { + addr = (addr & 0xf003); + if(prgram.size) addr = (addr & ~3) | ((addr & 2) >> 1) | ((addr & 1) << 1); + return vrc6.reg_write(addr, data); + } + } -void serialize(serializer& s) { - Board::serialize(s); - vrc6.serialize(s); -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(vrc6.ciram_addr(addr)); + return Board::chr_read(vrc6.chr_addr(addr)); + } -void main() { vrc6.main(); } -void power() { vrc6.power(); } -void reset() { vrc6.reset(); } + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(vrc6.ciram_addr(addr), data); + return Board::chr_write(vrc6.chr_addr(addr), data); + } -KonamiVRC6(Markup::Node& document) : Board(document), vrc6(*this) { -} + auto serialize(serializer& s) -> void { + Board::serialize(s); + vrc6.serialize(s); + } + auto main() -> void { vrc6.main(); } + auto power() -> void { vrc6.power(); } + auto reset() -> void { vrc6.reset(); } + + VRC6 vrc6; }; diff --git a/fc/cartridge/board/konami-vrc7.cpp b/fc/cartridge/board/konami-vrc7.cpp index 8c72a3f0..a5008717 100644 --- a/fc/cartridge/board/konami-vrc7.cpp +++ b/fc/cartridge/board/konami-vrc7.cpp @@ -1,47 +1,45 @@ struct KonamiVRC7 : Board { + KonamiVRC7(Markup::Node& document) : Board(document), vrc7(*this) { + } -VRC7 vrc7; + auto main() -> void { + return vrc7.main(); + } -void main() { - return vrc7.main(); -} + auto prg_read(uint addr) -> uint8 { + if(addr < 0x6000) return cpu.mdr(); + if(addr < 0x8000) return prgram.read(addr); + return prgrom.read(vrc7.prg_addr(addr)); + } -uint8 prg_read(unsigned addr) { - if(addr < 0x6000) return cpu.mdr(); - if(addr < 0x8000) return prgram.read(addr); - return prgrom.read(vrc7.prg_addr(addr)); -} + auto prg_write(uint addr, uint8 data) -> void { + if(addr < 0x6000) return; + if(addr < 0x8000) return prgram.write(addr, data); + return vrc7.reg_write(addr, data); + } -void prg_write(unsigned addr, uint8 data) { - if(addr < 0x6000) return; - if(addr < 0x8000) return prgram.write(addr, data); - return vrc7.reg_write(addr, data); -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(vrc7.ciram_addr(addr)); + return chrram.read(vrc7.chr_addr(addr)); + } -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(vrc7.ciram_addr(addr)); - return chrram.read(vrc7.chr_addr(addr)); -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(vrc7.ciram_addr(addr), data); + return chrram.write(vrc7.chr_addr(addr), data); + } -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(vrc7.ciram_addr(addr), data); - return chrram.write(vrc7.chr_addr(addr), data); -} + auto power() -> void { + vrc7.power(); + } -void power() { - vrc7.power(); -} + auto reset() -> void { + vrc7.reset(); + } -void reset() { - vrc7.reset(); -} - -void serialize(serializer& s) { - Board::serialize(s); - vrc7.serialize(s); -} - -KonamiVRC7(Markup::Node& document) : Board(document), vrc7(*this) { -} + auto serialize(serializer& s) -> void { + Board::serialize(s); + vrc7.serialize(s); + } + VRC7 vrc7; }; diff --git a/fc/cartridge/board/nes-axrom.cpp b/fc/cartridge/board/nes-axrom.cpp index 6d468cfd..dc79e005 100644 --- a/fc/cartridge/board/nes-axrom.cpp +++ b/fc/cartridge/board/nes-axrom.cpp @@ -4,48 +4,46 @@ //NES-AOROM struct NES_AxROM : Board { - -uint4 prg_bank; -bool mirror_select; - -uint8 prg_read(unsigned addr) { - if(addr & 0x8000) return prgrom.read((prg_bank << 15) | (addr & 0x7fff)); - return cpu.mdr(); -} - -void prg_write(unsigned addr, uint8 data) { - if(addr & 0x8000) { - prg_bank = data & 0x0f; - mirror_select = data & 0x10; + NES_AxROM(Markup::Node& document) : Board(document) { } -} -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read((mirror_select << 10) | (addr & 0x03ff)); - return Board::chr_read(addr); -} + auto prg_read(uint addr) -> uint8 { + if(addr & 0x8000) return prgrom.read((prg_bank << 15) | (addr & 0x7fff)); + return cpu.mdr(); + } -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write((mirror_select << 10) | (addr & 0x03ff), data); - return Board::chr_write(addr, data); -} + auto prg_write(uint addr, uint8 data) -> void { + if(addr & 0x8000) { + prg_bank = data & 0x0f; + mirror_select = data & 0x10; + } + } -void power() { -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read((mirror_select << 10) | (addr & 0x03ff)); + return Board::chr_read(addr); + } -void reset() { - prg_bank = 0x0f; - mirror_select = 0; -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write((mirror_select << 10) | (addr & 0x03ff), data); + return Board::chr_write(addr, data); + } -void serialize(serializer& s) { - Board::serialize(s); + auto power() -> void { + } - s.integer(prg_bank); - s.integer(mirror_select); -} + auto reset() -> void { + prg_bank = 0x0f; + mirror_select = 0; + } -NES_AxROM(Markup::Node& document) : Board(document) { -} + auto serialize(serializer& s) -> void { + Board::serialize(s); + s.integer(prg_bank); + s.integer(mirror_select); + } + + uint4 prg_bank; + bool mirror_select; }; diff --git a/fc/cartridge/board/nes-bnrom.cpp b/fc/cartridge/board/nes-bnrom.cpp index c6790b63..48a2e657 100644 --- a/fc/cartridge/board/nes-bnrom.cpp +++ b/fc/cartridge/board/nes-bnrom.cpp @@ -1,52 +1,50 @@ //NES-BN-ROM-01 struct NES_BNROM : Board { - -struct Settings { - bool mirror; //0 = horizontal, 1 = vertical -} settings; - -uint2 prg_bank; - -uint8 prg_read(unsigned addr) { - if(addr & 0x8000) return prgrom.read((prg_bank << 15) | (addr & 0x7fff)); - return cpu.mdr(); -} - -void prg_write(unsigned addr, uint8 data) { - if(addr & 0x8000) prg_bank = data & 0x03; -} - -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_read(addr); + NES_BNROM(Markup::Node& document) : Board(document) { + settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; } - return Board::chr_read(addr); -} -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_write(addr, data); + auto prg_read(uint addr) -> uint8 { + if(addr & 0x8000) return prgrom.read((prg_bank << 15) | (addr & 0x7fff)); + return cpu.mdr(); } - return Board::chr_write(addr, data); -} -void power() { -} + auto prg_write(uint addr, uint8 data) -> void { + if(addr & 0x8000) prg_bank = data & 0x03; + } -void reset() { - prg_bank = 0; -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_read(addr); + } + return Board::chr_read(addr); + } -void serialize(serializer& s) { - Board::serialize(s); - s.integer(prg_bank); -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr, data); + } + return Board::chr_write(addr, data); + } -NES_BNROM(Markup::Node& document) : Board(document) { - settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; -} + auto power() -> void { + } + auto reset() -> void { + prg_bank = 0; + } + + auto serialize(serializer& s) -> void { + Board::serialize(s); + s.integer(prg_bank); + } + + struct Settings { + bool mirror; //0 = horizontal, 1 = vertical + } settings; + + uint2 prg_bank; }; diff --git a/fc/cartridge/board/nes-cnrom.cpp b/fc/cartridge/board/nes-cnrom.cpp index fac9b016..3f1769ba 100644 --- a/fc/cartridge/board/nes-cnrom.cpp +++ b/fc/cartridge/board/nes-cnrom.cpp @@ -1,54 +1,52 @@ //NES-CNROM struct NES_CNROM : Board { - -struct Settings { - bool mirror; //0 = horizontal, 1 = vertical -} settings; - -uint2 chr_bank; - -uint8 prg_read(unsigned addr) { - if(addr & 0x8000) return prgrom.read(addr & 0x7fff); - return cpu.mdr(); -} - -void prg_write(unsigned addr, uint8 data) { - if(addr & 0x8000) chr_bank = data & 0x03; -} - -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_read(addr & 0x07ff); + NES_CNROM(Markup::Node& document) : Board(document) { + settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; } - addr = (chr_bank * 0x2000) + (addr & 0x1fff); - return Board::chr_read(addr); -} -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_write(addr & 0x07ff, data); + auto prg_read(uint addr) -> uint8 { + if(addr & 0x8000) return prgrom.read(addr & 0x7fff); + return cpu.mdr(); } - addr = (chr_bank * 0x2000) + (addr & 0x1fff); - Board::chr_write(addr, data); -} -void power() { -} + auto prg_write(uint addr, uint8 data) -> void { + if(addr & 0x8000) chr_bank = data & 0x03; + } -void reset() { - chr_bank = 0; -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_read(addr & 0x07ff); + } + addr = (chr_bank * 0x2000) + (addr & 0x1fff); + return Board::chr_read(addr); + } -void serialize(serializer& s) { - Board::serialize(s); - s.integer(chr_bank); -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr & 0x07ff, data); + } + addr = (chr_bank * 0x2000) + (addr & 0x1fff); + Board::chr_write(addr, data); + } -NES_CNROM(Markup::Node& document) : Board(document) { - settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; -} + auto power() -> void { + } + auto reset() -> void { + chr_bank = 0; + } + + auto serialize(serializer& s) -> void { + Board::serialize(s); + s.integer(chr_bank); + } + + struct Settings { + bool mirror; //0 = horizontal, 1 = vertical + } settings; + + uint2 chr_bank; }; diff --git a/fc/cartridge/board/nes-exrom.cpp b/fc/cartridge/board/nes-exrom.cpp index 42bd56c9..0c706114 100644 --- a/fc/cartridge/board/nes-exrom.cpp +++ b/fc/cartridge/board/nes-exrom.cpp @@ -1,53 +1,51 @@ struct NES_ExROM : Board { + NES_ExROM(Markup::Node& document) : Board(document), mmc5(*this) { + revision = Revision::ELROM; + } -enum class Revision : unsigned { - EKROM, - ELROM, - ETROM, - EWROM, -} revision; + auto main() -> void { + mmc5.main(); + } -MMC5 mmc5; + auto prg_read(uint addr) -> uint8 { + return mmc5.prg_read(addr); + } -void main() { - mmc5.main(); -} + auto prg_write(uint addr, uint8 data) -> void { + mmc5.prg_write(addr, data); + } -uint8 prg_read(unsigned addr) { - return mmc5.prg_read(addr); -} + auto chr_read(uint addr) -> uint8 { + return mmc5.chr_read(addr); + } -void prg_write(unsigned addr, uint8 data) { - mmc5.prg_write(addr, data); -} + auto chr_write(uint addr, uint8 data) -> void { + mmc5.chr_write(addr, data); + } -uint8 chr_read(unsigned addr) { - return mmc5.chr_read(addr); -} + auto scanline(uint y) -> void { + mmc5.scanline(y); + } -void chr_write(unsigned addr, uint8 data) { - mmc5.chr_write(addr, data); -} + auto power() -> void { + mmc5.power(); + } -void scanline(unsigned y) { - mmc5.scanline(y); -} + auto reset() -> void { + mmc5.reset(); + } -void power() { - mmc5.power(); -} + auto serialize(serializer& s) -> void { + Board::serialize(s); + mmc5.serialize(s); + } -void reset() { - mmc5.reset(); -} - -void serialize(serializer& s) { - Board::serialize(s); - mmc5.serialize(s); -} - -NES_ExROM(Markup::Node& document) : Board(document), mmc5(*this) { - revision = Revision::ELROM; -} + enum class Revision : uint { + EKROM, + ELROM, + ETROM, + EWROM, + } revision; + MMC5 mmc5; }; diff --git a/fc/cartridge/board/nes-fxrom.cpp b/fc/cartridge/board/nes-fxrom.cpp index 2c79e50b..170a0ab1 100644 --- a/fc/cartridge/board/nes-fxrom.cpp +++ b/fc/cartridge/board/nes-fxrom.cpp @@ -1,91 +1,89 @@ //MMC4 struct NES_FxROM : Board { - -enum Revision : unsigned { - FJROM, - FKROM, -} revision; - -uint4 prg_bank; -uint5 chr_bank[2][2]; -bool mirror; -bool latch[2]; - -uint8 prg_read(unsigned addr) { - if(addr < 0x6000) return cpu.mdr(); - if(addr < 0x8000) return prgram.read(addr); - unsigned bank = addr < 0xc000 ? prg_bank : (uint4)0x0f; - return prgrom.read((bank * 0x4000) | (addr & 0x3fff)); -} - -void prg_write(unsigned addr, uint8 data) { - if(addr < 0x6000) return; - if(addr < 0x8000) return prgram.write(addr, data); - - switch(addr & 0xf000) { - case 0xa000: prg_bank = data & 0x0f; break; - case 0xb000: chr_bank[0][0] = data & 0x1f; break; - case 0xc000: chr_bank[0][1] = data & 0x1f; break; - case 0xd000: chr_bank[1][0] = data & 0x1f; break; - case 0xe000: chr_bank[1][1] = data & 0x1f; break; - case 0xf000: mirror = data & 0x01; break; + NES_FxROM(Markup::Node& document) : Board(document) { + revision = Revision::FKROM; } -} -unsigned ciram_addr(unsigned addr) const { - switch(mirror) { - case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring - case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + auto prg_read(uint addr) -> uint8 { + if(addr < 0x6000) return cpu.mdr(); + if(addr < 0x8000) return prgram.read(addr); + uint bank = addr < 0xc000 ? prg_bank : (uint4)0x0f; + return prgrom.read((bank * 0x4000) | (addr & 0x3fff)); } -} -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(ciram_addr(addr)); - bool region = addr & 0x1000; - unsigned bank = chr_bank[region][latch[region]]; - if((addr & 0x0ff8) == 0x0fd8) latch[region] = 0; - if((addr & 0x0ff8) == 0x0fe8) latch[region] = 1; - return Board::chr_read((bank * 0x1000) | (addr & 0x0fff)); -} + auto prg_write(uint addr, uint8 data) -> void { + if(addr < 0x6000) return; + if(addr < 0x8000) return prgram.write(addr, data); -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(ciram_addr(addr), data); - bool region = addr & 0x1000; - unsigned bank = chr_bank[region][latch[region]]; - if((addr & 0x0ff8) == 0x0fd8) latch[region] = 0; - if((addr & 0x0ff8) == 0x0fe8) latch[region] = 1; - return Board::chr_write((bank * 0x1000) | (addr & 0x0fff), data); -} + switch(addr & 0xf000) { + case 0xa000: prg_bank = data & 0x0f; break; + case 0xb000: chr_bank[0][0] = data & 0x1f; break; + case 0xc000: chr_bank[0][1] = data & 0x1f; break; + case 0xd000: chr_bank[1][0] = data & 0x1f; break; + case 0xe000: chr_bank[1][1] = data & 0x1f; break; + case 0xf000: mirror = data & 0x01; break; + } + } -void power() { -} + auto ciram_addr(uint addr) const -> uint { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + } + } -void reset() { - prg_bank = 0; - chr_bank[0][0] = 0; - chr_bank[0][1] = 0; - chr_bank[1][0] = 0; - chr_bank[1][1] = 0; - mirror = 0; - latch[0] = 0; - latch[1] = 0; -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(ciram_addr(addr)); + bool region = addr & 0x1000; + uint bank = chr_bank[region][latch[region]]; + if((addr & 0x0ff8) == 0x0fd8) latch[region] = 0; + if((addr & 0x0ff8) == 0x0fe8) latch[region] = 1; + return Board::chr_read((bank * 0x1000) | (addr & 0x0fff)); + } -void serialize(serializer& s) { - Board::serialize(s); + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(ciram_addr(addr), data); + bool region = addr & 0x1000; + uint bank = chr_bank[region][latch[region]]; + if((addr & 0x0ff8) == 0x0fd8) latch[region] = 0; + if((addr & 0x0ff8) == 0x0fe8) latch[region] = 1; + return Board::chr_write((bank * 0x1000) | (addr & 0x0fff), data); + } - s.integer(prg_bank); - s.integer(chr_bank[0][0]); - s.integer(chr_bank[0][1]); - s.integer(chr_bank[1][0]); - s.integer(chr_bank[1][1]); - s.integer(mirror); - s.array(latch); -} + auto power() -> void { + } -NES_FxROM(Markup::Node& document) : Board(document) { - revision = Revision::FKROM; -} + auto reset() -> void { + prg_bank = 0; + chr_bank[0][0] = 0; + chr_bank[0][1] = 0; + chr_bank[1][0] = 0; + chr_bank[1][1] = 0; + mirror = 0; + latch[0] = 0; + latch[1] = 0; + } + auto serialize(serializer& s) -> void { + Board::serialize(s); + + s.integer(prg_bank); + s.integer(chr_bank[0][0]); + s.integer(chr_bank[0][1]); + s.integer(chr_bank[1][0]); + s.integer(chr_bank[1][1]); + s.integer(mirror); + s.array(latch); + } + + enum Revision : uint { + FJROM, + FKROM, + } revision; + + uint4 prg_bank; + uint5 chr_bank[2][2]; + bool mirror; + bool latch[2]; }; diff --git a/fc/cartridge/board/nes-gxrom.cpp b/fc/cartridge/board/nes-gxrom.cpp index 8e8d99af..4603f4b1 100644 --- a/fc/cartridge/board/nes-gxrom.cpp +++ b/fc/cartridge/board/nes-gxrom.cpp @@ -2,60 +2,58 @@ //NES-MHROM struct NES_GxROM : Board { - -struct Settings { - bool mirror; //0 = horizontal, 1 = vertical -} settings; - -uint2 prg_bank; -uint2 chr_bank; - -uint8 prg_read(unsigned addr) { - if(addr & 0x8000) return prgrom.read((prg_bank << 15) | (addr & 0x7fff)); - return cpu.mdr(); -} - -void prg_write(unsigned addr, uint8 data) { - if(addr & 0x8000) { - prg_bank = (data & 0x30) >> 4; - chr_bank = (data & 0x03) >> 0; + NES_GxROM(Markup::Node& document) : Board(document) { + settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; } -} -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_read(addr & 0x07ff); + auto prg_read(uint addr) -> uint8 { + if(addr & 0x8000) return prgrom.read((prg_bank << 15) | (addr & 0x7fff)); + return cpu.mdr(); } - addr = (chr_bank * 0x2000) + (addr & 0x1fff); - return Board::chr_read(addr); -} -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_write(addr & 0x07ff, data); + auto prg_write(uint addr, uint8 data) -> void { + if(addr & 0x8000) { + prg_bank = (data & 0x30) >> 4; + chr_bank = (data & 0x03) >> 0; + } } - addr = (chr_bank * 0x2000) + (addr & 0x1fff); - Board::chr_write(addr, data); -} -void power() { -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_read(addr & 0x07ff); + } + addr = (chr_bank * 0x2000) + (addr & 0x1fff); + return Board::chr_read(addr); + } -void reset() { - prg_bank = 0; - chr_bank = 0; -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr & 0x07ff, data); + } + addr = (chr_bank * 0x2000) + (addr & 0x1fff); + Board::chr_write(addr, data); + } -void serialize(serializer& s) { - Board::serialize(s); - s.integer(prg_bank); - s.integer(chr_bank); -} + auto power() -> void { + } -NES_GxROM(Markup::Node& document) : Board(document) { - settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; -} + auto reset() -> void { + prg_bank = 0; + chr_bank = 0; + } + auto serialize(serializer& s) -> void { + Board::serialize(s); + s.integer(prg_bank); + s.integer(chr_bank); + } + + struct Settings { + bool mirror; //0 = horizontal, 1 = vertical + } settings; + + uint2 prg_bank; + uint2 chr_bank; }; diff --git a/fc/cartridge/board/nes-hkrom.cpp b/fc/cartridge/board/nes-hkrom.cpp index 660785ec..599dd24b 100644 --- a/fc/cartridge/board/nes-hkrom.cpp +++ b/fc/cartridge/board/nes-hkrom.cpp @@ -1,48 +1,46 @@ struct NES_HKROM : Board { + NES_HKROM(Markup::Node& document) : Board(document), mmc6(*this) { + } -MMC6 mmc6; + auto main() -> void { + mmc6.main(); + } -void main() { - mmc6.main(); -} + auto prg_read(uint addr) -> uint8 { + if((addr & 0xf000) == 0x7000) return mmc6.ram_read(addr); + if(addr & 0x8000) return prgrom.read(mmc6.prg_addr(addr)); + return cpu.mdr(); + } -uint8 prg_read(unsigned addr) { - if((addr & 0xf000) == 0x7000) return mmc6.ram_read(addr); - if(addr & 0x8000) return prgrom.read(mmc6.prg_addr(addr)); - return cpu.mdr(); -} + auto prg_write(uint addr, uint8 data) -> void { + if((addr & 0xf000) == 0x7000) return mmc6.ram_write(addr, data); + if(addr & 0x8000) return mmc6.reg_write(addr, data); + } -void prg_write(unsigned addr, uint8 data) { - if((addr & 0xf000) == 0x7000) return mmc6.ram_write(addr, data); - if(addr & 0x8000) return mmc6.reg_write(addr, data); -} + auto chr_read(uint addr) -> uint8 { + mmc6.irq_test(addr); + if(addr & 0x2000) return ppu.ciram_read(mmc6.ciram_addr(addr)); + return Board::chr_read(mmc6.chr_addr(addr)); + } -uint8 chr_read(unsigned addr) { - mmc6.irq_test(addr); - if(addr & 0x2000) return ppu.ciram_read(mmc6.ciram_addr(addr)); - return Board::chr_read(mmc6.chr_addr(addr)); -} + auto chr_write(uint addr, uint8 data) -> void { + mmc6.irq_test(addr); + if(addr & 0x2000) return ppu.ciram_write(mmc6.ciram_addr(addr), data); + return Board::chr_write(mmc6.chr_addr(addr), data); + } -void chr_write(unsigned addr, uint8 data) { - mmc6.irq_test(addr); - if(addr & 0x2000) return ppu.ciram_write(mmc6.ciram_addr(addr), data); - return Board::chr_write(mmc6.chr_addr(addr), data); -} + auto power() -> void { + mmc6.power(); + } -void power() { - mmc6.power(); -} + auto reset() -> void { + mmc6.reset(); + } -void reset() { - mmc6.reset(); -} - -void serialize(serializer& s) { - Board::serialize(s); - mmc6.serialize(s); -} - -NES_HKROM(Markup::Node& document) : Board(document), mmc6(*this) { -} + auto serialize(serializer& s) -> void { + Board::serialize(s); + mmc6.serialize(s); + } + MMC6 mmc6; }; diff --git a/fc/cartridge/board/nes-nrom.cpp b/fc/cartridge/board/nes-nrom.cpp index 10f4eda6..462cf775 100644 --- a/fc/cartridge/board/nes-nrom.cpp +++ b/fc/cartridge/board/nes-nrom.cpp @@ -2,42 +2,40 @@ //NES-NROM-256 struct NES_NROM : Board { - -struct Settings { - bool mirror; //0 = horizontal, 1 = vertical -} settings; - -uint8 prg_read(unsigned addr) { - if(addr & 0x8000) return prgrom.read(addr); - return cpu.mdr(); -} - -void prg_write(unsigned addr, uint8 data) { -} - -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_read(addr & 0x07ff); + NES_NROM(Markup::Node& document) : Board(document) { + settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; } - if(chrram.size) return chrram.read(addr); - return chrrom.read(addr); -} -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_write(addr & 0x07ff, data); + auto prg_read(uint addr) -> uint8 { + if(addr & 0x8000) return prgrom.read(addr); + return cpu.mdr(); } - if(chrram.size) return chrram.write(addr, data); -} -void serialize(serializer& s) { - Board::serialize(s); -} + auto prg_write(uint addr, uint8 data) -> void { + } -NES_NROM(Markup::Node& document) : Board(document) { - settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_read(addr & 0x07ff); + } + if(chrram.size) return chrram.read(addr); + return chrrom.read(addr); + } + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr & 0x07ff, data); + } + if(chrram.size) return chrram.write(addr, data); + } + + auto serialize(serializer& s) -> void { + Board::serialize(s); + } + + struct Settings { + bool mirror; //0 = horizontal, 1 = vertical + } settings; }; diff --git a/fc/cartridge/board/nes-pxrom.cpp b/fc/cartridge/board/nes-pxrom.cpp index f6b0510e..473455ef 100644 --- a/fc/cartridge/board/nes-pxrom.cpp +++ b/fc/cartridge/board/nes-pxrom.cpp @@ -1,97 +1,95 @@ //MMC2 struct NES_PxROM : Board { - -enum Revision : unsigned { - PEEOROM, - PNROM, -} revision; - -uint4 prg_bank; -uint5 chr_bank[2][2]; -bool mirror; -bool latch[2]; - -uint8 prg_read(unsigned addr) { - if(addr < 0x6000) return cpu.mdr(); - if(addr < 0x8000) return prgram.read(addr); - unsigned bank = 0; - switch((addr / 0x2000) & 3) { - case 0: bank = prg_bank; break; - case 1: bank = 0x0d; break; - case 2: bank = 0x0e; break; - case 3: bank = 0x0f; break; + NES_PxROM(Markup::Node& document) : Board(document) { + revision = Revision::PNROM; } - return prgrom.read((bank * 0x2000) | (addr & 0x1fff)); -} -void prg_write(unsigned addr, uint8 data) { - if(addr < 0x6000) return; - if(addr < 0x8000) return prgram.write(addr, data); - - switch(addr & 0xf000) { - case 0xa000: prg_bank = data & 0x0f; break; - case 0xb000: chr_bank[0][0] = data & 0x1f; break; - case 0xc000: chr_bank[0][1] = data & 0x1f; break; - case 0xd000: chr_bank[1][0] = data & 0x1f; break; - case 0xe000: chr_bank[1][1] = data & 0x1f; break; - case 0xf000: mirror = data & 0x01; break; + auto prg_read(uint addr) -> uint8 { + if(addr < 0x6000) return cpu.mdr(); + if(addr < 0x8000) return prgram.read(addr); + uint bank = 0; + switch((addr / 0x2000) & 3) { + case 0: bank = prg_bank; break; + case 1: bank = 0x0d; break; + case 2: bank = 0x0e; break; + case 3: bank = 0x0f; break; + } + return prgrom.read((bank * 0x2000) | (addr & 0x1fff)); } -} -unsigned ciram_addr(unsigned addr) const { - switch(mirror) { - case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring - case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + auto prg_write(uint addr, uint8 data) -> void { + if(addr < 0x6000) return; + if(addr < 0x8000) return prgram.write(addr, data); + + switch(addr & 0xf000) { + case 0xa000: prg_bank = data & 0x0f; break; + case 0xb000: chr_bank[0][0] = data & 0x1f; break; + case 0xc000: chr_bank[0][1] = data & 0x1f; break; + case 0xd000: chr_bank[1][0] = data & 0x1f; break; + case 0xe000: chr_bank[1][1] = data & 0x1f; break; + case 0xf000: mirror = data & 0x01; break; + } } -} -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(ciram_addr(addr)); - bool region = addr & 0x1000; - unsigned bank = chr_bank[region][latch[region]]; - if((addr & 0x0ff8) == 0x0fd8) latch[region] = 0; - if((addr & 0x0ff8) == 0x0fe8) latch[region] = 1; - return Board::chr_read((bank * 0x1000) | (addr & 0x0fff)); -} + auto ciram_addr(uint addr) const -> uint { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + } + } -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(ciram_addr(addr), data); - bool region = addr & 0x1000; - unsigned bank = chr_bank[region][latch[region]]; - if((addr & 0x0ff8) == 0x0fd8) latch[region] = 0; - if((addr & 0x0ff8) == 0x0fe8) latch[region] = 1; - return Board::chr_write((bank * 0x1000) | (addr & 0x0fff), data); -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(ciram_addr(addr)); + bool region = addr & 0x1000; + uint bank = chr_bank[region][latch[region]]; + if((addr & 0x0ff8) == 0x0fd8) latch[region] = 0; + if((addr & 0x0ff8) == 0x0fe8) latch[region] = 1; + return Board::chr_read((bank * 0x1000) | (addr & 0x0fff)); + } -void power() { -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(ciram_addr(addr), data); + bool region = addr & 0x1000; + uint bank = chr_bank[region][latch[region]]; + if((addr & 0x0ff8) == 0x0fd8) latch[region] = 0; + if((addr & 0x0ff8) == 0x0fe8) latch[region] = 1; + return Board::chr_write((bank * 0x1000) | (addr & 0x0fff), data); + } -void reset() { - prg_bank = 0; - chr_bank[0][0] = 0; - chr_bank[0][1] = 0; - chr_bank[1][0] = 0; - chr_bank[1][1] = 0; - mirror = 0; - latch[0] = 0; - latch[1] = 0; -} + auto power() -> void { + } -void serialize(serializer& s) { - Board::serialize(s); + auto reset() -> void { + prg_bank = 0; + chr_bank[0][0] = 0; + chr_bank[0][1] = 0; + chr_bank[1][0] = 0; + chr_bank[1][1] = 0; + mirror = 0; + latch[0] = 0; + latch[1] = 0; + } - s.integer(prg_bank); - s.integer(chr_bank[0][0]); - s.integer(chr_bank[0][1]); - s.integer(chr_bank[1][0]); - s.integer(chr_bank[1][1]); - s.integer(mirror); - s.array(latch); -} + auto serialize(serializer& s) -> void { + Board::serialize(s); -NES_PxROM(Markup::Node& document) : Board(document) { - revision = Revision::PNROM; -} + s.integer(prg_bank); + s.integer(chr_bank[0][0]); + s.integer(chr_bank[0][1]); + s.integer(chr_bank[1][0]); + s.integer(chr_bank[1][1]); + s.integer(mirror); + s.array(latch); + } + enum Revision : uint { + PEEOROM, + PNROM, + } revision; + + uint4 prg_bank; + uint5 chr_bank[2][2]; + bool mirror; + bool latch[2]; }; diff --git a/fc/cartridge/board/nes-sxrom.cpp b/fc/cartridge/board/nes-sxrom.cpp index 7f51a6b1..0ef9bacc 100644 --- a/fc/cartridge/board/nes-sxrom.cpp +++ b/fc/cartridge/board/nes-sxrom.cpp @@ -1,101 +1,99 @@ struct NES_SxROM : Board { - -enum class Revision : unsigned { - SAROM, - SBROM, - SCROM, - SC1ROM, - SEROM, - SFROM, - SGROM, - SHROM, - SH1ROM, - SIROM, - SJROM, - SKROM, - SLROM, - SL1ROM, - SL2ROM, - SL3ROM, - SLRROM, - SMROM, - SNROM, - SOROM, - SUROM, - SXROM, -} revision; - -MMC1 mmc1; - -void main() { - return mmc1.main(); -} - -unsigned ram_addr(unsigned addr) { - unsigned bank = 0; - if(revision == Revision::SOROM) bank = (mmc1.chr_bank[0] & 0x08) >> 3; - if(revision == Revision::SUROM) bank = (mmc1.chr_bank[0] & 0x0c) >> 2; - if(revision == Revision::SXROM) bank = (mmc1.chr_bank[0] & 0x0c) >> 2; - return (bank << 13) | (addr & 0x1fff); -} - -uint8 prg_read(unsigned addr) { - if((addr & 0xe000) == 0x6000) { - if(revision == Revision::SNROM) { - if(mmc1.chr_bank[0] & 0x10) return cpu.mdr(); - } - if(mmc1.ram_disable) return 0x00; - return prgram.read(ram_addr(addr)); + NES_SxROM(Markup::Node& document) : Board(document), mmc1(*this) { + revision = Revision::SXROM; } - if(addr & 0x8000) { - addr = mmc1.prg_addr(addr); - if(revision == Revision::SXROM) { - addr |= ((mmc1.chr_bank[0] & 0x10) >> 4) << 18; - } - return prgrom.read(addr); + auto main() -> void { + return mmc1.main(); } - return cpu.mdr(); -} - -void prg_write(unsigned addr, uint8 data) { - if((addr & 0xe000) == 0x6000) { - if(revision == Revision::SNROM) { - if(mmc1.chr_bank[0] & 0x10) return; - } - if(mmc1.ram_disable) return; - return prgram.write(ram_addr(addr), data); + auto ram_addr(uint addr) -> uint { + uint bank = 0; + if(revision == Revision::SOROM) bank = (mmc1.chr_bank[0] & 0x08) >> 3; + if(revision == Revision::SUROM) bank = (mmc1.chr_bank[0] & 0x0c) >> 2; + if(revision == Revision::SXROM) bank = (mmc1.chr_bank[0] & 0x0c) >> 2; + return (bank << 13) | (addr & 0x1fff); } - if(addr & 0x8000) return mmc1.mmio_write(addr, data); -} + auto prg_read(uint addr) -> uint8 { + if((addr & 0xe000) == 0x6000) { + if(revision == Revision::SNROM) { + if(mmc1.chr_bank[0] & 0x10) return cpu.mdr(); + } + if(mmc1.ram_disable) return 0x00; + return prgram.read(ram_addr(addr)); + } -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(mmc1.ciram_addr(addr)); - return Board::chr_read(mmc1.chr_addr(addr)); -} + if(addr & 0x8000) { + addr = mmc1.prg_addr(addr); + if(revision == Revision::SXROM) { + addr |= ((mmc1.chr_bank[0] & 0x10) >> 4) << 18; + } + return prgrom.read(addr); + } -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(mmc1.ciram_addr(addr), data); - return Board::chr_write(mmc1.chr_addr(addr), data); -} + return cpu.mdr(); + } -void power() { - mmc1.power(); -} + auto prg_write(uint addr, uint8 data) -> void { + if((addr & 0xe000) == 0x6000) { + if(revision == Revision::SNROM) { + if(mmc1.chr_bank[0] & 0x10) return; + } + if(mmc1.ram_disable) return; + return prgram.write(ram_addr(addr), data); + } -void reset() { - mmc1.reset(); -} + if(addr & 0x8000) return mmc1.mmio_write(addr, data); + } -void serialize(serializer& s) { - Board::serialize(s); - mmc1.serialize(s); -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(mmc1.ciram_addr(addr)); + return Board::chr_read(mmc1.chr_addr(addr)); + } -NES_SxROM(Markup::Node& document) : Board(document), mmc1(*this) { - revision = Revision::SXROM; -} + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(mmc1.ciram_addr(addr), data); + return Board::chr_write(mmc1.chr_addr(addr), data); + } + auto power() -> void { + mmc1.power(); + } + + auto reset() -> void { + mmc1.reset(); + } + + auto serialize(serializer& s) -> void { + Board::serialize(s); + mmc1.serialize(s); + } + + enum class Revision : uint { + SAROM, + SBROM, + SCROM, + SC1ROM, + SEROM, + SFROM, + SGROM, + SHROM, + SH1ROM, + SIROM, + SJROM, + SKROM, + SLROM, + SL1ROM, + SL2ROM, + SL3ROM, + SLRROM, + SMROM, + SNROM, + SOROM, + SUROM, + SXROM, + } revision; + + MMC1 mmc1; }; diff --git a/fc/cartridge/board/nes-txrom.cpp b/fc/cartridge/board/nes-txrom.cpp index ee36d552..9f4b119e 100644 --- a/fc/cartridge/board/nes-txrom.cpp +++ b/fc/cartridge/board/nes-txrom.cpp @@ -1,67 +1,65 @@ struct NES_TxROM : Board { + NES_TxROM(Markup::Node& document) : Board(document), mmc3(*this) { + revision = Revision::TLROM; + } -enum class Revision : unsigned { - TBROM, - TEROM, - TFROM, - TGROM, - TKROM, - TKSROM, - TLROM, - TL1ROM, - TL2ROM, - TLSROM, - TNROM, - TQROM, - TR1ROM, - TSROM, - TVROM, -} revision; + auto main() -> void { + mmc3.main(); + } -MMC3 mmc3; + auto prg_read(uint addr) -> uint8 { + if((addr & 0xe000) == 0x6000) return mmc3.ram_read(addr); + if(addr & 0x8000) return prgrom.read(mmc3.prg_addr(addr)); + return cpu.mdr(); + } -void main() { - mmc3.main(); -} + auto prg_write(uint addr, uint8 data) -> void { + if((addr & 0xe000) == 0x6000) return mmc3.ram_write(addr, data); + if(addr & 0x8000) return mmc3.reg_write(addr, data); + } -uint8 prg_read(unsigned addr) { - if((addr & 0xe000) == 0x6000) return mmc3.ram_read(addr); - if(addr & 0x8000) return prgrom.read(mmc3.prg_addr(addr)); - return cpu.mdr(); -} + auto chr_read(uint addr) -> uint8 { + mmc3.irq_test(addr); + if(addr & 0x2000) return ppu.ciram_read(mmc3.ciram_addr(addr)); + return Board::chr_read(mmc3.chr_addr(addr)); + } -void prg_write(unsigned addr, uint8 data) { - if((addr & 0xe000) == 0x6000) return mmc3.ram_write(addr, data); - if(addr & 0x8000) return mmc3.reg_write(addr, data); -} + auto chr_write(uint addr, uint8 data) -> void { + mmc3.irq_test(addr); + if(addr & 0x2000) return ppu.ciram_write(mmc3.ciram_addr(addr), data); + return Board::chr_write(mmc3.chr_addr(addr), data); + } -uint8 chr_read(unsigned addr) { - mmc3.irq_test(addr); - if(addr & 0x2000) return ppu.ciram_read(mmc3.ciram_addr(addr)); - return Board::chr_read(mmc3.chr_addr(addr)); -} + auto power() -> void { + mmc3.power(); + } -void chr_write(unsigned addr, uint8 data) { - mmc3.irq_test(addr); - if(addr & 0x2000) return ppu.ciram_write(mmc3.ciram_addr(addr), data); - return Board::chr_write(mmc3.chr_addr(addr), data); -} + auto reset() -> void { + mmc3.reset(); + } -void power() { - mmc3.power(); -} + auto serialize(serializer& s) -> void { + Board::serialize(s); + mmc3.serialize(s); + } -void reset() { - mmc3.reset(); -} - -void serialize(serializer& s) { - Board::serialize(s); - mmc3.serialize(s); -} - -NES_TxROM(Markup::Node& document) : Board(document), mmc3(*this) { - revision = Revision::TLROM; -} + enum class Revision : uint { + TBROM, + TEROM, + TFROM, + TGROM, + TKROM, + TKSROM, + TLROM, + TL1ROM, + TL2ROM, + TLSROM, + TNROM, + TQROM, + TR1ROM, + TSROM, + TVROM, + } revision; + MMC3 mmc3; }; diff --git a/fc/cartridge/board/nes-uxrom.cpp b/fc/cartridge/board/nes-uxrom.cpp index f006e96b..f5b55b29 100644 --- a/fc/cartridge/board/nes-uxrom.cpp +++ b/fc/cartridge/board/nes-uxrom.cpp @@ -2,54 +2,52 @@ //NES-UOROM struct NES_UxROM : Board { - -struct Settings { - bool mirror; //0 = horizontal, 1 = vertical -} settings; - -uint4 prg_bank; - -uint8 prg_read(unsigned addr) { - if((addr & 0xc000) == 0x8000) return prgrom.read((prg_bank << 14) | (addr & 0x3fff)); - if((addr & 0xc000) == 0xc000) return prgrom.read(( 0x0f << 14) | (addr & 0x3fff)); - return cpu.mdr(); -} - -void prg_write(unsigned addr, uint8 data) { - if(addr & 0x8000) prg_bank = data & 0x0f; -} - -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_read(addr); + NES_UxROM(Markup::Node& document) : Board(document) { + settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; } - return Board::chr_read(addr); -} -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) { - if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); - return ppu.ciram_write(addr, data); + auto prg_read(uint addr) -> uint8 { + if((addr & 0xc000) == 0x8000) return prgrom.read((prg_bank << 14) | (addr & 0x3fff)); + if((addr & 0xc000) == 0xc000) return prgrom.read(( 0x0f << 14) | (addr & 0x3fff)); + return cpu.mdr(); } - return Board::chr_write(addr, data); -} -void power() { -} + auto prg_write(uint addr, uint8 data) -> void { + if(addr & 0x8000) prg_bank = data & 0x0f; + } -void reset() { - prg_bank = 0; -} + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_read(addr); + } + return Board::chr_read(addr); + } -void serialize(serializer& s) { - Board::serialize(s); + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr, data); + } + return Board::chr_write(addr, data); + } - s.integer(prg_bank); -} + auto power() -> void { + } -NES_UxROM(Markup::Node& document) : Board(document) { - settings.mirror = document["cartridge/mirror/mode"].text() == "vertical" ? 1 : 0; -} + auto reset() -> void { + prg_bank = 0; + } + auto serialize(serializer& s) -> void { + Board::serialize(s); + + s.integer(prg_bank); + } + + struct Settings { + bool mirror; //0 = horizontal, 1 = vertical + } settings; + + uint4 prg_bank; }; diff --git a/fc/cartridge/board/sunsoft-5b.cpp b/fc/cartridge/board/sunsoft-5b.cpp index bbfc4186..1003a19d 100644 --- a/fc/cartridge/board/sunsoft-5b.cpp +++ b/fc/cartridge/board/sunsoft-5b.cpp @@ -1,226 +1,224 @@ //SUNSOFT-5B struct Sunsoft5B : Board { - -uint4 mmu_port; -uint4 apu_port; - -uint8 prg_bank[4]; -uint8 chr_bank[8]; -uint2 mirror; -bool irq_enable; -bool irq_counter_enable; -uint16 irq_counter; - -int16 dac[16]; - -struct Pulse { - bool disable; - uint12 frequency; - uint4 volume; - - uint16 counter; //12-bit countdown + 4-bit phase - uint1 duty; - uint4 output; - - void clock() { - if(--counter == 0) { - counter = frequency << 4; - duty ^= 1; - } - output = duty ? volume : (uint4)0; - if(disable) output = 0; + Sunsoft5B(Markup::Node& document) : Board(document) { } - void reset() { - disable = 1; - frequency = 1; - volume = 0; - - counter = 0; - duty = 0; - output = 0; - } - - void serialize(serializer& s) { - s.integer(disable); - s.integer(frequency); - s.integer(volume); - - s.integer(counter); - s.integer(duty); - s.integer(output); - } -} pulse[3]; - -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + struct Pulse { + auto clock() -> void { + if(--counter == 0) { + counter = frequency << 4; + duty ^= 1; + } + output = duty ? volume : (uint4)0; + if(disable) output = 0; } - if(irq_counter_enable) { - if(--irq_counter == 0xffff) { - cpu.set_irq_line(irq_enable); + auto reset() -> void { + disable = 1; + frequency = 1; + volume = 0; + + counter = 0; + duty = 0; + output = 0; + } + + auto serialize(serializer& s) -> void { + s.integer(disable); + s.integer(frequency); + s.integer(volume); + + s.integer(counter); + s.integer(duty); + s.integer(output); + } + + bool disable; + uint12 frequency; + uint4 volume; + + uint16 counter; //12-bit countdown + 4-bit phase + uint1 duty; + uint4 output; + } pulse[3]; + + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } + + if(irq_counter_enable) { + if(--irq_counter == 0xffff) { + cpu.set_irq_line(irq_enable); + } + } + + pulse[0].clock(); + pulse[1].clock(); + pulse[2].clock(); + int16 output = dac[pulse[0].output] + dac[pulse[1].output] + dac[pulse[2].output]; + apu.set_sample(-output); + + tick(); + } + } + + auto prg_read(uint addr) -> uint8 { + if(addr < 0x6000) return cpu.mdr(); + + uint8 bank = 0x3f; //((addr & 0xe000) == 0xe000 + if((addr & 0xe000) == 0x6000) bank = prg_bank[0]; + if((addr & 0xe000) == 0x8000) bank = prg_bank[1]; + if((addr & 0xe000) == 0xa000) bank = prg_bank[2]; + if((addr & 0xe000) == 0xc000) bank = prg_bank[3]; + + bool ram_enable = bank & 0x80; + bool ram_select = bank & 0x40; + bank &= 0x3f; + + if(ram_select) { + if(ram_enable == false) return cpu.mdr(); + return prgram.data[addr & 0x1fff]; + } + + addr = (bank << 13) | (addr & 0x1fff); + return prgrom.read(addr); + } + + auto prg_write(uint addr, uint8 data) -> void { + if((addr & 0xe000) == 0x6000) { + prgram.data[addr & 0x1fff] = data; + } + + if(addr == 0x8000) { + mmu_port = data & 0x0f; + } + + if(addr == 0xa000) { + switch(mmu_port) { + case 0: chr_bank[0] = data; break; + case 1: chr_bank[1] = data; break; + case 2: chr_bank[2] = data; break; + case 3: chr_bank[3] = data; break; + case 4: chr_bank[4] = data; break; + case 5: chr_bank[5] = data; break; + case 6: chr_bank[6] = data; break; + case 7: chr_bank[7] = data; break; + case 8: prg_bank[0] = data; break; + case 9: prg_bank[1] = data; break; + case 10: prg_bank[2] = data; break; + case 11: prg_bank[3] = data; break; + case 12: mirror = data & 3; break; + case 13: + irq_enable = data & 0x80; + irq_counter_enable = data & 0x01; + if(irq_enable == 0) cpu.set_irq_line(0); + break; + case 14: irq_counter = (irq_counter & 0xff00) | (data << 0); break; + case 15: irq_counter = (irq_counter & 0x00ff) | (data << 8); break; } } - pulse[0].clock(); - pulse[1].clock(); - pulse[2].clock(); - int16 output = dac[pulse[0].output] + dac[pulse[1].output] + dac[pulse[2].output]; - apu.set_sample(-output); + if(addr == 0xc000) { + apu_port = data & 0x0f; + } - tick(); - } -} - -uint8 prg_read(unsigned addr) { - if(addr < 0x6000) return cpu.mdr(); - - uint8 bank = 0x3f; //((addr & 0xe000) == 0xe000 - if((addr & 0xe000) == 0x6000) bank = prg_bank[0]; - if((addr & 0xe000) == 0x8000) bank = prg_bank[1]; - if((addr & 0xe000) == 0xa000) bank = prg_bank[2]; - if((addr & 0xe000) == 0xc000) bank = prg_bank[3]; - - bool ram_enable = bank & 0x80; - bool ram_select = bank & 0x40; - bank &= 0x3f; - - if(ram_select) { - if(ram_enable == false) return cpu.mdr(); - return prgram.data[addr & 0x1fff]; - } - - addr = (bank << 13) | (addr & 0x1fff); - return prgrom.read(addr); -} - -void prg_write(unsigned addr, uint8 data) { - if((addr & 0xe000) == 0x6000) { - prgram.data[addr & 0x1fff] = data; - } - - if(addr == 0x8000) { - mmu_port = data & 0x0f; - } - - if(addr == 0xa000) { - switch(mmu_port) { - case 0: chr_bank[0] = data; break; - case 1: chr_bank[1] = data; break; - case 2: chr_bank[2] = data; break; - case 3: chr_bank[3] = data; break; - case 4: chr_bank[4] = data; break; - case 5: chr_bank[5] = data; break; - case 6: chr_bank[6] = data; break; - case 7: chr_bank[7] = data; break; - case 8: prg_bank[0] = data; break; - case 9: prg_bank[1] = data; break; - case 10: prg_bank[2] = data; break; - case 11: prg_bank[3] = data; break; - case 12: mirror = data & 3; break; - case 13: - irq_enable = data & 0x80; - irq_counter_enable = data & 0x01; - if(irq_enable == 0) cpu.set_irq_line(0); - break; - case 14: irq_counter = (irq_counter & 0xff00) | (data << 0); break; - case 15: irq_counter = (irq_counter & 0x00ff) | (data << 8); break; + if(addr == 0xe000) { + switch(apu_port) { + case 0: pulse[0].frequency = (pulse[0].frequency & 0xff00) | (data << 0); break; + case 1: pulse[0].frequency = (pulse[0].frequency & 0x00ff) | (data << 8); break; + case 2: pulse[1].frequency = (pulse[1].frequency & 0xff00) | (data << 0); break; + case 3: pulse[1].frequency = (pulse[1].frequency & 0x00ff) | (data << 8); break; + case 4: pulse[2].frequency = (pulse[2].frequency & 0xff00) | (data << 0); break; + case 5: pulse[2].frequency = (pulse[2].frequency & 0x00ff) | (data << 8); break; + case 7: + pulse[0].disable = data & 0x01; + pulse[1].disable = data & 0x02; + pulse[2].disable = data & 0x04; + break; + case 8: pulse[0].volume = data & 0x0f; break; + case 9: pulse[1].volume = data & 0x0f; break; + case 10: pulse[2].volume = data & 0x0f; break; + } } } - if(addr == 0xc000) { - apu_port = data & 0x0f; + auto chr_addr(uint addr) -> uint { + uint8 bank = (addr >> 10) & 7; + return (chr_bank[bank] << 10) | (addr & 0x03ff); } - if(addr == 0xe000) { - switch(apu_port) { - case 0: pulse[0].frequency = (pulse[0].frequency & 0xff00) | (data << 0); break; - case 1: pulse[0].frequency = (pulse[0].frequency & 0x00ff) | (data << 8); break; - case 2: pulse[1].frequency = (pulse[1].frequency & 0xff00) | (data << 0); break; - case 3: pulse[1].frequency = (pulse[1].frequency & 0x00ff) | (data << 8); break; - case 4: pulse[2].frequency = (pulse[2].frequency & 0xff00) | (data << 0); break; - case 5: pulse[2].frequency = (pulse[2].frequency & 0x00ff) | (data << 8); break; - case 7: - pulse[0].disable = data & 0x01; - pulse[1].disable = data & 0x02; - pulse[2].disable = data & 0x04; - break; - case 8: pulse[0].volume = data & 0x0f; break; - case 9: pulse[1].volume = data & 0x0f; break; - case 10: pulse[2].volume = data & 0x0f; break; + auto ciram_addr(uint addr) -> uint { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal + case 2: return 0x0000 | (addr & 0x03ff); //first + case 3: return 0x0400 | (addr & 0x03ff); //second } } -} -unsigned chr_addr(unsigned addr) { - uint8 bank = (addr >> 10) & 7; - return (chr_bank[bank] << 10) | (addr & 0x03ff); -} - -unsigned ciram_addr(unsigned addr) { - switch(mirror) { - case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical - case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal - case 2: return 0x0000 | (addr & 0x03ff); //first - case 3: return 0x0400 | (addr & 0x03ff); //second + auto chr_read(uint addr) -> uint8 { + if(addr & 0x2000) return ppu.ciram_read(ciram_addr(addr)); + return Board::chr_read(chr_addr(addr)); } -} -uint8 chr_read(unsigned addr) { - if(addr & 0x2000) return ppu.ciram_read(ciram_addr(addr)); - return Board::chr_read(chr_addr(addr)); -} - -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) return ppu.ciram_write(ciram_addr(addr), data); - return Board::chr_write(chr_addr(addr), data); -} - -void power() { - for(signed n = 0; n < 16; n++) { - double volume = 1.0 / pow(2, 1.0 / 2 * (15 - n)); - dac[n] = volume * 8192.0; + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) return ppu.ciram_write(ciram_addr(addr), data); + return Board::chr_write(chr_addr(addr), data); } -} -void reset() { - mmu_port = 0; - apu_port = 0; + auto power() -> void { + for(signed n : range(16)) { + double volume = 1.0 / pow(2, 1.0 / 2 * (15 - n)); + dac[n] = volume * 8192.0; + } + } - for(auto& n : prg_bank) n = 0; - for(auto& n : chr_bank) n = 0; - mirror = 0; - irq_enable = 0; - irq_counter_enable = 0; - irq_counter = 0; + auto reset() -> void { + mmu_port = 0; + apu_port = 0; - pulse[0].reset(); - pulse[1].reset(); - pulse[2].reset(); -} + for(auto& n : prg_bank) n = 0; + for(auto& n : chr_bank) n = 0; + mirror = 0; + irq_enable = 0; + irq_counter_enable = 0; + irq_counter = 0; -void serialize(serializer& s) { - Board::serialize(s); + pulse[0].reset(); + pulse[1].reset(); + pulse[2].reset(); + } - s.integer(mmu_port); - s.integer(apu_port); + auto serialize(serializer& s) -> void { + Board::serialize(s); - s.array(prg_bank); - s.array(chr_bank); - s.integer(mirror); - s.integer(irq_enable); - s.integer(irq_counter_enable); - s.integer(irq_counter); + s.integer(mmu_port); + s.integer(apu_port); - pulse[0].serialize(s); - pulse[1].serialize(s); - pulse[2].serialize(s); -} + s.array(prg_bank); + s.array(chr_bank); + s.integer(mirror); + s.integer(irq_enable); + s.integer(irq_counter_enable); + s.integer(irq_counter); -Sunsoft5B(Markup::Node& document) : Board(document) { -} + pulse[0].serialize(s); + pulse[1].serialize(s); + pulse[2].serialize(s); + } + uint4 mmu_port; + uint4 apu_port; + + uint8 prg_bank[4]; + uint8 chr_bank[8]; + uint2 mirror; + bool irq_enable; + bool irq_counter_enable; + uint16 irq_counter; + + int16 dac[16]; }; diff --git a/fc/cartridge/cartridge.cpp b/fc/cartridge/cartridge.cpp index ee4b500c..005d2b60 100644 --- a/fc/cartridge/cartridge.cpp +++ b/fc/cartridge/cartridge.cpp @@ -6,73 +6,77 @@ namespace Famicom { #include "board/board.cpp" Cartridge cartridge; -string Cartridge::title() { +auto Cartridge::loaded() const -> bool { + return _loaded; +} + +auto Cartridge::sha256() const -> string { + return _sha256; +} + +auto Cartridge::title() const -> string { return information.title; } -void Cartridge::Main() { +auto Cartridge::Main() -> void { cartridge.main(); } -void Cartridge::main() { +auto Cartridge::main() -> void { board->main(); } -void Cartridge::load() { +auto Cartridge::load() -> void { interface->loadRequest(ID::Manifest, "manifest.bml", true); Board::load(information.markup); //this call will set Cartridge::board if successful - if(board == nullptr) return; + if(!board) return; Hash::SHA256 sha; sha.data(board->prgrom.data, board->prgrom.size); sha.data(board->chrrom.data, board->chrrom.size); - sha256 = sha.digest(); + _sha256 = sha.digest(); system.load(); - loaded = true; + _loaded = true; } -void Cartridge::unload() { - if(loaded == false) return; - loaded = false; +auto Cartridge::unload() -> void { + if(!loaded()) return; + _loaded = false; memory.reset(); } -void Cartridge::power() { +auto Cartridge::power() -> void { board->power(); } -void Cartridge::reset() { +auto Cartridge::reset() -> void { create(Cartridge::Main, 21477272); board->reset(); } -Cartridge::Cartridge() { - loaded = false; -} - -uint8 Cartridge::prg_read(unsigned addr) { +auto Cartridge::prg_read(uint addr) -> uint8 { return board->prg_read(addr); } -void Cartridge::prg_write(unsigned addr, uint8 data) { +auto Cartridge::prg_write(uint addr, uint8 data) -> void { return board->prg_write(addr, data); } -uint8 Cartridge::chr_read(unsigned addr) { +auto Cartridge::chr_read(uint addr) -> uint8 { return board->chr_read(addr); } -void Cartridge::chr_write(unsigned addr, uint8 data) { +auto Cartridge::chr_write(uint addr, uint8 data) -> void { return board->chr_write(addr, data); } -void Cartridge::scanline(unsigned y) { +auto Cartridge::scanline(uint y) -> void { return board->scanline(y); } -void Cartridge::serialize(serializer& s) { +auto Cartridge::serialize(serializer& s) -> void { Thread::serialize(s); return board->serialize(s); } diff --git a/fc/cartridge/cartridge.hpp b/fc/cartridge/cartridge.hpp index 4c0c50cd..73d3570d 100644 --- a/fc/cartridge/cartridge.hpp +++ b/fc/cartridge/cartridge.hpp @@ -1,47 +1,47 @@ #include "chip/chip.hpp" #include "board/board.hpp" -struct Cartridge : Thread, property { - static void Main(); - void main(); +struct Cartridge : Thread { + static auto Main() -> void; + auto main() -> void; - void load(); - void unload(); + auto loaded() const -> bool; + auto sha256() const -> string; + auto title() const -> string; - void power(); - void reset(); + auto load() -> void; + auto unload() -> void; - readonly loaded; - readonly sha256; + auto power() -> void; + auto reset() -> void; + + auto serialize(serializer&) -> void; struct Information { string markup; string title; } information; - string title(); - struct Memory { unsigned id; string name; }; vector memory; - void serialize(serializer&); - Cartridge(); - //privileged: - Board *board; + Board* board = nullptr; + bool _loaded = false; + string _sha256; - uint8 prg_read(unsigned addr); - void prg_write(unsigned addr, uint8 data); + auto prg_read(uint addr) -> uint8; + auto prg_write(uint addr, uint8 data) -> void; - uint8 chr_read(unsigned addr); - void chr_write(unsigned addr, uint8 data); + auto chr_read(uint addr) -> uint8; + auto chr_write(uint addr, uint8 data) -> void; //scanline() is for debugging purposes only: //boards must detect scanline edges on their own - void scanline(unsigned y); + auto scanline(uint y) -> void; }; extern Cartridge cartridge; diff --git a/fc/cartridge/chip/chip.cpp b/fc/cartridge/chip/chip.cpp index e3cabdcf..7bb7afc9 100644 --- a/fc/cartridge/chip/chip.cpp +++ b/fc/cartridge/chip/chip.cpp @@ -9,9 +9,9 @@ #include "vrc6.cpp" #include "vrc7.cpp" -void Chip::tick() { - board.tick(); -} - Chip::Chip(Board& board) : board(board) { } + +auto Chip::tick() -> void { + board.tick(); +} diff --git a/fc/cartridge/chip/chip.hpp b/fc/cartridge/chip/chip.hpp index 3c331a9b..028acb24 100644 --- a/fc/cartridge/chip/chip.hpp +++ b/fc/cartridge/chip/chip.hpp @@ -1,7 +1,8 @@ struct Board; struct Chip { - Board& board; - void tick(); Chip(Board& board); + auto tick() -> void; + + Board& board; }; diff --git a/fc/cartridge/chip/mmc1.cpp b/fc/cartridge/chip/mmc1.cpp index 3983bdaf..30726496 100644 --- a/fc/cartridge/chip/mmc1.cpp +++ b/fc/cartridge/chip/mmc1.cpp @@ -1,136 +1,134 @@ struct MMC1 : Chip { + MMC1(Board& board) : Chip(board) { + revision = Revision::MMC1B2; + } -enum class Revision : unsigned { - MMC1, - MMC1A, - MMC1B1, - MMC1B2, - MMC1B3, - MMC1C, -} revision; + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } -unsigned writedelay; -unsigned shiftaddr; -unsigned shiftdata; + if(writedelay) writedelay--; + tick(); + } + } -bool chr_mode; -bool prg_size; //0 = 32K, 1 = 16K -bool prg_mode; -uint2 mirror; //0 = first, 1 = second, 2 = vertical, 3 = horizontal -uint5 chr_bank[2]; -bool ram_disable; -uint4 prg_bank; + auto prg_addr(uint addr) -> uint { + bool region = addr & 0x4000; + uint bank = (prg_bank & ~1) + region; -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + if(prg_size) { + bank = (region == 0 ? 0x0 : 0xf); + if(region != prg_mode) bank = prg_bank; } - if(writedelay) writedelay--; - tick(); - } -} - -unsigned prg_addr(unsigned addr) { - bool region = addr & 0x4000; - unsigned bank = (prg_bank & ~1) + region; - - if(prg_size) { - bank = (region == 0 ? 0x0 : 0xf); - if(region != prg_mode) bank = prg_bank; + return (bank << 14) | (addr & 0x3fff); } - return (bank << 14) | (addr & 0x3fff); -} - -unsigned chr_addr(unsigned addr) { - bool region = addr & 0x1000; - unsigned bank = chr_bank[region]; - if(chr_mode == 0) bank = (chr_bank[0] & ~1) | region; - return (bank << 12) | (addr & 0x0fff); -} - -unsigned ciram_addr(unsigned addr) { - switch(mirror) { - case 0: return 0x0000 | (addr & 0x03ff); - case 1: return 0x0400 | (addr & 0x03ff); - case 2: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); - case 3: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); + auto chr_addr(uint addr) -> uint { + bool region = addr & 0x1000; + uint bank = chr_bank[region]; + if(chr_mode == 0) bank = (chr_bank[0] & ~1) | region; + return (bank << 12) | (addr & 0x0fff); } -} -void mmio_write(unsigned addr, uint8 data) { - if(writedelay) return; - writedelay = 2; + auto ciram_addr(uint addr) -> uint { + switch(mirror) { + case 0: return 0x0000 | (addr & 0x03ff); + case 1: return 0x0400 | (addr & 0x03ff); + case 2: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); + case 3: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); + } + } - if(data & 0x80) { - shiftaddr = 0; - prg_size = 1; - prg_mode = 1; - } else { - shiftdata = ((data & 1) << 4) | (shiftdata >> 1); - if(++shiftaddr == 5) { + auto mmio_write(uint addr, uint8 data) -> void { + if(writedelay) return; + writedelay = 2; + + if(data & 0x80) { shiftaddr = 0; - switch((addr >> 13) & 3) { - case 0: - chr_mode = (shiftdata & 0x10); - prg_size = (shiftdata & 0x08); - prg_mode = (shiftdata & 0x04); - mirror = (shiftdata & 0x03); - break; + prg_size = 1; + prg_mode = 1; + } else { + shiftdata = ((data & 1) << 4) | (shiftdata >> 1); + if(++shiftaddr == 5) { + shiftaddr = 0; + switch((addr >> 13) & 3) { + case 0: + chr_mode = (shiftdata & 0x10); + prg_size = (shiftdata & 0x08); + prg_mode = (shiftdata & 0x04); + mirror = (shiftdata & 0x03); + break; - case 1: - chr_bank[0] = (shiftdata & 0x1f); - break; + case 1: + chr_bank[0] = (shiftdata & 0x1f); + break; - case 2: - chr_bank[1] = (shiftdata & 0x1f); - break; + case 2: + chr_bank[1] = (shiftdata & 0x1f); + break; - case 3: - ram_disable = (shiftdata & 0x10); - prg_bank = (shiftdata & 0x0f); - break; + case 3: + ram_disable = (shiftdata & 0x10); + prg_bank = (shiftdata & 0x0f); + break; + } } } } -} -void power() { -} + auto power() -> void { + } -void reset() { - writedelay = 0; - shiftaddr = 0; - shiftdata = 0; + auto reset() -> void { + writedelay = 0; + shiftaddr = 0; + shiftdata = 0; - chr_mode = 0; - prg_size = 1; - prg_mode = 1; - mirror = 0; - chr_bank[0] = 0; - chr_bank[1] = 1; - ram_disable = 0; - prg_bank = 0; -} + chr_mode = 0; + prg_size = 1; + prg_mode = 1; + mirror = 0; + chr_bank[0] = 0; + chr_bank[1] = 1; + ram_disable = 0; + prg_bank = 0; + } -void serialize(serializer& s) { - s.integer(writedelay); - s.integer(shiftaddr); - s.integer(shiftdata); + auto serialize(serializer& s) -> void { + s.integer(writedelay); + s.integer(shiftaddr); + s.integer(shiftdata); - s.integer(chr_mode); - s.integer(prg_size); - s.integer(prg_mode); - s.integer(mirror); - s.array(chr_bank); - s.integer(ram_disable); - s.integer(prg_bank); -} + s.integer(chr_mode); + s.integer(prg_size); + s.integer(prg_mode); + s.integer(mirror); + s.array(chr_bank); + s.integer(ram_disable); + s.integer(prg_bank); + } -MMC1(Board& board) : Chip(board) { - revision = Revision::MMC1B2; -} + enum class Revision : uint { + MMC1, + MMC1A, + MMC1B1, + MMC1B2, + MMC1B3, + MMC1C, + } revision; + uint writedelay; + uint shiftaddr; + uint shiftdata; + + bool chr_mode; + bool prg_size; //0 = 32K, 1 = 16K + bool prg_mode; + uint2 mirror; //0 = first, 1 = second, 2 = vertical, 3 = horizontal + uint5 chr_bank[2]; + bool ram_disable; + uint4 prg_bank; }; diff --git a/fc/cartridge/chip/mmc3.cpp b/fc/cartridge/chip/mmc3.cpp index a051d918..d3c6fa7f 100644 --- a/fc/cartridge/chip/mmc3.cpp +++ b/fc/cartridge/chip/mmc3.cpp @@ -1,189 +1,187 @@ struct MMC3 : Chip { - -bool chr_mode; -bool prg_mode; -uint3 bank_select; -uint8 prg_bank[2]; -uint8 chr_bank[6]; -bool mirror; -bool ram_enable; -bool ram_write_protect; -uint8 irq_latch; -uint8 irq_counter; -bool irq_enable; -unsigned irq_delay; -bool irq_line; - -uint16 chr_abus; - -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(irq_delay) irq_delay--; - cpu.set_irq_line(irq_line); - tick(); + MMC3(Board& board) : Chip(board) { } -} -void irq_test(unsigned addr) { - if(!(chr_abus & 0x1000) && (addr & 0x1000)) { - if(irq_delay == 0) { - if(irq_counter == 0) { - irq_counter = irq_latch; - } else if(--irq_counter == 0) { - if(irq_enable) irq_line = 1; + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); } + + if(irq_delay) irq_delay--; + cpu.set_irq_line(irq_line); + tick(); } - irq_delay = 6; } - chr_abus = addr; -} -unsigned prg_addr(unsigned addr) const { - switch((addr >> 13) & 3) { - case 0: - if(prg_mode == 1) return (0x3e << 13) | (addr & 0x1fff); - return (prg_bank[0] << 13) | (addr & 0x1fff); - case 1: - return (prg_bank[1] << 13) | (addr & 0x1fff); - case 2: - if(prg_mode == 0) return (0x3e << 13) | (addr & 0x1fff); - return (prg_bank[0] << 13) | (addr & 0x1fff); - case 3: - return (0x3f << 13) | (addr & 0x1fff); - } -} - -unsigned chr_addr(unsigned addr) const { - if(chr_mode == 0) { - if(addr <= 0x07ff) return (chr_bank[0] << 10) | (addr & 0x07ff); - if(addr <= 0x0fff) return (chr_bank[1] << 10) | (addr & 0x07ff); - if(addr <= 0x13ff) return (chr_bank[2] << 10) | (addr & 0x03ff); - if(addr <= 0x17ff) return (chr_bank[3] << 10) | (addr & 0x03ff); - if(addr <= 0x1bff) return (chr_bank[4] << 10) | (addr & 0x03ff); - if(addr <= 0x1fff) return (chr_bank[5] << 10) | (addr & 0x03ff); - } else { - if(addr <= 0x03ff) return (chr_bank[2] << 10) | (addr & 0x03ff); - if(addr <= 0x07ff) return (chr_bank[3] << 10) | (addr & 0x03ff); - if(addr <= 0x0bff) return (chr_bank[4] << 10) | (addr & 0x03ff); - if(addr <= 0x0fff) return (chr_bank[5] << 10) | (addr & 0x03ff); - if(addr <= 0x17ff) return (chr_bank[0] << 10) | (addr & 0x07ff); - if(addr <= 0x1fff) return (chr_bank[1] << 10) | (addr & 0x07ff); - } -} - -unsigned ciram_addr(unsigned addr) const { - if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); - if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); -} - -uint8 ram_read(unsigned addr) { - if(ram_enable) return board.prgram.data[addr & 0x1fff]; - return 0x00; -} - -void ram_write(unsigned addr, uint8 data) { - if(ram_enable && !ram_write_protect) board.prgram.data[addr & 0x1fff] = data; -} - -void reg_write(unsigned addr, uint8 data) { - switch(addr & 0xe001) { - case 0x8000: - chr_mode = data & 0x80; - prg_mode = data & 0x40; - bank_select = data & 0x07; - break; - - case 0x8001: - switch(bank_select) { - case 0: chr_bank[0] = data & ~1; break; - case 1: chr_bank[1] = data & ~1; break; - case 2: chr_bank[2] = data; break; - case 3: chr_bank[3] = data; break; - case 4: chr_bank[4] = data; break; - case 5: chr_bank[5] = data; break; - case 6: prg_bank[0] = data & 0x3f; break; - case 7: prg_bank[1] = data & 0x3f; break; + auto irq_test(uint addr) -> void { + if(!(chr_abus & 0x1000) && (addr & 0x1000)) { + if(irq_delay == 0) { + if(irq_counter == 0) { + irq_counter = irq_latch; + } else if(--irq_counter == 0) { + if(irq_enable) irq_line = 1; + } + } + irq_delay = 6; } - break; + chr_abus = addr; + } - case 0xa000: - mirror = data & 0x01; - break; + auto prg_addr(uint addr) const -> uint { + switch((addr >> 13) & 3) { + case 0: + if(prg_mode == 1) return (0x3e << 13) | (addr & 0x1fff); + return (prg_bank[0] << 13) | (addr & 0x1fff); + case 1: + return (prg_bank[1] << 13) | (addr & 0x1fff); + case 2: + if(prg_mode == 0) return (0x3e << 13) | (addr & 0x1fff); + return (prg_bank[0] << 13) | (addr & 0x1fff); + case 3: + return (0x3f << 13) | (addr & 0x1fff); + } + } - case 0xa001: - ram_enable = data & 0x80; - ram_write_protect = data & 0x40; - break; + auto chr_addr(uint addr) const -> uint { + if(chr_mode == 0) { + if(addr <= 0x07ff) return (chr_bank[0] << 10) | (addr & 0x07ff); + if(addr <= 0x0fff) return (chr_bank[1] << 10) | (addr & 0x07ff); + if(addr <= 0x13ff) return (chr_bank[2] << 10) | (addr & 0x03ff); + if(addr <= 0x17ff) return (chr_bank[3] << 10) | (addr & 0x03ff); + if(addr <= 0x1bff) return (chr_bank[4] << 10) | (addr & 0x03ff); + if(addr <= 0x1fff) return (chr_bank[5] << 10) | (addr & 0x03ff); + } else { + if(addr <= 0x03ff) return (chr_bank[2] << 10) | (addr & 0x03ff); + if(addr <= 0x07ff) return (chr_bank[3] << 10) | (addr & 0x03ff); + if(addr <= 0x0bff) return (chr_bank[4] << 10) | (addr & 0x03ff); + if(addr <= 0x0fff) return (chr_bank[5] << 10) | (addr & 0x03ff); + if(addr <= 0x17ff) return (chr_bank[0] << 10) | (addr & 0x07ff); + if(addr <= 0x1fff) return (chr_bank[1] << 10) | (addr & 0x07ff); + } + } - case 0xc000: - irq_latch = data; - break; + auto ciram_addr(uint addr) const -> uint { + if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); + if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); + } - case 0xc001: + auto ram_read(uint addr) -> uint8 { + if(ram_enable) return board.prgram.data[addr & 0x1fff]; + return 0x00; + } + + auto ram_write(uint addr, uint8 data) -> void { + if(ram_enable && !ram_write_protect) board.prgram.data[addr & 0x1fff] = data; + } + + auto reg_write(uint addr, uint8 data) -> void { + switch(addr & 0xe001) { + case 0x8000: + chr_mode = data & 0x80; + prg_mode = data & 0x40; + bank_select = data & 0x07; + break; + + case 0x8001: + switch(bank_select) { + case 0: chr_bank[0] = data & ~1; break; + case 1: chr_bank[1] = data & ~1; break; + case 2: chr_bank[2] = data; break; + case 3: chr_bank[3] = data; break; + case 4: chr_bank[4] = data; break; + case 5: chr_bank[5] = data; break; + case 6: prg_bank[0] = data & 0x3f; break; + case 7: prg_bank[1] = data & 0x3f; break; + } + break; + + case 0xa000: + mirror = data & 0x01; + break; + + case 0xa001: + ram_enable = data & 0x80; + ram_write_protect = data & 0x40; + break; + + case 0xc000: + irq_latch = data; + break; + + case 0xc001: + irq_counter = 0; + break; + + case 0xe000: + irq_enable = false; + irq_line = 0; + break; + + case 0xe001: + irq_enable = true; + break; + } + } + + auto power() -> void { + } + + auto reset() -> void { + chr_mode = 0; + prg_mode = 0; + bank_select = 0; + prg_bank[0] = 0; + prg_bank[1] = 0; + chr_bank[0] = 0; + chr_bank[1] = 0; + chr_bank[2] = 0; + chr_bank[3] = 0; + chr_bank[4] = 0; + chr_bank[5] = 0; + mirror = 0; + ram_enable = 1; + ram_write_protect = 0; + irq_latch = 0; irq_counter = 0; - break; - - case 0xe000: irq_enable = false; + irq_delay = 0; irq_line = 0; - break; - case 0xe001: - irq_enable = true; - break; + chr_abus = 0; } -} -void power() { -} + auto serialize(serializer& s) -> void { + s.integer(chr_mode); + s.integer(prg_mode); + s.integer(bank_select); + s.array(prg_bank); + s.array(chr_bank); + s.integer(mirror); + s.integer(ram_enable); + s.integer(ram_write_protect); + s.integer(irq_latch); + s.integer(irq_counter); + s.integer(irq_enable); + s.integer(irq_delay); + s.integer(irq_line); -void reset() { - chr_mode = 0; - prg_mode = 0; - bank_select = 0; - prg_bank[0] = 0; - prg_bank[1] = 0; - chr_bank[0] = 0; - chr_bank[1] = 0; - chr_bank[2] = 0; - chr_bank[3] = 0; - chr_bank[4] = 0; - chr_bank[5] = 0; - mirror = 0; - ram_enable = 1; - ram_write_protect = 0; - irq_latch = 0; - irq_counter = 0; - irq_enable = false; - irq_delay = 0; - irq_line = 0; + s.integer(chr_abus); + } - chr_abus = 0; -} - -void serialize(serializer& s) { - s.integer(chr_mode); - s.integer(prg_mode); - s.integer(bank_select); - s.array(prg_bank); - s.array(chr_bank); - s.integer(mirror); - s.integer(ram_enable); - s.integer(ram_write_protect); - s.integer(irq_latch); - s.integer(irq_counter); - s.integer(irq_enable); - s.integer(irq_delay); - s.integer(irq_line); - - s.integer(chr_abus); -} - -MMC3(Board& board) : Chip(board) { -} + bool chr_mode; + bool prg_mode; + uint3 bank_select; + uint8 prg_bank[2]; + uint8 chr_bank[6]; + bool mirror; + bool ram_enable; + bool ram_write_protect; + uint8 irq_latch; + uint8 irq_counter; + bool irq_enable; + uint irq_delay; + bool irq_line; + uint16 chr_abus; }; diff --git a/fc/cartridge/chip/mmc5.cpp b/fc/cartridge/chip/mmc5.cpp index 5cd94fa0..a1df5276 100644 --- a/fc/cartridge/chip/mmc5.cpp +++ b/fc/cartridge/chip/mmc5.cpp @@ -1,497 +1,495 @@ struct MMC5 : Chip { - -enum class Revision : unsigned { - MMC5, - MMC5B, -} revision; - -uint8 exram[1024]; - -//programmable registers - -uint2 prg_mode; //$5100 -uint2 chr_mode; //$5101 - -uint2 prgram_write_protect[2]; //$5102,$5103 - -uint2 exram_mode; //$5104 -uint2 nametable_mode[4]; //$5105 -uint8 fillmode_tile; //$5106 -uint8 fillmode_color; //$5107 - -bool ram_select; //$5113 -uint2 ram_bank; //$5113 -uint8 prg_bank[4]; //$5114-5117 -uint10 chr_sprite_bank[8]; //$5120-5127 -uint10 chr_bg_bank[4]; //$5128-512b -uint2 chr_bank_hi; //$5130 - -bool vs_enable; //$5200 -bool vs_side; //$5200 -uint5 vs_tile; //$5200 -uint8 vs_scroll; //$5201 -uint8 vs_bank; //$5202 - -uint8 irq_line; //$5203 -bool irq_enable; //$5204 - -uint8 multiplicand; //$5205 -uint8 multiplier; //$5206 - -//status registers - -unsigned cpu_cycle_counter; -unsigned irq_counter; -bool irq_pending; -bool in_frame; - -unsigned vcounter; -unsigned hcounter; -uint16 chr_access[4]; -bool chr_active; -bool sprite_8x16; - -uint8 exbank; -uint8 exattr; - -bool vs_fetch; -uint8 vs_vpos; -uint8 vs_hpos; - -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - //scanline() resets this; if no scanlines detected, enter video blanking period - if(++cpu_cycle_counter >= 200) blank(); //113-114 normal; ~2500 across Vblank period - - cpu.set_irq_line(irq_enable && irq_pending); - tick(); - } -} - -void scanline(unsigned y) { -//used for testing only, to verify MMC5 scanline detection is accurate: -//if(y != vcounter && y <= 240) print(y, " vs ", vcounter, "\n"); -} - -uint8 prg_access(bool write, unsigned addr, uint8 data = 0x00) { - unsigned bank; - - if((addr & 0xe000) == 0x6000) { - bank = (ram_select << 2) | ram_bank; - addr &= 0x1fff; - } else if(prg_mode == 0) { - bank = prg_bank[3] & ~3; - addr &= 0x7fff; - } else if(prg_mode == 1) { - if((addr & 0xc000) == 0x8000) bank = (prg_bank[1] & ~1); - if((addr & 0xe000) == 0xc000) bank = (prg_bank[3] & ~1); - addr &= 0x3fff; - } else if(prg_mode == 2) { - if((addr & 0xe000) == 0x8000) bank = (prg_bank[1] & ~1) | 0; - if((addr & 0xe000) == 0xa000) bank = (prg_bank[1] & ~1) | 1; - if((addr & 0xe000) == 0xc000) bank = (prg_bank[2]); - if((addr & 0xe000) == 0xe000) bank = (prg_bank[3]); - addr &= 0x1fff; - } else if(prg_mode == 3) { - if((addr & 0xe000) == 0x8000) bank = prg_bank[0]; - if((addr & 0xe000) == 0xa000) bank = prg_bank[1]; - if((addr & 0xe000) == 0xc000) bank = prg_bank[2]; - if((addr & 0xe000) == 0xe000) bank = prg_bank[3]; - addr &= 0x1fff; + MMC5(Board& board) : Chip(board) { + revision = Revision::MMC5; } - bool rom = bank & 0x80; - bank &= 0x7f; - - if(write == false) { - if(rom) { - return board.prgrom.read((bank << 13) | addr); - } else { - return board.prgram.read((bank << 13) | addr); - } - } else { - if(rom) { - board.prgrom.write((bank << 13) | addr, data); - } else { - if(prgram_write_protect[0] == 2 && prgram_write_protect[1] == 1) { - board.prgram.write((bank << 13) | addr, data); + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); } + + //scanline() resets this; if no scanlines detected, enter video blanking period + if(++cpu_cycle_counter >= 200) blank(); //113-114 normal; ~2500 across Vblank period + + cpu.set_irq_line(irq_enable && irq_pending); + tick(); } - return 0x00; - } -} - -uint8 prg_read(unsigned addr) { - if((addr & 0xfc00) == 0x5c00) { - if(exram_mode >= 2) return exram[addr & 0x03ff]; - return cpu.mdr(); } - if(addr >= 0x6000) { - return prg_access(0, addr); + auto scanline(uint y) -> void { + //used for testing only, to verify MMC5 scanline detection is accurate: + //if(y != vcounter && y <= 240) print(y, " vs ", vcounter, "\n"); } - switch(addr) { - case 0x5204: { - uint8 result = (irq_pending << 7) | (in_frame << 6); - irq_pending = false; + auto prg_access(bool write, uint addr, uint8 data = 0x00) -> uint8 { + uint bank; + + if((addr & 0xe000) == 0x6000) { + bank = (ram_select << 2) | ram_bank; + addr &= 0x1fff; + } else if(prg_mode == 0) { + bank = prg_bank[3] & ~3; + addr &= 0x7fff; + } else if(prg_mode == 1) { + if((addr & 0xc000) == 0x8000) bank = (prg_bank[1] & ~1); + if((addr & 0xe000) == 0xc000) bank = (prg_bank[3] & ~1); + addr &= 0x3fff; + } else if(prg_mode == 2) { + if((addr & 0xe000) == 0x8000) bank = (prg_bank[1] & ~1) | 0; + if((addr & 0xe000) == 0xa000) bank = (prg_bank[1] & ~1) | 1; + if((addr & 0xe000) == 0xc000) bank = (prg_bank[2]); + if((addr & 0xe000) == 0xe000) bank = (prg_bank[3]); + addr &= 0x1fff; + } else if(prg_mode == 3) { + if((addr & 0xe000) == 0x8000) bank = prg_bank[0]; + if((addr & 0xe000) == 0xa000) bank = prg_bank[1]; + if((addr & 0xe000) == 0xc000) bank = prg_bank[2]; + if((addr & 0xe000) == 0xe000) bank = prg_bank[3]; + addr &= 0x1fff; + } + + bool rom = bank & 0x80; + bank &= 0x7f; + + if(write == false) { + if(rom) { + return board.prgrom.read((bank << 13) | addr); + } else { + return board.prgram.read((bank << 13) | addr); + } + } else { + if(rom) { + board.prgrom.write((bank << 13) | addr, data); + } else { + if(prgram_write_protect[0] == 2 && prgram_write_protect[1] == 1) { + board.prgram.write((bank << 13) | addr, data); + } + } + return 0x00; + } + } + + auto prg_read(uint addr) -> uint8 { + if((addr & 0xfc00) == 0x5c00) { + if(exram_mode >= 2) return exram[addr & 0x03ff]; + return cpu.mdr(); + } + + if(addr >= 0x6000) { + return prg_access(0, addr); + } + + switch(addr) { + case 0x5204: { + uint8 result = (irq_pending << 7) | (in_frame << 6); + irq_pending = false; + return result; + } + case 0x5205: return (multiplier * multiplicand) >> 0; + case 0x5206: return (multiplier * multiplicand) >> 8; + } + } + + auto prg_write(uint addr, uint8 data) -> void { + if((addr & 0xfc00) == 0x5c00) { + //writes 0x00 *during* Vblank (not during screen rendering ...) + if(exram_mode == 0 || exram_mode == 1) exram[addr & 0x03ff] = in_frame ? data : 0x00; + if(exram_mode == 2) exram[addr & 0x03ff] = data; + return; + } + + if(addr >= 0x6000) { + prg_access(1, addr, data); + return; + } + + switch(addr) { + case 0x2000: + sprite_8x16 = data & 0x20; + break; + + case 0x2001: + //if BG+sprites are disabled; enter video blanking period + if((data & 0x18) == 0) blank(); + break; + + case 0x5100: prg_mode = data & 3; break; + case 0x5101: chr_mode = data & 3; break; + + case 0x5102: prgram_write_protect[0] = data & 3; break; + case 0x5103: prgram_write_protect[1] = data & 3; break; + + case 0x5104: + exram_mode = data & 3; + break; + + case 0x5105: + nametable_mode[0] = (data & 0x03) >> 0; + nametable_mode[1] = (data & 0x0c) >> 2; + nametable_mode[2] = (data & 0x30) >> 4; + nametable_mode[3] = (data & 0xc0) >> 6; + break; + + case 0x5106: + fillmode_tile = data; + break; + + case 0x5107: + fillmode_color = data & 3; + fillmode_color |= fillmode_color << 2; + fillmode_color |= fillmode_color << 4; + break; + + case 0x5113: + ram_select = data & 0x04; + ram_bank = data & 0x03; + break; + + case 0x5114: prg_bank[0] = data; break; + case 0x5115: prg_bank[1] = data; break; + case 0x5116: prg_bank[2] = data; break; + case 0x5117: prg_bank[3] = data | 0x80; break; + + case 0x5120: chr_sprite_bank[0] = (chr_bank_hi << 8) | data; chr_active = 0; break; + case 0x5121: chr_sprite_bank[1] = (chr_bank_hi << 8) | data; chr_active = 0; break; + case 0x5122: chr_sprite_bank[2] = (chr_bank_hi << 8) | data; chr_active = 0; break; + case 0x5123: chr_sprite_bank[3] = (chr_bank_hi << 8) | data; chr_active = 0; break; + case 0x5124: chr_sprite_bank[4] = (chr_bank_hi << 8) | data; chr_active = 0; break; + case 0x5125: chr_sprite_bank[5] = (chr_bank_hi << 8) | data; chr_active = 0; break; + case 0x5126: chr_sprite_bank[6] = (chr_bank_hi << 8) | data; chr_active = 0; break; + case 0x5127: chr_sprite_bank[7] = (chr_bank_hi << 8) | data; chr_active = 0; break; + + case 0x5128: chr_bg_bank[0] = (chr_bank_hi << 8) | data; chr_active = 1; break; + case 0x5129: chr_bg_bank[1] = (chr_bank_hi << 8) | data; chr_active = 1; break; + case 0x512a: chr_bg_bank[2] = (chr_bank_hi << 8) | data; chr_active = 1; break; + case 0x512b: chr_bg_bank[3] = (chr_bank_hi << 8) | data; chr_active = 1; break; + + case 0x5130: + chr_bank_hi = data & 3; + break; + + case 0x5200: + vs_enable = data & 0x80; + vs_side = data & 0x40; + vs_tile = data & 0x1f; + break; + + case 0x5201: + vs_scroll = data; + break; + + case 0x5202: + vs_bank = data; + break; + + case 0x5203: + irq_line = data; + break; + + case 0x5204: + irq_enable = data & 0x80; + break; + + case 0x5205: + multiplicand = data; + break; + + case 0x5206: + multiplier = data; + break; + } + } + + auto chr_sprite_addr(uint addr) -> uint { + if(chr_mode == 0) { + auto bank = chr_sprite_bank[7]; + return (bank * 0x2000) + (addr & 0x1fff); + } + + if(chr_mode == 1) { + auto bank = chr_sprite_bank[(addr / 0x1000) * 4 + 3]; + return (bank * 0x1000) + (addr & 0x0fff); + } + + if(chr_mode == 2) { + auto bank = chr_sprite_bank[(addr / 0x0800) * 2 + 1]; + return (bank * 0x0800) + (addr & 0x07ff); + } + + if(chr_mode == 3) { + auto bank = chr_sprite_bank[(addr / 0x0400)]; + return (bank * 0x0400) + (addr & 0x03ff); + } + } + + auto chr_bg_addr(uint addr) -> uint { + addr &= 0x0fff; + + if(chr_mode == 0) { + auto bank = chr_bg_bank[3]; + return (bank * 0x2000) + (addr & 0x0fff); + } + + if(chr_mode == 1) { + auto bank = chr_bg_bank[3]; + return (bank * 0x1000) + (addr & 0x0fff); + } + + if(chr_mode == 2) { + auto bank = chr_bg_bank[(addr / 0x0800) * 2 + 1]; + return (bank * 0x0800) + (addr & 0x07ff); + } + + if(chr_mode == 3) { + auto bank = chr_bg_bank[(addr / 0x0400)]; + return (bank * 0x0400) + (addr & 0x03ff); + } + } + + auto chr_vs_addr(uint addr) -> uint { + return (vs_bank * 0x1000) + (addr & 0x0ff8) + (vs_vpos & 7); + } + + auto blank() -> void { + in_frame = false; + } + + auto scanline() -> void { + hcounter = 0; + + if(in_frame == false) { + in_frame = true; + irq_pending = false; + vcounter = 0; + } else { + if(vcounter == irq_line) irq_pending = true; + vcounter++; + } + + cpu_cycle_counter = 0; + } + + auto ciram_read(uint addr) -> uint8 { + if(vs_fetch && (hcounter & 2) == 0) return exram[vs_vpos / 8 * 32 + vs_hpos / 8]; + if(vs_fetch && (hcounter & 2) != 0) return exram[vs_vpos / 32 * 8 + vs_hpos / 32 + 0x03c0]; + + switch(nametable_mode[(addr >> 10) & 3]) { + case 0: return ppu.ciram_read(0x0000 | (addr & 0x03ff)); + case 1: return ppu.ciram_read(0x0400 | (addr & 0x03ff)); + case 2: return exram_mode < 2 ? exram[addr & 0x03ff] : 0x00; + case 3: return (hcounter & 2) == 0 ? fillmode_tile : fillmode_color; + } + } + + auto chr_read(uint addr) -> uint8 { + chr_access[0] = chr_access[1]; + chr_access[1] = chr_access[2]; + chr_access[2] = chr_access[3]; + chr_access[3] = addr; + + //detect two unused nametable fetches at end of each scanline + if((chr_access[0] & 0x2000) == 0 + && (chr_access[1] & 0x2000) + && (chr_access[2] & 0x2000) + && (chr_access[3] & 0x2000)) scanline(); + + if(in_frame == false) { + vs_fetch = false; + if(addr & 0x2000) return ciram_read(addr); + return board.chrrom.read(chr_active ? chr_bg_addr(addr) : chr_sprite_addr(addr)); + } + + bool bg_fetch = (hcounter < 256 || hcounter >= 320); + uint8 result = 0x00; + + if((hcounter & 7) == 0) { + vs_hpos = hcounter >= 320 ? hcounter - 320 : hcounter + 16; + vs_vpos = vcounter + vs_scroll; + vs_fetch = vs_enable && bg_fetch && exram_mode < 2 + && (vs_side ? vs_hpos / 8 >= vs_tile : vs_hpos / 8 < vs_tile); + if(vs_vpos >= 240) vs_vpos -= 240; + + result = ciram_read(addr); + + exbank = (chr_bank_hi << 6) | (exram[addr & 0x03ff] & 0x3f); + exattr = exram[addr & 0x03ff] >> 6; + exattr |= exattr << 2; + exattr |= exattr << 4; + } else if((hcounter & 7) == 2) { + result = ciram_read(addr); + if(bg_fetch && exram_mode == 1) result = exattr; + } else { + if(vs_fetch) result = board.chrrom.read(chr_vs_addr(addr)); + else if(sprite_8x16 ? bg_fetch : chr_active) result = board.chrrom.read(chr_bg_addr(addr)); + else result = board.chrrom.read(chr_sprite_addr(addr)); + if(bg_fetch && exram_mode == 1) result = board.chrrom.read(exbank * 0x1000 + (addr & 0x0fff)); + } + + hcounter += 2; return result; } - case 0x5205: return (multiplier * multiplicand) >> 0; - case 0x5206: return (multiplier * multiplicand) >> 8; - } -} -void prg_write(unsigned addr, uint8 data) { - if((addr & 0xfc00) == 0x5c00) { - //writes 0x00 *during* Vblank (not during screen rendering ...) - if(exram_mode == 0 || exram_mode == 1) exram[addr & 0x03ff] = in_frame ? data : 0x00; - if(exram_mode == 2) exram[addr & 0x03ff] = data; - return; - } - - if(addr >= 0x6000) { - prg_access(1, addr, data); - return; - } - - switch(addr) { - case 0x2000: - sprite_8x16 = data & 0x20; - break; - - case 0x2001: - //if BG+sprites are disabled; enter video blanking period - if((data & 0x18) == 0) blank(); - break; - - case 0x5100: prg_mode = data & 3; break; - case 0x5101: chr_mode = data & 3; break; - - case 0x5102: prgram_write_protect[0] = data & 3; break; - case 0x5103: prgram_write_protect[1] = data & 3; break; - - case 0x5104: - exram_mode = data & 3; - break; - - case 0x5105: - nametable_mode[0] = (data & 0x03) >> 0; - nametable_mode[1] = (data & 0x0c) >> 2; - nametable_mode[2] = (data & 0x30) >> 4; - nametable_mode[3] = (data & 0xc0) >> 6; - break; - - case 0x5106: - fillmode_tile = data; - break; - - case 0x5107: - fillmode_color = data & 3; - fillmode_color |= fillmode_color << 2; - fillmode_color |= fillmode_color << 4; - break; - - case 0x5113: - ram_select = data & 0x04; - ram_bank = data & 0x03; - break; - - case 0x5114: prg_bank[0] = data; break; - case 0x5115: prg_bank[1] = data; break; - case 0x5116: prg_bank[2] = data; break; - case 0x5117: prg_bank[3] = data | 0x80; break; - - case 0x5120: chr_sprite_bank[0] = (chr_bank_hi << 8) | data; chr_active = 0; break; - case 0x5121: chr_sprite_bank[1] = (chr_bank_hi << 8) | data; chr_active = 0; break; - case 0x5122: chr_sprite_bank[2] = (chr_bank_hi << 8) | data; chr_active = 0; break; - case 0x5123: chr_sprite_bank[3] = (chr_bank_hi << 8) | data; chr_active = 0; break; - case 0x5124: chr_sprite_bank[4] = (chr_bank_hi << 8) | data; chr_active = 0; break; - case 0x5125: chr_sprite_bank[5] = (chr_bank_hi << 8) | data; chr_active = 0; break; - case 0x5126: chr_sprite_bank[6] = (chr_bank_hi << 8) | data; chr_active = 0; break; - case 0x5127: chr_sprite_bank[7] = (chr_bank_hi << 8) | data; chr_active = 0; break; - - case 0x5128: chr_bg_bank[0] = (chr_bank_hi << 8) | data; chr_active = 1; break; - case 0x5129: chr_bg_bank[1] = (chr_bank_hi << 8) | data; chr_active = 1; break; - case 0x512a: chr_bg_bank[2] = (chr_bank_hi << 8) | data; chr_active = 1; break; - case 0x512b: chr_bg_bank[3] = (chr_bank_hi << 8) | data; chr_active = 1; break; - - case 0x5130: - chr_bank_hi = data & 3; - break; - - case 0x5200: - vs_enable = data & 0x80; - vs_side = data & 0x40; - vs_tile = data & 0x1f; - break; - - case 0x5201: - vs_scroll = data; - break; - - case 0x5202: - vs_bank = data; - break; - - case 0x5203: - irq_line = data; - break; - - case 0x5204: - irq_enable = data & 0x80; - break; - - case 0x5205: - multiplicand = data; - break; - - case 0x5206: - multiplier = data; - break; - } -} - -unsigned chr_sprite_addr(unsigned addr) { - if(chr_mode == 0) { - auto bank = chr_sprite_bank[7]; - return (bank * 0x2000) + (addr & 0x1fff); - } - - if(chr_mode == 1) { - auto bank = chr_sprite_bank[(addr / 0x1000) * 4 + 3]; - return (bank * 0x1000) + (addr & 0x0fff); - } - - if(chr_mode == 2) { - auto bank = chr_sprite_bank[(addr / 0x0800) * 2 + 1]; - return (bank * 0x0800) + (addr & 0x07ff); - } - - if(chr_mode == 3) { - auto bank = chr_sprite_bank[(addr / 0x0400)]; - return (bank * 0x0400) + (addr & 0x03ff); - } -} - -unsigned chr_bg_addr(unsigned addr) { - addr &= 0x0fff; - - if(chr_mode == 0) { - auto bank = chr_bg_bank[3]; - return (bank * 0x2000) + (addr & 0x0fff); - } - - if(chr_mode == 1) { - auto bank = chr_bg_bank[3]; - return (bank * 0x1000) + (addr & 0x0fff); - } - - if(chr_mode == 2) { - auto bank = chr_bg_bank[(addr / 0x0800) * 2 + 1]; - return (bank * 0x0800) + (addr & 0x07ff); - } - - if(chr_mode == 3) { - auto bank = chr_bg_bank[(addr / 0x0400)]; - return (bank * 0x0400) + (addr & 0x03ff); - } -} - -unsigned chr_vs_addr(unsigned addr) { - return (vs_bank * 0x1000) + (addr & 0x0ff8) + (vs_vpos & 7); -} - -void blank() { - in_frame = false; -} - -void scanline() { - hcounter = 0; - - if(in_frame == false) { - in_frame = true; - irq_pending = false; - vcounter = 0; - } else { - if(vcounter == irq_line) irq_pending = true; - vcounter++; - } - - cpu_cycle_counter = 0; -} - -uint8 ciram_read(unsigned addr) { - if(vs_fetch && (hcounter & 2) == 0) return exram[vs_vpos / 8 * 32 + vs_hpos / 8]; - if(vs_fetch && (hcounter & 2) != 0) return exram[vs_vpos / 32 * 8 + vs_hpos / 32 + 0x03c0]; - - switch(nametable_mode[(addr >> 10) & 3]) { - case 0: return ppu.ciram_read(0x0000 | (addr & 0x03ff)); - case 1: return ppu.ciram_read(0x0400 | (addr & 0x03ff)); - case 2: return exram_mode < 2 ? exram[addr & 0x03ff] : 0x00; - case 3: return (hcounter & 2) == 0 ? fillmode_tile : fillmode_color; - } -} - -uint8 chr_read(unsigned addr) { - chr_access[0] = chr_access[1]; - chr_access[1] = chr_access[2]; - chr_access[2] = chr_access[3]; - chr_access[3] = addr; - - //detect two unused nametable fetches at end of each scanline - if((chr_access[0] & 0x2000) == 0 - && (chr_access[1] & 0x2000) - && (chr_access[2] & 0x2000) - && (chr_access[3] & 0x2000)) scanline(); - - if(in_frame == false) { - vs_fetch = false; - if(addr & 0x2000) return ciram_read(addr); - return board.chrrom.read(chr_active ? chr_bg_addr(addr) : chr_sprite_addr(addr)); - } - - bool bg_fetch = (hcounter < 256 || hcounter >= 320); - uint8 result = 0x00; - - if((hcounter & 7) == 0) { - vs_hpos = hcounter >= 320 ? hcounter - 320 : hcounter + 16; - vs_vpos = vcounter + vs_scroll; - vs_fetch = vs_enable && bg_fetch && exram_mode < 2 - && (vs_side ? vs_hpos / 8 >= vs_tile : vs_hpos / 8 < vs_tile); - if(vs_vpos >= 240) vs_vpos -= 240; - - result = ciram_read(addr); - - exbank = (chr_bank_hi << 6) | (exram[addr & 0x03ff] & 0x3f); - exattr = exram[addr & 0x03ff] >> 6; - exattr |= exattr << 2; - exattr |= exattr << 4; - } else if((hcounter & 7) == 2) { - result = ciram_read(addr); - if(bg_fetch && exram_mode == 1) result = exattr; - } else { - if(vs_fetch) result = board.chrrom.read(chr_vs_addr(addr)); - else if(sprite_8x16 ? bg_fetch : chr_active) result = board.chrrom.read(chr_bg_addr(addr)); - else result = board.chrrom.read(chr_sprite_addr(addr)); - if(bg_fetch && exram_mode == 1) result = board.chrrom.read(exbank * 0x1000 + (addr & 0x0fff)); - } - - hcounter += 2; - return result; -} - -void chr_write(unsigned addr, uint8 data) { - if(addr & 0x2000) { - switch(nametable_mode[(addr >> 10) & 3]) { - case 0: return ppu.ciram_write(0x0000 | (addr & 0x03ff), data); - case 1: return ppu.ciram_write(0x0400 | (addr & 0x03ff), data); - case 2: exram[addr & 0x03ff] = data; break; + auto chr_write(uint addr, uint8 data) -> void { + if(addr & 0x2000) { + switch(nametable_mode[(addr >> 10) & 3]) { + case 0: return ppu.ciram_write(0x0000 | (addr & 0x03ff), data); + case 1: return ppu.ciram_write(0x0400 | (addr & 0x03ff), data); + case 2: exram[addr & 0x03ff] = data; break; + } } } -} -void power() { -} + auto power() -> void { + } -void reset() { - for(auto& n : exram) n = 0xff; + auto reset() -> void { + for(auto& n : exram) n = 0xff; - prg_mode = 3; - chr_mode = 0; - for(auto& n : prgram_write_protect) n = 0; - exram_mode = 0; - for(auto& n : nametable_mode) n = 0; - fillmode_tile = 0; - fillmode_color = 0; - ram_select = 0; - ram_bank = 0; - prg_bank[0] = 0x00; - prg_bank[1] = 0x00; - prg_bank[2] = 0x00; - prg_bank[3] = 0xff; - for(auto& n : chr_sprite_bank) n = 0; - for(auto& n : chr_bg_bank) n = 0; - chr_bank_hi = 0; - vs_enable = 0; - vs_side = 0; - vs_tile = 0; - vs_scroll = 0; - vs_bank = 0; - irq_line = 0; - irq_enable = 0; - multiplicand = 0; - multiplier = 0; + prg_mode = 3; + chr_mode = 0; + for(auto& n : prgram_write_protect) n = 0; + exram_mode = 0; + for(auto& n : nametable_mode) n = 0; + fillmode_tile = 0; + fillmode_color = 0; + ram_select = 0; + ram_bank = 0; + prg_bank[0] = 0x00; + prg_bank[1] = 0x00; + prg_bank[2] = 0x00; + prg_bank[3] = 0xff; + for(auto& n : chr_sprite_bank) n = 0; + for(auto& n : chr_bg_bank) n = 0; + chr_bank_hi = 0; + vs_enable = 0; + vs_side = 0; + vs_tile = 0; + vs_scroll = 0; + vs_bank = 0; + irq_line = 0; + irq_enable = 0; + multiplicand = 0; + multiplier = 0; - cpu_cycle_counter = 0; - irq_counter = 0; - irq_pending = 0; - in_frame = 0; - vcounter = 0; - hcounter = 0; - for(auto& n : chr_access) n = 0; - chr_active = 0; - sprite_8x16 = 0; + cpu_cycle_counter = 0; + irq_counter = 0; + irq_pending = 0; + in_frame = 0; + vcounter = 0; + hcounter = 0; + for(auto& n : chr_access) n = 0; + chr_active = 0; + sprite_8x16 = 0; - exbank = 0; - exattr = 0; + exbank = 0; + exattr = 0; - vs_fetch = 0; - vs_vpos = 0; - vs_hpos = 0; -} + vs_fetch = 0; + vs_vpos = 0; + vs_hpos = 0; + } -void serialize(serializer& s) { - s.array(exram); + auto serialize(serializer& s) -> void { + s.array(exram); - s.integer(prg_mode); - s.integer(chr_mode); - for(auto& n : prgram_write_protect) s.integer(n); - s.integer(exram_mode); - for(auto& n : nametable_mode) s.integer(n); - s.integer(fillmode_tile); - s.integer(fillmode_color); - s.integer(ram_select); - s.integer(ram_bank); - for(auto& n : prg_bank) s.integer(n); - for(auto& n : chr_sprite_bank) s.integer(n); - for(auto& n : chr_bg_bank) s.integer(n); - s.integer(chr_bank_hi); - s.integer(vs_enable); - s.integer(vs_side); - s.integer(vs_tile); - s.integer(vs_scroll); - s.integer(vs_bank); - s.integer(irq_line); - s.integer(irq_enable); - s.integer(multiplicand); - s.integer(multiplier); + s.integer(prg_mode); + s.integer(chr_mode); + for(auto& n : prgram_write_protect) s.integer(n); + s.integer(exram_mode); + for(auto& n : nametable_mode) s.integer(n); + s.integer(fillmode_tile); + s.integer(fillmode_color); + s.integer(ram_select); + s.integer(ram_bank); + for(auto& n : prg_bank) s.integer(n); + for(auto& n : chr_sprite_bank) s.integer(n); + for(auto& n : chr_bg_bank) s.integer(n); + s.integer(chr_bank_hi); + s.integer(vs_enable); + s.integer(vs_side); + s.integer(vs_tile); + s.integer(vs_scroll); + s.integer(vs_bank); + s.integer(irq_line); + s.integer(irq_enable); + s.integer(multiplicand); + s.integer(multiplier); - s.integer(cpu_cycle_counter); - s.integer(irq_counter); - s.integer(irq_pending); - s.integer(in_frame); + s.integer(cpu_cycle_counter); + s.integer(irq_counter); + s.integer(irq_pending); + s.integer(in_frame); - s.integer(vcounter); - s.integer(hcounter); - for(auto& n : chr_access) s.integer(n); - s.integer(chr_active); - s.integer(sprite_8x16); + s.integer(vcounter); + s.integer(hcounter); + for(auto& n : chr_access) s.integer(n); + s.integer(chr_active); + s.integer(sprite_8x16); - s.integer(exbank); - s.integer(exattr); + s.integer(exbank); + s.integer(exattr); - s.integer(vs_fetch); - s.integer(vs_vpos); - s.integer(vs_hpos); -} + s.integer(vs_fetch); + s.integer(vs_vpos); + s.integer(vs_hpos); + } -MMC5(Board& board) : Chip(board) { - revision = Revision::MMC5; -} + enum class Revision : uint { + MMC5, + MMC5B, + } revision; + uint8 exram[1024]; + + //programmable registers + + uint2 prg_mode; //$5100 + uint2 chr_mode; //$5101 + + uint2 prgram_write_protect[2]; //$5102,$5103 + + uint2 exram_mode; //$5104 + uint2 nametable_mode[4]; //$5105 + uint8 fillmode_tile; //$5106 + uint8 fillmode_color; //$5107 + + bool ram_select; //$5113 + uint2 ram_bank; //$5113 + uint8 prg_bank[4]; //$5114-5117 + uint10 chr_sprite_bank[8]; //$5120-5127 + uint10 chr_bg_bank[4]; //$5128-512b + uint2 chr_bank_hi; //$5130 + + bool vs_enable; //$5200 + bool vs_side; //$5200 + uint5 vs_tile; //$5200 + uint8 vs_scroll; //$5201 + uint8 vs_bank; //$5202 + + uint8 irq_line; //$5203 + bool irq_enable; //$5204 + + uint8 multiplicand; //$5205 + uint8 multiplier; //$5206 + + //status registers + + uint cpu_cycle_counter; + uint irq_counter; + bool irq_pending; + bool in_frame; + + uint vcounter; + uint hcounter; + uint16 chr_access[4]; + bool chr_active; + bool sprite_8x16; + + uint8 exbank; + uint8 exattr; + + bool vs_fetch; + uint8 vs_vpos; + uint8 vs_hpos; }; diff --git a/fc/cartridge/chip/mmc6.cpp b/fc/cartridge/chip/mmc6.cpp index 624ed205..ad6500dc 100644 --- a/fc/cartridge/chip/mmc6.cpp +++ b/fc/cartridge/chip/mmc6.cpp @@ -1,200 +1,198 @@ struct MMC6 : Chip { - -bool chr_mode; -bool prg_mode; -bool ram_enable; -uint3 bank_select; -uint8 prg_bank[2]; -uint8 chr_bank[6]; -bool mirror; -bool ram_readable[2]; -bool ram_writable[2]; -uint8 irq_latch; -uint8 irq_counter; -bool irq_enable; -unsigned irq_delay; -bool irq_line; - -uint16 chr_abus; - -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(irq_delay) irq_delay--; - cpu.set_irq_line(irq_line); - tick(); + MMC6(Board& board) : Chip(board) { } -} -void irq_test(unsigned addr) { - if(!(chr_abus & 0x1000) && (addr & 0x1000)) { - if(irq_delay == 0) { - if(irq_counter == 0) { - irq_counter = irq_latch; - } else if(--irq_counter == 0) { - if(irq_enable) irq_line = 1; + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); } + + if(irq_delay) irq_delay--; + cpu.set_irq_line(irq_line); + tick(); } - irq_delay = 6; } - chr_abus = addr; -} -unsigned prg_addr(unsigned addr) const { - switch((addr >> 13) & 3) { - case 0: - if(prg_mode == 1) return (0x3e << 13) | (addr & 0x1fff); - return (prg_bank[0] << 13) | (addr & 0x1fff); - case 1: - return (prg_bank[1] << 13) | (addr & 0x1fff); - case 2: - if(prg_mode == 0) return (0x3e << 13) | (addr & 0x1fff); - return (prg_bank[0] << 13) | (addr & 0x1fff); - case 3: - return (0x3f << 13) | (addr & 0x1fff); - } -} - -unsigned chr_addr(unsigned addr) const { - if(chr_mode == 0) { - if(addr <= 0x07ff) return (chr_bank[0] << 10) | (addr & 0x07ff); - if(addr <= 0x0fff) return (chr_bank[1] << 10) | (addr & 0x07ff); - if(addr <= 0x13ff) return (chr_bank[2] << 10) | (addr & 0x03ff); - if(addr <= 0x17ff) return (chr_bank[3] << 10) | (addr & 0x03ff); - if(addr <= 0x1bff) return (chr_bank[4] << 10) | (addr & 0x03ff); - if(addr <= 0x1fff) return (chr_bank[5] << 10) | (addr & 0x03ff); - } else { - if(addr <= 0x03ff) return (chr_bank[2] << 10) | (addr & 0x03ff); - if(addr <= 0x07ff) return (chr_bank[3] << 10) | (addr & 0x03ff); - if(addr <= 0x0bff) return (chr_bank[4] << 10) | (addr & 0x03ff); - if(addr <= 0x0fff) return (chr_bank[5] << 10) | (addr & 0x03ff); - if(addr <= 0x17ff) return (chr_bank[0] << 10) | (addr & 0x07ff); - if(addr <= 0x1fff) return (chr_bank[1] << 10) | (addr & 0x07ff); - } -} - -unsigned ciram_addr(unsigned addr) const { - if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); - if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); -} - -uint8 ram_read(unsigned addr) { - if(ram_enable == false) return cpu.mdr(); - if(ram_readable[0] == false && ram_readable[1] == false) return cpu.mdr(); - bool region = addr & 0x0200; - if(ram_readable[region] == false) return 0x00; - return board.prgram.read((region * 0x0200) + (addr & 0x01ff)); -} - -void ram_write(unsigned addr, uint8 data) { - if(ram_enable == false) return; - bool region = addr & 0x0200; - if(ram_writable[region] == false) return; - return board.prgram.write((region * 0x0200) + (addr & 0x01ff), data); -} - -void reg_write(unsigned addr, uint8 data) { - switch(addr & 0xe001) { - case 0x8000: - chr_mode = data & 0x80; - prg_mode = data & 0x40; - ram_enable = data & 0x20; - bank_select = data & 0x07; - if(ram_enable == false) { - for(auto &n : ram_readable) n = false; - for(auto &n : ram_writable) n = false; + auto irq_test(uint addr) -> void { + if(!(chr_abus & 0x1000) && (addr & 0x1000)) { + if(irq_delay == 0) { + if(irq_counter == 0) { + irq_counter = irq_latch; + } else if(--irq_counter == 0) { + if(irq_enable) irq_line = 1; + } + } + irq_delay = 6; } - break; + chr_abus = addr; + } - case 0x8001: - switch(bank_select) { - case 0: chr_bank[0] = data & ~1; break; - case 1: chr_bank[1] = data & ~1; break; - case 2: chr_bank[2] = data; break; - case 3: chr_bank[3] = data; break; - case 4: chr_bank[4] = data; break; - case 5: chr_bank[5] = data; break; - case 6: prg_bank[0] = data & 0x3f; break; - case 7: prg_bank[1] = data & 0x3f; break; + auto prg_addr(uint addr) const -> uint { + switch((addr >> 13) & 3) { + case 0: + if(prg_mode == 1) return (0x3e << 13) | (addr & 0x1fff); + return (prg_bank[0] << 13) | (addr & 0x1fff); + case 1: + return (prg_bank[1] << 13) | (addr & 0x1fff); + case 2: + if(prg_mode == 0) return (0x3e << 13) | (addr & 0x1fff); + return (prg_bank[0] << 13) | (addr & 0x1fff); + case 3: + return (0x3f << 13) | (addr & 0x1fff); } - break; + } - case 0xa000: - mirror = data & 0x01; - break; + auto chr_addr(uint addr) const -> uint { + if(chr_mode == 0) { + if(addr <= 0x07ff) return (chr_bank[0] << 10) | (addr & 0x07ff); + if(addr <= 0x0fff) return (chr_bank[1] << 10) | (addr & 0x07ff); + if(addr <= 0x13ff) return (chr_bank[2] << 10) | (addr & 0x03ff); + if(addr <= 0x17ff) return (chr_bank[3] << 10) | (addr & 0x03ff); + if(addr <= 0x1bff) return (chr_bank[4] << 10) | (addr & 0x03ff); + if(addr <= 0x1fff) return (chr_bank[5] << 10) | (addr & 0x03ff); + } else { + if(addr <= 0x03ff) return (chr_bank[2] << 10) | (addr & 0x03ff); + if(addr <= 0x07ff) return (chr_bank[3] << 10) | (addr & 0x03ff); + if(addr <= 0x0bff) return (chr_bank[4] << 10) | (addr & 0x03ff); + if(addr <= 0x0fff) return (chr_bank[5] << 10) | (addr & 0x03ff); + if(addr <= 0x17ff) return (chr_bank[0] << 10) | (addr & 0x07ff); + if(addr <= 0x1fff) return (chr_bank[1] << 10) | (addr & 0x07ff); + } + } - case 0xa001: - if(ram_enable == false) break; - ram_readable[1] = data & 0x80; - ram_writable[1] = data & 0x40; - ram_readable[0] = data & 0x20; - ram_writable[0] = data & 0x10; - break; + auto ciram_addr(uint addr) const -> uint { + if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); + if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); + } - case 0xc000: - irq_latch = data; - break; + auto ram_read(uint addr) -> uint8 { + if(ram_enable == false) return cpu.mdr(); + if(ram_readable[0] == false && ram_readable[1] == false) return cpu.mdr(); + bool region = addr & 0x0200; + if(ram_readable[region] == false) return 0x00; + return board.prgram.read((region * 0x0200) + (addr & 0x01ff)); + } - case 0xc001: + auto ram_write(uint addr, uint8 data) -> void { + if(ram_enable == false) return; + bool region = addr & 0x0200; + if(ram_writable[region] == false) return; + return board.prgram.write((region * 0x0200) + (addr & 0x01ff), data); + } + + auto reg_write(uint addr, uint8 data) -> void { + switch(addr & 0xe001) { + case 0x8000: + chr_mode = data & 0x80; + prg_mode = data & 0x40; + ram_enable = data & 0x20; + bank_select = data & 0x07; + if(ram_enable == false) { + for(auto &n : ram_readable) n = false; + for(auto &n : ram_writable) n = false; + } + break; + + case 0x8001: + switch(bank_select) { + case 0: chr_bank[0] = data & ~1; break; + case 1: chr_bank[1] = data & ~1; break; + case 2: chr_bank[2] = data; break; + case 3: chr_bank[3] = data; break; + case 4: chr_bank[4] = data; break; + case 5: chr_bank[5] = data; break; + case 6: prg_bank[0] = data & 0x3f; break; + case 7: prg_bank[1] = data & 0x3f; break; + } + break; + + case 0xa000: + mirror = data & 0x01; + break; + + case 0xa001: + if(ram_enable == false) break; + ram_readable[1] = data & 0x80; + ram_writable[1] = data & 0x40; + ram_readable[0] = data & 0x20; + ram_writable[0] = data & 0x10; + break; + + case 0xc000: + irq_latch = data; + break; + + case 0xc001: + irq_counter = 0; + break; + + case 0xe000: + irq_enable = false; + irq_line = 0; + break; + + case 0xe001: + irq_enable = true; + break; + } + } + + auto power() -> void { + } + + auto reset() -> void { + chr_mode = 0; + prg_mode = 0; + ram_enable = 0; + bank_select = 0; + for(auto& n : prg_bank) n = 0; + for(auto& n : chr_bank) n = 0; + mirror = 0; + for(auto& n : ram_readable) n = 0; + for(auto& n : ram_writable) n = 0; + irq_latch = 0; irq_counter = 0; - break; - - case 0xe000: - irq_enable = false; + irq_enable = 0; + irq_delay = 0; irq_line = 0; - break; - case 0xe001: - irq_enable = true; - break; + chr_abus = 0; } -} -void power() { -} + auto serialize(serializer& s) -> void { + s.integer(chr_mode); + s.integer(prg_mode); + s.integer(ram_enable); + s.integer(bank_select); + for(auto& n : prg_bank) s.integer(n); + for(auto& n : chr_bank) s.integer(n); + s.integer(mirror); + for(auto& n : ram_readable) s.integer(n); + for(auto& n : ram_writable) s.integer(n); + s.integer(irq_latch); + s.integer(irq_counter); + s.integer(irq_enable); + s.integer(irq_delay); + s.integer(irq_line); -void reset() { - chr_mode = 0; - prg_mode = 0; - ram_enable = 0; - bank_select = 0; - for(auto& n : prg_bank) n = 0; - for(auto& n : chr_bank) n = 0; - mirror = 0; - for(auto& n : ram_readable) n = 0; - for(auto& n : ram_writable) n = 0; - irq_latch = 0; - irq_counter = 0; - irq_enable = 0; - irq_delay = 0; - irq_line = 0; + s.integer(chr_abus); + } - chr_abus = 0; -} - -void serialize(serializer& s) { - s.integer(chr_mode); - s.integer(prg_mode); - s.integer(ram_enable); - s.integer(bank_select); - for(auto& n : prg_bank) s.integer(n); - for(auto& n : chr_bank) s.integer(n); - s.integer(mirror); - for(auto& n : ram_readable) s.integer(n); - for(auto& n : ram_writable) s.integer(n); - s.integer(irq_latch); - s.integer(irq_counter); - s.integer(irq_enable); - s.integer(irq_delay); - s.integer(irq_line); - - s.integer(chr_abus); -} - -MMC6(Board& board) : Chip(board) { -} + bool chr_mode; + bool prg_mode; + bool ram_enable; + uint3 bank_select; + uint8 prg_bank[2]; + uint8 chr_bank[6]; + bool mirror; + bool ram_readable[2]; + bool ram_writable[2]; + uint8 irq_latch; + uint8 irq_counter; + bool irq_enable; + uint irq_delay; + bool irq_line; + uint16 chr_abus; }; diff --git a/fc/cartridge/chip/vrc1.cpp b/fc/cartridge/chip/vrc1.cpp index 76ca0784..0d6b5409 100644 --- a/fc/cartridge/chip/vrc1.cpp +++ b/fc/cartridge/chip/vrc1.cpp @@ -1,80 +1,78 @@ struct VRC1 : Chip { - -uint4 prg_bank[3]; -uint4 chr_banklo[2]; -bool chr_bankhi[2]; -bool mirror; - -unsigned prg_addr(unsigned addr) const { - unsigned bank = 0x0f; - if((addr & 0xe000) == 0x8000) bank = prg_bank[0]; - if((addr & 0xe000) == 0xa000) bank = prg_bank[1]; - if((addr & 0xe000) == 0xc000) bank = prg_bank[2]; - return (bank * 0x2000) + (addr & 0x1fff); -} - -unsigned chr_addr(unsigned addr) const { - unsigned bank = chr_banklo[(bool)(addr & 0x1000)]; - bank |= chr_bankhi[(bool)(addr & 0x1000)] << 4; - return (bank * 0x1000) + (addr & 0x0fff); -} - -unsigned ciram_addr(unsigned addr) const { - switch(mirror) { - case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring - case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + VRC1(Board& board) : Chip(board) { } - throw; -} -void reg_write(unsigned addr, uint8 data) { - switch(addr & 0xf000) { - case 0x8000: - prg_bank[0] = data & 0x0f; - break; - - case 0x9000: - chr_bankhi[1] = data & 0x04; - chr_bankhi[0] = data & 0x02; - mirror = data & 0x01; - break; - - case 0xa000: - prg_bank[1] = data & 0x0f; - break; - - case 0xc000: - prg_bank[2] = data & 0x0f; - break; - - case 0xe000: - chr_banklo[0] = data & 0x0f; - break; - - case 0xf000: - chr_banklo[1] = data & 0x0f; - break; + auto prg_addr(uint addr) const -> uint { + uint bank = 0x0f; + if((addr & 0xe000) == 0x8000) bank = prg_bank[0]; + if((addr & 0xe000) == 0xa000) bank = prg_bank[1]; + if((addr & 0xe000) == 0xc000) bank = prg_bank[2]; + return (bank * 0x2000) + (addr & 0x1fff); } -} -void power() { -} + auto chr_addr(uint addr) const -> uint { + uint bank = chr_banklo[(bool)(addr & 0x1000)]; + bank |= chr_bankhi[(bool)(addr & 0x1000)] << 4; + return (bank * 0x1000) + (addr & 0x0fff); + } -void reset() { - for(auto& n : prg_bank) n = 0; - for(auto& n : chr_banklo) n = 0; - for(auto& n : chr_bankhi) n = 0; - mirror = 0; -} + auto ciram_addr(uint addr) const -> uint { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + } + throw; + } -void serialize(serializer& s) { - for(auto& n : prg_bank) s.integer(n); - for(auto& n : chr_banklo) s.integer(n); - for(auto& n : chr_bankhi) s.integer(n); - s.integer(mirror); -} + auto reg_write(uint addr, uint8 data) -> void { + switch(addr & 0xf000) { + case 0x8000: + prg_bank[0] = data & 0x0f; + break; -VRC1(Board& board) : Chip(board) { -} + case 0x9000: + chr_bankhi[1] = data & 0x04; + chr_bankhi[0] = data & 0x02; + mirror = data & 0x01; + break; + case 0xa000: + prg_bank[1] = data & 0x0f; + break; + + case 0xc000: + prg_bank[2] = data & 0x0f; + break; + + case 0xe000: + chr_banklo[0] = data & 0x0f; + break; + + case 0xf000: + chr_banklo[1] = data & 0x0f; + break; + } + } + + auto power() -> void { + } + + auto reset() -> void { + for(auto& n : prg_bank) n = 0; + for(auto& n : chr_banklo) n = 0; + for(auto& n : chr_bankhi) n = 0; + mirror = 0; + } + + auto serialize(serializer& s) -> void { + for(auto& n : prg_bank) s.integer(n); + for(auto& n : chr_banklo) s.integer(n); + for(auto& n : chr_bankhi) s.integer(n); + s.integer(mirror); + } + + uint4 prg_bank[3]; + uint4 chr_banklo[2]; + bool chr_bankhi[2]; + bool mirror; }; diff --git a/fc/cartridge/chip/vrc2.cpp b/fc/cartridge/chip/vrc2.cpp index 94bfb604..bb86068c 100644 --- a/fc/cartridge/chip/vrc2.cpp +++ b/fc/cartridge/chip/vrc2.cpp @@ -1,110 +1,108 @@ struct VRC2 : Chip { - -uint5 prg_bank[2]; -uint8 chr_bank[8]; -uint2 mirror; -bool latch; - -unsigned prg_addr(unsigned addr) const { - unsigned bank; - switch(addr & 0xe000) { - case 0x8000: bank = prg_bank[0]; break; - case 0xa000: bank = prg_bank[1]; break; - case 0xc000: bank = 0x1e; break; - case 0xe000: bank = 0x1f; break; + VRC2(Board& board) : Chip(board) { } - return (bank * 0x2000) + (addr & 0x1fff); -} -unsigned chr_addr(unsigned addr) const { - unsigned bank = chr_bank[addr / 0x0400]; - return (bank * 0x0400) + (addr & 0x03ff); -} - -unsigned ciram_addr(unsigned addr) const { - switch(mirror) { - case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring - case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring - case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) - case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) + auto prg_addr(uint addr) const -> uint { + uint bank; + switch(addr & 0xe000) { + case 0x8000: bank = prg_bank[0]; break; + case 0xa000: bank = prg_bank[1]; break; + case 0xc000: bank = 0x1e; break; + case 0xe000: bank = 0x1f; break; + } + return (bank * 0x2000) + (addr & 0x1fff); } - throw; -} -uint8 ram_read(unsigned addr) { - if(board.prgram.size == 0) { - if((addr & 0xf000) == 0x6000) return cpu.mdr() | latch; - return cpu.mdr(); + auto chr_addr(uint addr) const -> uint { + uint bank = chr_bank[addr / 0x0400]; + return (bank * 0x0400) + (addr & 0x03ff); } - return board.prgram.read(addr & 0x1fff); -} -void ram_write(unsigned addr, uint8 data) { - if(board.prgram.size == 0) { - if((addr & 0xf000) == 0x6000) latch = data & 0x01; - return; + auto ciram_addr(uint addr) const -> uint { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) + case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) + } + throw; } - return board.prgram.write(addr & 0x1fff, data); -} -void reg_write(unsigned addr, uint8 data) { - switch(addr) { - case 0x8000: case 0x8001: case 0x8002: case 0x8003: - prg_bank[0] = data & 0x1f; - break; - - case 0x9000: case 0x9001: case 0x9002: case 0x9003: - mirror = data & 0x03; - break; - - case 0xa000: case 0xa001: case 0xa002: case 0xa003: - prg_bank[1] = data & 0x1f; - break; - - case 0xb000: chr_bank[0] = (chr_bank[0] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xb001: chr_bank[0] = (chr_bank[0] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xb002: chr_bank[1] = (chr_bank[1] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xb003: chr_bank[1] = (chr_bank[1] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xc000: chr_bank[2] = (chr_bank[2] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xc001: chr_bank[2] = (chr_bank[2] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xc002: chr_bank[3] = (chr_bank[3] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xc003: chr_bank[3] = (chr_bank[3] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xd000: chr_bank[4] = (chr_bank[4] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xd001: chr_bank[4] = (chr_bank[4] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xd002: chr_bank[5] = (chr_bank[5] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xd003: chr_bank[5] = (chr_bank[5] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xe000: chr_bank[6] = (chr_bank[6] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xe001: chr_bank[6] = (chr_bank[6] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xe002: chr_bank[7] = (chr_bank[7] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xe003: chr_bank[7] = (chr_bank[7] & 0x0f) | ((data & 0x0f) << 4); break; + auto ram_read(uint addr) -> uint8 { + if(board.prgram.size == 0) { + if((addr & 0xf000) == 0x6000) return cpu.mdr() | latch; + return cpu.mdr(); + } + return board.prgram.read(addr & 0x1fff); } -} -void power() { -} + auto ram_write(uint addr, uint8 data) -> void { + if(board.prgram.size == 0) { + if((addr & 0xf000) == 0x6000) latch = data & 0x01; + return; + } + return board.prgram.write(addr & 0x1fff, data); + } -void reset() { - for(auto& n : prg_bank) n = 0; - for(auto& n : chr_bank) n = 0; - mirror = 0; - latch = 0; -} + auto reg_write(uint addr, uint8 data) -> void { + switch(addr) { + case 0x8000: case 0x8001: case 0x8002: case 0x8003: + prg_bank[0] = data & 0x1f; + break; -void serialize(serializer& s) { - for(auto& n : prg_bank) s.integer(n); - for(auto& n : chr_bank) s.integer(n); - s.integer(mirror); - s.integer(latch); -} + case 0x9000: case 0x9001: case 0x9002: case 0x9003: + mirror = data & 0x03; + break; -VRC2(Board& board) : Chip(board) { -} + case 0xa000: case 0xa001: case 0xa002: case 0xa003: + prg_bank[1] = data & 0x1f; + break; + case 0xb000: chr_bank[0] = (chr_bank[0] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xb001: chr_bank[0] = (chr_bank[0] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xb002: chr_bank[1] = (chr_bank[1] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xb003: chr_bank[1] = (chr_bank[1] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xc000: chr_bank[2] = (chr_bank[2] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xc001: chr_bank[2] = (chr_bank[2] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xc002: chr_bank[3] = (chr_bank[3] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xc003: chr_bank[3] = (chr_bank[3] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xd000: chr_bank[4] = (chr_bank[4] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xd001: chr_bank[4] = (chr_bank[4] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xd002: chr_bank[5] = (chr_bank[5] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xd003: chr_bank[5] = (chr_bank[5] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xe000: chr_bank[6] = (chr_bank[6] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xe001: chr_bank[6] = (chr_bank[6] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xe002: chr_bank[7] = (chr_bank[7] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xe003: chr_bank[7] = (chr_bank[7] & 0x0f) | ((data & 0x0f) << 4); break; + } + } + + auto power() -> void { + } + + auto reset() -> void { + for(auto& n : prg_bank) n = 0; + for(auto& n : chr_bank) n = 0; + mirror = 0; + latch = 0; + } + + auto serialize(serializer& s) -> void { + for(auto& n : prg_bank) s.integer(n); + for(auto& n : chr_bank) s.integer(n); + s.integer(mirror); + s.integer(latch); + } + + uint5 prg_bank[2]; + uint8 chr_bank[8]; + uint2 mirror; + bool latch; }; diff --git a/fc/cartridge/chip/vrc3.cpp b/fc/cartridge/chip/vrc3.cpp index 56277586..1a9dcf38 100644 --- a/fc/cartridge/chip/vrc3.cpp +++ b/fc/cartridge/chip/vrc3.cpp @@ -1,100 +1,98 @@ struct VRC3 : Chip { - -uint4 prg_bank; -bool irq_mode; -bool irq_enable; -bool irq_acknowledge; -uint16 irq_latch; -struct { - union { - uint16 w; - struct { uint8 order_lsb2(l, h); }; - }; -} irq_counter; -bool irq_line; - -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(irq_enable) { - if(irq_mode == 0) { //16-bit - if(++irq_counter.w == 0) { - irq_line = 1; - irq_enable = irq_acknowledge; - irq_counter.w = irq_latch; - } - } - if(irq_mode == 1) { //8-bit - if(++irq_counter.l == 0) { - irq_line = 1; - irq_enable = irq_acknowledge; - irq_counter.l = irq_latch; - } - } - } - - cpu.set_irq_line(irq_line); - tick(); + VRC3(Board& board) : Chip(board) { } -} -unsigned prg_addr(unsigned addr) const { - unsigned bank = (addr < 0xc000 ? (unsigned)prg_bank : 0x0f); - return (bank * 0x4000) + (addr & 0x3fff); -} + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } -void reg_write(unsigned addr, uint8 data) { - switch(addr & 0xf000) { - case 0x8000: irq_latch = (irq_latch & 0xfff0) | ((data & 0x0f) << 0); break; - case 0x9000: irq_latch = (irq_latch & 0xff0f) | ((data & 0x0f) << 4); break; - case 0xa000: irq_latch = (irq_latch & 0xf0ff) | ((data & 0x0f) << 8); break; - case 0xb000: irq_latch = (irq_latch & 0x0fff) | ((data & 0x0f) << 12); break; + if(irq_enable) { + if(irq_mode == 0) { //16-bit + if(++irq_counter.w == 0) { + irq_line = 1; + irq_enable = irq_acknowledge; + irq_counter.w = irq_latch; + } + } + if(irq_mode == 1) { //8-bit + if(++irq_counter.l == 0) { + irq_line = 1; + irq_enable = irq_acknowledge; + irq_counter.l = irq_latch; + } + } + } - case 0xc000: - irq_mode = data & 0x04; - irq_enable = data & 0x02; - irq_acknowledge = data & 0x01; - if(irq_enable) irq_counter.w = irq_latch; - break; + cpu.set_irq_line(irq_line); + tick(); + } + } - case 0xd000: + auto prg_addr(uint addr) const -> uint { + uint bank = (addr < 0xc000 ? (uint)prg_bank : 0x0f); + return (bank * 0x4000) + (addr & 0x3fff); + } + + auto reg_write(uint addr, uint8 data) -> void { + switch(addr & 0xf000) { + case 0x8000: irq_latch = (irq_latch & 0xfff0) | ((data & 0x0f) << 0); break; + case 0x9000: irq_latch = (irq_latch & 0xff0f) | ((data & 0x0f) << 4); break; + case 0xa000: irq_latch = (irq_latch & 0xf0ff) | ((data & 0x0f) << 8); break; + case 0xb000: irq_latch = (irq_latch & 0x0fff) | ((data & 0x0f) << 12); break; + + case 0xc000: + irq_mode = data & 0x04; + irq_enable = data & 0x02; + irq_acknowledge = data & 0x01; + if(irq_enable) irq_counter.w = irq_latch; + break; + + case 0xd000: + irq_line = 0; + irq_enable = irq_acknowledge; + break; + + case 0xf000: + prg_bank = data & 0x0f; + break; + } + } + + auto power() -> void { + } + + auto reset() -> void { + prg_bank = 0; + irq_mode = 0; + irq_enable = 0; + irq_acknowledge = 0; + irq_latch = 0; + irq_counter.w = 0; irq_line = 0; - irq_enable = irq_acknowledge; - break; - - case 0xf000: - prg_bank = data & 0x0f; - break; } -} -void power() { -} - -void reset() { - prg_bank = 0; - irq_mode = 0; - irq_enable = 0; - irq_acknowledge = 0; - irq_latch = 0; - irq_counter.w = 0; - irq_line = 0; -} - -void serialize(serializer& s) { - s.integer(prg_bank); - s.integer(irq_mode); - s.integer(irq_enable); - s.integer(irq_acknowledge); - s.integer(irq_latch); - s.integer(irq_counter.w); - s.integer(irq_line); -} - -VRC3(Board& board) : Chip(board) { -} + auto serialize(serializer& s) -> void { + s.integer(prg_bank); + s.integer(irq_mode); + s.integer(irq_enable); + s.integer(irq_acknowledge); + s.integer(irq_latch); + s.integer(irq_counter.w); + s.integer(irq_line); + } + uint4 prg_bank; + bool irq_mode; + bool irq_enable; + bool irq_acknowledge; + uint16 irq_latch; + struct { + union { + uint16 w; + struct { uint8 order_lsb2(l, h); }; + }; + } irq_counter; + bool irq_line; }; diff --git a/fc/cartridge/chip/vrc4.cpp b/fc/cartridge/chip/vrc4.cpp index 0f8a7403..c7ee8b07 100644 --- a/fc/cartridge/chip/vrc4.cpp +++ b/fc/cartridge/chip/vrc4.cpp @@ -1,30 +1,28 @@ struct VRC4 : Chip { + VRC4(Board& board) : Chip(board) { + } -bool prg_mode; -uint5 prg_bank[2]; -uint2 mirror; -uint8 chr_bank[8]; + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } -uint8 irq_latch; -bool irq_mode; -bool irq_enable; -bool irq_acknowledge; + if(irq_enable) { + if(irq_mode == 0) { + irq_scalar -= 3; + if(irq_scalar <= 0) { + irq_scalar += 341; + if(irq_counter == 0xff) { + irq_counter = irq_latch; + irq_line = 1; + } else { + irq_counter++; + } + } + } -uint8 irq_counter; -signed irq_scalar; -bool irq_line; - -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(irq_enable) { - if(irq_mode == 0) { - irq_scalar -= 3; - if(irq_scalar <= 0) { - irq_scalar += 341; + if(irq_mode == 1) { if(irq_counter == 0xff) { irq_counter = irq_latch; irq_line = 1; @@ -34,151 +32,151 @@ void main() { } } - if(irq_mode == 1) { - if(irq_counter == 0xff) { - irq_counter = irq_latch; - irq_line = 1; - } else { - irq_counter++; - } + cpu.set_irq_line(irq_line); + tick(); + } + } + + auto prg_addr(uint addr) const -> uint { + uint bank = 0, banks = board.prgrom.size / 0x2000; + switch(addr & 0xe000) { + case 0x8000: bank = prg_mode == 0 ? (unsigned)prg_bank[0] : banks - 2; break; + case 0xa000: bank = prg_bank[1]; break; + case 0xc000: bank = prg_mode == 0 ? banks - 2 : (unsigned)prg_bank[0]; break; + case 0xe000: bank = banks - 1; break; + } + return (bank * 0x2000) + (addr & 0x1fff); + } + + auto chr_addr(uint addr) const -> uint { + uint bank = chr_bank[addr / 0x0400]; + return (bank * 0x0400) + (addr & 0x03ff); + } + + auto ciram_addr(uint addr) const -> uint { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) + case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) + } + throw; + } + + auto reg_write(uint addr, uint8 data) -> void { + switch(addr) { + case 0x8000: case 0x8001: case 0x8002: case 0x8003: + prg_bank[0] = data & 0x1f; + break; + + case 0x9000: case 0x9001: + mirror = data & 0x03; + break; + + case 0x9002: case 0x9003: + prg_mode = data & 0x02; + break; + + case 0xa000: case 0xa001: case 0xa002: case 0xa003: + prg_bank[1] = data & 0x1f; + break; + + case 0xb000: chr_bank[0] = (chr_bank[0] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xb001: chr_bank[0] = (chr_bank[0] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xb002: chr_bank[1] = (chr_bank[1] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xb003: chr_bank[1] = (chr_bank[1] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xc000: chr_bank[2] = (chr_bank[2] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xc001: chr_bank[2] = (chr_bank[2] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xc002: chr_bank[3] = (chr_bank[3] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xc003: chr_bank[3] = (chr_bank[3] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xd000: chr_bank[4] = (chr_bank[4] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xd001: chr_bank[4] = (chr_bank[4] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xd002: chr_bank[5] = (chr_bank[5] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xd003: chr_bank[5] = (chr_bank[5] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xe000: chr_bank[6] = (chr_bank[6] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xe001: chr_bank[6] = (chr_bank[6] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xe002: chr_bank[7] = (chr_bank[7] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xe003: chr_bank[7] = (chr_bank[7] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xf000: + irq_latch = (irq_latch & 0xf0) | ((data & 0x0f) << 0); + break; + + case 0xf001: + irq_latch = (irq_latch & 0x0f) | ((data & 0x0f) << 4); + break; + + case 0xf002: + irq_mode = data & 0x04; + irq_enable = data & 0x02; + irq_acknowledge = data & 0x01; + if(irq_enable) { + irq_counter = irq_latch; + irq_scalar = 341; } + irq_line = 0; + break; + + case 0xf003: + irq_enable = irq_acknowledge; + irq_line = 0; + break; } - - cpu.set_irq_line(irq_line); - tick(); } -} -unsigned prg_addr(unsigned addr) const { - unsigned bank = 0, banks = board.prgrom.size / 0x2000; - switch(addr & 0xe000) { - case 0x8000: bank = prg_mode == 0 ? (unsigned)prg_bank[0] : banks - 2; break; - case 0xa000: bank = prg_bank[1]; break; - case 0xc000: bank = prg_mode == 0 ? banks - 2 : (unsigned)prg_bank[0]; break; - case 0xe000: bank = banks - 1; break; + auto power() -> void { } - return (bank * 0x2000) + (addr & 0x1fff); -} -unsigned chr_addr(unsigned addr) const { - unsigned bank = chr_bank[addr / 0x0400]; - return (bank * 0x0400) + (addr & 0x03ff); -} + auto reset() -> void { + prg_mode = 0; + for(auto& n : prg_bank) n = 0; + mirror = 0; + for(auto& n : chr_bank) n = 0; -unsigned ciram_addr(unsigned addr) const { - switch(mirror) { - case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring - case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring - case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) - case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) - } - throw; -} + irq_latch = 0; + irq_mode = 0; + irq_enable = 0; + irq_acknowledge = 0; -void reg_write(unsigned addr, uint8 data) { - switch(addr) { - case 0x8000: case 0x8001: case 0x8002: case 0x8003: - prg_bank[0] = data & 0x1f; - break; - - case 0x9000: case 0x9001: - mirror = data & 0x03; - break; - - case 0x9002: case 0x9003: - prg_mode = data & 0x02; - break; - - case 0xa000: case 0xa001: case 0xa002: case 0xa003: - prg_bank[1] = data & 0x1f; - break; - - case 0xb000: chr_bank[0] = (chr_bank[0] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xb001: chr_bank[0] = (chr_bank[0] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xb002: chr_bank[1] = (chr_bank[1] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xb003: chr_bank[1] = (chr_bank[1] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xc000: chr_bank[2] = (chr_bank[2] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xc001: chr_bank[2] = (chr_bank[2] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xc002: chr_bank[3] = (chr_bank[3] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xc003: chr_bank[3] = (chr_bank[3] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xd000: chr_bank[4] = (chr_bank[4] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xd001: chr_bank[4] = (chr_bank[4] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xd002: chr_bank[5] = (chr_bank[5] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xd003: chr_bank[5] = (chr_bank[5] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xe000: chr_bank[6] = (chr_bank[6] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xe001: chr_bank[6] = (chr_bank[6] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xe002: chr_bank[7] = (chr_bank[7] & 0xf0) | ((data & 0x0f) << 0); break; - case 0xe003: chr_bank[7] = (chr_bank[7] & 0x0f) | ((data & 0x0f) << 4); break; - - case 0xf000: - irq_latch = (irq_latch & 0xf0) | ((data & 0x0f) << 0); - break; - - case 0xf001: - irq_latch = (irq_latch & 0x0f) | ((data & 0x0f) << 4); - break; - - case 0xf002: - irq_mode = data & 0x04; - irq_enable = data & 0x02; - irq_acknowledge = data & 0x01; - if(irq_enable) { - irq_counter = irq_latch; - irq_scalar = 341; - } + irq_counter = 0; + irq_scalar = 0; irq_line = 0; - break; - - case 0xf003: - irq_enable = irq_acknowledge; - irq_line = 0; - break; } -} -void power() { -} + auto serialize(serializer& s) -> void { + s.integer(prg_mode); + for(auto& n : prg_bank) s.integer(n); + s.integer(mirror); + for(auto& n : chr_bank) s.integer(n); -void reset() { - prg_mode = 0; - for(auto& n : prg_bank) n = 0; - mirror = 0; - for(auto& n : chr_bank) n = 0; + s.integer(irq_latch); + s.integer(irq_mode); + s.integer(irq_enable); + s.integer(irq_acknowledge); - irq_latch = 0; - irq_mode = 0; - irq_enable = 0; - irq_acknowledge = 0; + s.integer(irq_counter); + s.integer(irq_scalar); + s.integer(irq_line); + } - irq_counter = 0; - irq_scalar = 0; - irq_line = 0; -} + bool prg_mode; + uint5 prg_bank[2]; + uint2 mirror; + uint8 chr_bank[8]; -void serialize(serializer& s) { - s.integer(prg_mode); - for(auto& n : prg_bank) s.integer(n); - s.integer(mirror); - for(auto& n : chr_bank) s.integer(n); - - s.integer(irq_latch); - s.integer(irq_mode); - s.integer(irq_enable); - s.integer(irq_acknowledge); - - s.integer(irq_counter); - s.integer(irq_scalar); - s.integer(irq_line); -} - -VRC4(Board& board) : Chip(board) { -} + uint8 irq_latch; + bool irq_mode; + bool irq_enable; + bool irq_acknowledge; + uint8 irq_counter; + int irq_scalar; + bool irq_line; }; diff --git a/fc/cartridge/chip/vrc6.cpp b/fc/cartridge/chip/vrc6.cpp index c2af0a93..36f945f3 100644 --- a/fc/cartridge/chip/vrc6.cpp +++ b/fc/cartridge/chip/vrc6.cpp @@ -1,102 +1,102 @@ struct VRC6 : Chip { + VRC6(Board& board) : Chip(board) { + } -uint8 prg_bank[2]; -uint8 chr_bank[8]; -uint2 mirror; -uint8 irq_latch; -bool irq_mode; -bool irq_enable; -bool irq_acknowledge; + struct Pulse { + auto clock() -> void { + if(--divider == 0) { + divider = frequency + 1; + cycle++; + output = (mode == 1 || cycle > duty) ? volume : (uint4)0; + } -uint8 irq_counter; -signed irq_scalar; -bool irq_line; - -struct Pulse { - bool mode; - uint3 duty; - uint4 volume; - bool enable; - uint12 frequency; - - uint12 divider; - uint4 cycle; - uint4 output; - - void clock() { - if(--divider == 0) { - divider = frequency + 1; - cycle++; - output = (mode == 1 || cycle > duty) ? volume : (uint4)0; + if(enable == false) output = 0; } - if(enable == false) output = 0; - } + auto serialize(serializer& s) -> void { + s.integer(mode); + s.integer(duty); + s.integer(volume); + s.integer(enable); + s.integer(frequency); - void serialize(serializer& s) { - s.integer(mode); - s.integer(duty); - s.integer(volume); - s.integer(enable); - s.integer(frequency); + s.integer(divider); + s.integer(cycle); + s.integer(output); + } - s.integer(divider); - s.integer(cycle); - s.integer(output); - } -} pulse1, pulse2; + bool mode; + uint3 duty; + uint4 volume; + bool enable; + uint12 frequency; -struct Sawtooth { - uint6 rate; - bool enable; - uint12 frequency; + uint12 divider; + uint4 cycle; + uint4 output; + } pulse1, pulse2; - uint12 divider; - uint1 phase; - uint3 stage; - uint8 accumulator; - uint5 output; - - void clock() { - if(--divider == 0) { - divider = frequency + 1; - if(++phase == 0) { - accumulator += rate; - if(++stage == 7) { - stage = 0; - accumulator = 0; + struct Sawtooth { + auto clock() -> void { + if(--divider == 0) { + divider = frequency + 1; + if(++phase == 0) { + accumulator += rate; + if(++stage == 7) { + stage = 0; + accumulator = 0; + } } } + + output = accumulator >> 3; + if(enable == false) output = 0; } - output = accumulator >> 3; - if(enable == false) output = 0; - } + auto serialize(serializer& s) -> void { + s.integer(rate); + s.integer(enable); + s.integer(frequency); - void serialize(serializer& s) { - s.integer(rate); - s.integer(enable); - s.integer(frequency); - - s.integer(divider); - s.integer(phase); - s.integer(stage); - s.integer(accumulator); - s.integer(output); - } -} sawtooth; - -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + s.integer(divider); + s.integer(phase); + s.integer(stage); + s.integer(accumulator); + s.integer(output); } - if(irq_enable) { - if(irq_mode == 0) { - irq_scalar -= 3; - if(irq_scalar <= 0) { - irq_scalar += 341; + uint6 rate; + bool enable; + uint12 frequency; + + uint12 divider; + uint1 phase; + uint3 stage; + uint8 accumulator; + uint5 output; + } sawtooth; + + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } + + if(irq_enable) { + if(irq_mode == 0) { + irq_scalar -= 3; + if(irq_scalar <= 0) { + irq_scalar += 341; + if(irq_counter == 0xff) { + irq_counter = irq_latch; + irq_line = 1; + } else { + irq_counter++; + } + } + } + + if(irq_mode == 1) { if(irq_counter == 0xff) { irq_counter = irq_latch; irq_line = 1; @@ -105,217 +105,215 @@ void main() { } } } + cpu.set_irq_line(irq_line); - if(irq_mode == 1) { - if(irq_counter == 0xff) { - irq_counter = irq_latch; - irq_line = 1; - } else { - irq_counter++; - } + pulse1.clock(); + pulse2.clock(); + sawtooth.clock(); + int output = (pulse1.output + pulse2.output + sawtooth.output) << 7; + apu.set_sample(-output); + + tick(); + } + } + + auto prg_addr(uint addr) const -> uint { + if((addr & 0xc000) == 0x8000) return (prg_bank[0] << 14) | (addr & 0x3fff); + if((addr & 0xe000) == 0xc000) return (prg_bank[1] << 13) | (addr & 0x1fff); + if((addr & 0xe000) == 0xe000) return ( 0xff << 13) | (addr & 0x1fff); + } + + auto chr_addr(uint addr) const -> uint { + uint bank = chr_bank[(addr >> 10) & 7]; + return (bank << 10) | (addr & 0x03ff); + } + + auto ciram_addr(uint addr) const -> uint { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) + case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) + } + } + + auto ram_read(uint addr) -> uint8 { + return board.prgram.data[addr & 0x1fff]; + } + + auto ram_write(uint addr, uint8 data) -> void { + board.prgram.data[addr & 0x1fff] = data; + } + + auto reg_write(uint addr, uint8 data) -> void { + switch(addr) { + case 0x8000: case 0x8001: case 0x8002: case 0x8003: + prg_bank[0] = data; + break; + + case 0x9000: + pulse1.mode = data & 0x80; + pulse1.duty = (data & 0x70) >> 4; + pulse1.volume = data & 0x0f; + break; + + case 0x9001: + pulse1.frequency = (pulse1.frequency & 0x0f00) | ((data & 0xff) << 0); + break; + + case 0x9002: + pulse1.frequency = (pulse1.frequency & 0x00ff) | ((data & 0x0f) << 8); + pulse1.enable = data & 0x80; + break; + + case 0xa000: + pulse2.mode = data & 0x80; + pulse2.duty = (data & 0x70) >> 4; + pulse2.volume = data & 0x0f; + break; + + case 0xa001: + pulse2.frequency = (pulse2.frequency & 0x0f00) | ((data & 0xff) << 0); + break; + + case 0xa002: + pulse2.frequency = (pulse2.frequency & 0x00ff) | ((data & 0x0f) << 8); + pulse2.enable = data & 0x80; + break; + + case 0xb000: + sawtooth.rate = data & 0x3f; + break; + + case 0xb001: + sawtooth.frequency = (sawtooth.frequency & 0x0f00) | ((data & 0xff) << 0); + break; + + case 0xb002: + sawtooth.frequency = (sawtooth.frequency & 0x00ff) | ((data & 0x0f) << 8); + sawtooth.enable = data & 0x80; + break; + + case 0xb003: + mirror = (data >> 2) & 3; + break; + + case 0xc000: case 0xc001: case 0xc002: case 0xc003: + prg_bank[1] = data; + break; + + case 0xd000: case 0xd001: case 0xd002: case 0xd003: + chr_bank[0 + (addr & 3)] = data; + break; + + case 0xe000: case 0xe001: case 0xe002: case 0xe003: + chr_bank[4 + (addr & 3)] = data; + break; + + case 0xf000: + irq_latch = data; + break; + + case 0xf001: + irq_mode = data & 0x04; + irq_enable = data & 0x02; + irq_acknowledge = data & 0x01; + if(irq_enable) { + irq_counter = irq_latch; + irq_scalar = 341; } + irq_line = 0; + break; + + case 0xf002: + irq_enable = irq_acknowledge; + irq_line = 0; + break; } - cpu.set_irq_line(irq_line); - - pulse1.clock(); - pulse2.clock(); - sawtooth.clock(); - signed output = (pulse1.output + pulse2.output + sawtooth.output) << 7; - apu.set_sample(-output); - - tick(); } -} -unsigned prg_addr(unsigned addr) const { - if((addr & 0xc000) == 0x8000) return (prg_bank[0] << 14) | (addr & 0x3fff); - if((addr & 0xe000) == 0xc000) return (prg_bank[1] << 13) | (addr & 0x1fff); - if((addr & 0xe000) == 0xe000) return ( 0xff << 13) | (addr & 0x1fff); -} - -unsigned chr_addr(unsigned addr) const { - unsigned bank = chr_bank[(addr >> 10) & 7]; - return (bank << 10) | (addr & 0x03ff); -} - -unsigned ciram_addr(unsigned addr) const { - switch(mirror) { - case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring - case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring - case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) - case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) + auto power() -> void { } -} -uint8 ram_read(unsigned addr) { - return board.prgram.data[addr & 0x1fff]; -} + auto reset() -> void { + prg_bank[0] = 0; + prg_bank[1] = 0; + chr_bank[0] = 0; + chr_bank[1] = 0; + chr_bank[2] = 0; + chr_bank[3] = 0; + chr_bank[4] = 0; + chr_bank[5] = 0; + chr_bank[6] = 0; + chr_bank[7] = 0; + mirror = 0; + irq_latch = 0; + irq_mode = 0; + irq_enable = 0; + irq_acknowledge = 0; -void ram_write(unsigned addr, uint8 data) { - board.prgram.data[addr & 0x1fff] = data; -} - -void reg_write(unsigned addr, uint8 data) { - switch(addr) { - case 0x8000: case 0x8001: case 0x8002: case 0x8003: - prg_bank[0] = data; - break; - - case 0x9000: - pulse1.mode = data & 0x80; - pulse1.duty = (data & 0x70) >> 4; - pulse1.volume = data & 0x0f; - break; - - case 0x9001: - pulse1.frequency = (pulse1.frequency & 0x0f00) | ((data & 0xff) << 0); - break; - - case 0x9002: - pulse1.frequency = (pulse1.frequency & 0x00ff) | ((data & 0x0f) << 8); - pulse1.enable = data & 0x80; - break; - - case 0xa000: - pulse2.mode = data & 0x80; - pulse2.duty = (data & 0x70) >> 4; - pulse2.volume = data & 0x0f; - break; - - case 0xa001: - pulse2.frequency = (pulse2.frequency & 0x0f00) | ((data & 0xff) << 0); - break; - - case 0xa002: - pulse2.frequency = (pulse2.frequency & 0x00ff) | ((data & 0x0f) << 8); - pulse2.enable = data & 0x80; - break; - - case 0xb000: - sawtooth.rate = data & 0x3f; - break; - - case 0xb001: - sawtooth.frequency = (sawtooth.frequency & 0x0f00) | ((data & 0xff) << 0); - break; - - case 0xb002: - sawtooth.frequency = (sawtooth.frequency & 0x00ff) | ((data & 0x0f) << 8); - sawtooth.enable = data & 0x80; - break; - - case 0xb003: - mirror = (data >> 2) & 3; - break; - - case 0xc000: case 0xc001: case 0xc002: case 0xc003: - prg_bank[1] = data; - break; - - case 0xd000: case 0xd001: case 0xd002: case 0xd003: - chr_bank[0 + (addr & 3)] = data; - break; - - case 0xe000: case 0xe001: case 0xe002: case 0xe003: - chr_bank[4 + (addr & 3)] = data; - break; - - case 0xf000: - irq_latch = data; - break; - - case 0xf001: - irq_mode = data & 0x04; - irq_enable = data & 0x02; - irq_acknowledge = data & 0x01; - if(irq_enable) { - irq_counter = irq_latch; - irq_scalar = 341; - } + irq_counter = 0; + irq_scalar = 0; irq_line = 0; - break; - case 0xf002: - irq_enable = irq_acknowledge; - irq_line = 0; - break; + pulse1.mode = 0; + pulse1.duty = 0; + pulse1.volume = 0; + pulse1.enable = 0; + pulse1.frequency = 0; + + pulse1.divider = 1; + pulse1.cycle = 0; + pulse1.output = 0; + + pulse2.mode = 0; + pulse2.duty = 0; + pulse2.volume = 0; + pulse2.enable = 0; + pulse2.frequency = 0; + + pulse2.divider = 1; + pulse2.cycle = 0; + pulse2.output = 0; + + sawtooth.rate = 0; + sawtooth.enable = 0; + sawtooth.frequency = 0; + + sawtooth.divider = 1; + sawtooth.phase = 0; + sawtooth.stage = 0; + sawtooth.accumulator = 0; + sawtooth.output = 0; } -} -void power() { -} + auto serialize(serializer& s) -> void { + pulse1.serialize(s); + pulse2.serialize(s); + sawtooth.serialize(s); -void reset() { - prg_bank[0] = 0; - prg_bank[1] = 0; - chr_bank[0] = 0; - chr_bank[1] = 0; - chr_bank[2] = 0; - chr_bank[3] = 0; - chr_bank[4] = 0; - chr_bank[5] = 0; - chr_bank[6] = 0; - chr_bank[7] = 0; - mirror = 0; - irq_latch = 0; - irq_mode = 0; - irq_enable = 0; - irq_acknowledge = 0; + s.array(prg_bank); + s.array(chr_bank); + s.integer(mirror); + s.integer(irq_latch); + s.integer(irq_mode); + s.integer(irq_enable); + s.integer(irq_acknowledge); - irq_counter = 0; - irq_scalar = 0; - irq_line = 0; + s.integer(irq_counter); + s.integer(irq_scalar); + s.integer(irq_line); + } - pulse1.mode = 0; - pulse1.duty = 0; - pulse1.volume = 0; - pulse1.enable = 0; - pulse1.frequency = 0; - - pulse1.divider = 1; - pulse1.cycle = 0; - pulse1.output = 0; - - pulse2.mode = 0; - pulse2.duty = 0; - pulse2.volume = 0; - pulse2.enable = 0; - pulse2.frequency = 0; - - pulse2.divider = 1; - pulse2.cycle = 0; - pulse2.output = 0; - - sawtooth.rate = 0; - sawtooth.enable = 0; - sawtooth.frequency = 0; - - sawtooth.divider = 1; - sawtooth.phase = 0; - sawtooth.stage = 0; - sawtooth.accumulator = 0; - sawtooth.output = 0; -} - -void serialize(serializer& s) { - pulse1.serialize(s); - pulse2.serialize(s); - sawtooth.serialize(s); - - s.array(prg_bank); - s.array(chr_bank); - s.integer(mirror); - s.integer(irq_latch); - s.integer(irq_mode); - s.integer(irq_enable); - s.integer(irq_acknowledge); - - s.integer(irq_counter); - s.integer(irq_scalar); - s.integer(irq_line); -} - -VRC6(Board& board) : Chip(board) { -} + uint8 prg_bank[2]; + uint8 chr_bank[8]; + uint2 mirror; + uint8 irq_latch; + bool irq_mode; + bool irq_enable; + bool irq_acknowledge; + uint8 irq_counter; + int irq_scalar; + bool irq_line; }; diff --git a/fc/cartridge/chip/vrc7.cpp b/fc/cartridge/chip/vrc7.cpp index 6c752c5a..c94b73d5 100644 --- a/fc/cartridge/chip/vrc7.cpp +++ b/fc/cartridge/chip/vrc7.cpp @@ -2,31 +2,30 @@ //Yamaha YM2413 OPLL audio - not emulated struct VRC7 : Chip { + VRC7(Board& board) : Chip(board) { + } -uint8 prg_bank[3]; -uint8 chr_bank[8]; -uint2 mirror; + auto main() -> void { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } -uint8 irq_latch; -bool irq_mode; -bool irq_enable; -bool irq_acknowledge; + if(irq_enable) { + if(irq_mode == 0) { + irq_scalar -= 3; + if(irq_scalar <= 0) { + irq_scalar += 341; + if(irq_counter == 0xff) { + irq_counter = irq_latch; + irq_line = 1; + } else { + irq_counter++; + } + } + } -uint8 irq_counter; -signed irq_scalar; -bool irq_line; - -void main() { - while(true) { - if(scheduler.sync == Scheduler::SynchronizeMode::All) { - scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); - } - - if(irq_enable) { - if(irq_mode == 0) { - irq_scalar -= 3; - if(irq_scalar <= 0) { - irq_scalar += 341; + if(irq_mode == 1) { if(irq_counter == 0xff) { irq_counter = irq_latch; irq_line = 1; @@ -35,120 +34,119 @@ void main() { } } } + cpu.set_irq_line(irq_line); - if(irq_mode == 1) { - if(irq_counter == 0xff) { - irq_counter = irq_latch; - irq_line = 1; - } else { - irq_counter++; - } + tick(); + } + } + + auto reg_write(uint addr, uint8 data) -> void { + switch(addr) { + case 0x8000: prg_bank[0] = data; break; + case 0x8010: prg_bank[1] = data; break; + case 0x9000: prg_bank[2] = data; break; + case 0x9010: break; //APU addr port + case 0x9030: break; //APU data port + case 0xa000: chr_bank[0] = data; break; + case 0xa010: chr_bank[1] = data; break; + case 0xb000: chr_bank[2] = data; break; + case 0xb010: chr_bank[3] = data; break; + case 0xc000: chr_bank[4] = data; break; + case 0xc010: chr_bank[5] = data; break; + case 0xd000: chr_bank[6] = data; break; + case 0xd010: chr_bank[7] = data; break; + case 0xe000: mirror = data & 0x03; break; + + case 0xe010: + irq_latch = data; + break; + + case 0xf000: + irq_mode = data & 0x04; + irq_enable = data & 0x02; + irq_acknowledge = data & 0x01; + if(irq_enable) { + irq_counter = irq_latch; + irq_scalar = 341; } + irq_line = 0; + break; + + case 0xf010: + irq_enable = irq_acknowledge; + irq_line = 0; + break; } - cpu.set_irq_line(irq_line); - - tick(); } -} -void reg_write(unsigned addr, uint8 data) { - switch(addr) { - case 0x8000: prg_bank[0] = data; break; - case 0x8010: prg_bank[1] = data; break; - case 0x9000: prg_bank[2] = data; break; - case 0x9010: break; //APU addr port - case 0x9030: break; //APU data port - case 0xa000: chr_bank[0] = data; break; - case 0xa010: chr_bank[1] = data; break; - case 0xb000: chr_bank[2] = data; break; - case 0xb010: chr_bank[3] = data; break; - case 0xc000: chr_bank[4] = data; break; - case 0xc010: chr_bank[5] = data; break; - case 0xd000: chr_bank[6] = data; break; - case 0xd010: chr_bank[7] = data; break; - case 0xe000: mirror = data & 0x03; break; - - case 0xe010: - irq_latch = data; - break; - - case 0xf000: - irq_mode = data & 0x04; - irq_enable = data & 0x02; - irq_acknowledge = data & 0x01; - if(irq_enable) { - irq_counter = irq_latch; - irq_scalar = 341; + auto prg_addr(uint addr) const -> uint { + uint bank = 0; + switch(addr & 0xe000) { + case 0x8000: bank = prg_bank[0]; break; + case 0xa000: bank = prg_bank[1]; break; + case 0xc000: bank = prg_bank[2]; break; + case 0xe000: bank = 0xff; break; } + return (bank * 0x2000) + (addr & 0x1fff); + } + + auto chr_addr(uint addr) const -> uint { + uint bank = chr_bank[addr / 0x0400]; + return (bank * 0x0400) + (addr & 0x03ff); + } + + auto ciram_addr(uint addr) const -> uint { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) + case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) + } + } + + auto power() -> void { + } + + auto reset() -> void { + for(auto& n : prg_bank) n = 0; + for(auto& n : chr_bank) n = 0; + mirror = 0; + + irq_latch = 0; + irq_mode = 0; + irq_enable = 0; + irq_acknowledge = 0; + + irq_counter = 0; + irq_scalar = 0; irq_line = 0; - break; - - case 0xf010: - irq_enable = irq_acknowledge; - irq_line = 0; - break; } -} -unsigned prg_addr(unsigned addr) const { - unsigned bank = 0; - switch(addr & 0xe000) { - case 0x8000: bank = prg_bank[0]; break; - case 0xa000: bank = prg_bank[1]; break; - case 0xc000: bank = prg_bank[2]; break; - case 0xe000: bank = 0xff; break; + auto serialize(serializer& s) -> void { + s.array(prg_bank); + s.array(chr_bank); + s.integer(mirror); + + s.integer(irq_latch); + s.integer(irq_mode); + s.integer(irq_enable); + s.integer(irq_acknowledge); + + s.integer(irq_counter); + s.integer(irq_scalar); + s.integer(irq_line); } - return (bank * 0x2000) + (addr & 0x1fff); -} -unsigned chr_addr(unsigned addr) const { - unsigned bank = chr_bank[addr / 0x0400]; - return (bank * 0x0400) + (addr & 0x03ff); -} + uint8 prg_bank[3]; + uint8 chr_bank[8]; + uint2 mirror; -unsigned ciram_addr(unsigned addr) const { - switch(mirror) { - case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring - case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring - case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) - case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) - } -} - -void power() { -} - -void reset() { - for(auto& n : prg_bank) n = 0; - for(auto& n : chr_bank) n = 0; - mirror = 0; - - irq_latch = 0; - irq_mode = 0; - irq_enable = 0; - irq_acknowledge = 0; - - irq_counter = 0; - irq_scalar = 0; - irq_line = 0; -} - -void serialize(serializer& s) { - s.array(prg_bank); - s.array(chr_bank); - s.integer(mirror); - - s.integer(irq_latch); - s.integer(irq_mode); - s.integer(irq_enable); - s.integer(irq_acknowledge); - - s.integer(irq_counter); - s.integer(irq_scalar); - s.integer(irq_line); -} - -VRC7(Board& board) : Chip(board) { -} + uint8 irq_latch; + bool irq_mode; + bool irq_enable; + bool irq_acknowledge; + uint8 irq_counter; + int irq_scalar; + bool irq_line; }; diff --git a/fc/cheat/cheat.cpp b/fc/cheat/cheat.cpp index 3d1e1f57..b50c99f0 100644 --- a/fc/cheat/cheat.cpp +++ b/fc/cheat/cheat.cpp @@ -4,19 +4,19 @@ namespace Famicom { Cheat cheat; -void Cheat::reset() { +auto Cheat::reset() -> void { codes.reset(); } -void Cheat::append(unsigned addr, unsigned data) { +auto Cheat::append(uint addr, uint data) -> void { codes.append({addr, Unused, data}); } -void Cheat::append(unsigned addr, unsigned comp, unsigned data) { +auto Cheat::append(uint addr, uint comp, uint data) -> void { codes.append({addr, comp, data}); } -maybe Cheat::find(unsigned addr, unsigned comp) { +auto Cheat::find(uint addr, uint comp) -> maybe { for(auto& code : codes) { if(code.addr == addr && (code.comp == Unused || code.comp == comp)) { return code.data; diff --git a/fc/cheat/cheat.hpp b/fc/cheat/cheat.hpp index 43f2d05c..4400f07c 100644 --- a/fc/cheat/cheat.hpp +++ b/fc/cheat/cheat.hpp @@ -1,17 +1,17 @@ struct Cheat { struct Code { - unsigned addr; - unsigned comp; - unsigned data; + uint addr; + uint comp; + uint data; }; vector codes; - enum : unsigned { Unused = ~0u }; + enum : uint { Unused = ~0u }; - alwaysinline bool enable() const { return codes.size() > 0; } - void reset(); - void append(unsigned addr, unsigned data); - void append(unsigned addr, unsigned comp, unsigned data); - maybe find(unsigned addr, unsigned comp); + alwaysinline auto enable() const -> bool { return codes.size() > 0; } + auto reset() -> void; + auto append(uint addr, uint data) -> void; + auto append(uint addr, uint comp, uint data) -> void; + auto find(uint addr, uint comp) -> maybe; }; extern Cheat cheat; diff --git a/fc/cpu/cpu.cpp b/fc/cpu/cpu.cpp index 652e1385..fa17dee4 100644 --- a/fc/cpu/cpu.cpp +++ b/fc/cpu/cpu.cpp @@ -6,7 +6,7 @@ namespace Famicom { #include "serialization.cpp" CPU cpu; -void CPU::Enter() { +auto CPU::Enter() -> void { while(true) { if(scheduler.sync == Scheduler::SynchronizeMode::All) { scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); @@ -16,7 +16,7 @@ void CPU::Enter() { } } -void CPU::main() { +auto CPU::main() -> void { if(status.interrupt_pending) { interrupt(); return; @@ -25,7 +25,7 @@ void CPU::main() { exec(); } -void CPU::add_clocks(unsigned clocks) { +auto CPU::add_clocks(uint clocks) -> void { apu.clock -= clocks; if(apu.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(apu.thread); @@ -36,17 +36,17 @@ void CPU::add_clocks(unsigned clocks) { if(cartridge.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cartridge.thread); } -void CPU::power() { +auto CPU::power() -> void { R6502::power(); - for(unsigned addr = 0; addr < 0x0800; addr++) ram[addr] = 0xff; + for(auto addr : range(0x0800)) ram[addr] = 0xff; ram[0x0008] = 0xf7; ram[0x0009] = 0xef; ram[0x000a] = 0xdf; ram[0x000f] = 0xbf; } -void CPU::reset() { +auto CPU::reset() -> void { R6502::reset(); create(CPU::Enter, 21477272); @@ -71,19 +71,19 @@ void CPU::reset() { status.controller_port1 = 0; } -uint8 CPU::debugger_read(uint16 addr) { +auto CPU::debugger_read(uint16 addr) -> uint8 { return bus.read(addr); } -uint8 CPU::ram_read(uint16 addr) { +auto CPU::ram_read(uint16 addr) -> uint8 { return ram[addr & 0x07ff]; } -void CPU::ram_write(uint16 addr, uint8 data) { +auto CPU::ram_write(uint16 addr, uint8 data) -> void { ram[addr & 0x07ff] = data; } -uint8 CPU::read(uint16 addr) { +auto CPU::read(uint16 addr) -> uint8 { if(addr == 0x4016) { return (mdr() & 0xc0) | input.data(0); } @@ -95,7 +95,7 @@ uint8 CPU::read(uint16 addr) { return apu.read(addr); } -void CPU::write(uint16 addr, uint8 data) { +auto CPU::write(uint16 addr, uint8 data) -> void { if(addr == 0x4014) { status.oam_dma_page = data; status.oam_dma_pending = true; diff --git a/fc/cpu/cpu.hpp b/fc/cpu/cpu.hpp index b265292b..62bab543 100644 --- a/fc/cpu/cpu.hpp +++ b/fc/cpu/cpu.hpp @@ -1,4 +1,37 @@ struct CPU : Processor::R6502, Thread { + static auto Enter() -> void; + auto main() -> void; + auto add_clocks(uint clocks) -> void; + + auto power() -> void; + auto reset() -> void; + + auto debugger_read(uint16 addr) -> uint8; + + auto ram_read(uint16 addr) -> uint8; + auto ram_write(uint16 addr, uint8 data) -> void; + + auto read(uint16 addr) -> uint8; + auto write(uint16 addr, uint8 data) -> void; + + auto serialize(serializer&) -> void; + + //timing.cpp + auto op_read(uint16 addr) -> uint8; + auto op_write(uint16 addr, uint8 data) -> void; + auto last_cycle() -> void; + auto nmi(uint16& vector) -> void; + + auto oam_dma() -> void; + + auto set_nmi_line(bool) -> void; + auto set_irq_line(bool) -> void; + auto set_irq_apu_line(bool) -> void; + + auto set_rdy_line(bool) -> void; + auto set_rdy_addr(bool valid, uint16 value = 0) -> void; + +//protected: uint8 ram[0x0800]; struct Status { @@ -16,41 +49,9 @@ struct CPU : Processor::R6502, Thread { uint8 oam_dma_page; bool controller_latch; - unsigned controller_port0; - unsigned controller_port1; + uint controller_port0; + uint controller_port1; } status; - - static void Enter(); - void main(); - void add_clocks(unsigned clocks); - - void power(); - void reset(); - - uint8 debugger_read(uint16 addr); - - uint8 ram_read(uint16 addr); - void ram_write(uint16 addr, uint8 data); - - uint8 read(uint16 addr); - void write(uint16 addr, uint8 data); - - void serialize(serializer&); - - //timing.cpp - uint8 op_read(uint16 addr); - void op_write(uint16 addr, uint8 data); - void last_cycle(); - void nmi(uint16 &vector); - - void oam_dma(); - - void set_nmi_line(bool); - void set_irq_line(bool); - void set_irq_apu_line(bool); - - void set_rdy_line(bool); - void set_rdy_addr(bool valid, uint16 value = 0); }; extern CPU cpu; diff --git a/fc/cpu/serialization.cpp b/fc/cpu/serialization.cpp index 833453e7..84c7d5d9 100644 --- a/fc/cpu/serialization.cpp +++ b/fc/cpu/serialization.cpp @@ -1,4 +1,4 @@ -void CPU::serialize(serializer& s) { +auto CPU::serialize(serializer& s) -> void { R6502::serialize(s); Thread::serialize(s); diff --git a/fc/cpu/timing.cpp b/fc/cpu/timing.cpp index 86547105..7ced27e1 100644 --- a/fc/cpu/timing.cpp +++ b/fc/cpu/timing.cpp @@ -1,4 +1,4 @@ -uint8 CPU::op_read(uint16 addr) { +auto CPU::op_read(uint16 addr) -> uint8 { if(status.oam_dma_pending) { status.oam_dma_pending = false; op_read(addr); @@ -15,50 +15,50 @@ uint8 CPU::op_read(uint16 addr) { return regs.mdr; } -void CPU::op_write(uint16 addr, uint8 data) { +auto CPU::op_write(uint16 addr, uint8 data) -> void { bus.write(addr, regs.mdr = data); add_clocks(12); } -void CPU::last_cycle() { +auto CPU::last_cycle() -> void { status.interrupt_pending = ((status.irq_line | status.irq_apu_line) & ~regs.p.i) | status.nmi_pending; } -void CPU::nmi(uint16 &vector) { +auto CPU::nmi(uint16& vector) -> void { if(status.nmi_pending) { status.nmi_pending = false; vector = 0xfffa; } } -void CPU::oam_dma() { - for(unsigned n = 0; n < 256; n++) { +auto CPU::oam_dma() -> void { + for(uint n : range(256)) { uint8 data = op_read((status.oam_dma_page << 8) + n); op_write(0x2004, data); } } -void CPU::set_nmi_line(bool line) { +auto CPU::set_nmi_line(bool line) -> void { //edge-sensitive (0->1) if(!status.nmi_line && line) status.nmi_pending = true; status.nmi_line = line; } -void CPU::set_irq_line(bool line) { +auto CPU::set_irq_line(bool line) -> void { //level-sensitive status.irq_line = line; } -void CPU::set_irq_apu_line(bool line) { +auto CPU::set_irq_apu_line(bool line) -> void { //level-sensitive status.irq_apu_line = line; } -void CPU::set_rdy_line(bool line) { +auto CPU::set_rdy_line(bool line) -> void { status.rdy_line = line; } -void CPU::set_rdy_addr(bool valid, uint16 value) { +auto CPU::set_rdy_addr(bool valid, uint16 value) -> void { status.rdy_addr_valid = valid; status.rdy_addr_value = value; } diff --git a/fc/input/input.cpp b/fc/input/input.cpp index 31c6b156..b2b235a2 100644 --- a/fc/input/input.cpp +++ b/fc/input/input.cpp @@ -5,7 +5,7 @@ namespace Famicom { #include "serialization.cpp" Input input; -void Input::latch(bool data) { +auto Input::latch(bool data) -> void { latchdata = data; if(latchdata == 1) { @@ -14,7 +14,7 @@ void Input::latch(bool data) { } } -bool Input::data(bool port) { +auto Input::data(bool port) -> bool { bool result = 0; if(port == 0) { @@ -36,15 +36,15 @@ bool Input::data(bool port) { return result; } -void Input::connect(bool port, Device device) { +auto Input::connect(bool port, Device device) -> void { if(port == 0) port1 = device, counter1 = 0; if(port == 1) port2 = device, counter2 = 0; } -void Input::power() { +auto Input::power() -> void { } -void Input::reset() { +auto Input::reset() -> void { latchdata = 0; counter1 = 0; counter2 = 0; diff --git a/fc/input/input.hpp b/fc/input/input.hpp index 8e424761..735f2b9c 100644 --- a/fc/input/input.hpp +++ b/fc/input/input.hpp @@ -1,25 +1,25 @@ struct Input { - enum class Device : unsigned { + enum class Device : uint { Joypad, None, }; - void latch(bool data); - bool data(bool port); - void connect(bool port, Device device); + auto latch(bool data) -> void; + auto data(bool port) -> bool; + auto connect(bool port, Device device) -> void; - void power(); - void reset(); + auto power() -> void; + auto reset() -> void; - void serialize(serializer&); + auto serialize(serializer&) -> void; private: Device port1; Device port2; bool latchdata; - unsigned counter1; - unsigned counter2; + uint counter1; + uint counter2; }; extern Input input; diff --git a/fc/input/serialization.cpp b/fc/input/serialization.cpp index c0eb132f..643841ca 100644 --- a/fc/input/serialization.cpp +++ b/fc/input/serialization.cpp @@ -1,6 +1,6 @@ -void Input::serialize(serializer& s) { - s.integer((unsigned&)port1); - s.integer((unsigned&)port2); +auto Input::serialize(serializer& s) -> void { + s.integer((uint&)port1); + s.integer((uint&)port2); s.integer(latchdata); s.integer(counter1); diff --git a/fc/interface/interface.cpp b/fc/interface/interface.cpp index e495a48d..1e66f50d 100644 --- a/fc/interface/interface.cpp +++ b/fc/interface/interface.cpp @@ -4,27 +4,66 @@ namespace Famicom { Interface* interface = nullptr; -string Interface::title() { +Interface::Interface() { + interface = this; + + information.name = "Famicom"; + information.width = 256; + information.height = 240; + information.overscan = true; + information.aspectRatio = 8.0 / 7.0; + information.resettable = true; + information.capability.states = true; + information.capability.cheats = true; + + media.append({ID::Famicom, "Famicom", "fc", true}); + + { Device device{0, ID::Port1 | ID::Port2, "Controller"}; + device.input.append({0, 0, "A" }); + device.input.append({1, 0, "B" }); + device.input.append({2, 0, "Select"}); + device.input.append({3, 0, "Start" }); + device.input.append({4, 0, "Up" }); + device.input.append({5, 0, "Down" }); + device.input.append({6, 0, "Left" }); + device.input.append({7, 0, "Right" }); + device.order = {4, 5, 6, 7, 1, 0, 2, 3}; + this->device.append(device); + } + + port.append({0, "Port 1"}); + port.append({1, "Port 2"}); + + for(auto& device : this->device) { + for(auto& port : this->port) { + if(device.portmask & (1 << port.id)) { + port.device.append(device); + } + } + } +} + +auto Interface::title() -> string { return cartridge.title(); } -double Interface::videoFrequency() { +auto Interface::videoFrequency() -> double { return 21477272.0 / (262.0 * 1364.0 - 4.0); } -double Interface::audioFrequency() { +auto Interface::audioFrequency() -> double { return 21477272.0 / 12.0; } -bool Interface::loaded() { +auto Interface::loaded() -> bool { return cartridge.loaded(); } -string Interface::sha256() { +auto Interface::sha256() -> string { return cartridge.sha256(); } -unsigned Interface::group(unsigned id) { +auto Interface::group(uint id) -> uint { switch(id) { case ID::SystemManifest: return 0; @@ -39,17 +78,17 @@ unsigned Interface::group(unsigned id) { throw; } -void Interface::load(unsigned id) { +auto Interface::load(uint id) -> void { cartridge.load(); } -void Interface::save() { +auto Interface::save() -> void { for(auto& memory : cartridge.memory) { saveRequest(memory.id, memory.name); } } -void Interface::load(unsigned id, const stream& stream) { +auto Interface::load(uint id, const stream& stream) -> void { if(id == ID::SystemManifest) { system.information.manifest = stream.text(); } @@ -75,7 +114,7 @@ void Interface::load(unsigned id, const stream& stream) { } } -void Interface::save(unsigned id, const stream& stream) { +auto Interface::save(uint id, const stream& stream) -> void { if(id == ID::ProgramRAM) { stream.write(cartridge.board->prgram.data, cartridge.board->prgram.size); } @@ -85,33 +124,33 @@ void Interface::save(unsigned id, const stream& stream) { } } -void Interface::unload() { +auto Interface::unload() -> void { save(); cartridge.unload(); } -void Interface::power() { +auto Interface::power() -> void { system.power(); } -void Interface::reset() { +auto Interface::reset() -> void { system.reset(); } -void Interface::run() { +auto Interface::run() -> void { system.run(); } -serializer Interface::serialize() { +auto Interface::serialize() -> serializer { system.runtosave(); return system.serialize(); } -bool Interface::unserialize(serializer& s) { +auto Interface::unserialize(serializer& s) -> bool { return system.unserialize(s); } -void Interface::cheatSet(const lstring& list) { +auto Interface::cheatSet(const lstring& list) -> void { cheat.reset(); for(auto& codeset : list) { lstring codes = codeset.split("+"); @@ -123,48 +162,8 @@ void Interface::cheatSet(const lstring& list) { } } -void Interface::paletteUpdate(PaletteMode mode) { +auto Interface::paletteUpdate(PaletteMode mode) -> void { video.generate_palette(mode); } -Interface::Interface() { - interface = this; - - information.name = "Famicom"; - information.width = 256; - information.height = 240; - information.overscan = true; - information.aspectRatio = 8.0 / 7.0; - information.resettable = true; - information.capability.states = true; - information.capability.cheats = true; - - media.append({ID::Famicom, "Famicom", "fc", true}); - - { - Device device{0, ID::Port1 | ID::Port2, "Controller"}; - device.input.append({0, 0, "A" }); - device.input.append({1, 0, "B" }); - device.input.append({2, 0, "Select"}); - device.input.append({3, 0, "Start" }); - device.input.append({4, 0, "Up" }); - device.input.append({5, 0, "Down" }); - device.input.append({6, 0, "Left" }); - device.input.append({7, 0, "Right" }); - device.order = {4, 5, 6, 7, 1, 0, 2, 3}; - this->device.append(device); - } - - port.append({0, "Port 1"}); - port.append({1, "Port 2"}); - - for(auto& device : this->device) { - for(auto& port : this->port) { - if(device.portmask & (1 << port.id)) { - port.device.append(device); - } - } - } -} - } diff --git a/fc/interface/interface.hpp b/fc/interface/interface.hpp index 9e5c1a78..0fb1f394 100644 --- a/fc/interface/interface.hpp +++ b/fc/interface/interface.hpp @@ -3,12 +3,12 @@ namespace Famicom { #endif struct ID { - enum : unsigned { + enum : uint { System, Famicom, }; - enum : unsigned { + enum : uint { SystemManifest, Manifest, @@ -18,39 +18,39 @@ struct ID { CharacterRAM, }; - enum : unsigned { + enum : uint { Port1 = 1, Port2 = 2, }; }; struct Interface : Emulator::Interface { - string title(); - double videoFrequency(); - double audioFrequency(); - - bool loaded(); - string sha256(); - unsigned group(unsigned id); - void load(unsigned id); - void save(); - void load(unsigned id, const stream& stream); - void save(unsigned id, const stream& stream); - void unload(); - - void power(); - void reset(); - void run(); - - serializer serialize(); - bool unserialize(serializer&); - - void cheatSet(const lstring&); - - void paletteUpdate(PaletteMode mode); - Interface(); + auto title() -> string; + auto videoFrequency() -> double; + auto audioFrequency() -> double; + + auto loaded() -> bool; + auto sha256() -> string; + auto group(uint id) -> uint; + auto load(uint id) -> void; + auto save() -> void; + auto load(uint id, const stream& stream) -> void; + auto save(uint id, const stream& stream) -> void; + auto unload() -> void; + + auto power() -> void; + auto reset() -> void; + auto run() -> void; + + auto serialize() -> serializer; + auto unserialize(serializer&) -> bool; + + auto cheatSet(const lstring&) -> void; + + auto paletteUpdate(PaletteMode mode) -> void; + private: vector device; }; diff --git a/fc/memory/memory.cpp b/fc/memory/memory.cpp index 0e7d1d15..f6c576fb 100644 --- a/fc/memory/memory.cpp +++ b/fc/memory/memory.cpp @@ -11,7 +11,7 @@ Bus bus; //$4000-4017 = APU + I/O //$4018-ffff = Cartridge -uint8 Bus::read(uint16 addr) { +auto Bus::read(uint16 addr) -> uint8 { uint8 data = cartridge.prg_read(addr); if(addr <= 0x1fff) data = cpu.ram_read(addr); else if(addr <= 0x3fff) data = ppu.read(addr); @@ -24,7 +24,7 @@ uint8 Bus::read(uint16 addr) { return data; } -void Bus::write(uint16 addr, uint8 data) { +auto Bus::write(uint16 addr, uint8 data) -> void { cartridge.prg_write(addr, data); if(addr <= 0x1fff) return cpu.ram_write(addr, data); if(addr <= 0x3fff) return ppu.write(addr, data); diff --git a/fc/memory/memory.hpp b/fc/memory/memory.hpp index 6ee5a463..5a9596a9 100644 --- a/fc/memory/memory.hpp +++ b/fc/memory/memory.hpp @@ -1,6 +1,6 @@ struct Bus { - uint8 read(uint16 addr); - void write(uint16 addr, uint8 data); + auto read(uint16 addr) -> uint8; + auto write(uint16 addr, uint8 data) -> void; }; extern Bus bus; diff --git a/fc/ppu/ppu.cpp b/fc/ppu/ppu.cpp index b4de38a5..53b9b7e2 100644 --- a/fc/ppu/ppu.cpp +++ b/fc/ppu/ppu.cpp @@ -5,11 +5,11 @@ namespace Famicom { #include "serialization.cpp" PPU ppu; -void PPU::Main() { +auto PPU::Main() -> void { ppu.main(); } -void PPU::main() { +auto PPU::main() -> void { while(true) { if(scheduler.sync == Scheduler::SynchronizeMode::PPU) { scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); @@ -19,7 +19,7 @@ void PPU::main() { } } -void PPU::tick() { +auto PPU::tick() -> void { if(status.ly == 240 && status.lx == 340) status.nmi_hold = 1; if(status.ly == 241 && status.lx == 0) status.nmi_flag = status.nmi_hold; if(status.ly == 241 && status.lx == 2) cpu.set_nmi_line(status.nmi_enable && status.nmi_flag); @@ -36,7 +36,7 @@ void PPU::tick() { status.lx++; } -void PPU::scanline() { +auto PPU::scanline() -> void { status.lx = 0; if(++status.ly == 262) { status.ly = 0; @@ -45,15 +45,15 @@ void PPU::scanline() { cartridge.scanline(status.ly); } -void PPU::frame() { +auto PPU::frame() -> void { status.field ^= 1; scheduler.exit(Scheduler::ExitReason::FrameEvent); } -void PPU::power() { +auto PPU::power() -> void { } -void PPU::reset() { +auto PPU::reset() -> void { create(PPU::Main, 21477272); status.mdr = 0x00; @@ -98,7 +98,7 @@ void PPU::reset() { for(auto& n : oam ) n = 0; } -uint8 PPU::read(uint16 addr) { +auto PPU::read(uint16 addr) -> uint8 { uint8 result = 0x00; switch(addr & 7) { @@ -136,7 +136,7 @@ uint8 PPU::read(uint16 addr) { return result; } -void PPU::write(uint16 addr, uint8 data) { +auto PPU::write(uint16 addr, uint8 data) -> void { status.mdr = data; switch(addr & 7) { @@ -200,22 +200,22 @@ void PPU::write(uint16 addr, uint8 data) { } } -uint8 PPU::ciram_read(uint16 addr) { +auto PPU::ciram_read(uint16 addr) -> uint8 { return ciram[addr & 0x07ff]; } -void PPU::ciram_write(uint16 addr, uint8 data) { +auto PPU::ciram_write(uint16 addr, uint8 data) -> void { ciram[addr & 0x07ff] = data; } -uint8 PPU::cgram_read(uint16 addr) { +auto PPU::cgram_read(uint16 addr) -> uint8 { if((addr & 0x13) == 0x10) addr &= ~0x10; uint8 data = cgram[addr & 0x1f]; if(status.grayscale) data &= 0x30; return data; } -void PPU::cgram_write(uint16 addr, uint8 data) { +auto PPU::cgram_write(uint16 addr, uint8 data) -> void { if((addr & 0x13) == 0x10) addr &= ~0x10; cgram[addr & 0x1f] = data; } @@ -229,36 +229,36 @@ void PPU::cgram_write(uint16 addr, uint8 data) { //YYYYY = Y nametable (y:d3-d7) //XXXXX = X nametable (x:d3-d7) -bool PPU::raster_enable() const { +auto PPU::raster_enable() const -> bool { return (status.bg_enable || status.sprite_enable); } -unsigned PPU::nametable_addr() const { +auto PPU::nametable_addr() const -> uint { return 0x2000 + (status.vaddr & 0x0c00); } -unsigned PPU::scrollx() const { +auto PPU::scrollx() const -> uint { return ((status.vaddr & 0x1f) << 3) | status.xaddr; } -unsigned PPU::scrolly() const { +auto PPU::scrolly() const -> uint { return (((status.vaddr >> 5) & 0x1f) << 3) | ((status.vaddr >> 12) & 7); } -unsigned PPU::sprite_height() const { +auto PPU::sprite_height() const -> uint { return status.sprite_size == 0 ? 8 : 16; } // -uint8 PPU::chr_load(uint16 addr) { +auto PPU::chr_load(uint16 addr) -> uint8 { if(raster_enable() == false) return 0x00; return cartridge.chr_read(addr); } // -void PPU::scrollx_increment() { +auto PPU::scrollx_increment() -> void { if(raster_enable() == false) return; status.vaddr = (status.vaddr & 0x7fe0) | ((status.vaddr + 0x0001) & 0x001f); if((status.vaddr & 0x001f) == 0x0000) { @@ -266,7 +266,7 @@ void PPU::scrollx_increment() { } } -void PPU::scrolly_increment() { +auto PPU::scrolly_increment() -> void { if(raster_enable() == false) return; status.vaddr = (status.vaddr & 0x0fff) | ((status.vaddr + 0x1000) & 0x7000); if((status.vaddr & 0x7000) == 0x0000) { @@ -280,16 +280,16 @@ void PPU::scrolly_increment() { // -void PPU::raster_pixel() { +auto PPU::raster_pixel() -> void { uint32* output = buffer + status.ly * 256; - unsigned mask = 0x8000 >> (status.xaddr + (status.lx & 7)); - unsigned palette = 0, object_palette = 0; + uint mask = 0x8000 >> (status.xaddr + (status.lx & 7)); + uint palette = 0, object_palette = 0; bool object_priority = 0; palette |= (raster.tiledatalo & mask) ? 1 : 0; palette |= (raster.tiledatahi & mask) ? 2 : 0; if(palette) { - unsigned attr = raster.attribute; + uint attr = raster.attribute; if(mask >= 256) attr >>= 2; palette |= (attr & 3) << 2; } @@ -298,16 +298,16 @@ void PPU::raster_pixel() { if(status.bg_edge_enable == false && status.lx < 8) palette = 0; if(status.sprite_enable == true) - for(signed sprite = 7; sprite >= 0; sprite--) { + for(int sprite = 7; sprite >= 0; sprite--) { if(status.sprite_edge_enable == false && status.lx < 8) continue; if(raster.oam[sprite].id == 64) continue; - unsigned spritex = status.lx - raster.oam[sprite].x; + uint spritex = status.lx - raster.oam[sprite].x; if(spritex >= 8) continue; if(raster.oam[sprite].attr & 0x40) spritex ^= 7; - unsigned mask = 0x80 >> spritex; - unsigned sprite_palette = 0; + uint mask = 0x80 >> spritex; + uint sprite_palette = 0; sprite_palette |= (raster.oam[sprite].tiledatalo & mask) ? 1 : 0; sprite_palette |= (raster.oam[sprite].tiledatahi & mask) ? 2 : 0; if(sprite_palette == 0) continue; @@ -327,12 +327,12 @@ void PPU::raster_pixel() { output[status.lx] = (status.emphasis << 6) | cgram_read(palette); } -void PPU::raster_sprite() { +auto PPU::raster_sprite() -> void { if(raster_enable() == false) return; - unsigned n = raster.oam_iterator++; - signed ly = (status.ly == 261 ? -1 : status.ly); - unsigned y = ly - oam[(n * 4) + 0]; + uint n = raster.oam_iterator++; + int ly = (status.ly == 261 ? -1 : status.ly); + uint y = ly - oam[(n * 4) + 0]; if(y >= sprite_height()) return; if(raster.oam_counter == 8) { @@ -348,16 +348,16 @@ void PPU::raster_sprite() { raster.oam_counter++; } -void PPU::raster_scanline() { +auto PPU::raster_scanline() -> void { if((status.ly >= 240 && status.ly <= 260)) { - for(unsigned x = 0; x < 341; x++) tick(); + for(auto x : range(341)) tick(); return scanline(); } raster.oam_iterator = 0; raster.oam_counter = 0; - for(unsigned n = 0; n < 8; n++) { + for(auto n : range(8)) { raster.soam[n].id = 64; raster.soam[n].y = 0xff; raster.soam[n].tile = 0xff; @@ -367,16 +367,16 @@ void PPU::raster_scanline() { raster.soam[n].tiledatahi = 0; } - for(unsigned tile = 0; tile < 32; tile++) { // 0-255 - unsigned nametable = chr_load(0x2000 | (status.vaddr & 0x0fff)); - unsigned tileaddr = status.bg_addr + (nametable << 4) + (scrolly() & 7); + for(uint tile : range(32)) { // 0-255 + uint nametable = chr_load(0x2000 | (status.vaddr & 0x0fff)); + uint tileaddr = status.bg_addr + (nametable << 4) + (scrolly() & 7); raster_pixel(); tick(); raster_pixel(); tick(); - unsigned attribute = chr_load(0x23c0 | (status.vaddr & 0x0fc0) | ((scrolly() >> 5) << 3) | (scrollx() >> 5)); + uint attribute = chr_load(0x23c0 | (status.vaddr & 0x0fc0) | ((scrolly() >> 5) << 3) | (scrollx() >> 5)); if(scrolly() & 16) attribute >>= 4; if(scrollx() & 16) attribute >>= 2; raster_pixel(); @@ -388,14 +388,14 @@ void PPU::raster_scanline() { raster_sprite(); tick(); - unsigned tiledatalo = chr_load(tileaddr + 0); + uint tiledatalo = chr_load(tileaddr + 0); raster_pixel(); tick(); raster_pixel(); tick(); - unsigned tiledatahi = chr_load(tileaddr + 8); + uint tiledatahi = chr_load(tileaddr + 8); raster_pixel(); tick(); @@ -409,23 +409,23 @@ void PPU::raster_scanline() { raster.tiledatahi = (raster.tiledatahi << 8) | tiledatahi; } - for(unsigned n = 0; n < 8; n++) raster.oam[n] = raster.soam[n]; + for(auto n : range(8)) raster.oam[n] = raster.soam[n]; - for(unsigned sprite = 0; sprite < 8; sprite++) { //256-319 - unsigned nametable = chr_load(0x2000 | (status.vaddr & 0x0fff)); + for(uint sprite : range(8)) { //256-319 + uint nametable = chr_load(0x2000 | (status.vaddr & 0x0fff)); tick(); if(raster_enable() && sprite == 0) status.vaddr = (status.vaddr & 0x7be0) | (status.taddr & 0x041f); //257 tick(); - unsigned attribute = chr_load(0x23c0 | (status.vaddr & 0x0fc0) | ((scrolly() >> 5) << 3) | (scrollx() >> 5)); - unsigned tileaddr = (sprite_height() == 8) + uint attribute = chr_load(0x23c0 | (status.vaddr & 0x0fc0) | ((scrolly() >> 5) << 3) | (scrollx() >> 5)); + uint tileaddr = (sprite_height() == 8) ? status.sprite_addr + raster.oam[sprite].tile * 16 : ((raster.oam[sprite].tile & ~1) * 16) + ((raster.oam[sprite].tile & 1) * 0x1000); tick(); tick(); - unsigned spritey = (status.ly - raster.oam[sprite].y) & (sprite_height() - 1); + uint spritey = (status.ly - raster.oam[sprite].y) & (sprite_height() - 1); if(raster.oam[sprite].attr & 0x80) spritey ^= (sprite_height() - 1); tileaddr += spritey + (spritey & 8); @@ -440,13 +440,13 @@ void PPU::raster_scanline() { if(raster_enable() && sprite == 6 && status.ly == 261) status.vaddr = status.taddr; //304 } - for(unsigned tile = 0; tile < 2; tile++) { //320-335 - unsigned nametable = chr_load(0x2000 | (status.vaddr & 0x0fff)); - unsigned tileaddr = status.bg_addr + (nametable << 4) + (scrolly() & 7); + for(uint tile : range(2)) { //320-335 + uint nametable = chr_load(0x2000 | (status.vaddr & 0x0fff)); + uint tileaddr = status.bg_addr + (nametable << 4) + (scrolly() & 7); tick(); tick(); - unsigned attribute = chr_load(0x23c0 | (status.vaddr & 0x0fc0) | ((scrolly() >> 5) << 3) | (scrollx() >> 5)); + uint attribute = chr_load(0x23c0 | (status.vaddr & 0x0fc0) | ((scrolly() >> 5) << 3) | (scrollx() >> 5)); if(scrolly() & 16) attribute >>= 4; if(scrollx() & 16) attribute >>= 2; tick(); @@ -454,11 +454,11 @@ void PPU::raster_scanline() { scrollx_increment(); tick(); - unsigned tiledatalo = chr_load(tileaddr + 0); + uint tiledatalo = chr_load(tileaddr + 0); tick(); tick(); - unsigned tiledatahi = chr_load(tileaddr + 8); + uint tiledatahi = chr_load(tileaddr + 8); tick(); tick(); diff --git a/fc/ppu/ppu.hpp b/fc/ppu/ppu.hpp index 0a7cca0a..4ad53455 100644 --- a/fc/ppu/ppu.hpp +++ b/fc/ppu/ppu.hpp @@ -1,46 +1,46 @@ struct PPU : Thread { - static void Main(); - void main(); - void tick(); + static auto Main() -> void; + auto main() -> void; + auto tick() -> void; - void scanline(); - void frame(); + auto scanline() -> void; + auto frame() -> void; - void power(); - void reset(); + auto power() -> void; + auto reset() -> void; - uint8 read(uint16 addr); - void write(uint16 addr, uint8 data); + auto read(uint16 addr) -> uint8; + auto write(uint16 addr, uint8 data) -> void; - uint8 ciram_read(uint16 addr); - void ciram_write(uint16 addr, uint8 data); + auto ciram_read(uint16 addr) -> uint8; + auto ciram_write(uint16 addr, uint8 data) -> void; - uint8 cgram_read(uint16 addr); - void cgram_write(uint16 addr, uint8 data); + auto cgram_read(uint16 addr) -> uint8; + auto cgram_write(uint16 addr, uint8 data) -> void; - bool raster_enable() const; - unsigned nametable_addr() const; - unsigned scrollx() const; - unsigned scrolly() const; - unsigned sprite_height() const; + auto raster_enable() const -> bool; + auto nametable_addr() const -> uint; + auto scrollx() const -> uint; + auto scrolly() const -> uint; + auto sprite_height() const -> uint; - uint8 chr_load(uint16 addr); + auto chr_load(uint16 addr) -> uint8; - void scrollx_increment(); - void scrolly_increment(); + auto scrollx_increment() -> void; + auto scrolly_increment() -> void; - void raster_pixel(); - void raster_sprite(); - void raster_scanline(); + auto raster_pixel() -> void; + auto raster_sprite() -> void; + auto raster_scanline() -> void; - void serialize(serializer&); + auto serialize(serializer&) -> void; struct Status { uint8 mdr; bool field; - unsigned lx; - unsigned ly; + uint lx; + uint ly; uint8 bus_data; @@ -57,9 +57,9 @@ struct PPU : Thread { bool nmi_enable; bool master_select; bool sprite_size; - unsigned bg_addr; - unsigned sprite_addr; - unsigned vram_increment; + uint bg_addr; + uint sprite_addr; + uint vram_increment; //$2001 uint3 emphasis; @@ -83,8 +83,8 @@ struct PPU : Thread { uint16 tiledatalo; uint16 tiledatahi; - unsigned oam_iterator; - unsigned oam_counter; + uint oam_iterator; + uint oam_counter; struct OAM { uint8 id; diff --git a/fc/ppu/serialization.cpp b/fc/ppu/serialization.cpp index 12b17a8c..63123d8f 100644 --- a/fc/ppu/serialization.cpp +++ b/fc/ppu/serialization.cpp @@ -1,4 +1,4 @@ -void PPU::serialize(serializer& s) { +auto PPU::serialize(serializer& s) -> void { Thread::serialize(s); s.integer(status.mdr); @@ -45,7 +45,7 @@ void PPU::serialize(serializer& s) { s.integer(raster.oam_iterator); s.integer(raster.oam_counter); - for(unsigned n = 0; n < 8; n++) { + for(auto n : range(8)) { s.integer(raster.oam[n].id); s.integer(raster.oam[n].y); s.integer(raster.oam[n].tile); @@ -56,7 +56,7 @@ void PPU::serialize(serializer& s) { s.integer(raster.oam[n].tiledatahi); } - for(unsigned n = 0; n < 8; n++) { + for(auto n : range(8)) { s.integer(raster.soam[n].id); s.integer(raster.soam[n].y); s.integer(raster.soam[n].tile); diff --git a/fc/scheduler/scheduler.cpp b/fc/scheduler/scheduler.cpp index ee565a26..8df229a1 100644 --- a/fc/scheduler/scheduler.cpp +++ b/fc/scheduler/scheduler.cpp @@ -4,21 +4,21 @@ namespace Famicom { Scheduler scheduler; -void Scheduler::enter() { +auto Scheduler::enter() -> void { host_thread = co_active(); co_switch(thread); } -void Scheduler::exit(ExitReason reason) { +auto Scheduler::exit(ExitReason reason) -> void { exit_reason = reason; thread = co_active(); co_switch(host_thread); } -void Scheduler::power() { +auto Scheduler::power() -> void { } -void Scheduler::reset() { +auto Scheduler::reset() -> void { host_thread = co_active(); thread = cpu.thread; sync = SynchronizeMode::None; diff --git a/fc/scheduler/scheduler.hpp b/fc/scheduler/scheduler.hpp index 518a5d45..7a111857 100644 --- a/fc/scheduler/scheduler.hpp +++ b/fc/scheduler/scheduler.hpp @@ -1,16 +1,16 @@ struct Scheduler : property { - enum class SynchronizeMode : unsigned { None, PPU, All } sync; - enum class ExitReason : unsigned { UnknownEvent, FrameEvent, SynchronizeEvent }; - readonly exit_reason; + enum class SynchronizeMode : uint { None, PPU, All } sync; + enum class ExitReason : uint { UnknownEvent, FrameEvent, SynchronizeEvent }; + + auto enter() -> void; + auto exit(ExitReason) -> void; + + auto power() -> void; + auto reset() -> void; cothread_t host_thread; //program thread (used to exit emulation) cothread_t thread; //active emulation thread (used to enter emulation) - - void enter(); - void exit(ExitReason); - - void power(); - void reset(); + readonly exit_reason; }; extern Scheduler scheduler; diff --git a/fc/system/serialization.cpp b/fc/system/serialization.cpp index 1d2c750f..da5a5d2e 100644 --- a/fc/system/serialization.cpp +++ b/fc/system/serialization.cpp @@ -1,7 +1,7 @@ -serializer System::serialize() { +auto System::serialize() -> serializer { serializer s(serialize_size); - unsigned signature = 0x31545342, version = Info::SerializerVersion; + uint signature = 0x31545342, version = Info::SerializerVersion; char hash[64], description[512]; memcpy(&hash, (const char*)cartridge.sha256(), 64); memset(&description, 0, sizeof description); @@ -15,8 +15,8 @@ serializer System::serialize() { return s; } -bool System::unserialize(serializer& s) { - unsigned signature, version; +auto System::unserialize(serializer& s) -> bool { + uint signature, version; char hash[64], description[512]; s.integer(signature); @@ -32,10 +32,10 @@ bool System::unserialize(serializer& s) { return true; } -void System::serialize(serializer& s) { +auto System::serialize(serializer& s) -> void { } -void System::serialize_all(serializer& s) { +auto System::serialize_all(serializer& s) -> void { system.serialize(s); input.serialize(s); cartridge.serialize(s); @@ -44,10 +44,10 @@ void System::serialize_all(serializer& s) { ppu.serialize(s); } -void System::serialize_init() { +auto System::serialize_init() -> void { serializer s; - unsigned signature = 0, version = 0; + uint signature = 0, version = 0; char hash[64], description[512]; s.integer(signature); diff --git a/fc/system/system.cpp b/fc/system/system.cpp index 2de228c9..667447d5 100644 --- a/fc/system/system.cpp +++ b/fc/system/system.cpp @@ -5,14 +5,14 @@ namespace Famicom { #include "serialization.cpp" System system; -void System::run() { +auto System::run() -> void { scheduler.enter(); if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) { interface->videoRefresh(video.palette, ppu.buffer, 4 * 256, 256, 240); } } -void System::runtosave() { +auto System::runtosave() -> void { scheduler.sync = Scheduler::SynchronizeMode::PPU; runthreadtosave(); @@ -31,7 +31,7 @@ void System::runtosave() { scheduler.sync = Scheduler::SynchronizeMode::None; } -void System::runthreadtosave() { +auto System::runthreadtosave() -> void { while(true) { scheduler.enter(); if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break; @@ -41,14 +41,14 @@ void System::runthreadtosave() { } } -void System::load() { +auto System::load() -> void { interface->loadRequest(ID::SystemManifest, "manifest.bml", true); auto document = BML::unserialize(information.manifest); serialize_init(); } -void System::power() { +auto System::power() -> void { cartridge.power(); cpu.power(); apu.power(); @@ -58,7 +58,7 @@ void System::power() { reset(); } -void System::reset() { +auto System::reset() -> void { cartridge.reset(); cpu.reset(); apu.reset(); @@ -67,13 +67,13 @@ void System::reset() { scheduler.reset(); } -void System::init() { +auto System::init() -> void { assert(interface != 0); input.connect(0, Input::Device::Joypad); input.connect(1, Input::Device::None); } -void System::term() { +auto System::term() -> void { } } diff --git a/fc/system/system.hpp b/fc/system/system.hpp index bda553a9..728103d0 100644 --- a/fc/system/system.hpp +++ b/fc/system/system.hpp @@ -1,26 +1,27 @@ struct System { - void run(); - void runtosave(); - void runthreadtosave(); + auto run() -> void; + auto runtosave() -> void; + auto runthreadtosave() -> void; - void load(); - void power(); - void reset(); + auto load() -> void; + auto power() -> void; + auto reset() -> void; - void init(); - void term(); + auto init() -> void; + auto term() -> void; - serializer serialize(); - bool unserialize(serializer&); + auto serialize() -> serializer; + auto unserialize(serializer&) -> bool; - void serialize(serializer&); - void serialize_all(serializer&); - void serialize_init(); - unsigned serialize_size; + auto serialize(serializer&) -> void; + auto serialize_all(serializer&) -> void; + auto serialize_init() -> void; struct Information { string manifest; } information; + + uint serialize_size; }; extern System system; diff --git a/fc/video/video.cpp b/fc/video/video.cpp index bdb476a0..36ce5846 100644 --- a/fc/video/video.cpp +++ b/fc/video/video.cpp @@ -6,14 +6,22 @@ namespace Famicom { Video video; -void Video::generate_palette(Emulator::Interface::PaletteMode mode) { - for(unsigned color = 0; color < (1 << 9); color++) { +Video::Video() { + palette = new uint32_t[1 << 9](); +} + +Video::~Video() { + delete[] palette; +} + +auto Video::generate_palette(Emulator::Interface::PaletteMode mode) -> void { + for(auto color : range(1 << 9)) { if(mode == Emulator::Interface::PaletteMode::Literal) { palette[color] = color; } else if(mode == Emulator::Interface::PaletteMode::Channel) { - unsigned emphasis = (color >> 6) & 7; - unsigned luma = (color >> 4) & 3; - unsigned chroma = (color >> 0) & 15; + uint emphasis = (color >> 6) & 7; + uint luma = (color >> 4) & 3; + uint chroma = (color >> 0) & 15; emphasis = image::normalize(emphasis, 3, 16); luma = image::normalize(luma, 2, 16); chroma = image::normalize(chroma, 4, 16); @@ -26,19 +34,11 @@ void Video::generate_palette(Emulator::Interface::PaletteMode mode) { } } -Video::Video() { - palette = new uint32_t[1 << 9](); -} - -Video::~Video() { - delete[] palette; -} - -uint32_t Video::generate_color( - unsigned n, double saturation, double hue, +auto Video::generate_color( + uint n, double saturation, double hue, double contrast, double brightness, double gamma -) { - signed color = (n & 0x0f), level = color < 0xe ? (n >> 4) & 3 : 1; +) -> uint32 { + int color = (n & 0x0f), level = color < 0xe ? (n >> 4) & 3 : 1; static const double black = 0.518, white = 1.962, attenuation = 0.746; static const double levels[8] = { @@ -52,8 +52,8 @@ uint32_t Video::generate_color( }; double y = 0.0, i = 0.0, q = 0.0; - auto wave = [](signed p, signed color) { return (color + p + 8) % 12 < 6; }; - for(signed p = 0; p < 12; p++) { + auto wave = [](int p, int color) { return (color + p + 8) % 12 < 6; }; + for(int p : range(12)) { double spot = lo_and_hi[wave(p, color)]; if(((n & 0x040) && wave(p, 12)) @@ -75,9 +75,9 @@ uint32_t Video::generate_color( q *= saturation; auto gammaAdjust = [=](double f) { return f < 0.0 ? 0.0 : std::pow(f, 2.2 / gamma); }; - unsigned r = 65535.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q); - unsigned g = 65535.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q); - unsigned b = 65535.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q); + uint r = 65535.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q); + uint g = 65535.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q); + uint b = 65535.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q); return interface->videoColor(n, 0, uclamp<16>(r), uclamp<16>(g), uclamp<16>(b)); } diff --git a/fc/video/video.hpp b/fc/video/video.hpp index f49930ba..7a2ebc8d 100644 --- a/fc/video/video.hpp +++ b/fc/video/video.hpp @@ -1,12 +1,13 @@ struct Video { - uint32_t* palette = nullptr; - void generate_palette(Emulator::Interface::PaletteMode mode); - Video(); ~Video(); + auto generate_palette(Emulator::Interface::PaletteMode mode) -> void; + + uint32* palette = nullptr; + private: - uint32_t generate_color(unsigned, double, double, double, double, double); + auto generate_color(uint, double, double, double, double, double) -> uint32; }; extern Video video; diff --git a/nall/GNUmakefile b/nall/GNUmakefile index 1d836fcf..a98e24a5 100644 --- a/nall/GNUmakefile +++ b/nall/GNUmakefile @@ -69,7 +69,7 @@ endif # windows settings ifeq ($(platform),windows) - link := $(link) -lws2_32 -lole32 + link += -lws2_32 -lole32 endif # macosx settings @@ -78,6 +78,11 @@ ifeq ($(platform),macosx) link += -lc++ -lobjc endif +# linux settings +ifeq ($(platform),linux) + link += -ldl +endif + # bsd settings ifeq ($(platform),bsd) flags += -I/usr/local/include @@ -93,12 +98,6 @@ ifeq ($(threaded),true) endif endif -# cross-compilation support -ifeq ($(arch),x86) - flags := -m32 $(flags) - link := -m32 $(link) -endif - # paths prefix := $(HOME)/.local diff --git a/sfc/alt/cpu/cpu.cpp b/sfc/alt/cpu/cpu.cpp index f1039478..3d93a781 100644 --- a/sfc/alt/cpu/cpu.cpp +++ b/sfc/alt/cpu/cpu.cpp @@ -18,12 +18,12 @@ void CPU::step(unsigned clocks) { auto& chip = *coprocessors[i]; chip.clock -= clocks * (uint64)chip.frequency; } - input.port1->clock -= clocks * (uint64)input.port1->frequency; - input.port2->clock -= clocks * (uint64)input.port2->frequency; - synchronize_controllers(); + device.controllerPort1->clock -= clocks * (uint64)device.controllerPort1->frequency; + device.controllerPort2->clock -= clocks * (uint64)device.controllerPort2->frequency; + synchronizeDevices(); } -void CPU::synchronize_smp() { +void CPU::synchronizeSMP() { if(SMP::Threaded == true) { if(smp.clock < 0) co_switch(smp.thread); } else { @@ -31,7 +31,7 @@ void CPU::synchronize_smp() { } } -void CPU::synchronize_ppu() { +void CPU::synchronizePPU() { if(PPU::Threaded == true) { if(ppu.clock < 0) co_switch(ppu.thread); } else { @@ -39,16 +39,16 @@ void CPU::synchronize_ppu() { } } -void CPU::synchronize_coprocessors() { +void CPU::synchronizeCoprocessors() { for(unsigned i = 0; i < coprocessors.size(); i++) { auto& chip = *coprocessors[i]; if(chip.clock < 0) co_switch(chip.thread); } } -void CPU::synchronize_controllers() { - if(input.port1->clock < 0) co_switch(input.port1->thread); - if(input.port2->clock < 0) co_switch(input.port2->thread); +void CPU::synchronizeDevices() { + if(device.controllerPort1->clock < 0) co_switch(device.controllerPort1->thread); + if(device.controllerPort2->clock < 0) co_switch(device.controllerPort2->thread); } void CPU::Enter() { cpu.enter(); } @@ -110,7 +110,7 @@ void CPU::power() { } void CPU::reset() { - create(Enter, system.cpu_frequency()); + create(Enter, system.cpuFrequency()); coprocessors.reset(); PPUcounter::reset(); diff --git a/sfc/alt/cpu/cpu.hpp b/sfc/alt/cpu/cpu.hpp index 0573e532..6e6aae4d 100644 --- a/sfc/alt/cpu/cpu.hpp +++ b/sfc/alt/cpu/cpu.hpp @@ -4,10 +4,10 @@ struct CPU : Processor::R65816, Thread, public PPUcounter { enum : bool { Threaded = true }; vector coprocessors; alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_smp(); - void synchronize_ppu(); - void synchronize_coprocessors(); - void synchronize_controllers(); + alwaysinline void synchronizeSMP(); + void synchronizePPU(); + void synchronizeCoprocessors(); + void synchronizeDevices(); uint8 pio(); bool joylatch(); diff --git a/sfc/alt/cpu/mmio.cpp b/sfc/alt/cpu/mmio.cpp index 09bd7bc0..0113f37d 100644 --- a/sfc/alt/cpu/mmio.cpp +++ b/sfc/alt/cpu/mmio.cpp @@ -2,7 +2,7 @@ uint8 CPU::mmio_read(unsigned addr) { if((addr & 0xffc0) == 0x2140) { - synchronize_smp(); + synchronizeSMP(); return smp.port_read(addr & 3); } @@ -15,13 +15,13 @@ uint8 CPU::mmio_read(unsigned addr) { case 0x4016: { uint8 result = regs.mdr & 0xfc; - result |= input.port1->data() & 3; + result |= device.controllerPort1->data() & 3; return result; } case 0x4017: { uint8 result = (regs.mdr & 0xe0) | 0x1c; - result |= input.port2->data() & 3; + result |= device.controllerPort2->data() & 3; return result; } @@ -99,7 +99,7 @@ uint8 CPU::mmio_read(unsigned addr) { void CPU::mmio_write(unsigned addr, uint8 data) { if((addr & 0xffc0) == 0x2140) { - synchronize_smp(); + synchronizeSMP(); port_write(addr & 3, data); return; } @@ -127,8 +127,8 @@ void CPU::mmio_write(unsigned addr, uint8 data) { } case 0x4016: { - input.port1->latch(data & 1); - input.port2->latch(data & 1); + device.controllerPort1->latch(data & 1); + device.controllerPort2->latch(data & 1); return; } diff --git a/sfc/alt/cpu/timing.cpp b/sfc/alt/cpu/timing.cpp index 7964eb78..d00a0253 100644 --- a/sfc/alt/cpu/timing.cpp +++ b/sfc/alt/cpu/timing.cpp @@ -59,9 +59,9 @@ void CPU::add_clocks(unsigned clocks) { } void CPU::scanline() { - synchronize_smp(); - synchronize_ppu(); - synchronize_coprocessors(); + synchronizeSMP(); + synchronizePPU(); + synchronizeCoprocessors(); system.scanline(); if(vcounter() == 0) hdma_init(); @@ -87,15 +87,15 @@ void CPU::scanline() { } void CPU::run_auto_joypad_poll() { - input.port1->latch(1); - input.port2->latch(1); - input.port1->latch(0); - input.port2->latch(0); + device.controllerPort1->latch(1); + device.controllerPort2->latch(1); + device.controllerPort1->latch(0); + device.controllerPort2->latch(0); uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0; for(unsigned i = 0; i < 16; i++) { - uint8 port0 = input.port1->data(); - uint8 port1 = input.port2->data(); + uint8 port0 = device.controllerPort1->data(); + uint8 port1 = device.controllerPort2->data(); joy1 |= (port0 & 1) ? (0x8000 >> i) : 0; joy2 |= (port1 & 1) ? (0x8000 >> i) : 0; diff --git a/sfc/alt/dsp/dsp.cpp b/sfc/alt/dsp/dsp.cpp index d3103984..71fa8102 100644 --- a/sfc/alt/dsp/dsp.cpp +++ b/sfc/alt/dsp/dsp.cpp @@ -1,6 +1,5 @@ #include -#define DSP_CPP namespace SuperFamicom { DSP dsp; @@ -8,11 +7,15 @@ DSP dsp; #include "serialization.cpp" #include "SPC_DSP.cpp" -void DSP::step(unsigned clocks) { +DSP::DSP() { + for(auto i : range(8)) channel_enabled[i] = true; +} + +auto DSP::step(uint clocks) -> void { clock += clocks; } -void DSP::synchronize_smp() { +auto DSP::synchronizeSMP() -> void { if(SMP::Threaded == true) { if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(smp.thread); } else { @@ -20,52 +23,48 @@ void DSP::synchronize_smp() { } } -void DSP::enter() { +auto DSP::enter() -> void { spc_dsp.run(1); step(24); - signed count = spc_dsp.sample_count(); + int count = spc_dsp.sample_count(); if(count > 0) { - for(unsigned n = 0; n < count; n += 2) audio.sample(samplebuffer[n + 0], samplebuffer[n + 1]); + for(uint n = 0; n < count; n += 2) audio.sample(samplebuffer[n + 0], samplebuffer[n + 1]); spc_dsp.set_output(samplebuffer, 8192); } } -bool DSP::mute() { +auto DSP::mute() -> bool { return spc_dsp.mute(); } -uint8 DSP::read(uint8 addr) { +auto DSP::read(uint8 addr) -> uint8 { return spc_dsp.read(addr); } -void DSP::write(uint8 addr, uint8 data) { +auto DSP::write(uint8 addr, uint8 data) -> void { spc_dsp.write(addr, data); } -void DSP::power() { +auto DSP::power() -> void { spc_dsp.init(smp.apuram); spc_dsp.reset(); spc_dsp.set_output(samplebuffer, 8192); } -void DSP::reset() { +auto DSP::reset() -> void { Thread::clock = 0; spc_dsp.soft_reset(); spc_dsp.set_output(samplebuffer, 8192); } -void DSP::channel_enable(unsigned channel, bool enable) { +auto DSP::channel_enable(uint channel, bool enable) -> void { channel_enabled[channel & 7] = enable; - unsigned mask = 0; - for(unsigned i = 0; i < 8; i++) { + uint mask = 0; + for(auto i : range(8)) { if(channel_enabled[i] == false) mask |= 1 << i; } spc_dsp.mute_voices(mask); } -DSP::DSP() { - for(unsigned i = 0; i < 8; i++) channel_enabled[i] = true; -} - } diff --git a/sfc/alt/dsp/dsp.hpp b/sfc/alt/dsp/dsp.hpp index 5114efb0..92c116e9 100644 --- a/sfc/alt/dsp/dsp.hpp +++ b/sfc/alt/dsp/dsp.hpp @@ -2,22 +2,24 @@ struct DSP : Thread { enum : bool { Threaded = false }; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_smp(); - bool mute(); - uint8 read(uint8 addr); - void write(uint8 addr, uint8 data); - - void enter(); - void power(); - void reset(); - - void channel_enable(unsigned channel, bool enable); - - void serialize(serializer&); DSP(); + alwaysinline auto step(uint clocks) -> void; + alwaysinline auto synchronizeSMP() -> void; + + auto mute() -> bool; + auto read(uint8 addr) -> uint8; + auto write(uint8 addr, uint8 data) -> void; + + auto enter() -> void; + auto power() -> void; + auto reset() -> void; + + auto channel_enable(uint channel, bool enable) -> void; + + auto serialize(serializer&) -> void; + private: SPC_DSP spc_dsp; int16 samplebuffer[8192]; diff --git a/sfc/alt/dsp/serialization.cpp b/sfc/alt/dsp/serialization.cpp index cdb1e423..b2113496 100644 --- a/sfc/alt/dsp/serialization.cpp +++ b/sfc/alt/dsp/serialization.cpp @@ -1,16 +1,14 @@ -#ifdef DSP_CPP - -static void dsp_state_save(unsigned char **out, void *in, size_t size) { +static auto dsp_state_save(unsigned char** out, void* in, size_t size) -> void { memcpy(*out, in, size); *out += size; } -static void dsp_state_load(unsigned char **in, void *out, size_t size) { +static auto dsp_state_load(unsigned char** in, void* out, size_t size) -> void { memcpy(out, *in, size); *in += size; } -void DSP::serialize(serializer &s) { +auto DSP::serialize(serializer &s) -> void { Thread::serialize(s); s.array(samplebuffer); @@ -27,5 +25,3 @@ void DSP::serialize(serializer &s) { s.array(state); } } - -#endif diff --git a/sfc/alt/ppu-balanced/memory/memory.cpp b/sfc/alt/ppu-balanced/memory/memory.cpp index 3f120d84..4c60e96d 100644 --- a/sfc/alt/ppu-balanced/memory/memory.cpp +++ b/sfc/alt/ppu-balanced/memory/memory.cpp @@ -1,12 +1,10 @@ -#ifdef PPU_CPP - -void PPU::latch_counters() { +auto PPU::latch_counters() -> void { regs.hcounter = cpu.hdot(); regs.vcounter = cpu.vcounter(); regs.counters_latched = true; } -uint16 PPU::get_vram_address() { +auto PPU::get_vram_address() -> uint16 { uint16 addr = regs.vram_addr; switch(regs.vram_mapping) { case 0: break; //direct mapping @@ -22,7 +20,7 @@ uint16 PPU::get_vram_address() { //been validated on hardware, as has the edge case where the S-CPU MDR can be written if the //write occurs during the very last clock cycle of vblank. -uint8 PPU::vram_mmio_read(uint16 addr) { +auto PPU::vram_mmio_read(uint16 addr) -> uint8 { uint8 data; if(regs.display_disabled == true) { @@ -51,7 +49,7 @@ uint8 PPU::vram_mmio_read(uint16 addr) { return data; } -void PPU::vram_mmio_write(uint16 addr, uint8 data) { +auto PPU::vram_mmio_write(uint16 addr, uint8 data) -> void { if(regs.display_disabled == true) { vram[addr] = data; } else { @@ -79,7 +77,7 @@ void PPU::vram_mmio_write(uint16 addr, uint8 data) { } } -uint8 PPU::oam_mmio_read(uint16 addr) { +auto PPU::oam_mmio_read(uint16 addr) -> uint8 { addr &= 0x03ff; if(addr & 0x0200) addr &= 0x021f; uint8 data; @@ -97,7 +95,7 @@ uint8 PPU::oam_mmio_read(uint16 addr) { return data; } -void PPU::oam_mmio_write(uint16 addr, uint8 data) { +auto PPU::oam_mmio_write(uint16 addr, uint8 data) -> void { addr &= 0x03ff; if(addr & 0x0200) addr &= 0x021f; @@ -117,7 +115,7 @@ void PPU::oam_mmio_write(uint16 addr, uint8 data) { } } -uint8 PPU::cgram_mmio_read(uint16 addr) { +auto PPU::cgram_mmio_read(uint16 addr) -> uint8 { addr &= 0x01ff; uint8 data; @@ -137,7 +135,7 @@ uint8 PPU::cgram_mmio_read(uint16 addr) { return data; } -void PPU::cgram_mmio_write(uint16 addr, uint8 data) { +auto PPU::cgram_mmio_write(uint16 addr, uint8 data) -> void { addr &= 0x01ff; if(addr & 1) data &= 0x7f; @@ -153,5 +151,3 @@ void PPU::cgram_mmio_write(uint16 addr, uint8 data) { } } } - -#endif diff --git a/sfc/alt/ppu-balanced/memory/memory.hpp b/sfc/alt/ppu-balanced/memory/memory.hpp index 3af9a56e..6ae3703c 100644 --- a/sfc/alt/ppu-balanced/memory/memory.hpp +++ b/sfc/alt/ppu-balanced/memory/memory.hpp @@ -1,10 +1,10 @@ -uint16 get_vram_address(); +auto get_vram_address() -> uint16; -uint8 vram_mmio_read(uint16 addr); -void vram_mmio_write(uint16 addr, uint8 data); +auto vram_mmio_read(uint16 addr) -> uint8; +auto vram_mmio_write(uint16 addr, uint8 data) -> void; -uint8 oam_mmio_read(uint16 addr); -void oam_mmio_write(uint16 addr, uint8 data); +auto oam_mmio_read(uint16 addr) -> uint8; +auto oam_mmio_write(uint16 addr, uint8 data) -> void; -uint8 cgram_mmio_read(uint16 addr); -void cgram_mmio_write(uint16 addr, uint8 data); +auto cgram_mmio_read(uint16 addr) -> uint8; +auto cgram_mmio_write(uint16 addr, uint8 data) -> void; diff --git a/sfc/alt/ppu-balanced/mmio/mmio.cpp b/sfc/alt/ppu-balanced/mmio/mmio.cpp index d058c48d..c17c93f9 100644 --- a/sfc/alt/ppu-balanced/mmio/mmio.cpp +++ b/sfc/alt/ppu-balanced/mmio/mmio.cpp @@ -1,7 +1,5 @@ -#ifdef PPU_CPP - //INIDISP -void PPU::mmio_w2100(uint8 value) { +auto PPU::mmio_w2100(uint8 value) -> void { if(regs.display_disabled == true && cpu.vcounter() == (!overscan() ? 225 : 240)) { regs.oam_addr = regs.oam_baseaddr << 1; regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127; @@ -12,14 +10,14 @@ void PPU::mmio_w2100(uint8 value) { } //OBSEL -void PPU::mmio_w2101(uint8 value) { +auto PPU::mmio_w2101(uint8 value) -> void { regs.oam_basesize = (value >> 5) & 7; regs.oam_nameselect = (value >> 3) & 3; regs.oam_tdaddr = (value & 3) << 14; } //OAMADDL -void PPU::mmio_w2102(uint8 data) { +auto PPU::mmio_w2102(uint8 data) -> void { regs.oam_baseaddr = (regs.oam_baseaddr & ~0xff) | (data << 0); regs.oam_baseaddr &= 0x01ff; regs.oam_addr = regs.oam_baseaddr << 1; @@ -27,7 +25,7 @@ void PPU::mmio_w2102(uint8 data) { } //OAMADDH -void PPU::mmio_w2103(uint8 data) { +auto PPU::mmio_w2103(uint8 data) -> void { regs.oam_priority = !!(data & 0x80); regs.oam_baseaddr = (regs.oam_baseaddr & 0xff) | (data << 8); regs.oam_baseaddr &= 0x01ff; @@ -36,7 +34,7 @@ void PPU::mmio_w2103(uint8 data) { } //OAMDATA -void PPU::mmio_w2104(uint8 data) { +auto PPU::mmio_w2104(uint8 data) -> void { if((regs.oam_addr & 1) == 0) regs.oam_latchdata = data; if(regs.oam_addr & 0x0200) { @@ -52,7 +50,7 @@ void PPU::mmio_w2104(uint8 data) { } //BGMODE -void PPU::mmio_w2105(uint8 value) { +auto PPU::mmio_w2105(uint8 value) -> void { regs.bg_tilesize[BG4] = !!(value & 0x80); regs.bg_tilesize[BG3] = !!(value & 0x40); regs.bg_tilesize[BG2] = !!(value & 0x20); @@ -62,7 +60,7 @@ void PPU::mmio_w2105(uint8 value) { } //MOSAIC -void PPU::mmio_w2106(uint8 value) { +auto PPU::mmio_w2106(uint8 value) -> void { regs.mosaic_size = (value >> 4) & 15; regs.mosaic_enabled[BG4] = !!(value & 0x08); regs.mosaic_enabled[BG3] = !!(value & 0x04); @@ -71,43 +69,43 @@ void PPU::mmio_w2106(uint8 value) { } //BG1SC -void PPU::mmio_w2107(uint8 value) { +auto PPU::mmio_w2107(uint8 value) -> void { regs.bg_scaddr[BG1] = (value & 0x7c) << 9; regs.bg_scsize[BG1] = value & 3; } //BG2SC -void PPU::mmio_w2108(uint8 value) { +auto PPU::mmio_w2108(uint8 value) -> void { regs.bg_scaddr[BG2] = (value & 0x7c) << 9; regs.bg_scsize[BG2] = value & 3; } //BG3SC -void PPU::mmio_w2109(uint8 value) { +auto PPU::mmio_w2109(uint8 value) -> void { regs.bg_scaddr[BG3] = (value & 0x7c) << 9; regs.bg_scsize[BG3] = value & 3; } //BG4SC -void PPU::mmio_w210a(uint8 value) { +auto PPU::mmio_w210a(uint8 value) -> void { regs.bg_scaddr[BG4] = (value & 0x7c) << 9; regs.bg_scsize[BG4] = value & 3; } //BG12NBA -void PPU::mmio_w210b(uint8 value) { +auto PPU::mmio_w210b(uint8 value) -> void { regs.bg_tdaddr[BG1] = (value & 0x07) << 13; regs.bg_tdaddr[BG2] = (value & 0x70) << 9; } //BG34NBA -void PPU::mmio_w210c(uint8 value) { +auto PPU::mmio_w210c(uint8 value) -> void { regs.bg_tdaddr[BG3] = (value & 0x07) << 13; regs.bg_tdaddr[BG4] = (value & 0x70) << 9; } //BG1HOFS -void PPU::mmio_w210d(uint8 value) { +auto PPU::mmio_w210d(uint8 value) -> void { regs.m7_hofs = (value << 8) | regs.m7_latch; regs.m7_latch = value; @@ -116,7 +114,7 @@ void PPU::mmio_w210d(uint8 value) { } //BG1VOFS -void PPU::mmio_w210e(uint8 value) { +auto PPU::mmio_w210e(uint8 value) -> void { regs.m7_vofs = (value << 8) | regs.m7_latch; regs.m7_latch = value; @@ -125,43 +123,43 @@ void PPU::mmio_w210e(uint8 value) { } //BG2HOFS -void PPU::mmio_w210f(uint8 value) { +auto PPU::mmio_w210f(uint8 value) -> void { regs.bg_hofs[BG2] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG2] >> 8) & 7); regs.bg_ofslatch = value; } //BG2VOFS -void PPU::mmio_w2110(uint8 value) { +auto PPU::mmio_w2110(uint8 value) -> void { regs.bg_vofs[BG2] = (value << 8) | (regs.bg_ofslatch); regs.bg_ofslatch = value; } //BG3HOFS -void PPU::mmio_w2111(uint8 value) { +auto PPU::mmio_w2111(uint8 value) -> void { regs.bg_hofs[BG3] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG3] >> 8) & 7); regs.bg_ofslatch = value; } //BG3VOFS -void PPU::mmio_w2112(uint8 value) { +auto PPU::mmio_w2112(uint8 value) -> void { regs.bg_vofs[BG3] = (value << 8) | (regs.bg_ofslatch); regs.bg_ofslatch = value; } //BG4HOFS -void PPU::mmio_w2113(uint8 value) { +auto PPU::mmio_w2113(uint8 value) -> void { regs.bg_hofs[BG4] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG4] >> 8) & 7); regs.bg_ofslatch = value; } //BG4VOFS -void PPU::mmio_w2114(uint8 value) { +auto PPU::mmio_w2114(uint8 value) -> void { regs.bg_vofs[BG4] = (value << 8) | (regs.bg_ofslatch); regs.bg_ofslatch = value; } //VMAIN -void PPU::mmio_w2115(uint8 value) { +auto PPU::mmio_w2115(uint8 value) -> void { regs.vram_incmode = !!(value & 0x80); regs.vram_mapping = (value >> 2) & 3; switch(value & 3) { @@ -173,7 +171,7 @@ void PPU::mmio_w2115(uint8 value) { } //VMADDL -void PPU::mmio_w2116(uint8 value) { +auto PPU::mmio_w2116(uint8 value) -> void { regs.vram_addr = (regs.vram_addr & 0xff00) | value; uint16 addr = get_vram_address(); regs.vram_readbuffer = vram_mmio_read(addr + 0); @@ -181,7 +179,7 @@ void PPU::mmio_w2116(uint8 value) { } //VMADDH -void PPU::mmio_w2117(uint8 value) { +auto PPU::mmio_w2117(uint8 value) -> void { regs.vram_addr = (value << 8) | (regs.vram_addr & 0x00ff); uint16 addr = get_vram_address(); regs.vram_readbuffer = vram_mmio_read(addr + 0); @@ -189,8 +187,8 @@ void PPU::mmio_w2117(uint8 value) { } //VMDATAL -void PPU::mmio_w2118(uint8 value) { -uint16 addr = get_vram_address(); +auto PPU::mmio_w2118(uint8 value) -> void { + uint16 addr = get_vram_address(); vram_mmio_write(addr, value); bg_tiledata_state[TILE_2BIT][(addr >> 4)] = 1; bg_tiledata_state[TILE_4BIT][(addr >> 5)] = 1; @@ -202,8 +200,8 @@ uint16 addr = get_vram_address(); } //VMDATAH -void PPU::mmio_w2119(uint8 value) { -uint16 addr = get_vram_address() + 1; +auto PPU::mmio_w2119(uint8 value) -> void { + uint16 addr = get_vram_address() + 1; vram_mmio_write(addr, value); bg_tiledata_state[TILE_2BIT][(addr >> 4)] = 1; bg_tiledata_state[TILE_4BIT][(addr >> 5)] = 1; @@ -215,50 +213,50 @@ uint16 addr = get_vram_address() + 1; } //M7SEL -void PPU::mmio_w211a(uint8 value) { +auto PPU::mmio_w211a(uint8 value) -> void { regs.mode7_repeat = (value >> 6) & 3; regs.mode7_vflip = !!(value & 0x02); regs.mode7_hflip = !!(value & 0x01); } //M7A -void PPU::mmio_w211b(uint8 value) { +auto PPU::mmio_w211b(uint8 value) -> void { regs.m7a = (value << 8) | regs.m7_latch; regs.m7_latch = value; } //M7B -void PPU::mmio_w211c(uint8 value) { +auto PPU::mmio_w211c(uint8 value) -> void { regs.m7b = (value << 8) | regs.m7_latch; regs.m7_latch = value; } //M7C -void PPU::mmio_w211d(uint8 value) { +auto PPU::mmio_w211d(uint8 value) -> void { regs.m7c = (value << 8) | regs.m7_latch; regs.m7_latch = value; } //M7D -void PPU::mmio_w211e(uint8 value) { +auto PPU::mmio_w211e(uint8 value) -> void { regs.m7d = (value << 8) | regs.m7_latch; regs.m7_latch = value; } //M7X -void PPU::mmio_w211f(uint8 value) { +auto PPU::mmio_w211f(uint8 value) -> void { regs.m7x = (value << 8) | regs.m7_latch; regs.m7_latch = value; } //M7Y -void PPU::mmio_w2120(uint8 value) { +auto PPU::mmio_w2120(uint8 value) -> void { regs.m7y = (value << 8) | regs.m7_latch; regs.m7_latch = value; } //CGADD -void PPU::mmio_w2121(uint8 value) { +auto PPU::mmio_w2121(uint8 value) -> void { regs.cgram_addr = value << 1; } @@ -270,7 +268,7 @@ void PPU::mmio_w2121(uint8 value) { //anomie indicates writes to CGDATA work the same //as writes to OAMDATA's low table. need to verify //this on hardware. -void PPU::mmio_w2122(uint8 value) { +auto PPU::mmio_w2122(uint8 value) -> void { if(!(regs.cgram_addr & 1)) { regs.cgram_latchdata = value; } else { @@ -282,7 +280,7 @@ void PPU::mmio_w2122(uint8 value) { } //W12SEL -void PPU::mmio_w2123(uint8 value) { +auto PPU::mmio_w2123(uint8 value) -> void { regs.window2_enabled[BG2] = !!(value & 0x80); regs.window2_invert [BG2] = !!(value & 0x40); regs.window1_enabled[BG2] = !!(value & 0x20); @@ -294,7 +292,7 @@ void PPU::mmio_w2123(uint8 value) { } //W34SEL -void PPU::mmio_w2124(uint8 value) { +auto PPU::mmio_w2124(uint8 value) -> void { regs.window2_enabled[BG4] = !!(value & 0x80); regs.window2_invert [BG4] = !!(value & 0x40); regs.window1_enabled[BG4] = !!(value & 0x20); @@ -306,7 +304,7 @@ void PPU::mmio_w2124(uint8 value) { } //WOBJSEL -void PPU::mmio_w2125(uint8 value) { +auto PPU::mmio_w2125(uint8 value) -> void { regs.window2_enabled[COL] = !!(value & 0x80); regs.window2_invert [COL] = !!(value & 0x40); regs.window1_enabled[COL] = !!(value & 0x20); @@ -318,27 +316,27 @@ void PPU::mmio_w2125(uint8 value) { } //WH0 -void PPU::mmio_w2126(uint8 value) { +auto PPU::mmio_w2126(uint8 value) -> void { regs.window1_left = value; } //WH1 -void PPU::mmio_w2127(uint8 value) { +auto PPU::mmio_w2127(uint8 value) -> void { regs.window1_right = value; } //WH2 -void PPU::mmio_w2128(uint8 value) { +auto PPU::mmio_w2128(uint8 value) -> void { regs.window2_left = value; } //WH3 -void PPU::mmio_w2129(uint8 value) { +auto PPU::mmio_w2129(uint8 value) -> void { regs.window2_right = value; } //WBGLOG -void PPU::mmio_w212a(uint8 value) { +auto PPU::mmio_w212a(uint8 value) -> void { regs.window_mask[BG4] = (value >> 6) & 3; regs.window_mask[BG3] = (value >> 4) & 3; regs.window_mask[BG2] = (value >> 2) & 3; @@ -346,13 +344,13 @@ void PPU::mmio_w212a(uint8 value) { } //WOBJLOG -void PPU::mmio_w212b(uint8 value) { +auto PPU::mmio_w212b(uint8 value) -> void { regs.window_mask[COL] = (value >> 2) & 3; regs.window_mask[OAM] = (value ) & 3; } //TM -void PPU::mmio_w212c(uint8 value) { +auto PPU::mmio_w212c(uint8 value) -> void { regs.bg_enabled[OAM] = !!(value & 0x10); regs.bg_enabled[BG4] = !!(value & 0x08); regs.bg_enabled[BG3] = !!(value & 0x04); @@ -361,7 +359,7 @@ void PPU::mmio_w212c(uint8 value) { } //TS -void PPU::mmio_w212d(uint8 value) { +auto PPU::mmio_w212d(uint8 value) -> void { regs.bgsub_enabled[OAM] = !!(value & 0x10); regs.bgsub_enabled[BG4] = !!(value & 0x08); regs.bgsub_enabled[BG3] = !!(value & 0x04); @@ -370,7 +368,7 @@ void PPU::mmio_w212d(uint8 value) { } //TMW -void PPU::mmio_w212e(uint8 value) { +auto PPU::mmio_w212e(uint8 value) -> void { regs.window_enabled[OAM] = !!(value & 0x10); regs.window_enabled[BG4] = !!(value & 0x08); regs.window_enabled[BG3] = !!(value & 0x04); @@ -379,7 +377,7 @@ void PPU::mmio_w212e(uint8 value) { } //TSW -void PPU::mmio_w212f(uint8 value) { +auto PPU::mmio_w212f(uint8 value) -> void { regs.sub_window_enabled[OAM] = !!(value & 0x10); regs.sub_window_enabled[BG4] = !!(value & 0x08); regs.sub_window_enabled[BG3] = !!(value & 0x04); @@ -388,7 +386,7 @@ void PPU::mmio_w212f(uint8 value) { } //CGWSEL -void PPU::mmio_w2130(uint8 value) { +auto PPU::mmio_w2130(uint8 value) -> void { regs.color_mask = (value >> 6) & 3; regs.colorsub_mask = (value >> 4) & 3; regs.addsub_mode = !!(value & 0x02); @@ -396,7 +394,7 @@ void PPU::mmio_w2130(uint8 value) { } //CGADDSUB -void PPU::mmio_w2131(uint8 value) { +auto PPU::mmio_w2131(uint8 value) -> void { regs.color_mode = !!(value & 0x80); regs.color_halve = !!(value & 0x40); regs.color_enabled[BACK] = !!(value & 0x20); @@ -408,7 +406,7 @@ void PPU::mmio_w2131(uint8 value) { } //COLDATA -void PPU::mmio_w2132(uint8 value) { +auto PPU::mmio_w2132(uint8 value) -> void { if(value & 0x80) regs.color_b = value & 0x1f; if(value & 0x40) regs.color_g = value & 0x1f; if(value & 0x20) regs.color_r = value & 0x1f; @@ -419,7 +417,7 @@ void PPU::mmio_w2132(uint8 value) { } //SETINI -void PPU::mmio_w2133(uint8 value) { +auto PPU::mmio_w2133(uint8 value) -> void { regs.mode7_extbg = !!(value & 0x40); regs.pseudo_hires = !!(value & 0x08); regs.overscan = !!(value & 0x04); @@ -431,31 +429,31 @@ void PPU::mmio_w2133(uint8 value) { } //MPYL -uint8 PPU::mmio_r2134() { -uint32 r; +auto PPU::mmio_r2134() -> uint8 { + uint32 r; r = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); regs.ppu1_mdr = r; return regs.ppu1_mdr; } //MPYM -uint8 PPU::mmio_r2135() { -uint32 r; +auto PPU::mmio_r2135() -> uint8 { + uint32 r; r = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); regs.ppu1_mdr = r >> 8; return regs.ppu1_mdr; } //MPYH -uint8 PPU::mmio_r2136() { -uint32 r; +auto PPU::mmio_r2136() -> uint8 { + uint32 r; r = ((int16)regs.m7a * (int8)(regs.m7b >> 8)); regs.ppu1_mdr = r >> 16; return regs.ppu1_mdr; } //SLHV -uint8 PPU::mmio_r2137() { +auto PPU::mmio_r2137() -> uint8 { if(cpu.pio() & 0x80) { latch_counters(); } @@ -463,7 +461,7 @@ uint8 PPU::mmio_r2137() { } //OAMDATAREAD -uint8 PPU::mmio_r2138() { +auto PPU::mmio_r2138() -> uint8 { regs.ppu1_mdr = oam_mmio_read(regs.oam_addr); regs.oam_addr++; @@ -474,8 +472,8 @@ uint8 PPU::mmio_r2138() { } //VMDATALREAD -uint8 PPU::mmio_r2139() { -uint16 addr = get_vram_address(); +auto PPU::mmio_r2139() -> uint8 { + uint16 addr = get_vram_address(); regs.ppu1_mdr = regs.vram_readbuffer; if(regs.vram_incmode == 0) { addr &= 0xfffe; @@ -487,8 +485,8 @@ uint16 addr = get_vram_address(); } //VMDATAHREAD -uint8 PPU::mmio_r213a() { -uint16 addr = get_vram_address() + 1; +auto PPU::mmio_r213a() -> uint8 { + uint16 addr = get_vram_address() + 1; regs.ppu1_mdr = regs.vram_readbuffer >> 8; if(regs.vram_incmode == 1) { addr &= 0xfffe; @@ -503,7 +501,7 @@ uint16 addr = get_vram_address() + 1; //note: CGRAM palette data is 15-bits (0,bbbbb,ggggg,rrrrr) //therefore, the high byte read from each color does not //update bit 7 of the PPU2 MDR. -uint8 PPU::mmio_r213b() { +auto PPU::mmio_r213b() -> uint8 { if(!(regs.cgram_addr & 1)) { regs.ppu2_mdr = cgram_mmio_read(regs.cgram_addr) & 0xff; } else { @@ -516,7 +514,7 @@ uint8 PPU::mmio_r213b() { } //OPHCT -uint8 PPU::mmio_r213c() { +auto PPU::mmio_r213c() -> uint8 { if(!regs.latch_hcounter) { regs.ppu2_mdr = regs.hcounter & 0xff; } else { @@ -528,7 +526,7 @@ uint8 PPU::mmio_r213c() { } //OPVCT -uint8 PPU::mmio_r213d() { +auto PPU::mmio_r213d() -> uint8 { if(!regs.latch_vcounter) { regs.ppu2_mdr = regs.vcounter & 0xff; } else { @@ -540,8 +538,8 @@ uint8 PPU::mmio_r213d() { } //STAT77 -uint8 PPU::mmio_r213e() { -uint8 r = 0x00; +auto PPU::mmio_r213e() -> uint8 { + uint8 r = 0x00; r |= (regs.time_over) ? 0x80 : 0x00; r |= (regs.range_over) ? 0x40 : 0x00; r |= (regs.ppu1_mdr & 0x10); @@ -551,8 +549,8 @@ uint8 r = 0x00; } //STAT78 -uint8 PPU::mmio_r213f() { -uint8 r = 0x00; +auto PPU::mmio_r213f() -> uint8 { + uint8 r = 0x00; regs.latch_hcounter = 0; regs.latch_vcounter = 0; @@ -570,8 +568,8 @@ uint8 r = 0x00; return regs.ppu2_mdr; } -uint8 PPU::mmio_read(unsigned addr) { - cpu.synchronize_ppu(); +auto PPU::mmio_read(uint addr) -> uint8 { + cpu.synchronizePPU(); switch(addr & 0xffff) { case 0x2104: @@ -609,8 +607,8 @@ uint8 PPU::mmio_read(unsigned addr) { return cpu.regs.mdr; } -void PPU::mmio_write(unsigned addr, uint8 data) { - cpu.synchronize_ppu(); +auto PPU::mmio_write(uint addr, uint8 data) -> void { + cpu.synchronizePPU(); switch(addr & 0xffff) { case 0x2100: return mmio_w2100(data); //INIDISP @@ -667,5 +665,3 @@ void PPU::mmio_write(unsigned addr, uint8 data) { case 0x2133: return mmio_w2133(data); //SETINI } } - -#endif diff --git a/sfc/alt/ppu-balanced/mmio/mmio.hpp b/sfc/alt/ppu-balanced/mmio/mmio.hpp index aeb1c3a6..1b452c0d 100644 --- a/sfc/alt/ppu-balanced/mmio/mmio.hpp +++ b/sfc/alt/ppu-balanced/mmio/mmio.hpp @@ -130,73 +130,73 @@ struct { uint16 oam_itemcount, oam_tilecount; } regs; -void mmio_w2100(uint8 value); //INIDISP -void mmio_w2101(uint8 value); //OBSEL -void mmio_w2102(uint8 value); //OAMADDL -void mmio_w2103(uint8 value); //OAMADDH -void mmio_w2104(uint8 value); //OAMDATA -void mmio_w2105(uint8 value); //BGMODE -void mmio_w2106(uint8 value); //MOSAIC -void mmio_w2107(uint8 value); //BG1SC -void mmio_w2108(uint8 value); //BG2SC -void mmio_w2109(uint8 value); //BG3SC -void mmio_w210a(uint8 value); //BG4SC -void mmio_w210b(uint8 value); //BG12NBA -void mmio_w210c(uint8 value); //BG34NBA -void mmio_w210d(uint8 value); //BG1HOFS -void mmio_w210e(uint8 value); //BG1VOFS -void mmio_w210f(uint8 value); //BG2HOFS -void mmio_w2110(uint8 value); //BG2VOFS -void mmio_w2111(uint8 value); //BG3HOFS -void mmio_w2112(uint8 value); //BG3VOFS -void mmio_w2113(uint8 value); //BG4HOFS -void mmio_w2114(uint8 value); //BG4VOFS -void mmio_w2115(uint8 value); //VMAIN -void mmio_w2116(uint8 value); //VMADDL -void mmio_w2117(uint8 value); //VMADDH -void mmio_w2118(uint8 value); //VMDATAL -void mmio_w2119(uint8 value); //VMDATAH -void mmio_w211a(uint8 value); //M7SEL -void mmio_w211b(uint8 value); //M7A -void mmio_w211c(uint8 value); //M7B -void mmio_w211d(uint8 value); //M7C -void mmio_w211e(uint8 value); //M7D -void mmio_w211f(uint8 value); //M7X -void mmio_w2120(uint8 value); //M7Y -void mmio_w2121(uint8 value); //CGADD -void mmio_w2122(uint8 value); //CGDATA -void mmio_w2123(uint8 value); //W12SEL -void mmio_w2124(uint8 value); //W34SEL -void mmio_w2125(uint8 value); //WOBJSEL -void mmio_w2126(uint8 value); //WH0 -void mmio_w2127(uint8 value); //WH1 -void mmio_w2128(uint8 value); //WH2 -void mmio_w2129(uint8 value); //WH3 -void mmio_w212a(uint8 value); //WBGLOG -void mmio_w212b(uint8 value); //WOBJLOG -void mmio_w212c(uint8 value); //TM -void mmio_w212d(uint8 value); //TS -void mmio_w212e(uint8 value); //TMW -void mmio_w212f(uint8 value); //TSW -void mmio_w2130(uint8 value); //CGWSEL -void mmio_w2131(uint8 value); //CGADDSUB -void mmio_w2132(uint8 value); //COLDATA -void mmio_w2133(uint8 value); //SETINI +auto mmio_w2100(uint8 value) -> void; //INIDISP +auto mmio_w2101(uint8 value) -> void; //OBSEL +auto mmio_w2102(uint8 value) -> void; //OAMADDL +auto mmio_w2103(uint8 value) -> void; //OAMADDH +auto mmio_w2104(uint8 value) -> void; //OAMDATA +auto mmio_w2105(uint8 value) -> void; //BGMODE +auto mmio_w2106(uint8 value) -> void; //MOSAIC +auto mmio_w2107(uint8 value) -> void; //BG1SC +auto mmio_w2108(uint8 value) -> void; //BG2SC +auto mmio_w2109(uint8 value) -> void; //BG3SC +auto mmio_w210a(uint8 value) -> void; //BG4SC +auto mmio_w210b(uint8 value) -> void; //BG12NBA +auto mmio_w210c(uint8 value) -> void; //BG34NBA +auto mmio_w210d(uint8 value) -> void; //BG1HOFS +auto mmio_w210e(uint8 value) -> void; //BG1VOFS +auto mmio_w210f(uint8 value) -> void; //BG2HOFS +auto mmio_w2110(uint8 value) -> void; //BG2VOFS +auto mmio_w2111(uint8 value) -> void; //BG3HOFS +auto mmio_w2112(uint8 value) -> void; //BG3VOFS +auto mmio_w2113(uint8 value) -> void; //BG4HOFS +auto mmio_w2114(uint8 value) -> void; //BG4VOFS +auto mmio_w2115(uint8 value) -> void; //VMAIN +auto mmio_w2116(uint8 value) -> void; //VMADDL +auto mmio_w2117(uint8 value) -> void; //VMADDH +auto mmio_w2118(uint8 value) -> void; //VMDATAL +auto mmio_w2119(uint8 value) -> void; //VMDATAH +auto mmio_w211a(uint8 value) -> void; //M7SEL +auto mmio_w211b(uint8 value) -> void; //M7A +auto mmio_w211c(uint8 value) -> void; //M7B +auto mmio_w211d(uint8 value) -> void; //M7C +auto mmio_w211e(uint8 value) -> void; //M7D +auto mmio_w211f(uint8 value) -> void; //M7X +auto mmio_w2120(uint8 value) -> void; //M7Y +auto mmio_w2121(uint8 value) -> void; //CGADD +auto mmio_w2122(uint8 value) -> void; //CGDATA +auto mmio_w2123(uint8 value) -> void; //W12SEL +auto mmio_w2124(uint8 value) -> void; //W34SEL +auto mmio_w2125(uint8 value) -> void; //WOBJSEL +auto mmio_w2126(uint8 value) -> void; //WH0 +auto mmio_w2127(uint8 value) -> void; //WH1 +auto mmio_w2128(uint8 value) -> void; //WH2 +auto mmio_w2129(uint8 value) -> void; //WH3 +auto mmio_w212a(uint8 value) -> void; //WBGLOG +auto mmio_w212b(uint8 value) -> void; //WOBJLOG +auto mmio_w212c(uint8 value) -> void; //TM +auto mmio_w212d(uint8 value) -> void; //TS +auto mmio_w212e(uint8 value) -> void; //TMW +auto mmio_w212f(uint8 value) -> void; //TSW +auto mmio_w2130(uint8 value) -> void; //CGWSEL +auto mmio_w2131(uint8 value) -> void; //CGADDSUB +auto mmio_w2132(uint8 value) -> void; //COLDATA +auto mmio_w2133(uint8 value) -> void; //SETINI -uint8 mmio_r2134(); //MPYL -uint8 mmio_r2135(); //MPYM -uint8 mmio_r2136(); //MPYH -uint8 mmio_r2137(); //SLHV -uint8 mmio_r2138(); //OAMDATAREAD -uint8 mmio_r2139(); //VMDATALREAD -uint8 mmio_r213a(); //VMDATAHREAD -uint8 mmio_r213b(); //CGDATAREAD -uint8 mmio_r213c(); //OPHCT -uint8 mmio_r213d(); //OPVCT -uint8 mmio_r213e(); //STAT77 -uint8 mmio_r213f(); //STAT78 +auto mmio_r2134() -> uint8; //MPYL +auto mmio_r2135() -> uint8; //MPYM +auto mmio_r2136() -> uint8; //MPYH +auto mmio_r2137() -> uint8; //SLHV +auto mmio_r2138() -> uint8; //OAMDATAREAD +auto mmio_r2139() -> uint8; //VMDATALREAD +auto mmio_r213a() -> uint8; //VMDATAHREAD +auto mmio_r213b() -> uint8; //CGDATAREAD +auto mmio_r213c() -> uint8; //OPHCT +auto mmio_r213d() -> uint8; //OPVCT +auto mmio_r213e() -> uint8; //STAT77 +auto mmio_r213f() -> uint8; //STAT78 -uint8 mmio_read(unsigned addr); -void mmio_write(unsigned addr, uint8 data); +auto mmio_read(uint addr) -> uint8; +auto mmio_write(uint addr, uint8 data) -> void; -void latch_counters(); +auto latch_counters() -> void; diff --git a/sfc/alt/ppu-balanced/ppu.cpp b/sfc/alt/ppu-balanced/ppu.cpp index ad4fd139..f044965b 100644 --- a/sfc/alt/ppu-balanced/ppu.cpp +++ b/sfc/alt/ppu-balanced/ppu.cpp @@ -1,6 +1,5 @@ #include -#define PPU_CPP namespace SuperFamicom { PPU ppu; @@ -10,11 +9,44 @@ PPU ppu; #include "render/render.cpp" #include "serialization.cpp" -void PPU::step(unsigned clocks) { +PPU::PPU() { + surface = new uint32[512 * 512]; + output = surface + 16 * 512; + + alloc_tiledata_cache(); + + for(uint l : range(16)) { + for(uint i : range(4096)) { + mosaic_table[l][i] = (i / (l + 1)) * (l + 1); + } + } + + layer_enabled[BG1][0] = true; + layer_enabled[BG1][1] = true; + layer_enabled[BG2][0] = true; + layer_enabled[BG2][1] = true; + layer_enabled[BG3][0] = true; + layer_enabled[BG3][1] = true; + layer_enabled[BG4][0] = true; + layer_enabled[BG4][1] = true; + layer_enabled[OAM][0] = true; + layer_enabled[OAM][1] = true; + layer_enabled[OAM][2] = true; + layer_enabled[OAM][3] = true; + frameskip = 0; + framecounter = 0; +} + +PPU::~PPU() { + delete[] surface; + free_tiledata_cache(); +} + +auto PPU::step(uint clocks) -> void { clock += clocks; } -void PPU::synchronize_cpu() { +auto PPU::synchronizeCPU() -> void { if(CPU::Threaded == true) { if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); } else { @@ -22,9 +54,9 @@ void PPU::synchronize_cpu() { } } -void PPU::Enter() { ppu.enter(); } +auto PPU::Enter() -> void { ppu.enter(); } -void PPU::enter() { +auto PPU::enter() -> void { while(true) { if(scheduler.sync == Scheduler::SynchronizeMode::All) { scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); @@ -67,13 +99,13 @@ void PPU::enter() { } } -void PPU::add_clocks(unsigned clocks) { +auto PPU::add_clocks(uint clocks) -> void { tick(clocks); step(clocks); - synchronize_cpu(); + synchronizeCPU(); } -void PPU::scanline() { +auto PPU::scanline() -> void { line = vcounter(); if(line == 0) { @@ -98,7 +130,7 @@ void PPU::scanline() { } } -void PPU::render_scanline() { +auto PPU::render_scanline() -> void { if(line >= 1 && line < (!overscan() ? 225 : 240)) { if(framecounter) return; render_line_oam_rto(); @@ -106,7 +138,7 @@ void PPU::render_scanline() { } } -void PPU::frame() { +auto PPU::frame() -> void { system.frame(); if(field() == 0) { @@ -117,15 +149,15 @@ void PPU::frame() { framecounter = (frameskip == 0 ? 0 : (framecounter + 1) % frameskip); } -void PPU::enable() { - function reader = {&PPU::mmio_read, (PPU*)&ppu}; - function writer = {&PPU::mmio_write, (PPU*)&ppu}; +auto PPU::enable() -> void { + function reader = {&PPU::mmio_read, (PPU*)&ppu}; + function writer = {&PPU::mmio_write, (PPU*)&ppu}; bus.map(reader, writer, 0x00, 0x3f, 0x2100, 0x213f); bus.map(reader, writer, 0x80, 0xbf, 0x2100, 0x213f); } -void PPU::power() { +auto PPU::power() -> void { for(auto& n : vram) n = 0x00; for(auto& n : oam) n = 0x00; for(auto& n : cgram) n = 0x00; @@ -340,8 +372,8 @@ void PPU::power() { reset(); } -void PPU::reset() { - create(Enter, system.cpu_frequency()); +auto PPU::reset() -> void { + create(Enter, system.cpuFrequency()); PPUcounter::reset(); memset(surface, 0, 512 * 512 * sizeof(uint32)); @@ -368,7 +400,7 @@ void PPU::reset() { regs.bg_y[3] = 0; } -void PPU::layer_enable(unsigned layer, unsigned priority, bool enable) { +auto PPU::layer_enable(uint layer, uint priority, bool enable) -> void { switch(layer * 4 + priority) { case 0: layer_enabled[BG1][0] = enable; break; case 1: layer_enabled[BG1][1] = enable; break; @@ -385,42 +417,9 @@ void PPU::layer_enable(unsigned layer, unsigned priority, bool enable) { } } -void PPU::set_frameskip(unsigned frameskip_) { +auto PPU::set_frameskip(uint frameskip_) -> void { frameskip = frameskip_; framecounter = 0; } -PPU::PPU() { - surface = new uint32[512 * 512]; - output = surface + 16 * 512; - - alloc_tiledata_cache(); - - for(unsigned l = 0; l < 16; l++) { - for(unsigned i = 0; i < 4096; i++) { - mosaic_table[l][i] = (i / (l + 1)) * (l + 1); - } - } - - layer_enabled[BG1][0] = true; - layer_enabled[BG1][1] = true; - layer_enabled[BG2][0] = true; - layer_enabled[BG2][1] = true; - layer_enabled[BG3][0] = true; - layer_enabled[BG3][1] = true; - layer_enabled[BG4][0] = true; - layer_enabled[BG4][1] = true; - layer_enabled[OAM][0] = true; - layer_enabled[OAM][1] = true; - layer_enabled[OAM][2] = true; - layer_enabled[OAM][3] = true; - frameskip = 0; - framecounter = 0; -} - -PPU::~PPU() { - delete[] surface; - free_tiledata_cache(); -} - } diff --git a/sfc/alt/ppu-balanced/ppu.hpp b/sfc/alt/ppu-balanced/ppu.hpp index 106780f9..74a80198 100644 --- a/sfc/alt/ppu-balanced/ppu.hpp +++ b/sfc/alt/ppu-balanced/ppu.hpp @@ -1,31 +1,55 @@ struct PPU : Thread, public PPUcounter { - uint8 vram[128 * 1024]; - uint8 oam[544]; - uint8 cgram[512]; - enum : bool { Threaded = true }; - alwaysinline void step(unsigned clocks); - alwaysinline void synchronize_cpu(); + + PPU(); + ~PPU(); + + alwaysinline auto step(uint clocks) -> void; + alwaysinline auto synchronizeCPU() -> void; #include "memory/memory.hpp" #include "mmio/mmio.hpp" #include "render/render.hpp" + static auto Enter() -> void; + auto add_clocks(uint clocks) -> void; + + alwaysinline auto interlace() const -> bool { return display.interlace; } + alwaysinline auto overscan() const -> bool { return display.overscan; } + alwaysinline auto hires() const -> bool { return (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6); } + + auto render_line() -> void; + auto update_oam_status() -> void; + + auto scanline() -> void; + auto render_scanline() -> void; + auto frame() -> void; + auto enter() -> void; + auto enable() -> void; + auto power() -> void; + auto reset() -> void; + + auto layer_enable(uint layer, uint priority, bool enable) -> void; + auto set_frameskip(uint frameskip) -> void; + + auto serialize(serializer&) -> void; + + enum : uint { NTSC = 0, PAL = 1 }; + enum : uint { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 }; + enum : uint { SC_32x32 = 0, SC_64x32 = 1, SC_32x64 = 2, SC_64x64 = 3 }; + + uint8 vram[128 * 1024]; + uint8 oam[544]; + uint8 cgram[512]; + uint32* surface; uint32* output; - unsigned ppu1_version = 1; - unsigned ppu2_version = 3; - - static void Enter(); - void add_clocks(unsigned clocks); + uint ppu1_version = 1; + uint ppu2_version = 3; uint8 region; - unsigned line; - - enum { NTSC = 0, PAL = 1 }; - enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 }; - enum { SC_32x32 = 0, SC_64x32 = 1, SC_32x64 = 2, SC_64x64 = 3 }; + uint line; struct { bool interlace; @@ -45,32 +69,10 @@ struct PPU : Thread, public PPUcounter { uint16 m7a, m7b, m7c, m7d, m7x, m7y; } cache; - alwaysinline bool interlace() const { return display.interlace; } - alwaysinline bool overscan() const { return display.overscan; } - alwaysinline bool hires() const { return (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6); } - uint16 mosaic_table[16][4096]; - void render_line(); - - void update_oam_status(); - //required functions - void scanline(); - void render_scanline(); - void frame(); - void enter(); - void enable(); - void power(); - void reset(); - bool layer_enabled[5][4]; - void layer_enable(unsigned layer, unsigned priority, bool enable); - unsigned frameskip; - unsigned framecounter; - void set_frameskip(unsigned frameskip); - - void serialize(serializer&); - PPU(); - ~PPU(); + uint frameskip; + uint framecounter; }; extern PPU ppu; diff --git a/sfc/alt/ppu-balanced/render/addsub.cpp b/sfc/alt/ppu-balanced/render/addsub.cpp index fc88bad3..fb320199 100644 --- a/sfc/alt/ppu-balanced/render/addsub.cpp +++ b/sfc/alt/ppu-balanced/render/addsub.cpp @@ -1,19 +1,17 @@ -#ifdef PPU_CPP - //color addition / subtraction //thanks go to blargg for the optimized algorithms -inline uint16 PPU::addsub(uint32 x, uint32 y, bool halve) { +inline auto PPU::addsub(uint32 x, uint32 y, bool halve) -> uint16 { if(!regs.color_mode) { if(!halve) { - unsigned sum = x + y; - unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420; + uint sum = x + y; + uint carry = (sum - ((x ^ y) & 0x0421)) & 0x8420; return (sum - carry) | (carry - (carry >> 5)); } else { return (x + y - ((x ^ y) & 0x0421)) >> 1; } } else { - unsigned diff = x - y + 0x8420; - unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420; + uint diff = x - y + 0x8420; + uint borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420; if(!halve) { return (diff - borrow) & (borrow - (borrow >> 5)); } else { @@ -21,5 +19,3 @@ inline uint16 PPU::addsub(uint32 x, uint32 y, bool halve) { } } } - -#endif diff --git a/sfc/alt/ppu-balanced/render/bg.cpp b/sfc/alt/ppu-balanced/render/bg.cpp index f7a5a1d6..54ad3a41 100644 --- a/sfc/alt/ppu-balanced/render/bg.cpp +++ b/sfc/alt/ppu-balanced/render/bg.cpp @@ -1,7 +1,5 @@ -#ifdef PPU_CPP - //called once at the start of every rendered scanline -void PPU::update_bg_info() { +auto PPU::update_bg_info() -> void { const unsigned hires = (regs.bg_mode == 5 || regs.bg_mode == 6); const unsigned width = (!hires ? 256 : 512); @@ -22,8 +20,8 @@ void PPU::update_bg_info() { } } -template -uint16 PPU::bg_get_tile(uint16 x, uint16 y) { +template +auto PPU::bg_get_tile(uint16 x, uint16 y) -> uint16 { x = (x & bg_info[bg].mx) >> bg_info[bg].tw; y = (y & bg_info[bg].my) >> bg_info[bg].th; @@ -51,8 +49,8 @@ uint16 PPU::bg_get_tile(uint16 x, uint16 y) { pixel_cache[x].ce_sub = false; \ } -template -void PPU::render_line_bg(uint8 pri0_pos, uint8 pri1_pos) { +template +auto PPU::render_line_bg(uint8 pri0_pos, uint8 pri1_pos) -> void { if(layer_enabled[bg][0] == false) pri0_pos = 0; if(layer_enabled[bg][1] == false) pri1_pos = 0; if(pri0_pos + pri1_pos == 0) return; @@ -205,5 +203,3 @@ void PPU::render_line_bg(uint8 pri0_pos, uint8 pri1_pos) { #undef setpixel_main #undef setpixel_sub - -#endif diff --git a/sfc/alt/ppu-balanced/render/cache.cpp b/sfc/alt/ppu-balanced/render/cache.cpp index 8e88b850..8bedcbe9 100644 --- a/sfc/alt/ppu-balanced/render/cache.cpp +++ b/sfc/alt/ppu-balanced/render/cache.cpp @@ -1,5 +1,3 @@ -#ifdef PPU_CPP - #define render_bg_tile_line_2bpp(mask) \ col = !!(d0 & mask) << 0; \ col += !!(d1 & mask) << 1; \ @@ -23,8 +21,8 @@ col += !!(d7 & mask) << 7; \ *dest++ = col -template -void PPU::render_bg_tile(uint16 tile_num) { +template +auto PPU::render_bg_tile(uint16 tile_num) -> void { uint8 col, d0, d1, d2, d3, d4, d5, d6, d7; if(color_depth == COLORDEPTH_4) { @@ -100,7 +98,7 @@ void PPU::render_bg_tile(uint16 tile_num) { #undef render_bg_tile_line_4bpp #undef render_bg_tile_line_8bpp -void PPU::flush_pixel_cache() { +auto PPU::flush_pixel_cache() -> void { uint16 main = get_palette(0); uint16 sub = (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6) ? main @@ -119,7 +117,7 @@ void PPU::flush_pixel_cache() { } while(i--); } -void PPU::alloc_tiledata_cache() { +auto PPU::alloc_tiledata_cache() -> void { bg_tiledata[TILE_2BIT] = new uint8_t[262144](); bg_tiledata[TILE_4BIT] = new uint8_t[131072](); bg_tiledata[TILE_8BIT] = new uint8_t[ 65536](); @@ -129,13 +127,13 @@ void PPU::alloc_tiledata_cache() { } //marks all tiledata cache entries as dirty -void PPU::flush_tiledata_cache() { +auto PPU::flush_tiledata_cache() -> void { for(unsigned i = 0; i < 4096; i++) bg_tiledata_state[TILE_2BIT][i] = 1; for(unsigned i = 0; i < 2048; i++) bg_tiledata_state[TILE_4BIT][i] = 1; for(unsigned i = 0; i < 1024; i++) bg_tiledata_state[TILE_8BIT][i] = 1; } -void PPU::free_tiledata_cache() { +auto PPU::free_tiledata_cache() -> void { delete[] bg_tiledata[TILE_2BIT]; delete[] bg_tiledata[TILE_4BIT]; delete[] bg_tiledata[TILE_8BIT]; @@ -143,5 +141,3 @@ void PPU::free_tiledata_cache() { delete[] bg_tiledata_state[TILE_4BIT]; delete[] bg_tiledata_state[TILE_8BIT]; } - -#endif diff --git a/sfc/alt/ppu-balanced/render/line.cpp b/sfc/alt/ppu-balanced/render/line.cpp index 298013d8..430a8cd9 100644 --- a/sfc/alt/ppu-balanced/render/line.cpp +++ b/sfc/alt/ppu-balanced/render/line.cpp @@ -1,20 +1,18 @@ -#ifdef PPU_CPP - -inline uint16 PPU::get_palette(uint8 index) { - const unsigned addr = index << 1; +inline auto PPU::get_palette(uint8 index) -> uint16 { + const uint addr = index << 1; return cgram[addr] + (cgram[addr + 1] << 8); } //p = 00000bgr //t = BBGGGRRR //r = 0BBb00GGGg0RRRr0 -inline uint16 PPU::get_direct_color(uint8 p, uint8 t) { +inline auto PPU::get_direct_color(uint8 p, uint8 t) -> uint16 { return ((t & 7) << 2) | ((p & 1) << 1) | (((t >> 3) & 7) << 7) | (((p >> 1) & 1) << 6) | ((t >> 6) << 13) | ((p >> 2) << 12); } -inline uint16 PPU::get_pixel_normal(uint32 x) { +inline auto PPU::get_pixel_normal(uint32 x) -> uint16 { pixel_t& p = pixel_cache[x]; uint16 src_main, src_sub; uint8 bg_sub; @@ -50,7 +48,7 @@ inline uint16 PPU::get_pixel_normal(uint32 x) { return src_main; } -inline uint16 PPU::get_pixel_swap(uint32 x) { +inline auto PPU::get_pixel_swap(uint32 x) -> uint16 { pixel_t& p = pixel_cache[x]; uint16 src_main, src_sub; uint8 bg_sub; @@ -86,7 +84,7 @@ inline uint16 PPU::get_pixel_swap(uint32 x) { return src_main; } -inline void PPU::render_line_output() { +inline auto PPU::render_line_output() -> void { uint32* ptr = (uint32*)output + (line * 1024) + ((interlace() && field()) ? 512 : 0); uint32 curr, prev; @@ -111,10 +109,8 @@ inline void PPU::render_line_output() { } } -inline void PPU::render_line_clear() { +inline auto PPU::render_line_clear() -> void { uint32* ptr = (uint32*)output + (line * 1024) + ((interlace() && field()) ? 512 : 0); - unsigned width = (!regs.pseudo_hires && regs.bg_mode != 5 && regs.bg_mode != 6) ? 256 : 512; + uint width = (!regs.pseudo_hires && regs.bg_mode != 5 && regs.bg_mode != 6) ? 256 : 512; memset(ptr, 0, width * 2 * sizeof(uint32)); } - -#endif diff --git a/sfc/alt/ppu-balanced/render/mode7.cpp b/sfc/alt/ppu-balanced/render/mode7.cpp index f3b5ba9b..f4bff7c9 100644 --- a/sfc/alt/ppu-balanced/render/mode7.cpp +++ b/sfc/alt/ppu-balanced/render/mode7.cpp @@ -1,5 +1,3 @@ -#ifdef PPU_CPP - //bsnes mode7 renderer // //base algorithm written by anomie @@ -12,8 +10,8 @@ //--s---vvvvvvvvvv -> ssssssvvvvvvvvvv #define CLIP(x) ( ((x) & 0x2000) ? ( (x) | ~0x03ff) : ((x) & 0x03ff) ) -template -void PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) { +template +auto PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) -> void { if(layer_enabled[bg][0] == false) pri0_pos = 0; if(layer_enabled[bg][1] == false) pri1_pos = 0; if(pri0_pos + pri1_pos == 0) return; @@ -140,5 +138,3 @@ void PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) { } #undef CLIP - -#endif diff --git a/sfc/alt/ppu-balanced/render/oam.cpp b/sfc/alt/ppu-balanced/render/oam.cpp index c7415271..b5eae808 100644 --- a/sfc/alt/ppu-balanced/render/oam.cpp +++ b/sfc/alt/ppu-balanced/render/oam.cpp @@ -1,6 +1,4 @@ -#ifdef PPU_CPP - -void PPU::update_sprite_list(unsigned addr, uint8 data) { +auto PPU::update_sprite_list(uint addr, uint8 data) -> void { if(addr < 0x0200) { unsigned i = addr >> 2; switch(addr & 3) { @@ -26,7 +24,7 @@ void PPU::update_sprite_list(unsigned addr, uint8 data) { } } -void PPU::build_sprite_list() { +auto PPU::build_sprite_list() -> void { if(sprite_list_valid == true) return; sprite_list_valid = true; @@ -65,7 +63,7 @@ void PPU::build_sprite_list() { } } -bool PPU::is_sprite_on_scanline() { +auto PPU::is_sprite_on_scanline() -> bool { //if sprite is entirely offscreen and doesn't wrap around to the left side of the screen, //then it is not counted. this *should* be 256, and not 255, even though dot 256 is offscreen. sprite_item* spr = &sprite_list[active_sprite]; @@ -77,7 +75,7 @@ bool PPU::is_sprite_on_scanline() { return false; } -void PPU::load_oam_tiles() { +auto PPU::load_oam_tiles() -> void { sprite_item* spr = &sprite_list[active_sprite]; uint16 tile_width = spr->width >> 3; int x = spr->x; @@ -130,7 +128,7 @@ void PPU::load_oam_tiles() { } } -void PPU::render_oam_tile(int tile_num) { +auto PPU::render_oam_tile(int tile_num) -> void { oam_tileitem* t = &oam_tilelist[tile_num]; uint8* oam_td = (uint8*)bg_tiledata[COLORDEPTH_16]; uint8* oam_td_state = (uint8*)bg_tiledata_state[COLORDEPTH_16]; @@ -155,7 +153,7 @@ void PPU::render_oam_tile(int tile_num) { } } -void PPU::render_line_oam_rto() { +auto PPU::render_line_oam_rto() -> void { build_sprite_list(); regs.oam_itemcount = 0; @@ -200,7 +198,7 @@ void PPU::render_line_oam_rto() { pixel_cache[x].ce_sub = (oam_line_pal[x] < 192); \ } -void PPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) { +auto PPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) -> void { if(layer_enabled[OAM][0] == false) pri0_pos = 0; if(layer_enabled[OAM][1] == false) pri1_pos = 0; if(layer_enabled[OAM][2] == false) pri2_pos = 0; @@ -233,5 +231,3 @@ void PPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 #undef setpixel_main #undef setpixel_sub - -#endif diff --git a/sfc/alt/ppu-balanced/render/render.cpp b/sfc/alt/ppu-balanced/render/render.cpp index 5d558e1b..ea6f60ce 100644 --- a/sfc/alt/ppu-balanced/render/render.cpp +++ b/sfc/alt/ppu-balanced/render/render.cpp @@ -1,5 +1,3 @@ -#ifdef PPU_CPP - #include "cache.cpp" #include "windows.cpp" #include "bg.cpp" @@ -11,7 +9,7 @@ //Mode 0: -> // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 // BG4B, BG3B, OAM0, BG4A, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3 -void PPU::render_line_mode0() { +auto PPU::render_line_mode0() -> void { render_line_bg<0, BG1, COLORDEPTH_4>(8, 11); render_line_bg<0, BG2, COLORDEPTH_4>(7, 10); render_line_bg<0, BG3, COLORDEPTH_4>(2, 5); @@ -26,7 +24,7 @@ void PPU::render_line_mode0() { //Mode 1 (pri=0): -> // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 // BG3B, OAM0, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3 -void PPU::render_line_mode1() { +auto PPU::render_line_mode1() -> void { if(regs.bg3_priority) { render_line_bg<1, BG1, COLORDEPTH_16>(5, 8); render_line_bg<1, BG2, COLORDEPTH_16>(4, 7); @@ -43,7 +41,7 @@ void PPU::render_line_mode1() { //Mode 2: -> // 1, 2, 3, 4, 5, 6, 7, 8 // BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 -void PPU::render_line_mode2() { +auto PPU::render_line_mode2() -> void { render_line_bg<2, BG1, COLORDEPTH_16>(3, 7); render_line_bg<2, BG2, COLORDEPTH_16>(1, 5); render_line_oam(2, 4, 6, 8); @@ -52,7 +50,7 @@ void PPU::render_line_mode2() { //Mode 3: -> // 1, 2, 3, 4, 5, 6, 7, 8 // BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 -void PPU::render_line_mode3() { +auto PPU::render_line_mode3() -> void { render_line_bg<3, BG1, COLORDEPTH_256>(3, 7); render_line_bg<3, BG2, COLORDEPTH_16 >(1, 5); render_line_oam(2, 4, 6, 8); @@ -61,7 +59,7 @@ void PPU::render_line_mode3() { //Mode 4: -> // 1, 2, 3, 4, 5, 6, 7, 8 // BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 -void PPU::render_line_mode4() { +auto PPU::render_line_mode4() -> void { render_line_bg<4, BG1, COLORDEPTH_256>(3, 7); render_line_bg<4, BG2, COLORDEPTH_4 >(1, 5); render_line_oam(2, 4, 6, 8); @@ -70,7 +68,7 @@ void PPU::render_line_mode4() { //Mode 5: -> // 1, 2, 3, 4, 5, 6, 7, 8 // BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 -void PPU::render_line_mode5() { +auto PPU::render_line_mode5() -> void { render_line_bg<5, BG1, COLORDEPTH_16>(3, 7); render_line_bg<5, BG2, COLORDEPTH_4 >(1, 5); render_line_oam(2, 4, 6, 8); @@ -79,7 +77,7 @@ void PPU::render_line_mode5() { //Mode 6: -> // 1, 2, 3, 4, 5, 6 // OAM0, BG1B, OAM1, OAM2, BG1A, OAM3 -void PPU::render_line_mode6() { +auto PPU::render_line_mode6() -> void { render_line_bg<6, BG1, COLORDEPTH_16>(2, 5); render_line_oam(1, 3, 4, 6); } @@ -91,7 +89,7 @@ void PPU::render_line_mode6() { //Mode 7 EXTBG: -> // 1, 2, 3, 4, 5, 6, 7 // BG2B, OAM0, BG1n, OAM1, BG2A, OAM2, OAM3 -void PPU::render_line_mode7() { +auto PPU::render_line_mode7() -> void { if(regs.mode7_extbg == false) { render_line_mode7(2, 2); render_line_oam(1, 3, 4, 5); @@ -102,7 +100,7 @@ void PPU::render_line_mode7() { } } -void PPU::render_line() { +auto PPU::render_line() -> void { if(regs.display_disabled == true) { render_line_clear(); return; @@ -125,5 +123,3 @@ void PPU::render_line() { render_line_output(); } - -#endif diff --git a/sfc/alt/ppu-balanced/render/render.hpp b/sfc/alt/ppu-balanced/render/render.hpp index 9f7545d5..73d0cc33 100644 --- a/sfc/alt/ppu-balanced/render/render.hpp +++ b/sfc/alt/ppu-balanced/render/render.hpp @@ -1,16 +1,16 @@ //render.cpp -inline void render_line_mode0(); -inline void render_line_mode1(); -inline void render_line_mode2(); -inline void render_line_mode3(); -inline void render_line_mode4(); -inline void render_line_mode5(); -inline void render_line_mode6(); -inline void render_line_mode7(); +inline auto render_line_mode0() -> void; +inline auto render_line_mode1() -> void; +inline auto render_line_mode2() -> void; +inline auto render_line_mode3() -> void; +inline auto render_line_mode4() -> void; +inline auto render_line_mode5() -> void; +inline auto render_line_mode6() -> void; +inline auto render_line_mode7() -> void; //cache.cpp -enum { COLORDEPTH_4 = 0, COLORDEPTH_16 = 1, COLORDEPTH_256 = 2 }; -enum { TILE_2BIT = 0, TILE_4BIT = 1, TILE_8BIT = 2 }; +enum : uint { COLORDEPTH_4 = 0, COLORDEPTH_16 = 1, COLORDEPTH_256 = 2 }; +enum : uint { TILE_2BIT = 0, TILE_4BIT = 1, TILE_8BIT = 2 }; struct pixel_t { //bgr555 color data for main/subscreen pixels: 0x0000 = transparent / use palette color # 0 @@ -28,19 +28,19 @@ struct pixel_t { uint8* bg_tiledata[3]; uint8* bg_tiledata_state[3]; //0 = valid, 1 = dirty -template void render_bg_tile(uint16 tile_num); -inline void flush_pixel_cache(); -void alloc_tiledata_cache(); -void flush_tiledata_cache(); -void free_tiledata_cache(); +template auto render_bg_tile(uint16 tile_num) -> void; +inline auto flush_pixel_cache() -> void; +auto alloc_tiledata_cache() -> void; +auto flush_tiledata_cache() -> void; +auto free_tiledata_cache() -> void; //windows.cpp struct window_t { uint8 main[256], sub[256]; } window[6]; -void build_window_table(uint8 bg, bool mainscreen); -void build_window_tables(uint8 bg); +auto build_window_table(uint8 bg, bool mainscreen) -> void; +auto build_window_tables(uint8 bg) -> void; //bg.cpp struct { @@ -48,10 +48,10 @@ struct { uint16 mx, my; //screen mask x, y uint16 scx, scy; //sc index offsets } bg_info[4]; -void update_bg_info(); +auto update_bg_info() -> void; -template uint16 bg_get_tile(uint16 x, uint16 y); -template void render_line_bg(uint8 pri0_pos, uint8 pri1_pos); +template auto bg_get_tile(uint16 x, uint16 y) -> uint16; +template auto render_line_bg(uint8 pri0_pos, uint8 pri1_pos) -> void; //oam.cpp struct sprite_item { @@ -65,7 +65,7 @@ struct sprite_item { bool size; } sprite_list[128]; bool sprite_list_valid; -unsigned active_sprite; +uint active_sprite; uint8 oam_itemlist[32]; struct oam_tileitem { @@ -73,27 +73,27 @@ struct oam_tileitem { bool hflip; } oam_tilelist[34]; -enum { OAM_PRI_NONE = 4 }; +enum : uint { OAM_PRI_NONE = 4 }; uint8 oam_line_pal[256], oam_line_pri[256]; -void update_sprite_list(unsigned addr, uint8 data); -void build_sprite_list(); -bool is_sprite_on_scanline(); -void load_oam_tiles(); -void render_oam_tile(int tile_num); -void render_line_oam_rto(); -void render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos); +auto update_sprite_list(unsigned addr, uint8 data) -> void; +auto build_sprite_list() -> void; +auto is_sprite_on_scanline() -> bool; +auto load_oam_tiles() -> void; +auto render_oam_tile(int tile_num) -> void; +auto render_line_oam_rto() -> void; +auto render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) -> void; //mode7.cpp -template void render_line_mode7(uint8 pri0_pos, uint8 pri1_pos); +template auto render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) -> void; //addsub.cpp -inline uint16 addsub(uint32 x, uint32 y, bool halve); +inline auto addsub(uint32 x, uint32 y, bool halve) -> uint16; //line.cpp -inline uint16 get_palette(uint8 index); -inline uint16 get_direct_color(uint8 p, uint8 t); -inline uint16 get_pixel_normal(uint32 x); -inline uint16 get_pixel_swap(uint32 x); -void render_line_output(); -void render_line_clear(); +inline auto get_palette(uint8 index) -> uint16; +inline auto get_direct_color(uint8 p, uint8 t) -> uint16; +inline auto get_pixel_normal(uint32 x) -> uint16; +inline auto get_pixel_swap(uint32 x) -> uint16; +auto render_line_output() -> void; +auto render_line_clear() -> void; diff --git a/sfc/alt/ppu-balanced/render/windows.cpp b/sfc/alt/ppu-balanced/render/windows.cpp index 79e1347e..1d95212d 100644 --- a/sfc/alt/ppu-balanced/render/windows.cpp +++ b/sfc/alt/ppu-balanced/render/windows.cpp @@ -1,7 +1,5 @@ -#ifdef PPU_CPP - //screen: 0 = main, 1 = sub -void PPU::build_window_table(uint8 bg, bool screen) { +auto PPU::build_window_table(uint8 bg, bool screen) -> void { bool set = 1, clr = 0; uint8* table = (screen == 0 ? window[bg].main : window[bg].sub); @@ -62,9 +60,7 @@ void PPU::build_window_table(uint8 bg, bool screen) { } } -void PPU::build_window_tables(uint8 bg) { +auto PPU::build_window_tables(uint8 bg) -> void { build_window_table(bg, 0); build_window_table(bg, 1); } - -#endif diff --git a/sfc/alt/ppu-balanced/serialization.cpp b/sfc/alt/ppu-balanced/serialization.cpp index 282fd65e..797b598c 100644 --- a/sfc/alt/ppu-balanced/serialization.cpp +++ b/sfc/alt/ppu-balanced/serialization.cpp @@ -1,6 +1,4 @@ -#ifdef PPU_CPP - -void PPUcounter::serialize(serializer& s) { +auto PPUcounter::serialize(serializer& s) -> void { s.integer(status.interlace); s.integer(status.field); s.integer(status.vcounter); @@ -12,7 +10,7 @@ void PPUcounter::serialize(serializer& s) { s.integer(history.index); } -void PPU::serialize(serializer& s) { +auto PPU::serialize(serializer& s) -> void { Thread::serialize(s); PPUcounter::serialize(s); @@ -35,7 +33,7 @@ void PPU::serialize(serializer& s) { s.integer(regs.ppu1_mdr); s.integer(regs.ppu2_mdr); - for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_y[n]); + for(uint n = 0; n < 4; n++) s.integer(regs.bg_y[n]); s.integer(regs.ioamaddr); s.integer(regs.icgramaddr); @@ -54,24 +52,24 @@ void PPU::serialize(serializer& s) { s.integer(regs.oam_latchdata); - for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_tilesize[n]); + for(uint n = 0; n < 4; n++) s.integer(regs.bg_tilesize[n]); s.integer(regs.bg3_priority); s.integer(regs.bg_mode); s.integer(regs.mosaic_size); - for(unsigned n = 0; n < 4; n++) s.integer(regs.mosaic_enabled[n]); + for(uint n = 0; n < 4; n++) s.integer(regs.mosaic_enabled[n]); s.integer(regs.mosaic_countdown); - for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_scaddr[n]); - for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_scsize[n]); + for(uint n = 0; n < 4; n++) s.integer(regs.bg_scaddr[n]); + for(uint n = 0; n < 4; n++) s.integer(regs.bg_scsize[n]); - for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_tdaddr[n]); + for(uint n = 0; n < 4; n++) s.integer(regs.bg_tdaddr[n]); s.integer(regs.bg_ofslatch); s.integer(regs.m7_hofs); s.integer(regs.m7_vofs); - for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_hofs[n]); - for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_vofs[n]); + for(uint n = 0; n < 4; n++) s.integer(regs.bg_hofs[n]); + for(uint n = 0; n < 4; n++) s.integer(regs.bg_vofs[n]); s.integer(regs.vram_incmode); s.integer(regs.vram_mapping); @@ -95,21 +93,21 @@ void PPU::serialize(serializer& s) { s.integer(regs.cgram_latchdata); - for(unsigned n = 0; n < 6; n++) s.integer(regs.window1_enabled[n]); - for(unsigned n = 0; n < 6; n++) s.integer(regs.window1_invert [n]); - for(unsigned n = 0; n < 6; n++) s.integer(regs.window2_enabled[n]); - for(unsigned n = 0; n < 6; n++) s.integer(regs.window2_invert [n]); + for(uint n = 0; n < 6; n++) s.integer(regs.window1_enabled[n]); + for(uint n = 0; n < 6; n++) s.integer(regs.window1_invert [n]); + for(uint n = 0; n < 6; n++) s.integer(regs.window2_enabled[n]); + for(uint n = 0; n < 6; n++) s.integer(regs.window2_invert [n]); s.integer(regs.window1_left); s.integer(regs.window1_right); s.integer(regs.window2_left); s.integer(regs.window2_right); - for(unsigned n = 0; n < 6; n++) s.integer(regs.window_mask[n]); - for(unsigned n = 0; n < 5; n++) s.integer(regs.bg_enabled[n]); - for(unsigned n = 0; n < 5; n++) s.integer(regs.bgsub_enabled[n]); - for(unsigned n = 0; n < 5; n++) s.integer(regs.window_enabled[n]); - for(unsigned n = 0; n < 5; n++) s.integer(regs.sub_window_enabled[n]); + for(uint n = 0; n < 6; n++) s.integer(regs.window_mask[n]); + for(uint n = 0; n < 5; n++) s.integer(regs.bg_enabled[n]); + for(uint n = 0; n < 5; n++) s.integer(regs.bgsub_enabled[n]); + for(uint n = 0; n < 5; n++) s.integer(regs.window_enabled[n]); + for(uint n = 0; n < 5; n++) s.integer(regs.sub_window_enabled[n]); s.integer(regs.color_mask); s.integer(regs.colorsub_mask); @@ -118,7 +116,7 @@ void PPU::serialize(serializer& s) { s.integer(regs.color_mode); s.integer(regs.color_halve); - for(unsigned n = 0; n < 6; n++) s.integer(regs.color_enabled[n]); + for(uint n = 0; n < 6; n++) s.integer(regs.color_enabled[n]); s.integer(regs.color_r); s.integer(regs.color_g); @@ -145,7 +143,7 @@ void PPU::serialize(serializer& s) { s.integer(regs.oam_itemcount); s.integer(regs.oam_tilecount); - for(unsigned n = 0; n < 256; n++) { + for(uint n = 0; n < 256; n++) { s.integer(pixel_cache[n].src_main); s.integer(pixel_cache[n].src_sub); s.integer(pixel_cache[n].bg_main); @@ -159,12 +157,12 @@ void PPU::serialize(serializer& s) { //better to just take a small speed hit than store all of bg_tiledata[3][] ... flush_tiledata_cache(); - for(unsigned n = 0; n < 6; n++) { + for(uint n = 0; n < 6; n++) { s.array(window[n].main, 256); s.array(window[n].sub, 256); } - for(unsigned n = 0; n < 4; n++) { + for(uint n = 0; n < 4; n++) { s.integer(bg_info[n].tw); s.integer(bg_info[n].th); s.integer(bg_info[n].mx); @@ -173,7 +171,7 @@ void PPU::serialize(serializer& s) { s.integer(bg_info[n].scy); } - for(unsigned n = 0; n < 128; n++) { + for(uint n = 0; n < 128; n++) { s.integer(sprite_list[n].width); s.integer(sprite_list[n].height); s.integer(sprite_list[n].x); @@ -191,7 +189,7 @@ void PPU::serialize(serializer& s) { s.array(oam_itemlist, 32); - for(unsigned n = 0; n < 34; n++) { + for(uint n = 0; n < 34; n++) { s.integer(oam_tilelist[n].x); s.integer(oam_tilelist[n].y); s.integer(oam_tilelist[n].pri); @@ -203,5 +201,3 @@ void PPU::serialize(serializer& s) { s.array(oam_line_pal, 256); s.array(oam_line_pri, 256); } - -#endif diff --git a/sfc/alt/ppu-performance/mmio/mmio.cpp b/sfc/alt/ppu-performance/mmio/mmio.cpp index 46244e23..ca99aa33 100644 --- a/sfc/alt/ppu-performance/mmio/mmio.cpp +++ b/sfc/alt/ppu-performance/mmio/mmio.cpp @@ -158,7 +158,7 @@ void PPU::mmio_update_video_mode() { } uint8 PPU::mmio_read(unsigned addr) { - cpu.synchronize_ppu(); + cpu.synchronizePPU(); switch(addr & 0xffff) { case 0x2104: case 0x2105: case 0x2106: case 0x2108: case 0x2109: case 0x210a: @@ -279,7 +279,7 @@ uint8 PPU::mmio_read(unsigned addr) { } void PPU::mmio_write(unsigned addr, uint8 data) { - cpu.synchronize_ppu(); + cpu.synchronizePPU(); switch(addr & 0xffff) { case 0x2100: { //INIDISP diff --git a/sfc/alt/ppu-performance/ppu.cpp b/sfc/alt/ppu-performance/ppu.cpp index b598cc70..9c1f7728 100644 --- a/sfc/alt/ppu-performance/ppu.cpp +++ b/sfc/alt/ppu-performance/ppu.cpp @@ -97,7 +97,7 @@ void PPU::power() { } void PPU::reset() { - create(Enter, system.cpu_frequency()); + create(Enter, system.cpuFrequency()); PPUcounter::reset(); memset(surface, 0, 512 * 512 * sizeof(uint32)); mmio_reset(); diff --git a/sfc/alt/smp/smp.cpp b/sfc/alt/smp/smp.cpp index 21c7e0ce..0dded63d 100644 --- a/sfc/alt/smp/smp.cpp +++ b/sfc/alt/smp/smp.cpp @@ -33,7 +33,7 @@ void SMP::enter() { } void SMP::power() { - Thread::frequency = system.apu_frequency(); + Thread::frequency = system.apuFrequency(); Thread::clock = 0; timer0.target = 0; diff --git a/sfc/profile-performance.hpp b/sfc/profile-performance.hpp index 5809c498..da48b143 100644 --- a/sfc/profile-performance.hpp +++ b/sfc/profile-performance.hpp @@ -2,7 +2,6 @@ #error "bsnes: debugger not supported with performance profile." #endif -#include #include #include #include diff --git a/sfc/sfc.hpp b/sfc/sfc.hpp index dc13b736..767bce3e 100644 --- a/sfc/sfc.hpp +++ b/sfc/sfc.hpp @@ -26,6 +26,10 @@ namespace SuperFamicom { #include #include +#if defined(PROFILE_PERFORMANCE) + #include +#endif + namespace SuperFamicom { struct Thread { ~Thread() {