Renaming
This commit is contained in:
parent
d1993751f6
commit
b7788f946b
|
@ -1,7 +1,6 @@
|
||||||
#ifndef __HQN_H__
|
#ifndef __HQN_H__
|
||||||
#define __HQN_H__
|
#define __HQN_H__
|
||||||
|
|
||||||
#include <Nes_Emu.hpp>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@ -9,15 +8,15 @@
|
||||||
|
|
||||||
// Creating emulator instance
|
// Creating emulator instance
|
||||||
#ifdef _USE_QUICKNES
|
#ifdef _USE_QUICKNES
|
||||||
|
#include <Nes_Emu.hpp>
|
||||||
typedef Nes_Emu emulator_t;
|
typedef Nes_Emu emulator_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _USE_QUICKERNES
|
#ifdef _USE_QUICKERNES
|
||||||
typedef quickerNES::Nes_Emu emulator_t;
|
#include <emu.hpp>
|
||||||
|
typedef quickerNES::Emu emulator_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace hqn
|
namespace hqn
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _USE_QUICKERNES
|
#ifdef _USE_QUICKERNES
|
||||||
typedef quickerNES::Nes_Emu emulator_t;
|
typedef quickerNES::Emu emulator_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct stepData_t
|
struct stepData_t
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/libs/
|
// Nes_Emu 0.7.0. http://www.slack.net/~ant/libs/
|
||||||
|
|
||||||
#include "apu/Nes_Effects_Buffer.hpp"
|
#include "apu/NESEffectsBuffer.hpp"
|
||||||
#include "apu/apu.hpp"
|
#include "apu/apu.hpp"
|
||||||
|
|
||||||
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
|
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
|
||||||
|
@ -27,7 +27,7 @@ Nes_Effects_Buffer::Nes_Effects_Buffer() : Effects_Buffer(true) // nes never use
|
||||||
|
|
||||||
Nes_Effects_Buffer::~Nes_Effects_Buffer() {}
|
Nes_Effects_Buffer::~Nes_Effects_Buffer() {}
|
||||||
|
|
||||||
Multi_Buffer *set_apu(Nes_Effects_Buffer *buf, Nes_Apu *apu)
|
Multi_Buffer *set_apu(Nes_Effects_Buffer *buf, Apu *apu)
|
||||||
{
|
{
|
||||||
buf->set_apu(apu);
|
buf->set_apu(apu);
|
||||||
return buf;
|
return buf;
|
||||||
|
@ -35,9 +35,8 @@ Multi_Buffer *set_apu(Nes_Effects_Buffer *buf, Nes_Apu *apu)
|
||||||
|
|
||||||
void Nes_Effects_Buffer::enable_nonlinearity(bool b)
|
void Nes_Effects_Buffer::enable_nonlinearity(bool b)
|
||||||
{
|
{
|
||||||
if (b)
|
if (b) clear();
|
||||||
clear();
|
Apu *apu = nonlin.enable(b, channel(2).center);
|
||||||
Nes_Apu *apu = nonlin.enable(b, channel(2).center);
|
|
||||||
apu->osc_output(0, channel(0).center);
|
apu->osc_output(0, channel(0).center);
|
||||||
apu->osc_output(1, channel(1).center);
|
apu->osc_output(1, channel(1).center);
|
||||||
}
|
}
|
|
@ -3,8 +3,8 @@
|
||||||
// Effects_Buffer with non-linear sound
|
// Effects_Buffer with non-linear sound
|
||||||
// Nes_Emu 0.7.0
|
// Nes_Emu 0.7.0
|
||||||
|
|
||||||
#include "Effects_Buffer.hpp"
|
#include "effectsBuffer.hpp"
|
||||||
#include "Nes_Buffer.hpp"
|
#include "buffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ class Nes_Effects_Buffer : public Effects_Buffer
|
||||||
|
|
||||||
// Setup APU for use with buffer, including setting its output to this buffer.
|
// Setup APU for use with buffer, including setting its output to this buffer.
|
||||||
// If you're using Nes_Emu, this is automatically called for you.
|
// If you're using Nes_Emu, this is automatically called for you.
|
||||||
void set_apu(Nes_Apu *apu) { nonlin.set_apu(apu); }
|
void set_apu(Apu *apu) { nonlin.set_apu(apu); }
|
||||||
|
|
||||||
// Enable/disable non-linear output
|
// Enable/disable non-linear output
|
||||||
void enable_nonlinearity(bool = true);
|
void enable_nonlinearity(bool = true);
|
||||||
|
@ -34,8 +34,8 @@ class Nes_Effects_Buffer : public Effects_Buffer
|
||||||
void RestoreAudioBufferState();
|
void RestoreAudioBufferState();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Nes_Nonlinearizer nonlin;
|
Nonlinearizer nonlin;
|
||||||
friend Multi_Buffer *set_apu(Nes_Effects_Buffer *, Nes_Apu *);
|
friend Multi_Buffer *set_apu(Nes_Effects_Buffer *, Apu *);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickNES
|
|
@ -1,4 +1,4 @@
|
||||||
// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
// Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "apu.hpp"
|
#include "apu.hpp"
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ namespace quickerNES
|
||||||
|
|
||||||
int const amp_range = 15;
|
int const amp_range = 15;
|
||||||
|
|
||||||
Nes_Apu::Nes_Apu() : square1(&square_synth),
|
Apu::Apu() : square1(&square_synth),
|
||||||
square2(&square_synth)
|
square2(&square_synth)
|
||||||
{
|
{
|
||||||
dmc.apu = this;
|
dmc.apu = this;
|
||||||
|
@ -36,11 +36,11 @@ Nes_Apu::Nes_Apu() : square1(&square_synth),
|
||||||
reset(false);
|
reset(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Apu::~Nes_Apu()
|
Apu::~Apu()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Apu::treble_eq(const blip_eq_t &eq)
|
void Apu::treble_eq(const blip_eq_t &eq)
|
||||||
{
|
{
|
||||||
square_synth.treble_eq(eq);
|
square_synth.treble_eq(eq);
|
||||||
triangle.synth.treble_eq(eq);
|
triangle.synth.treble_eq(eq);
|
||||||
|
@ -48,7 +48,7 @@ void Nes_Apu::treble_eq(const blip_eq_t &eq)
|
||||||
dmc.synth.treble_eq(eq);
|
dmc.synth.treble_eq(eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Apu::enable_nonlinear(double v)
|
void Apu::enable_nonlinear(double v)
|
||||||
{
|
{
|
||||||
dmc.nonlinear = true;
|
dmc.nonlinear = true;
|
||||||
square_synth.volume(1.3 * 0.25751258 / 0.742467605 * 0.25 / amp_range * v);
|
square_synth.volume(1.3 * 0.25751258 / 0.742467605 * 0.25 / amp_range * v);
|
||||||
|
@ -65,7 +65,7 @@ void Nes_Apu::enable_nonlinear(double v)
|
||||||
dmc.last_amp = 0;
|
dmc.last_amp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Apu::volume(double v)
|
void Apu::volume(double v)
|
||||||
{
|
{
|
||||||
dmc.nonlinear = false;
|
dmc.nonlinear = false;
|
||||||
square_synth.volume(0.1128 / amp_range * v);
|
square_synth.volume(0.1128 / amp_range * v);
|
||||||
|
@ -74,13 +74,13 @@ void Nes_Apu::volume(double v)
|
||||||
dmc.synth.volume(0.42545 / 127 * v);
|
dmc.synth.volume(0.42545 / 127 * v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Apu::output(Blip_Buffer *buffer)
|
void Apu::output(Blip_Buffer *buffer)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < osc_count; i++)
|
for (int i = 0; i < osc_count; i++)
|
||||||
osc_output(i, buffer);
|
osc_output(i, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Apu::reset(bool pal_mode, int initial_dmc_dac)
|
void Apu::reset(bool pal_mode, int initial_dmc_dac)
|
||||||
{
|
{
|
||||||
// to do: time pal frame periods exactly
|
// to do: time pal frame periods exactly
|
||||||
frame_period = pal_mode ? 8314 : 7458;
|
frame_period = pal_mode ? 8314 : 7458;
|
||||||
|
@ -111,7 +111,7 @@ void Nes_Apu::reset(bool pal_mode, int initial_dmc_dac)
|
||||||
// dmc.last_amp = initial_dmc_dac; // prevent output transition
|
// dmc.last_amp = initial_dmc_dac; // prevent output transition
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Apu::irq_changed()
|
void Apu::irq_changed()
|
||||||
{
|
{
|
||||||
nes_time_t new_irq = dmc.next_irq;
|
nes_time_t new_irq = dmc.next_irq;
|
||||||
if (dmc.irq_flag | irq_flag)
|
if (dmc.irq_flag | irq_flag)
|
||||||
|
@ -133,7 +133,7 @@ void Nes_Apu::irq_changed()
|
||||||
|
|
||||||
// frames
|
// frames
|
||||||
|
|
||||||
void Nes_Apu::run_until(nes_time_t end_time)
|
void Apu::run_until(nes_time_t end_time)
|
||||||
{
|
{
|
||||||
if (end_time > next_dmc_read_time())
|
if (end_time > next_dmc_read_time())
|
||||||
{
|
{
|
||||||
|
@ -143,7 +143,7 @@ void Nes_Apu::run_until(nes_time_t end_time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Apu::run_until_(nes_time_t end_time)
|
void Apu::run_until_(nes_time_t end_time)
|
||||||
{
|
{
|
||||||
if (end_time == last_time)
|
if (end_time == last_time)
|
||||||
return;
|
return;
|
||||||
|
@ -227,7 +227,7 @@ inline void zero_apu_osc(T *osc, nes_time_t time)
|
||||||
osc->synth.offset(time, -last_amp, output);
|
osc->synth.offset(time, -last_amp, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Apu::end_frame(nes_time_t end_time)
|
void Apu::end_frame(nes_time_t end_time)
|
||||||
{
|
{
|
||||||
if (end_time > last_time)
|
if (end_time > last_time)
|
||||||
run_until_(end_time);
|
run_until_(end_time);
|
||||||
|
@ -266,7 +266,7 @@ void Nes_Apu::end_frame(nes_time_t end_time)
|
||||||
static const unsigned char length_table[0x20] = {
|
static const unsigned char length_table[0x20] = {
|
||||||
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};
|
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};
|
||||||
|
|
||||||
void Nes_Apu::write_register(nes_time_t time, nes_addr_t addr, int data)
|
void Apu::write_register(nes_time_t time, nes_addr_t addr, int data)
|
||||||
{
|
{
|
||||||
// Ignore addresses outside range
|
// Ignore addresses outside range
|
||||||
if (addr < start_addr || end_addr < addr)
|
if (addr < start_addr || end_addr < addr)
|
||||||
|
@ -278,7 +278,7 @@ void Nes_Apu::write_register(nes_time_t time, nes_addr_t addr, int data)
|
||||||
{
|
{
|
||||||
// Write to channel
|
// Write to channel
|
||||||
int osc_index = (addr - start_addr) >> 2;
|
int osc_index = (addr - start_addr) >> 2;
|
||||||
Nes_Osc *osc = oscs[osc_index];
|
Osc *osc = oscs[osc_index];
|
||||||
|
|
||||||
int reg = addr & 3;
|
int reg = addr & 3;
|
||||||
osc->regs[reg] = data;
|
osc->regs[reg] = data;
|
||||||
|
@ -297,7 +297,7 @@ void Nes_Apu::write_register(nes_time_t time, nes_addr_t addr, int data)
|
||||||
|
|
||||||
// reset square phase
|
// reset square phase
|
||||||
if (osc_index < 2)
|
if (osc_index < 2)
|
||||||
((Nes_Square *)osc)->phase = Nes_Square::phase_range - 1;
|
((Square *)osc)->phase = Square::phase_range - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (addr == 0x4015)
|
else if (addr == 0x4015)
|
||||||
|
@ -351,7 +351,7 @@ void Nes_Apu::write_register(nes_time_t time, nes_addr_t addr, int data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Nes_Apu::read_status(nes_time_t time)
|
int Apu::read_status(nes_time_t time)
|
||||||
{
|
{
|
||||||
run_until_(time - 1);
|
run_until_(time - 1);
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// NES 2A03 APU sound chip emulator
|
// NES 2A03 APU sound chip emulator
|
||||||
// Nes_Snd_Emu 0.1.7
|
// Snd_Emu 0.1.7
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "Nes_Oscs.hpp"
|
#include "oscs.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Nes_Apu
|
class Apu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef uint8_t env_t[3];
|
typedef uint8_t env_t[3];
|
||||||
|
@ -82,8 +82,8 @@ class Nes_Apu
|
||||||
};
|
};
|
||||||
static_assert(sizeof(apu_state_t) == 72);
|
static_assert(sizeof(apu_state_t) == 72);
|
||||||
|
|
||||||
Nes_Apu();
|
Apu();
|
||||||
~Nes_Apu();
|
~Apu();
|
||||||
|
|
||||||
// Set buffer to generate all sound into, or disable sound if NULL
|
// Set buffer to generate all sound into, or disable sound if NULL
|
||||||
void output(Blip_Buffer *);
|
void output(Blip_Buffer *);
|
||||||
|
@ -162,23 +162,23 @@ class Nes_Apu
|
||||||
|
|
||||||
// End of public interface.
|
// End of public interface.
|
||||||
private:
|
private:
|
||||||
friend class Nes_Nonlinearizer;
|
friend class Nonlinearizer;
|
||||||
void enable_nonlinear(double volume);
|
void enable_nonlinear(double volume);
|
||||||
static double nonlinear_tnd_gain() { return 0.75; }
|
static double nonlinear_tnd_gain() { return 0.75; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct Nes_Dmc;
|
friend struct Dmc;
|
||||||
|
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Nes_Apu(const Nes_Apu &);
|
Apu(const Apu &);
|
||||||
Nes_Apu &operator=(const Nes_Apu &);
|
Apu &operator=(const Apu &);
|
||||||
|
|
||||||
Nes_Osc *oscs[osc_count];
|
Osc *oscs[osc_count];
|
||||||
Nes_Square square1;
|
Square square1;
|
||||||
Nes_Square square2;
|
Square square2;
|
||||||
Nes_Noise noise;
|
Noise noise;
|
||||||
Nes_Triangle triangle;
|
Triangle triangle;
|
||||||
Nes_Dmc dmc;
|
Dmc dmc;
|
||||||
|
|
||||||
nes_time_t last_time; // has been run until this time in current frame
|
nes_time_t last_time; // has been run until this time in current frame
|
||||||
nes_time_t last_dmc_time;
|
nes_time_t last_dmc_time;
|
||||||
|
@ -192,66 +192,66 @@ class Nes_Apu
|
||||||
bool irq_flag;
|
bool irq_flag;
|
||||||
void (*irq_notifier_)(void *user_data);
|
void (*irq_notifier_)(void *user_data);
|
||||||
void *irq_data;
|
void *irq_data;
|
||||||
Nes_Square::Synth square_synth; // shared by squares
|
Square::Synth square_synth; // shared by squares
|
||||||
|
|
||||||
void irq_changed();
|
void irq_changed();
|
||||||
void state_restored();
|
void state_restored();
|
||||||
void run_until_(nes_time_t);
|
void run_until_(nes_time_t);
|
||||||
|
|
||||||
// TODO: remove
|
// TODO: remove
|
||||||
friend class Nes_Core;
|
friend class Core;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Nes_Apu::osc_output(int osc, Blip_Buffer *buf)
|
inline void Apu::osc_output(int osc, Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
oscs[osc]->output = buf;
|
oscs[osc]->output = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline nes_time_t Nes_Apu::earliest_irq(nes_time_t) const
|
inline nes_time_t Apu::earliest_irq(nes_time_t) const
|
||||||
{
|
{
|
||||||
return earliest_irq_;
|
return earliest_irq_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Apu::dmc_reader(int (*func)(void *, nes_addr_t), void *user_data)
|
inline void Apu::dmc_reader(int (*func)(void *, nes_addr_t), void *user_data)
|
||||||
{
|
{
|
||||||
dmc.prg_reader_data = user_data;
|
dmc.prg_reader_data = user_data;
|
||||||
dmc.prg_reader = func;
|
dmc.prg_reader = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Apu::irq_notifier(void (*func)(void *user_data), void *user_data)
|
inline void Apu::irq_notifier(void (*func)(void *user_data), void *user_data)
|
||||||
{
|
{
|
||||||
irq_notifier_ = func;
|
irq_notifier_ = func;
|
||||||
irq_data = user_data;
|
irq_data = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Nes_Apu::count_dmc_reads(nes_time_t time, nes_time_t *last_read) const
|
inline int Apu::count_dmc_reads(nes_time_t time, nes_time_t *last_read) const
|
||||||
{
|
{
|
||||||
return dmc.count_reads(time, last_read);
|
return dmc.count_reads(time, last_read);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline nes_time_t Nes_Dmc::next_read_time() const
|
inline nes_time_t Dmc::next_read_time() const
|
||||||
{
|
{
|
||||||
if (length_counter == 0)
|
if (length_counter == 0)
|
||||||
return Nes_Apu::no_irq; // not reading
|
return Apu::no_irq; // not reading
|
||||||
|
|
||||||
return apu->last_dmc_time + delay + long(bits_remain - 1) * period;
|
return apu->last_dmc_time + delay + long(bits_remain - 1) * period;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline nes_time_t Nes_Apu::next_dmc_read_time() const { return dmc.next_read_time(); }
|
inline nes_time_t Apu::next_dmc_read_time() const { return dmc.next_read_time(); }
|
||||||
|
|
||||||
template <int mode>
|
template <int mode>
|
||||||
struct apu_reflection
|
struct apu_reflection
|
||||||
{
|
{
|
||||||
#define REFLECT(apu, state) (mode ? void(apu = state) : void(state = apu))
|
#define REFLECT(apu, state) (mode ? void(apu = state) : void(state = apu))
|
||||||
|
|
||||||
static void reflect_env(Nes_Apu::env_t *state, Nes_Envelope &osc)
|
static void reflect_env(Apu::env_t *state, Envelope &osc)
|
||||||
{
|
{
|
||||||
REFLECT((*state)[0], osc.env_delay);
|
REFLECT((*state)[0], osc.env_delay);
|
||||||
REFLECT((*state)[1], osc.envelope);
|
REFLECT((*state)[1], osc.envelope);
|
||||||
REFLECT((*state)[2], osc.reg_written[3]);
|
REFLECT((*state)[2], osc.reg_written[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reflect_square(Nes_Apu::square_t &state, Nes_Square &osc)
|
static void reflect_square(Apu::square_t &state, Square &osc)
|
||||||
{
|
{
|
||||||
reflect_env(&state.env, osc);
|
reflect_env(&state.env, osc);
|
||||||
REFLECT(state.delay, osc.delay);
|
REFLECT(state.delay, osc.delay);
|
||||||
|
@ -261,7 +261,7 @@ struct apu_reflection
|
||||||
REFLECT(state.swp_reset, osc.reg_written[1]);
|
REFLECT(state.swp_reset, osc.reg_written[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reflect_triangle(Nes_Apu::triangle_t &state, Nes_Triangle &osc)
|
static void reflect_triangle(Apu::triangle_t &state, Triangle &osc)
|
||||||
{
|
{
|
||||||
REFLECT(state.delay, osc.delay);
|
REFLECT(state.delay, osc.delay);
|
||||||
REFLECT(state.length_counter, osc.length_counter);
|
REFLECT(state.length_counter, osc.length_counter);
|
||||||
|
@ -270,7 +270,7 @@ struct apu_reflection
|
||||||
REFLECT(state.linear_mode, osc.reg_written[3]);
|
REFLECT(state.linear_mode, osc.reg_written[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reflect_noise(Nes_Apu::noise_t &state, Nes_Noise &osc)
|
static void reflect_noise(Apu::noise_t &state, Noise &osc)
|
||||||
{
|
{
|
||||||
reflect_env(&state.env, osc);
|
reflect_env(&state.env, osc);
|
||||||
REFLECT(state.delay, osc.delay);
|
REFLECT(state.delay, osc.delay);
|
||||||
|
@ -278,7 +278,7 @@ struct apu_reflection
|
||||||
REFLECT(state.shift_reg, osc.noise);
|
REFLECT(state.shift_reg, osc.noise);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reflect_dmc(Nes_Apu::dmc_t &state, Nes_Dmc &osc)
|
static void reflect_dmc(Apu::dmc_t &state, Dmc &osc)
|
||||||
{
|
{
|
||||||
REFLECT(state.delay, osc.delay);
|
REFLECT(state.delay, osc.delay);
|
||||||
REFLECT(state.remain, osc.length_counter);
|
REFLECT(state.remain, osc.length_counter);
|
||||||
|
@ -295,7 +295,7 @@ struct apu_reflection
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Nes_Apu::save_state(apu_state_t *state) const
|
inline void Apu::save_state(apu_state_t *state) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < osc_count * 4; i++)
|
for (int i = 0; i < osc_count * 4; i++)
|
||||||
{
|
{
|
||||||
|
@ -313,7 +313,7 @@ inline void Nes_Apu::save_state(apu_state_t *state) const
|
||||||
state->apu.irq_flag = irq_flag;
|
state->apu.irq_flag = irq_flag;
|
||||||
|
|
||||||
typedef apu_reflection<1> refl;
|
typedef apu_reflection<1> refl;
|
||||||
Nes_Apu &apu = *(Nes_Apu *)this; // const_cast
|
Apu &apu = *(Apu *)this; // const_cast
|
||||||
refl::reflect_square(state->square1, apu.square1);
|
refl::reflect_square(state->square1, apu.square1);
|
||||||
refl::reflect_square(state->square2, apu.square2);
|
refl::reflect_square(state->square2, apu.square2);
|
||||||
refl::reflect_triangle(state->triangle, apu.triangle);
|
refl::reflect_triangle(state->triangle, apu.triangle);
|
||||||
|
@ -321,7 +321,7 @@ inline void Nes_Apu::save_state(apu_state_t *state) const
|
||||||
refl::reflect_dmc(state->dmc, apu.dmc);
|
refl::reflect_dmc(state->dmc, apu.dmc);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Apu::load_state(apu_state_t const &state)
|
inline void Apu::load_state(apu_state_t const &state)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/libs/
|
// Emu 0.7.0. http://www.slack.net/~ant/libs/
|
||||||
|
|
||||||
#include "apu/Nes_Buffer.hpp"
|
#include "apu/buffer.hpp"
|
||||||
#include "apu/apu.hpp"
|
#include "apu/apu.hpp"
|
||||||
|
|
||||||
/* Library Copyright (C) 2003-2006 Shay Green. This library is free software;
|
/* Library Copyright (C) 2003-2006 Shay Green. This library is free software;
|
||||||
|
@ -17,29 +17,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
// Nes_Buffer
|
// Buffer
|
||||||
|
|
||||||
Nes_Buffer::Nes_Buffer() : Multi_Buffer(1) {}
|
Buffer::Buffer() : Multi_Buffer(1) {}
|
||||||
|
|
||||||
Nes_Buffer::~Nes_Buffer() {}
|
Buffer::~Buffer() {}
|
||||||
|
|
||||||
Multi_Buffer *set_apu(Nes_Buffer *buf, Nes_Apu *apu)
|
Multi_Buffer *set_apu(Buffer *buf, Apu *apu)
|
||||||
{
|
{
|
||||||
buf->set_apu(apu);
|
buf->set_apu(apu);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Buffer::enable_nonlinearity(bool b)
|
void Buffer::enable_nonlinearity(bool b)
|
||||||
{
|
{
|
||||||
if (b)
|
if (b)
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
Nes_Apu *apu = nonlin.enable(b, &tnd);
|
Apu *apu = nonlin.enable(b, &tnd);
|
||||||
apu->osc_output(0, &buf);
|
apu->osc_output(0, &buf);
|
||||||
apu->osc_output(1, &buf);
|
apu->osc_output(1, &buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Nes_Buffer::set_sample_rate(long rate, int msec)
|
const char *Buffer::set_sample_rate(long rate, int msec)
|
||||||
{
|
{
|
||||||
enable_nonlinearity(nonlin.enabled); // reapply
|
enable_nonlinearity(nonlin.enabled); // reapply
|
||||||
buf.set_sample_rate(rate, msec);
|
buf.set_sample_rate(rate, msec);
|
||||||
|
@ -47,26 +47,26 @@ const char *Nes_Buffer::set_sample_rate(long rate, int msec)
|
||||||
return Multi_Buffer::set_sample_rate(buf.sample_rate(), buf.length());
|
return Multi_Buffer::set_sample_rate(buf.sample_rate(), buf.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Buffer::clock_rate(long rate)
|
void Buffer::clock_rate(long rate)
|
||||||
{
|
{
|
||||||
buf.clock_rate(rate);
|
buf.clock_rate(rate);
|
||||||
tnd.clock_rate(rate);
|
tnd.clock_rate(rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Buffer::bass_freq(int freq)
|
void Buffer::bass_freq(int freq)
|
||||||
{
|
{
|
||||||
buf.bass_freq(freq);
|
buf.bass_freq(freq);
|
||||||
tnd.bass_freq(freq);
|
tnd.bass_freq(freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Buffer::clear()
|
void Buffer::clear()
|
||||||
{
|
{
|
||||||
nonlin.clear();
|
nonlin.clear();
|
||||||
buf.clear();
|
buf.clear();
|
||||||
tnd.clear();
|
tnd.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Buffer::channel_t Nes_Buffer::channel(int i)
|
Buffer::channel_t Buffer::channel(int i)
|
||||||
{
|
{
|
||||||
channel_t c;
|
channel_t c;
|
||||||
c.center = &buf;
|
c.center = &buf;
|
||||||
|
@ -77,18 +77,18 @@ Nes_Buffer::channel_t Nes_Buffer::channel(int i)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Buffer::end_frame(blip_time_t length, bool)
|
void Buffer::end_frame(blip_time_t length, bool)
|
||||||
{
|
{
|
||||||
buf.end_frame(length);
|
buf.end_frame(length);
|
||||||
tnd.end_frame(length);
|
tnd.end_frame(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
long Nes_Buffer::samples_avail() const
|
long Buffer::samples_avail() const
|
||||||
{
|
{
|
||||||
return buf.samples_avail();
|
return buf.samples_avail();
|
||||||
}
|
}
|
||||||
|
|
||||||
long Nes_Buffer::read_samples(blip_sample_t *out, long count)
|
long Buffer::read_samples(blip_sample_t *out, long count)
|
||||||
{
|
{
|
||||||
count = nonlin.make_nonlinear(tnd, count);
|
count = nonlin.make_nonlinear(tnd, count);
|
||||||
if (count)
|
if (count)
|
||||||
|
@ -132,7 +132,7 @@ long Nes_Buffer::read_samples(blip_sample_t *out, long count)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Buffer::SaveAudioBufferState()
|
void Buffer::SaveAudioBufferState()
|
||||||
{
|
{
|
||||||
SaveAudioBufferStatePrivate();
|
SaveAudioBufferStatePrivate();
|
||||||
nonlin.SaveAudioBufferState();
|
nonlin.SaveAudioBufferState();
|
||||||
|
@ -140,7 +140,7 @@ void Nes_Buffer::SaveAudioBufferState()
|
||||||
tnd.SaveAudioBufferState();
|
tnd.SaveAudioBufferState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Buffer::RestoreAudioBufferState()
|
void Buffer::RestoreAudioBufferState()
|
||||||
{
|
{
|
||||||
RestoreAudioBufferStatePrivate();
|
RestoreAudioBufferStatePrivate();
|
||||||
nonlin.RestoreAudioBufferState();
|
nonlin.RestoreAudioBufferState();
|
||||||
|
@ -148,16 +148,16 @@ void Nes_Buffer::RestoreAudioBufferState()
|
||||||
tnd.RestoreAudioBufferState();
|
tnd.RestoreAudioBufferState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nes_Nonlinearizer
|
// Nonlinearizer
|
||||||
|
|
||||||
Nes_Nonlinearizer::Nes_Nonlinearizer()
|
Nonlinearizer::Nonlinearizer()
|
||||||
{
|
{
|
||||||
apu = nullptr;
|
apu = nullptr;
|
||||||
enabled = true;
|
enabled = true;
|
||||||
|
|
||||||
float const gain = 0x7fff * 1.3f;
|
float const gain = 0x7fff * 1.3f;
|
||||||
// don't use entire range, so any overflow will stay within table
|
// don't use entire range, so any overflow will stay within table
|
||||||
int const range = (int)((double)table_size * Nes_Apu::nonlinear_tnd_gain());
|
int const range = (int)((double)table_size * Apu::nonlinear_tnd_gain());
|
||||||
for (int i = 0; i < table_size; i++)
|
for (int i = 0; i < table_size; i++)
|
||||||
{
|
{
|
||||||
int const offset = table_size - range;
|
int const offset = table_size - range;
|
||||||
|
@ -174,7 +174,7 @@ Nes_Nonlinearizer::Nes_Nonlinearizer()
|
||||||
extra_prev = 0;
|
extra_prev = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Apu *Nes_Nonlinearizer::enable(bool b, Blip_Buffer *buf)
|
Apu *Nonlinearizer::enable(bool b, Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
apu->osc_output(2, buf);
|
apu->osc_output(2, buf);
|
||||||
apu->osc_output(3, buf);
|
apu->osc_output(3, buf);
|
||||||
|
@ -189,7 +189,7 @@ Nes_Apu *Nes_Nonlinearizer::enable(bool b, Blip_Buffer *buf)
|
||||||
|
|
||||||
#define ENTRY(s) table[(s) >> (blip_sample_bits - table_bits - 1) & (table_size - 1)]
|
#define ENTRY(s) table[(s) >> (blip_sample_bits - table_bits - 1) & (table_size - 1)]
|
||||||
|
|
||||||
long Nes_Nonlinearizer::make_nonlinear(Blip_Buffer &buf, long count)
|
long Nonlinearizer::make_nonlinear(Blip_Buffer &buf, long count)
|
||||||
{
|
{
|
||||||
long avail = buf.samples_avail();
|
long avail = buf.samples_avail();
|
||||||
if (count > avail)
|
if (count > avail)
|
||||||
|
@ -214,20 +214,20 @@ long Nes_Nonlinearizer::make_nonlinear(Blip_Buffer &buf, long count)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Nonlinearizer::clear()
|
void Nonlinearizer::clear()
|
||||||
{
|
{
|
||||||
accum = 0;
|
accum = 0;
|
||||||
prev = ENTRY(86016000); // avoid thump due to APU's triangle dc bias
|
prev = ENTRY(86016000); // avoid thump due to APU's triangle dc bias
|
||||||
// TODO: still results in slight clicks and thumps
|
// TODO: still results in slight clicks and thumps
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Nonlinearizer::SaveAudioBufferState()
|
void Nonlinearizer::SaveAudioBufferState()
|
||||||
{
|
{
|
||||||
extra_accum = accum;
|
extra_accum = accum;
|
||||||
extra_prev = prev;
|
extra_prev = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Nonlinearizer::RestoreAudioBufferState()
|
void Nonlinearizer::RestoreAudioBufferState()
|
||||||
{
|
{
|
||||||
accum = extra_accum;
|
accum = extra_accum;
|
||||||
prev = extra_prev;
|
prev = extra_prev;
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// NES non-linear audio buffer
|
// NES non-linear audio buffer
|
||||||
// Nes_Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include "Multi_Buffer.hpp"
|
#include "Multi_Buffer.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
@ -9,9 +9,9 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Nes_Apu;
|
class Apu;
|
||||||
|
|
||||||
class Nes_Nonlinearizer
|
class Nonlinearizer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
|
@ -23,7 +23,7 @@ class Nes_Nonlinearizer
|
||||||
table_size = 1 << table_bits
|
table_size = 1 << table_bits
|
||||||
};
|
};
|
||||||
int16_t table[table_size];
|
int16_t table[table_size];
|
||||||
Nes_Apu *apu;
|
Apu *apu;
|
||||||
long accum;
|
long accum;
|
||||||
long prev;
|
long prev;
|
||||||
|
|
||||||
|
@ -31,25 +31,25 @@ class Nes_Nonlinearizer
|
||||||
long extra_prev;
|
long extra_prev;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Nes_Nonlinearizer();
|
Nonlinearizer();
|
||||||
bool enabled;
|
bool enabled;
|
||||||
void clear();
|
void clear();
|
||||||
void set_apu(Nes_Apu *a) { apu = a; }
|
void set_apu(Apu *a) { apu = a; }
|
||||||
Nes_Apu *enable(bool, Blip_Buffer *tnd);
|
Apu *enable(bool, Blip_Buffer *tnd);
|
||||||
long make_nonlinear(Blip_Buffer &buf, long count);
|
long make_nonlinear(Blip_Buffer &buf, long count);
|
||||||
void SaveAudioBufferState();
|
void SaveAudioBufferState();
|
||||||
void RestoreAudioBufferState();
|
void RestoreAudioBufferState();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Nes_Buffer : public Multi_Buffer
|
class Buffer : public Multi_Buffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nes_Buffer();
|
Buffer();
|
||||||
~Nes_Buffer();
|
~Buffer();
|
||||||
|
|
||||||
// Setup APU for use with buffer, including setting its output to this buffer.
|
// Setup APU for use with buffer, including setting its output to this buffer.
|
||||||
// If you're using Nes_Emu, this is automatically called for you.
|
// If you're using Emu, this is automatically called for you.
|
||||||
void set_apu(Nes_Apu *apu) { nonlin.set_apu(apu); }
|
void set_apu(Apu *apu) { nonlin.set_apu(apu); }
|
||||||
|
|
||||||
// Enable/disable non-linear output
|
// Enable/disable non-linear output
|
||||||
void enable_nonlinearity(bool = true);
|
void enable_nonlinearity(bool = true);
|
||||||
|
@ -71,8 +71,8 @@ class Nes_Buffer : public Multi_Buffer
|
||||||
private:
|
private:
|
||||||
Blip_Buffer buf;
|
Blip_Buffer buf;
|
||||||
Blip_Buffer tnd;
|
Blip_Buffer tnd;
|
||||||
Nes_Nonlinearizer nonlin;
|
Nonlinearizer nonlin;
|
||||||
friend Multi_Buffer *set_apu(Nes_Buffer *, Nes_Apu *);
|
friend Multi_Buffer *set_apu(Buffer *, Apu *);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void SaveAudioBufferState();
|
virtual void SaveAudioBufferState();
|
|
@ -1,7 +1,7 @@
|
||||||
// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
|
// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Effects_Buffer.hpp"
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "effectsBuffer.hpp"
|
||||||
|
|
||||||
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
|
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
|
||||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
can redistribute it and/or modify it under the terms of the GNU Lesser
|
|
@ -7,7 +7,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
// Effects_Buffer uses several buffers and outputs stereo sample pairs.
|
// Effects_Buffer uses several buffers and outputs stereo sample pairs.
|
||||||
class Effects_Buffer : public Multi_Buffer
|
class Effects_Buffer : public Multi_Buffer
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "apu/fme7/apu.hpp"
|
#include "apu/fme7/apu.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
void Nes_Fme7_Apu::reset()
|
void Fme7_Apu::reset()
|
||||||
{
|
{
|
||||||
last_time = 0;
|
last_time = 0;
|
||||||
|
|
||||||
|
@ -29,14 +29,14 @@ void Nes_Fme7_Apu::reset()
|
||||||
memset(state, 0, sizeof *state);
|
memset(state, 0, sizeof *state);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char Nes_Fme7_Apu::amp_table[16] =
|
unsigned char Fme7_Apu::amp_table[16] =
|
||||||
{
|
{
|
||||||
#define ENTRY(n) (unsigned char)(n * +amp_range + 0.5)
|
#define ENTRY(n) (unsigned char)(n * +amp_range + 0.5)
|
||||||
ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156), ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624), ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498), ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
|
ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156), ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624), ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498), ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
|
||||||
#undef ENTRY
|
#undef ENTRY
|
||||||
};
|
};
|
||||||
|
|
||||||
void Nes_Fme7_Apu::run_until(blip_time_t end_time)
|
void Fme7_Apu::run_until(blip_time_t end_time)
|
||||||
{
|
{
|
||||||
for (int index = 0; index < osc_count; index++)
|
for (int index = 0; index < osc_count; index++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Sunsoft FME-7 sound emulator
|
// Sunsoft FME-7 sound emulator
|
||||||
// Nes_Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "apu/Blip_Buffer.hpp"
|
#include "apu/Blip_Buffer.hpp"
|
||||||
|
@ -22,12 +22,12 @@ struct fme7_apu_state_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(fme7_apu_state_t) == 24);
|
static_assert(sizeof(fme7_apu_state_t) == 24);
|
||||||
|
|
||||||
class Nes_Fme7_Apu : private fme7_apu_state_t
|
class Fme7_Apu : private fme7_apu_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nes_Fme7_Apu();
|
Fme7_Apu();
|
||||||
|
|
||||||
// See Nes_Apu.h for reference
|
// See Apu.h for reference
|
||||||
void reset();
|
void reset();
|
||||||
void volume(double);
|
void volume(double);
|
||||||
void treble_eq(blip_eq_t const &);
|
void treble_eq(blip_eq_t const &);
|
||||||
|
@ -64,8 +64,8 @@ class Nes_Fme7_Apu : private fme7_apu_state_t
|
||||||
// End of public interface
|
// End of public interface
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Nes_Fme7_Apu(const Nes_Fme7_Apu &);
|
Fme7_Apu(const Fme7_Apu &);
|
||||||
Nes_Fme7_Apu &operator=(const Nes_Fme7_Apu &);
|
Fme7_Apu &operator=(const Fme7_Apu &);
|
||||||
|
|
||||||
static unsigned char amp_table[16];
|
static unsigned char amp_table[16];
|
||||||
|
|
||||||
|
@ -85,37 +85,37 @@ class Nes_Fme7_Apu : private fme7_apu_state_t
|
||||||
void run_until(blip_time_t);
|
void run_until(blip_time_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Nes_Fme7_Apu::volume(double v)
|
inline void Fme7_Apu::volume(double v)
|
||||||
{
|
{
|
||||||
synth.volume(0.38 / +amp_range * v); // to do: fine-tune
|
synth.volume(0.38 / +amp_range * v); // to do: fine-tune
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Fme7_Apu::treble_eq(blip_eq_t const &eq)
|
inline void Fme7_Apu::treble_eq(blip_eq_t const &eq)
|
||||||
{
|
{
|
||||||
synth.treble_eq(eq);
|
synth.treble_eq(eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Fme7_Apu::osc_output(int i, Blip_Buffer *buf)
|
inline void Fme7_Apu::osc_output(int i, Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
oscs[i].output = buf;
|
oscs[i].output = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Fme7_Apu::output(Blip_Buffer *buf)
|
inline void Fme7_Apu::output(Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < osc_count; i++)
|
for (int i = 0; i < osc_count; i++)
|
||||||
osc_output(i, buf);
|
osc_output(i, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Nes_Fme7_Apu::Nes_Fme7_Apu()
|
inline Fme7_Apu::Fme7_Apu()
|
||||||
{
|
{
|
||||||
output(0);
|
output(0);
|
||||||
volume(1.0);
|
volume(1.0);
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Fme7_Apu::write_latch(int data) { latch = data; }
|
inline void Fme7_Apu::write_latch(int data) { latch = data; }
|
||||||
|
|
||||||
inline void Nes_Fme7_Apu::write_data(blip_time_t time, int data)
|
inline void Fme7_Apu::write_data(blip_time_t time, int data)
|
||||||
{
|
{
|
||||||
if ((unsigned)latch >= reg_count)
|
if ((unsigned)latch >= reg_count)
|
||||||
{
|
{
|
||||||
|
@ -129,7 +129,7 @@ inline void Nes_Fme7_Apu::write_data(blip_time_t time, int data)
|
||||||
regs[latch] = data;
|
regs[latch] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Fme7_Apu::end_frame(blip_time_t time)
|
inline void Fme7_Apu::end_frame(blip_time_t time)
|
||||||
{
|
{
|
||||||
if (time > last_time)
|
if (time > last_time)
|
||||||
run_until(time);
|
run_until(time);
|
||||||
|
@ -137,12 +137,12 @@ inline void Nes_Fme7_Apu::end_frame(blip_time_t time)
|
||||||
last_time -= time;
|
last_time -= time;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Fme7_Apu::save_state(fme7_apu_state_t *out) const
|
inline void Fme7_Apu::save_state(fme7_apu_state_t *out) const
|
||||||
{
|
{
|
||||||
*out = *this;
|
*out = *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Fme7_Apu::load_state(fme7_apu_state_t const &in)
|
inline void Fme7_Apu::load_state(fme7_apu_state_t const &in)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
fme7_apu_state_t *state = this;
|
fme7_apu_state_t *state = this;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
// Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "apu/namco/apu.hpp"
|
#include "apu/namco/apu.hpp"
|
||||||
#include "apu/Blip_Buffer.hpp"
|
#include "apu/Blip_Buffer.hpp"
|
||||||
|
@ -18,18 +18,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
Nes_Namco_Apu::Nes_Namco_Apu()
|
Namco_Apu::Namco_Apu()
|
||||||
{
|
{
|
||||||
output(0);
|
output(0);
|
||||||
volume(1.0);
|
volume(1.0);
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Namco_Apu::~Nes_Namco_Apu()
|
Namco_Apu::~Namco_Apu()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Namco_Apu::reset()
|
void Namco_Apu::reset()
|
||||||
{
|
{
|
||||||
last_time = 0;
|
last_time = 0;
|
||||||
addr_reg = 0;
|
addr_reg = 0;
|
||||||
|
@ -47,14 +47,14 @@ void Nes_Namco_Apu::reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Namco_Apu::output(Blip_Buffer *buf)
|
void Namco_Apu::output(Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < osc_count; i++)
|
for (int i = 0; i < osc_count; i++)
|
||||||
osc_output(i, buf);
|
osc_output(i, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void Nes_Namco_Apu::reflect_state( Tagged_Data& data )
|
void Namco_Apu::reflect_state( Tagged_Data& data )
|
||||||
{
|
{
|
||||||
reflect_int16( data, 'ADDR', &addr_reg );
|
reflect_int16( data, 'ADDR', &addr_reg );
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ void Nes_Namco_Apu::reflect_state( Tagged_Data& data )
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Nes_Namco_Apu::end_frame(nes_time_t time)
|
void Namco_Apu::end_frame(nes_time_t time)
|
||||||
{
|
{
|
||||||
if (time > last_time)
|
if (time > last_time)
|
||||||
run_until(time);
|
run_until(time);
|
||||||
|
@ -79,7 +79,7 @@ void Nes_Namco_Apu::end_frame(nes_time_t time)
|
||||||
last_time -= time;
|
last_time -= time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Namco_Apu::run_until(nes_time_t nes_end_time)
|
void Namco_Apu::run_until(nes_time_t nes_end_time)
|
||||||
{
|
{
|
||||||
int active_oscs = (reg[0x7F] >> 4 & 7) + 1;
|
int active_oscs = (reg[0x7F] >> 4 & 7) + 1;
|
||||||
for (int i = osc_count - active_oscs; i < osc_count; i++)
|
for (int i = osc_count - active_oscs; i < osc_count; i++)
|
||||||
|
@ -147,7 +147,7 @@ void Nes_Namco_Apu::run_until(nes_time_t nes_end_time)
|
||||||
last_time = nes_end_time;
|
last_time = nes_end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Namco_Apu::save_state(namco_state_t *out) const
|
void Namco_Apu::save_state(namco_state_t *out) const
|
||||||
{
|
{
|
||||||
out->addr = addr_reg;
|
out->addr = addr_reg;
|
||||||
for (int r = 0; r < reg_count; r++)
|
for (int r = 0; r < reg_count; r++)
|
||||||
|
@ -162,7 +162,7 @@ void Nes_Namco_Apu::save_state(namco_state_t *out) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Namco_Apu::load_state(namco_state_t const &in)
|
void Namco_Apu::load_state(namco_state_t const &in)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
addr_reg = in.addr;
|
addr_reg = in.addr;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Namco 106 sound chip emulator
|
// Namco 106 sound chip emulator
|
||||||
// Nes_Snd_Emu 0.1.7
|
// Snd_Emu 0.1.7
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "apu/apu.hpp"
|
#include "apu/apu.hpp"
|
||||||
|
@ -19,13 +19,13 @@ struct namco_state_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(namco_state_t) == 172);
|
static_assert(sizeof(namco_state_t) == 172);
|
||||||
|
|
||||||
class Nes_Namco_Apu
|
class Namco_Apu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nes_Namco_Apu();
|
Namco_Apu();
|
||||||
~Nes_Namco_Apu();
|
~Namco_Apu();
|
||||||
|
|
||||||
// See Nes_Apu.h for reference.
|
// See Apu.h for reference.
|
||||||
void volume(double);
|
void volume(double);
|
||||||
void treble_eq(const blip_eq_t &);
|
void treble_eq(const blip_eq_t &);
|
||||||
void output(Blip_Buffer *);
|
void output(Blip_Buffer *);
|
||||||
|
@ -58,8 +58,8 @@ class Nes_Namco_Apu
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Nes_Namco_Apu(const Nes_Namco_Apu &);
|
Namco_Apu(const Namco_Apu &);
|
||||||
Nes_Namco_Apu &operator=(const Nes_Namco_Apu &);
|
Namco_Apu &operator=(const Namco_Apu &);
|
||||||
|
|
||||||
struct Namco_Osc
|
struct Namco_Osc
|
||||||
{
|
{
|
||||||
|
@ -85,7 +85,7 @@ class Nes_Namco_Apu
|
||||||
void run_until(nes_time_t);
|
void run_until(nes_time_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline uint8_t &Nes_Namco_Apu::access()
|
inline uint8_t &Namco_Apu::access()
|
||||||
{
|
{
|
||||||
int addr = addr_reg & 0x7f;
|
int addr = addr_reg & 0x7f;
|
||||||
if (addr_reg & 0x80)
|
if (addr_reg & 0x80)
|
||||||
|
@ -93,20 +93,20 @@ inline uint8_t &Nes_Namco_Apu::access()
|
||||||
return reg[addr];
|
return reg[addr];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Namco_Apu::volume(double v) { synth.volume(0.10 / +osc_count * v); }
|
inline void Namco_Apu::volume(double v) { synth.volume(0.10 / +osc_count * v); }
|
||||||
|
|
||||||
inline void Nes_Namco_Apu::treble_eq(const blip_eq_t &eq) { synth.treble_eq(eq); }
|
inline void Namco_Apu::treble_eq(const blip_eq_t &eq) { synth.treble_eq(eq); }
|
||||||
|
|
||||||
inline void Nes_Namco_Apu::write_addr(int v) { addr_reg = v; }
|
inline void Namco_Apu::write_addr(int v) { addr_reg = v; }
|
||||||
|
|
||||||
inline int Nes_Namco_Apu::read_data() { return access(); }
|
inline int Namco_Apu::read_data() { return access(); }
|
||||||
|
|
||||||
inline void Nes_Namco_Apu::osc_output(int i, Blip_Buffer *buf)
|
inline void Namco_Apu::osc_output(int i, Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
oscs[i].output = buf;
|
oscs[i].output = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Namco_Apu::write_data(nes_time_t time, int data)
|
inline void Namco_Apu::write_data(nes_time_t time, int data)
|
||||||
{
|
{
|
||||||
run_until(time);
|
run_until(time);
|
||||||
access() = data;
|
access() = data;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
// Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "apu.hpp"
|
#include "apu.hpp"
|
||||||
|
|
||||||
|
@ -17,15 +17,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
// Nes_Osc
|
// Osc
|
||||||
|
|
||||||
void Nes_Osc::clock_length(int halt_mask)
|
void Osc::clock_length(int halt_mask)
|
||||||
{
|
{
|
||||||
if (length_counter && !(regs[0] & halt_mask))
|
if (length_counter && !(regs[0] & halt_mask))
|
||||||
length_counter--;
|
length_counter--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Envelope::clock_envelope()
|
void Envelope::clock_envelope()
|
||||||
{
|
{
|
||||||
int period = regs[0] & 15;
|
int period = regs[0] & 15;
|
||||||
if (reg_written[3])
|
if (reg_written[3])
|
||||||
|
@ -42,15 +42,15 @@ void Nes_Envelope::clock_envelope()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Nes_Envelope::volume() const
|
int Envelope::volume() const
|
||||||
{
|
{
|
||||||
return length_counter == 0 ? 0 : (regs[0] & 0x10) ? (regs[0] & 15)
|
return length_counter == 0 ? 0 : (regs[0] & 0x10) ? (regs[0] & 15)
|
||||||
: envelope;
|
: envelope;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nes_Square
|
// Square
|
||||||
|
|
||||||
void Nes_Square::clock_sweep(int negative_adjust)
|
void Square::clock_sweep(int negative_adjust)
|
||||||
{
|
{
|
||||||
int sweep = regs[1];
|
int sweep = regs[1];
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ void Nes_Square::clock_sweep(int negative_adjust)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: clean up
|
// TODO: clean up
|
||||||
inline nes_time_t Nes_Square::maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period)
|
inline nes_time_t Square::maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period)
|
||||||
{
|
{
|
||||||
long remain = end_time - time;
|
long remain = end_time - time;
|
||||||
if (remain > 0)
|
if (remain > 0)
|
||||||
|
@ -97,7 +97,7 @@ inline nes_time_t Nes_Square::maintain_phase(nes_time_t time, nes_time_t end_tim
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Square::run(nes_time_t time, nes_time_t end_time)
|
void Square::run(nes_time_t time, nes_time_t end_time)
|
||||||
{
|
{
|
||||||
const int period = this->period();
|
const int period = this->period();
|
||||||
const int timer_period = (period + 1) * 2;
|
const int timer_period = (period + 1) * 2;
|
||||||
|
@ -168,9 +168,9 @@ void Nes_Square::run(nes_time_t time, nes_time_t end_time)
|
||||||
delay = time - end_time;
|
delay = time - end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nes_Triangle
|
// Triangle
|
||||||
|
|
||||||
void Nes_Triangle::clock_linear_counter()
|
void Triangle::clock_linear_counter()
|
||||||
{
|
{
|
||||||
if (reg_written[3])
|
if (reg_written[3])
|
||||||
linear_counter = regs[0] & 0x7f;
|
linear_counter = regs[0] & 0x7f;
|
||||||
|
@ -181,7 +181,7 @@ void Nes_Triangle::clock_linear_counter()
|
||||||
reg_written[3] = false;
|
reg_written[3] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Nes_Triangle::calc_amp() const
|
inline int Triangle::calc_amp() const
|
||||||
{
|
{
|
||||||
int amp = phase_range - phase;
|
int amp = phase_range - phase;
|
||||||
if (amp < 0)
|
if (amp < 0)
|
||||||
|
@ -190,7 +190,7 @@ inline int Nes_Triangle::calc_amp() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: clean up
|
// TODO: clean up
|
||||||
inline nes_time_t Nes_Triangle::maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period)
|
inline nes_time_t Triangle::maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period)
|
||||||
{
|
{
|
||||||
long remain = end_time - time;
|
long remain = end_time - time;
|
||||||
if (remain > 0)
|
if (remain > 0)
|
||||||
|
@ -203,7 +203,7 @@ inline nes_time_t Nes_Triangle::maintain_phase(nes_time_t time, nes_time_t end_t
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Triangle::run(nes_time_t time, nes_time_t end_time)
|
void Triangle::run(nes_time_t time, nes_time_t end_time)
|
||||||
{
|
{
|
||||||
const int timer_period = period() + 1;
|
const int timer_period = period() + 1;
|
||||||
if (!output)
|
if (!output)
|
||||||
|
@ -261,9 +261,9 @@ void Nes_Triangle::run(nes_time_t time, nes_time_t end_time)
|
||||||
delay = time - end_time;
|
delay = time - end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nes_Dmc
|
// Dmc
|
||||||
|
|
||||||
void Nes_Dmc::reset()
|
void Dmc::reset()
|
||||||
{
|
{
|
||||||
address = 0;
|
address = 0;
|
||||||
dac = 0;
|
dac = 0;
|
||||||
|
@ -272,17 +272,17 @@ void Nes_Dmc::reset()
|
||||||
bits = 0;
|
bits = 0;
|
||||||
buf_full = false;
|
buf_full = false;
|
||||||
silence = true;
|
silence = true;
|
||||||
next_irq = Nes_Apu::no_irq;
|
next_irq = Apu::no_irq;
|
||||||
irq_flag = false;
|
irq_flag = false;
|
||||||
irq_enabled = false;
|
irq_enabled = false;
|
||||||
|
|
||||||
Nes_Osc::reset();
|
Osc::reset();
|
||||||
period = 0x1ac;
|
period = 0x1ac;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Dmc::recalc_irq()
|
void Dmc::recalc_irq()
|
||||||
{
|
{
|
||||||
nes_time_t irq = Nes_Apu::no_irq;
|
nes_time_t irq = Apu::no_irq;
|
||||||
if (irq_enabled && length_counter)
|
if (irq_enabled && length_counter)
|
||||||
irq = apu->last_dmc_time + delay +
|
irq = apu->last_dmc_time + delay +
|
||||||
((length_counter - 1) * 8 + bits_remain - 1) * nes_time_t(period) + 1;
|
((length_counter - 1) * 8 + bits_remain - 1) * nes_time_t(period) + 1;
|
||||||
|
@ -293,7 +293,7 @@ void Nes_Dmc::recalc_irq()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Nes_Dmc::count_reads(nes_time_t time, nes_time_t *last_read) const
|
int Dmc::count_reads(nes_time_t time, nes_time_t *last_read) const
|
||||||
{
|
{
|
||||||
if (last_read)
|
if (last_read)
|
||||||
*last_read = time;
|
*last_read = time;
|
||||||
|
@ -338,7 +338,7 @@ static const short dmc_period_table[2][16] = {
|
||||||
0x032} // to do: verify PAL periods
|
0x032} // to do: verify PAL periods
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Nes_Dmc::reload_sample()
|
inline void Dmc::reload_sample()
|
||||||
{
|
{
|
||||||
address = 0x4000 + regs[2] * 0x40;
|
address = 0x4000 + regs[2] * 0x40;
|
||||||
length_counter = regs[3] * 0x10 + 1;
|
length_counter = regs[3] * 0x10 + 1;
|
||||||
|
@ -476,7 +476,7 @@ static const unsigned char dac_table[128] =
|
||||||
83,
|
83,
|
||||||
};
|
};
|
||||||
|
|
||||||
void Nes_Dmc::write_register(int addr, int data)
|
void Dmc::write_register(int addr, int data)
|
||||||
{
|
{
|
||||||
if (addr == 0)
|
if (addr == 0)
|
||||||
{
|
{
|
||||||
|
@ -498,14 +498,14 @@ void Nes_Dmc::write_register(int addr, int data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Dmc::start()
|
void Dmc::start()
|
||||||
{
|
{
|
||||||
reload_sample();
|
reload_sample();
|
||||||
fill_buffer();
|
fill_buffer();
|
||||||
recalc_irq();
|
recalc_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Dmc::fill_buffer()
|
void Dmc::fill_buffer()
|
||||||
{
|
{
|
||||||
if (!buf_full && length_counter)
|
if (!buf_full && length_counter)
|
||||||
{
|
{
|
||||||
|
@ -522,14 +522,14 @@ void Nes_Dmc::fill_buffer()
|
||||||
{
|
{
|
||||||
apu->osc_enables &= ~0x10;
|
apu->osc_enables &= ~0x10;
|
||||||
irq_flag = irq_enabled;
|
irq_flag = irq_enabled;
|
||||||
next_irq = Nes_Apu::no_irq;
|
next_irq = Apu::no_irq;
|
||||||
apu->irq_changed();
|
apu->irq_changed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Dmc::run(nes_time_t time, nes_time_t end_time)
|
void Dmc::run(nes_time_t time, nes_time_t end_time)
|
||||||
{
|
{
|
||||||
int delta = update_amp(dac);
|
int delta = update_amp(dac);
|
||||||
if (!output)
|
if (!output)
|
||||||
|
@ -597,12 +597,12 @@ void Nes_Dmc::run(nes_time_t time, nes_time_t end_time)
|
||||||
delay = time - end_time;
|
delay = time - end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nes_Noise
|
// Noise
|
||||||
|
|
||||||
static const short noise_period_table[16] = {
|
static const short noise_period_table[16] = {
|
||||||
0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0, 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4};
|
0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0, 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4};
|
||||||
|
|
||||||
void Nes_Noise::run(nes_time_t time, nes_time_t end_time)
|
void Noise::run(nes_time_t time, nes_time_t end_time)
|
||||||
{
|
{
|
||||||
int period = noise_period_table[regs[2] & 15];
|
int period = noise_period_table[regs[2] & 15];
|
||||||
#if NES_APU_NOISE_LOW_CPU
|
#if NES_APU_NOISE_LOW_CPU
|
|
@ -1,20 +1,20 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Private oscillators used by Nes_Apu
|
// Private oscillators used by Apu
|
||||||
// Nes_Snd_Emu 0.1.7
|
// Snd_Emu 0.1.7
|
||||||
|
|
||||||
#include "Blip_Buffer.hpp"
|
#include "Blip_Buffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Nes_Apu;
|
class Apu;
|
||||||
|
|
||||||
typedef long nes_time_t; // CPU clock cycle count
|
typedef long nes_time_t; // CPU clock cycle count
|
||||||
typedef unsigned nes_addr_t; // 16-bit memory address
|
typedef unsigned nes_addr_t; // 16-bit memory address
|
||||||
|
|
||||||
struct Nes_Osc
|
struct Osc
|
||||||
{
|
{
|
||||||
unsigned char regs[4];
|
unsigned char regs[4];
|
||||||
bool reg_written[4];
|
bool reg_written[4];
|
||||||
|
@ -41,7 +41,7 @@ struct Nes_Osc
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Nes_Envelope : Nes_Osc
|
struct Envelope : Osc
|
||||||
{
|
{
|
||||||
int envelope;
|
int envelope;
|
||||||
int env_delay;
|
int env_delay;
|
||||||
|
@ -52,12 +52,12 @@ struct Nes_Envelope : Nes_Osc
|
||||||
{
|
{
|
||||||
envelope = 0;
|
envelope = 0;
|
||||||
env_delay = 0;
|
env_delay = 0;
|
||||||
Nes_Osc::reset();
|
Osc::reset();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Nes_Square
|
// Square
|
||||||
struct Nes_Square : Nes_Envelope
|
struct Square : Envelope
|
||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -77,20 +77,20 @@ struct Nes_Square : Nes_Envelope
|
||||||
typedef Blip_Synth<blip_good_quality, 1> Synth;
|
typedef Blip_Synth<blip_good_quality, 1> Synth;
|
||||||
Synth const &synth; // shared between squares
|
Synth const &synth; // shared between squares
|
||||||
|
|
||||||
Nes_Square(Synth const *s) : synth(*s) {}
|
Square(Synth const *s) : synth(*s) {}
|
||||||
|
|
||||||
void clock_sweep(int adjust);
|
void clock_sweep(int adjust);
|
||||||
void run(nes_time_t, nes_time_t);
|
void run(nes_time_t, nes_time_t);
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
sweep_delay = 0;
|
sweep_delay = 0;
|
||||||
Nes_Envelope::reset();
|
Envelope::reset();
|
||||||
}
|
}
|
||||||
nes_time_t maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period);
|
nes_time_t maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Nes_Triangle
|
// Triangle
|
||||||
struct Nes_Triangle : Nes_Osc
|
struct Triangle : Osc
|
||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -107,13 +107,13 @@ struct Nes_Triangle : Nes_Osc
|
||||||
{
|
{
|
||||||
linear_counter = 0;
|
linear_counter = 0;
|
||||||
phase = 1;
|
phase = 1;
|
||||||
Nes_Osc::reset();
|
Osc::reset();
|
||||||
}
|
}
|
||||||
nes_time_t maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period);
|
nes_time_t maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Nes_Noise
|
// Noise
|
||||||
struct Nes_Noise : Nes_Envelope
|
struct Noise : Envelope
|
||||||
{
|
{
|
||||||
int noise;
|
int noise;
|
||||||
Blip_Synth<blip_med_quality, 1> synth;
|
Blip_Synth<blip_med_quality, 1> synth;
|
||||||
|
@ -122,16 +122,16 @@ struct Nes_Noise : Nes_Envelope
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
noise = 1 << 14;
|
noise = 1 << 14;
|
||||||
Nes_Envelope::reset();
|
Envelope::reset();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Nes_Dmc
|
// Dmc
|
||||||
struct Nes_Dmc : Nes_Osc
|
struct Dmc : Osc
|
||||||
{
|
{
|
||||||
int address; // address of next byte to read
|
int address; // address of next byte to read
|
||||||
int period;
|
int period;
|
||||||
// int length_counter; // bytes remaining to play (already defined in Nes_Osc)
|
// int length_counter; // bytes remaining to play (already defined in Osc)
|
||||||
int buf;
|
int buf;
|
||||||
int bits_remain;
|
int bits_remain;
|
||||||
int bits;
|
int bits;
|
||||||
|
@ -154,7 +154,7 @@ struct Nes_Dmc : Nes_Osc
|
||||||
int (*prg_reader)(void *, nes_addr_t); // needs to be initialized to prg read function
|
int (*prg_reader)(void *, nes_addr_t); // needs to be initialized to prg read function
|
||||||
void *prg_reader_data;
|
void *prg_reader_data;
|
||||||
|
|
||||||
Nes_Apu *apu;
|
Apu *apu;
|
||||||
|
|
||||||
Blip_Synth<blip_med_quality, 1> synth;
|
Blip_Synth<blip_med_quality, 1> synth;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
// Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "apu/vrc6/apu.hpp"
|
#include "apu/vrc6/apu.hpp"
|
||||||
|
|
||||||
|
@ -17,18 +17,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
Nes_Vrc6_Apu::Nes_Vrc6_Apu()
|
Vrc6_Apu::Vrc6_Apu()
|
||||||
{
|
{
|
||||||
output(0);
|
output(0);
|
||||||
volume(1.0);
|
volume(1.0);
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Vrc6_Apu::~Nes_Vrc6_Apu()
|
Vrc6_Apu::~Vrc6_Apu()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc6_Apu::reset()
|
void Vrc6_Apu::reset()
|
||||||
{
|
{
|
||||||
last_time = 0;
|
last_time = 0;
|
||||||
for (int i = 0; i < osc_count; i++)
|
for (int i = 0; i < osc_count; i++)
|
||||||
|
@ -43,13 +43,13 @@ void Nes_Vrc6_Apu::reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc6_Apu::output(Blip_Buffer *buf)
|
void Vrc6_Apu::output(Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < osc_count; i++)
|
for (int i = 0; i < osc_count; i++)
|
||||||
osc_output(i, buf);
|
osc_output(i, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc6_Apu::run_until(nes_time_t time)
|
void Vrc6_Apu::run_until(nes_time_t time)
|
||||||
{
|
{
|
||||||
run_square(oscs[0], time);
|
run_square(oscs[0], time);
|
||||||
run_square(oscs[1], time);
|
run_square(oscs[1], time);
|
||||||
|
@ -57,13 +57,13 @@ void Nes_Vrc6_Apu::run_until(nes_time_t time)
|
||||||
last_time = time;
|
last_time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc6_Apu::write_osc(nes_time_t time, int osc_index, int reg, int data)
|
void Vrc6_Apu::write_osc(nes_time_t time, int osc_index, int reg, int data)
|
||||||
{
|
{
|
||||||
run_until(time);
|
run_until(time);
|
||||||
oscs[osc_index].regs[reg] = data;
|
oscs[osc_index].regs[reg] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc6_Apu::end_frame(nes_time_t time)
|
void Vrc6_Apu::end_frame(nes_time_t time)
|
||||||
{
|
{
|
||||||
if (time > last_time)
|
if (time > last_time)
|
||||||
run_until(time);
|
run_until(time);
|
||||||
|
@ -71,7 +71,7 @@ void Nes_Vrc6_Apu::end_frame(nes_time_t time)
|
||||||
last_time -= time;
|
last_time -= time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc6_Apu::save_state(vrc6_apu_state_t *out) const
|
void Vrc6_Apu::save_state(vrc6_apu_state_t *out) const
|
||||||
{
|
{
|
||||||
out->saw_amp = oscs[2].amp;
|
out->saw_amp = oscs[2].amp;
|
||||||
for (int i = 0; i < osc_count; i++)
|
for (int i = 0; i < osc_count; i++)
|
||||||
|
@ -85,7 +85,7 @@ void Nes_Vrc6_Apu::save_state(vrc6_apu_state_t *out) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc6_Apu::load_state(vrc6_apu_state_t const &in)
|
void Vrc6_Apu::load_state(vrc6_apu_state_t const &in)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
oscs[2].amp = in.saw_amp;
|
oscs[2].amp = in.saw_amp;
|
||||||
|
@ -105,7 +105,7 @@ void Nes_Vrc6_Apu::load_state(vrc6_apu_state_t const &in)
|
||||||
this->run_until(this->last_time);
|
this->run_until(this->last_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc6_Apu::run_square(Vrc6_Osc &osc, nes_time_t end_time)
|
void Vrc6_Apu::run_square(Vrc6_Osc &osc, nes_time_t end_time)
|
||||||
{
|
{
|
||||||
Blip_Buffer *output = osc.output;
|
Blip_Buffer *output = osc.output;
|
||||||
if (!output)
|
if (!output)
|
||||||
|
@ -157,7 +157,7 @@ void Nes_Vrc6_Apu::run_square(Vrc6_Osc &osc, nes_time_t end_time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc6_Apu::run_saw(nes_time_t end_time)
|
void Vrc6_Apu::run_saw(nes_time_t end_time)
|
||||||
{
|
{
|
||||||
Vrc6_Osc &osc = oscs[2];
|
Vrc6_Osc &osc = oscs[2];
|
||||||
Blip_Buffer *output = osc.output;
|
Blip_Buffer *output = osc.output;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Konami VRC6 sound chip emulator
|
// Konami VRC6 sound chip emulator
|
||||||
// Nes_Snd_Emu 0.1.7
|
// Snd_Emu 0.1.7
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "apu/Blip_Buffer.hpp"
|
#include "apu/Blip_Buffer.hpp"
|
||||||
|
@ -13,13 +13,13 @@ namespace quickerNES
|
||||||
|
|
||||||
struct vrc6_apu_state_t;
|
struct vrc6_apu_state_t;
|
||||||
|
|
||||||
class Nes_Vrc6_Apu
|
class Vrc6_Apu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nes_Vrc6_Apu();
|
Vrc6_Apu();
|
||||||
~Nes_Vrc6_Apu();
|
~Vrc6_Apu();
|
||||||
|
|
||||||
// See Nes_Apu.h for reference
|
// See Apu.h for reference
|
||||||
void reset();
|
void reset();
|
||||||
void volume(double);
|
void volume(double);
|
||||||
void treble_eq(blip_eq_t const &);
|
void treble_eq(blip_eq_t const &);
|
||||||
|
@ -52,8 +52,8 @@ class Nes_Vrc6_Apu
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Nes_Vrc6_Apu(const Nes_Vrc6_Apu &);
|
Vrc6_Apu(const Vrc6_Apu &);
|
||||||
Nes_Vrc6_Apu &operator=(const Nes_Vrc6_Apu &);
|
Vrc6_Apu &operator=(const Vrc6_Apu &);
|
||||||
|
|
||||||
struct Vrc6_Osc
|
struct Vrc6_Osc
|
||||||
{
|
{
|
||||||
|
@ -91,19 +91,19 @@ struct vrc6_apu_state_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(vrc6_apu_state_t) == 20);
|
static_assert(sizeof(vrc6_apu_state_t) == 20);
|
||||||
|
|
||||||
inline void Nes_Vrc6_Apu::osc_output(int i, Blip_Buffer *buf)
|
inline void Vrc6_Apu::osc_output(int i, Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
oscs[i].output = buf;
|
oscs[i].output = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Vrc6_Apu::volume(double v)
|
inline void Vrc6_Apu::volume(double v)
|
||||||
{
|
{
|
||||||
double const factor = 0.0967 * 2;
|
double const factor = 0.0967 * 2;
|
||||||
saw_synth.volume(factor / 31 * v);
|
saw_synth.volume(factor / 31 * v);
|
||||||
square_synth.volume(factor * 0.5 / 15 * v);
|
square_synth.volume(factor * 0.5 / 15 * v);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Vrc6_Apu::treble_eq(blip_eq_t const &eq)
|
inline void Vrc6_Apu::treble_eq(blip_eq_t const &eq)
|
||||||
{
|
{
|
||||||
saw_synth.treble_eq(eq);
|
saw_synth.treble_eq(eq);
|
||||||
square_synth.treble_eq(eq);
|
square_synth.treble_eq(eq);
|
||||||
|
|
|
@ -24,7 +24,7 @@ static bool IsLittleEndian()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Vrc7::Nes_Vrc7()
|
Vrc7::Vrc7()
|
||||||
{
|
{
|
||||||
opll = OPLL_new(3579545);
|
opll = OPLL_new(3579545);
|
||||||
output(NULL);
|
output(NULL);
|
||||||
|
@ -32,12 +32,12 @@ Nes_Vrc7::Nes_Vrc7()
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Vrc7::~Nes_Vrc7()
|
Vrc7::~Vrc7()
|
||||||
{
|
{
|
||||||
OPLL_delete((OPLL *)opll);
|
OPLL_delete((OPLL *)opll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::reset()
|
void Vrc7::reset()
|
||||||
{
|
{
|
||||||
last_time = 0;
|
last_time = 0;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -53,23 +53,23 @@ void Nes_Vrc7::reset()
|
||||||
OPLL_reset((OPLL *)opll);
|
OPLL_reset((OPLL *)opll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::volume(double v)
|
void Vrc7::volume(double v)
|
||||||
{
|
{
|
||||||
synth.volume(v * 1. / 3.);
|
synth.volume(v * 1. / 3.);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::treble_eq(blip_eq_t const &eq)
|
void Vrc7::treble_eq(blip_eq_t const &eq)
|
||||||
{
|
{
|
||||||
synth.treble_eq(eq);
|
synth.treble_eq(eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::output(Blip_Buffer *buf)
|
void Vrc7::output(Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < osc_count; i++)
|
for (int i = 0; i < osc_count; i++)
|
||||||
osc_output(i, buf);
|
osc_output(i, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::run_until(nes_time_t end_time)
|
void Vrc7::run_until(nes_time_t end_time)
|
||||||
{
|
{
|
||||||
nes_time_t time = last_time;
|
nes_time_t time = last_time;
|
||||||
|
|
||||||
|
@ -105,12 +105,12 @@ void Nes_Vrc7::run_until(nes_time_t end_time)
|
||||||
last_time = end_time;
|
last_time = end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::write_reg(int data)
|
void Vrc7::write_reg(int data)
|
||||||
{
|
{
|
||||||
OPLL_writeIO((OPLL *)opll, 0, data);
|
OPLL_writeIO((OPLL *)opll, 0, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::write_data(nes_time_t time, int data)
|
void Vrc7::write_data(nes_time_t time, int data)
|
||||||
{
|
{
|
||||||
if ((unsigned)(((OPLL *)opll)->adr - 0x10) < 0x36)
|
if ((unsigned)(((OPLL *)opll)->adr - 0x10) < 0x36)
|
||||||
{
|
{
|
||||||
|
@ -124,14 +124,14 @@ void Nes_Vrc7::write_data(nes_time_t time, int data)
|
||||||
OPLL_writeIO((OPLL *)opll, 1, data);
|
OPLL_writeIO((OPLL *)opll, 1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::end_frame(nes_time_t time)
|
void Vrc7::end_frame(nes_time_t time)
|
||||||
{
|
{
|
||||||
if (time > last_time)
|
if (time > last_time)
|
||||||
run_until(time);
|
run_until(time);
|
||||||
last_time -= time;
|
last_time -= time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::save_snapshot(vrc7_snapshot_t *out)
|
void Vrc7::save_snapshot(vrc7_snapshot_t *out)
|
||||||
{
|
{
|
||||||
out->latch = ((OPLL *)opll)->adr;
|
out->latch = ((OPLL *)opll)->adr;
|
||||||
memcpy(out->inst, ((OPLL *)opll)->CustInst, 8);
|
memcpy(out->inst, ((OPLL *)opll)->CustInst, 8);
|
||||||
|
@ -152,7 +152,7 @@ void Nes_Vrc7::save_snapshot(vrc7_snapshot_t *out)
|
||||||
OPLL_state_byteswap(&(out->internal_opl_state));
|
OPLL_state_byteswap(&(out->internal_opl_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::load_snapshot(vrc7_snapshot_t &in, int dataSize)
|
void Vrc7::load_snapshot(vrc7_snapshot_t &in, int dataSize)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
write_reg(in.latch);
|
write_reg(in.latch);
|
||||||
|
@ -190,7 +190,7 @@ void Nes_Vrc7::load_snapshot(vrc7_snapshot_t &in, int dataSize)
|
||||||
update_last_amp();
|
update_last_amp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Vrc7::update_last_amp()
|
void Vrc7::update_last_amp()
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < osc_count; ++i)
|
for (unsigned i = 0; i < osc_count; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Konami VRC7 sound chip emulator
|
// Konami VRC7 sound chip emulator
|
||||||
// Nes_Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
|
// Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "apu/Blip_Buffer.hpp"
|
#include "apu/Blip_Buffer.hpp"
|
||||||
|
@ -14,13 +14,13 @@ namespace quickerNES
|
||||||
struct vrc7_snapshot_t;
|
struct vrc7_snapshot_t;
|
||||||
typedef long nes_time_t;
|
typedef long nes_time_t;
|
||||||
|
|
||||||
class Nes_Vrc7
|
class Vrc7
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nes_Vrc7();
|
Vrc7();
|
||||||
~Nes_Vrc7();
|
~Vrc7();
|
||||||
|
|
||||||
// See Nes_Apu.h for reference
|
// See Apu.h for reference
|
||||||
void reset();
|
void reset();
|
||||||
void volume(double);
|
void volume(double);
|
||||||
void treble_eq(blip_eq_t const &);
|
void treble_eq(blip_eq_t const &);
|
||||||
|
@ -40,8 +40,8 @@ class Nes_Vrc7
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Nes_Vrc7(const Nes_Vrc7 &);
|
Vrc7(const Vrc7 &);
|
||||||
Nes_Vrc7 &operator=(const Nes_Vrc7 &);
|
Vrc7 &operator=(const Vrc7 &);
|
||||||
|
|
||||||
struct Vrc7_Osc
|
struct Vrc7_Osc
|
||||||
{
|
{
|
||||||
|
@ -71,7 +71,7 @@ struct vrc7_snapshot_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(vrc7_snapshot_t) == 28 + 440 + 4);
|
static_assert(sizeof(vrc7_snapshot_t) == 28 + 440 + 4);
|
||||||
|
|
||||||
inline void Nes_Vrc7::osc_output(int i, Blip_Buffer *buf)
|
inline void Vrc7::osc_output(int i, Blip_Buffer *buf)
|
||||||
{
|
{
|
||||||
oscs[i].output = buf;
|
oscs[i].output = buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ more details. You should have received a copy of the GNU Lesser General
|
||||||
Public License along with this module; if not, write to the Free Software
|
Public License along with this module; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -22,10 +22,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Nes_Cart
|
class Cart
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nes_Cart() = default;
|
Cart() = default;
|
||||||
|
|
||||||
struct ines_header_t
|
struct ines_header_t
|
||||||
{
|
{
|
|
@ -13,19 +13,19 @@ more details. You should have received a copy of the GNU Lesser General
|
||||||
Public License along with this module; if not, write to the Free Software
|
Public License along with this module; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
// Nes_Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include "Nes_Cpu.hpp"
|
#include "cpu.hpp"
|
||||||
#include "apu/apu.hpp"
|
#include "apu/apu.hpp"
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
#include "ppu/Nes_Ppu.hpp"
|
#include "ppu/ppu.hpp"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Nes_Cart;
|
class Cart;
|
||||||
|
|
||||||
#undef NES_EMU_CPU_HOOK
|
#undef NES_EMU_CPU_HOOK
|
||||||
#ifndef NES_EMU_CPU_HOOK
|
#ifndef NES_EMU_CPU_HOOK
|
||||||
|
@ -34,7 +34,7 @@ class Nes_Cart;
|
||||||
|
|
||||||
bool const wait_states_enabled = true;
|
bool const wait_states_enabled = true;
|
||||||
bool const single_instruction_mode = false; // for debugging irq/nmi timing issues
|
bool const single_instruction_mode = false; // for debugging irq/nmi timing issues
|
||||||
const int unmapped_fill = Nes_Cpu::page_wrap_opcode;
|
const int unmapped_fill = Cpu::page_wrap_opcode;
|
||||||
unsigned const low_ram_size = 0x800;
|
unsigned const low_ram_size = 0x800;
|
||||||
unsigned const low_ram_end = 0x2000;
|
unsigned const low_ram_end = 0x2000;
|
||||||
unsigned const sram_end = 0x8000;
|
unsigned const sram_end = 0x8000;
|
||||||
|
@ -68,12 +68,12 @@ struct cpu_state_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(cpu_state_t) == 8);
|
static_assert(sizeof(cpu_state_t) == 8);
|
||||||
|
|
||||||
class Nes_Core : private Nes_Cpu
|
class Core : private Cpu
|
||||||
{
|
{
|
||||||
typedef Nes_Cpu cpu;
|
typedef Cpu cpu;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Nes_Core() : ppu(this)
|
Core() : ppu(this)
|
||||||
{
|
{
|
||||||
cart = NULL;
|
cart = NULL;
|
||||||
impl = NULL;
|
impl = NULL;
|
||||||
|
@ -82,7 +82,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
memset(&joypad, 0, sizeof joypad);
|
memset(&joypad, 0, sizeof joypad);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Nes_Core()
|
~Core()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
delete impl;
|
delete impl;
|
||||||
|
@ -100,7 +100,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void open(Nes_Cart const *new_cart)
|
void open(Cart const *new_cart)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
init();
|
init();
|
||||||
|
@ -109,7 +109,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
auto mapperCode = new_cart->mapper_code();
|
auto mapperCode = new_cart->mapper_code();
|
||||||
|
|
||||||
// Getting mapper corresponding to that code
|
// Getting mapper corresponding to that code
|
||||||
mapper = Nes_Mapper::getMapperFromCode(mapperCode);
|
mapper = Mapper::getMapperFromCode(mapperCode);
|
||||||
|
|
||||||
// If no mapper was found, return null (error) now
|
// If no mapper was found, return null (error) now
|
||||||
if (mapper == nullptr)
|
if (mapper == nullptr)
|
||||||
|
@ -136,11 +136,11 @@ class Nes_Core : private Nes_Cpu
|
||||||
size += sizeof(nes_state_t);
|
size += sizeof(nes_state_t);
|
||||||
size += sizeof(registers_t);
|
size += sizeof(registers_t);
|
||||||
size += sizeof(ppu_state_t);
|
size += sizeof(ppu_state_t);
|
||||||
size += sizeof(Nes_Apu::apu_state_t);
|
size += sizeof(Apu::apu_state_t);
|
||||||
size += sizeof(joypad_state_t);
|
size += sizeof(joypad_state_t);
|
||||||
size += mapper->state_size;
|
size += mapper->state_size;
|
||||||
size += low_ram_size;
|
size += low_ram_size;
|
||||||
size += Nes_Ppu::spr_ram_size;
|
size += Ppu::spr_ram_size;
|
||||||
size_t nametable_size = 0x800;
|
size_t nametable_size = 0x800;
|
||||||
if (ppu.nt_banks[3] >= &ppu.impl->nt_ram[0xC00]) nametable_size = 0x1000;
|
if (ppu.nt_banks[3] >= &ppu.impl->nt_ram[0xC00]) nametable_size = 0x1000;
|
||||||
size += nametable_size;
|
size += nametable_size;
|
||||||
|
@ -171,7 +171,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
|
|
||||||
size += sizeof(char[4]); // APUR Block
|
size += sizeof(char[4]); // APUR Block
|
||||||
size += sizeof(uint32_t); // Block Size
|
size += sizeof(uint32_t); // Block Size
|
||||||
size += sizeof(Nes_Apu::apu_state_t);
|
size += sizeof(Apu::apu_state_t);
|
||||||
|
|
||||||
size += sizeof(char[4]); // CTRL Block
|
size += sizeof(char[4]); // CTRL Block
|
||||||
size += sizeof(uint32_t); // Block Size
|
size += sizeof(uint32_t); // Block Size
|
||||||
|
@ -187,7 +187,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
|
|
||||||
size += sizeof(char[4]); // SPRT Block
|
size += sizeof(char[4]); // SPRT Block
|
||||||
size += sizeof(uint32_t); // Block Size
|
size += sizeof(uint32_t); // Block Size
|
||||||
size += Nes_Ppu::spr_ram_size;
|
size += Ppu::spr_ram_size;
|
||||||
|
|
||||||
size += sizeof(char[4]); // NTAB Block
|
size += sizeof(char[4]); // NTAB Block
|
||||||
size += sizeof(uint32_t); // Block Size
|
size += sizeof(uint32_t); // Block Size
|
||||||
|
@ -271,9 +271,9 @@ class Nes_Core : private Nes_Cpu
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "APUR"; // APUR Block
|
headerCode = "APUR"; // APUR Block
|
||||||
Nes_Apu::apu_state_t apuState;
|
Apu::apu_state_t apuState;
|
||||||
impl->apu.save_state(&apuState);
|
impl->apu.save_state(&apuState);
|
||||||
blockSize = sizeof(Nes_Apu::apu_state_t);
|
blockSize = sizeof(Apu::apu_state_t);
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||||
|
@ -312,7 +312,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
headerCode = "SPRT"; // SPRT Block
|
headerCode = "SPRT"; // SPRT Block
|
||||||
blockSize = Nes_Ppu::spr_ram_size;
|
blockSize = Ppu::spr_ram_size;
|
||||||
dataSource = (void *)ppu.spr_ram;
|
dataSource = (void *)ppu.spr_ram;
|
||||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
|
@ -415,8 +415,8 @@ class Nes_Core : private Nes_Cpu
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
// APUR Block
|
// APUR Block
|
||||||
Nes_Apu::apu_state_t apuState;
|
Apu::apu_state_t apuState;
|
||||||
blockSize = sizeof(Nes_Apu::apu_state_t);
|
blockSize = sizeof(Apu::apu_state_t);
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy(&apuState, &buffer[pos], blockSize);
|
memcpy(&apuState, &buffer[pos], blockSize);
|
||||||
|
@ -448,7 +448,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
pos += blockSize;
|
pos += blockSize;
|
||||||
|
|
||||||
// SPRT Block
|
// SPRT Block
|
||||||
blockSize = Nes_Ppu::spr_ram_size;
|
blockSize = Ppu::spr_ram_size;
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
pos += headerSize;
|
pos += headerSize;
|
||||||
memcpy((void *)ppu.spr_ram, &buffer[pos], blockSize);
|
memcpy((void *)ppu.spr_ram, &buffer[pos], blockSize);
|
||||||
|
@ -588,7 +588,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
|
|
||||||
public:
|
public:
|
||||||
private:
|
private:
|
||||||
friend class Nes_Emu;
|
friend class Emu;
|
||||||
|
|
||||||
struct impl_t
|
struct impl_t
|
||||||
{
|
{
|
||||||
|
@ -597,11 +597,11 @@ class Nes_Core : private Nes_Cpu
|
||||||
sram_size = 0x2000
|
sram_size = 0x2000
|
||||||
};
|
};
|
||||||
uint8_t sram[sram_size];
|
uint8_t sram[sram_size];
|
||||||
Nes_Apu apu;
|
Apu apu;
|
||||||
|
|
||||||
// extra byte allows CPU to always read operand of instruction, which
|
// extra byte allows CPU to always read operand of instruction, which
|
||||||
// might go past end of data
|
// might go past end of data
|
||||||
uint8_t unmapped_page[Nes_Cpu::page_size + 1];
|
uint8_t unmapped_page[Cpu::page_size + 1];
|
||||||
};
|
};
|
||||||
impl_t *impl; // keep large arrays separate
|
impl_t *impl; // keep large arrays separate
|
||||||
unsigned long error_count;
|
unsigned long error_count;
|
||||||
|
@ -609,15 +609,15 @@ class Nes_Core : private Nes_Cpu
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned long current_joypad[2];
|
unsigned long current_joypad[2];
|
||||||
Nes_Cart const *cart;
|
Cart const *cart;
|
||||||
Nes_Mapper *mapper;
|
Mapper *mapper;
|
||||||
nes_state_t nes;
|
nes_state_t nes;
|
||||||
Nes_Ppu ppu;
|
Ppu ppu;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Nes_Core(const Nes_Core &);
|
Core(const Core &);
|
||||||
Nes_Core &operator=(const Nes_Core &);
|
Core &operator=(const Core &);
|
||||||
|
|
||||||
// Timing
|
// Timing
|
||||||
nes_time_t ppu_2002_time;
|
nes_time_t ppu_2002_time;
|
||||||
|
@ -672,7 +672,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
return result & 1;
|
return result & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr == Nes_Apu::status_addr)
|
if (addr == Apu::status_addr)
|
||||||
return impl->apu.read_status(clock());
|
return impl->apu.read_status(clock());
|
||||||
|
|
||||||
return addr >> 8; // simulate open bus
|
return addr >> 8; // simulate open bus
|
||||||
|
@ -719,7 +719,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
|
|
||||||
static inline int read_dmc(void *data, nes_addr_t addr)
|
static inline int read_dmc(void *data, nes_addr_t addr)
|
||||||
{
|
{
|
||||||
Nes_Core *emu = (Nes_Core *)data;
|
Core *emu = (Core *)data;
|
||||||
int result = *emu->cpu::get_code(addr);
|
int result = *emu->cpu::get_code(addr);
|
||||||
if (wait_states_enabled)
|
if (wait_states_enabled)
|
||||||
emu->cpu_adjust_time(4);
|
emu->cpu_adjust_time(4);
|
||||||
|
@ -728,7 +728,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
|
|
||||||
static inline void apu_irq_changed(void *emu)
|
static inline void apu_irq_changed(void *emu)
|
||||||
{
|
{
|
||||||
((Nes_Core *)emu)->irq_changed();
|
((Core *)emu)->irq_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
|
@ -740,7 +740,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
|
|
||||||
nes_time_t emulate_frame_()
|
nes_time_t emulate_frame_()
|
||||||
{
|
{
|
||||||
Nes_Cpu::result_t last_result = cpu::result_cycles;
|
Cpu::result_t last_result = cpu::result_cycles;
|
||||||
int extra_instructions = 0;
|
int extra_instructions = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -852,12 +852,12 @@ class Nes_Core : private Nes_Cpu
|
||||||
|
|
||||||
public:
|
public:
|
||||||
private:
|
private:
|
||||||
friend class Nes_Ppu;
|
friend class Ppu;
|
||||||
void set_ppu_2002_time(nes_time_t t) { ppu_2002_time = t - 1 - cpu_time_offset; }
|
void set_ppu_2002_time(nes_time_t t) { ppu_2002_time = t - 1 - cpu_time_offset; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
private:
|
private:
|
||||||
friend class Nes_Mapper;
|
friend class Mapper;
|
||||||
|
|
||||||
void enable_prg_6000()
|
void enable_prg_6000()
|
||||||
{
|
{
|
||||||
|
@ -903,7 +903,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
|
|
||||||
public:
|
public:
|
||||||
private:
|
private:
|
||||||
friend class Nes_Cpu;
|
friend class Cpu;
|
||||||
int cpu_read_ppu(nes_addr_t, nes_time_t);
|
int cpu_read_ppu(nes_addr_t, nes_time_t);
|
||||||
int cpu_read(nes_addr_t, nes_time_t);
|
int cpu_read(nes_addr_t, nes_time_t);
|
||||||
void cpu_write(nes_addr_t, int data, nes_time_t);
|
void cpu_write(nes_addr_t, int data, nes_time_t);
|
||||||
|
@ -914,7 +914,7 @@ class Nes_Core : private Nes_Cpu
|
||||||
unsigned char data_writer_mapped[page_count + 1];
|
unsigned char data_writer_mapped[page_count + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int Nes_Core::cpu_read(nes_addr_t addr, nes_time_t time)
|
inline int Core::cpu_read(nes_addr_t addr, nes_time_t time)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
int result = cpu::low_mem[addr & 0x7FF];
|
int result = cpu::low_mem[addr & 0x7FF];
|
||||||
|
@ -952,7 +952,7 @@ inline int Nes_Core::cpu_read(nes_addr_t addr, nes_time_t time)
|
||||||
return addr >> 8; // simulate open bus
|
return addr >> 8; // simulate open bus
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Nes_Core::cpu_read_ppu(nes_addr_t addr, nes_time_t time)
|
inline int Core::cpu_read_ppu(nes_addr_t addr, nes_time_t time)
|
||||||
{
|
{
|
||||||
// LOG_FREQ( "cpu_read_ppu", 16, addr >> 12 );
|
// LOG_FREQ( "cpu_read_ppu", 16, addr >> 12 );
|
||||||
|
|
||||||
|
@ -976,14 +976,14 @@ inline int Nes_Core::cpu_read_ppu(nes_addr_t addr, nes_time_t time)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Core::cpu_write_2007(int data)
|
inline void Core::cpu_write_2007(int data)
|
||||||
{
|
{
|
||||||
// ppu.write_2007() is inlined
|
// ppu.write_2007() is inlined
|
||||||
if (ppu.write_2007(data) & Nes_Ppu::vaddr_clock_mask)
|
if (ppu.write_2007(data) & Ppu::vaddr_clock_mask)
|
||||||
mapper->a12_clocked();
|
mapper->a12_clocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Core::cpu_write(nes_addr_t addr, int data, nes_time_t time)
|
inline void Core::cpu_write(nes_addr_t addr, int data, nes_time_t time)
|
||||||
{
|
{
|
||||||
// LOG_FREQ( "cpu_write", 16, addr >> 12 );
|
// LOG_FREQ( "cpu_write", 16, addr >> 12 );
|
||||||
|
|
||||||
|
@ -1027,14 +1027,14 @@ inline void Nes_Core::cpu_write(nes_addr_t addr, int data, nes_time_t time)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NES_CPU_READ_PPU(cpu, addr, time) \
|
#define NES_CPU_READ_PPU(cpu, addr, time) \
|
||||||
static_cast<Nes_Core &>(*cpu).cpu_read_ppu(addr, time)
|
static_cast<Core &>(*cpu).cpu_read_ppu(addr, time)
|
||||||
|
|
||||||
#define NES_CPU_READ(cpu, addr, time) \
|
#define NES_CPU_READ(cpu, addr, time) \
|
||||||
static_cast<Nes_Core &>(*cpu).cpu_read(addr, time)
|
static_cast<Core &>(*cpu).cpu_read(addr, time)
|
||||||
|
|
||||||
#define NES_CPU_WRITEX(cpu, addr, data, time) \
|
#define NES_CPU_WRITEX(cpu, addr, data, time) \
|
||||||
{ \
|
{ \
|
||||||
static_cast<Nes_Core &>(*cpu).cpu_write(addr, data, time); \
|
static_cast<Core &>(*cpu).cpu_write(addr, data, time); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NES_CPU_WRITE(cpu, addr, data, time) \
|
#define NES_CPU_WRITE(cpu, addr, data, time) \
|
||||||
|
@ -1042,9 +1042,9 @@ inline void Nes_Core::cpu_write(nes_addr_t addr, int data, nes_time_t time)
|
||||||
if (addr < 0x800) \
|
if (addr < 0x800) \
|
||||||
cpu->low_mem[addr] = data; \
|
cpu->low_mem[addr] = data; \
|
||||||
else if (addr == 0x2007) \
|
else if (addr == 0x2007) \
|
||||||
static_cast<Nes_Core &>(*cpu).cpu_write_2007(data); \
|
static_cast<Core &>(*cpu).cpu_write_2007(data); \
|
||||||
else \
|
else \
|
||||||
static_cast<Nes_Core &>(*cpu).cpu_write(addr, data, time); \
|
static_cast<Core &>(*cpu).cpu_write(addr, data, time); \
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickNES
|
|
@ -1,10 +1,10 @@
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/nes-emu/
|
// Emu 0.7.0. http://www.slack.net/~ant/nes-emu/
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include "Nes_Cpu.hpp"
|
#include "cpu.hpp"
|
||||||
#include "Nes_Core.hpp"
|
#include "core.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimizations by Sergio Martin (eien86) 2023-2024
|
* Optimizations by Sergio Martin (eien86) 2023-2024
|
||||||
|
@ -130,7 +130,7 @@ imm##op: \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Nes_Cpu::reset( void const* unmapped_page )
|
void Cpu::reset( void const* unmapped_page )
|
||||||
{
|
{
|
||||||
r.status = 0;
|
r.status = 0;
|
||||||
r.sp = 0;
|
r.sp = 0;
|
||||||
|
@ -190,12 +190,12 @@ void Nes_Cpu::reset( void const* unmapped_page )
|
||||||
nz |= ~in & st_z; \
|
nz |= ~in & st_z; \
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
inline int32_t Nes_Cpu::read( nes_addr_t addr )
|
inline int32_t Cpu::read( nes_addr_t addr )
|
||||||
{
|
{
|
||||||
return READ( addr );
|
return READ( addr );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Cpu::write( nes_addr_t addr, int value )
|
inline void Cpu::write( nes_addr_t addr, int value )
|
||||||
{
|
{
|
||||||
WRITE( addr, value );
|
WRITE( addr, value );
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,7 @@ inline void Nes_Cpu::write( nes_addr_t addr, int value )
|
||||||
extern uint8_t clock_table [256];
|
extern uint8_t clock_table [256];
|
||||||
|
|
||||||
__attribute__((optimize("align-functions=" _PAGE_SIZE)))
|
__attribute__((optimize("align-functions=" _PAGE_SIZE)))
|
||||||
Nes_Cpu::result_t Nes_Cpu::run ( nes_time_t end )
|
Cpu::result_t Cpu::run ( nes_time_t end )
|
||||||
{
|
{
|
||||||
set_end_time_( end );
|
set_end_time_( end );
|
||||||
clock_count = 0;
|
clock_count = 0;
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// NES 6502 CPU emulator
|
// NES 6502 CPU emulator
|
||||||
// Nes_Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ namespace quickerNES
|
||||||
typedef long nes_time_t; // clock cycle count
|
typedef long nes_time_t; // clock cycle count
|
||||||
typedef unsigned nes_addr_t; // 16-bit address
|
typedef unsigned nes_addr_t; // 16-bit address
|
||||||
|
|
||||||
class Nes_Cpu
|
class Cpu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// NES 6502 registers. *Not* kept updated during a call to run().
|
// NES 6502 registers. *Not* kept updated during a call to run().
|
|
@ -1,8 +1,8 @@
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
#include "Nes_Emu.hpp"
|
#include "emu.hpp"
|
||||||
|
|
||||||
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
|
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
|
||||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||||
|
@ -20,17 +20,17 @@ namespace quickerNES
|
||||||
|
|
||||||
int const sound_fade_size = 384;
|
int const sound_fade_size = 384;
|
||||||
|
|
||||||
Nes_Emu::equalizer_t const Nes_Emu::nes_eq = { -1.0, 80 };
|
Emu::equalizer_t const Emu::nes_eq = { -1.0, 80 };
|
||||||
Nes_Emu::equalizer_t const Nes_Emu::famicom_eq = { -15.0, 80 };
|
Emu::equalizer_t const Emu::famicom_eq = { -15.0, 80 };
|
||||||
Nes_Emu::equalizer_t const Nes_Emu::tv_eq = { -12.0, 180 };
|
Emu::equalizer_t const Emu::tv_eq = { -12.0, 180 };
|
||||||
Nes_Emu::equalizer_t const Nes_Emu::flat_eq = { 0.0, 1 };
|
Emu::equalizer_t const Emu::flat_eq = { 0.0, 1 };
|
||||||
Nes_Emu::equalizer_t const Nes_Emu::crisp_eq = { 5.0, 1 };
|
Emu::equalizer_t const Emu::crisp_eq = { 5.0, 1 };
|
||||||
Nes_Emu::equalizer_t const Nes_Emu::tinny_eq = { -47.0, 2000 };
|
Emu::equalizer_t const Emu::tinny_eq = { -47.0, 2000 };
|
||||||
|
|
||||||
Nes_Emu::Nes_Emu()
|
Emu::Emu()
|
||||||
{
|
{
|
||||||
frame_ = &single_frame;
|
frame_ = &single_frame;
|
||||||
buffer_height_ = Nes_Ppu::buffer_height + 2;
|
buffer_height_ = Ppu::buffer_height + 2;
|
||||||
default_sound_buf = NULL;
|
default_sound_buf = NULL;
|
||||||
sound_buf = &silent_buffer;
|
sound_buf = &silent_buffer;
|
||||||
sound_buf_changed_count = 0;
|
sound_buf_changed_count = 0;
|
||||||
|
@ -49,17 +49,17 @@ Nes_Emu::Nes_Emu()
|
||||||
extra_sound_buf_changed_count = 0;
|
extra_sound_buf_changed_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Emu::~Nes_Emu()
|
Emu::~Emu()
|
||||||
{
|
{
|
||||||
delete default_sound_buf;
|
delete default_sound_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * Nes_Emu::init_()
|
const char * Emu::init_()
|
||||||
{
|
{
|
||||||
return emu.init();
|
return emu.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char * Nes_Emu::auto_init()
|
inline const char * Emu::auto_init()
|
||||||
{
|
{
|
||||||
if ( !init_called )
|
if ( !init_called )
|
||||||
{
|
{
|
||||||
|
@ -70,40 +70,40 @@ inline const char * Nes_Emu::auto_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void Nes_Emu::clear_sound_buf()
|
inline void Emu::clear_sound_buf()
|
||||||
{
|
{
|
||||||
fade_sound_out = false;
|
fade_sound_out = false;
|
||||||
fade_sound_in = true;
|
fade_sound_in = true;
|
||||||
sound_buf->clear();
|
sound_buf->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Emu::set_cart( Nes_Cart const* new_cart )
|
void Emu::set_cart( Cart const* new_cart )
|
||||||
{
|
{
|
||||||
auto_init();
|
auto_init();
|
||||||
emu.open( new_cart );
|
emu.open( new_cart );
|
||||||
|
|
||||||
channel_count_ = Nes_Apu::osc_count + emu.mapper->channel_count();
|
channel_count_ = Apu::osc_count + emu.mapper->channel_count();
|
||||||
sound_buf->set_channel_count( channel_count() );
|
sound_buf->set_channel_count( channel_count() );
|
||||||
set_equalizer( equalizer_ );
|
set_equalizer( equalizer_ );
|
||||||
enable_sound( true );
|
enable_sound( true );
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Emu::reset( bool full_reset, bool erase_battery_ram )
|
void Emu::reset( bool full_reset, bool erase_battery_ram )
|
||||||
{
|
{
|
||||||
clear_sound_buf();
|
clear_sound_buf();
|
||||||
set_timestamp( 0 );
|
set_timestamp( 0 );
|
||||||
emu.reset( full_reset, erase_battery_ram );
|
emu.reset( full_reset, erase_battery_ram );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Emu::set_palette_range( int begin, int end )
|
void Emu::set_palette_range( int begin, int end )
|
||||||
{
|
{
|
||||||
// round up to alignment
|
// round up to alignment
|
||||||
emu.ppu.palette_begin = (begin + palette_alignment - 1) & ~(palette_alignment - 1);
|
emu.ppu.palette_begin = (begin + palette_alignment - 1) & ~(palette_alignment - 1);
|
||||||
host_palette_size = end - emu.ppu.palette_begin;
|
host_palette_size = end - emu.ppu.palette_begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * Nes_Emu::emulate_skip_frame( int joypad1, int joypad2 )
|
const char * Emu::emulate_skip_frame( int joypad1, int joypad2 )
|
||||||
{
|
{
|
||||||
char *old_host_pixels = host_pixels;
|
char *old_host_pixels = host_pixels;
|
||||||
host_pixels = NULL;
|
host_pixels = NULL;
|
||||||
|
@ -112,7 +112,7 @@ const char * Nes_Emu::emulate_skip_frame( int joypad1, int joypad2 )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * Nes_Emu::emulate_frame( int joypad1, int joypad2 )
|
const char * Emu::emulate_frame( int joypad1, int joypad2 )
|
||||||
{
|
{
|
||||||
emu.ppu.host_pixels = NULL;
|
emu.ppu.host_pixels = NULL;
|
||||||
|
|
||||||
|
@ -166,41 +166,41 @@ const char * Nes_Emu::emulate_frame( int joypad1, int joypad2 )
|
||||||
|
|
||||||
// Extras
|
// Extras
|
||||||
|
|
||||||
void Nes_Emu::load_ines( const uint8_t* buffer )
|
void Emu::load_ines( const uint8_t* buffer )
|
||||||
{
|
{
|
||||||
private_cart.load_ines( buffer );
|
private_cart.load_ines( buffer );
|
||||||
set_cart( &private_cart );
|
set_cart( &private_cart );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Emu::write_chr( void const* p, long count, long offset )
|
void Emu::write_chr( void const* p, long count, long offset )
|
||||||
{
|
{
|
||||||
long end = offset + count;
|
long end = offset + count;
|
||||||
memcpy( (uint8_t*) chr_mem() + offset, p, count );
|
memcpy( (uint8_t*) chr_mem() + offset, p, count );
|
||||||
emu.ppu.rebuild_chr( offset, end );
|
emu.ppu.rebuild_chr( offset, end );
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * Nes_Emu::set_sample_rate( long rate, class Nes_Buffer* buf )
|
const char * Emu::set_sample_rate( long rate, class Buffer* buf )
|
||||||
{
|
{
|
||||||
extern Multi_Buffer* set_apu( class Nes_Buffer*, Nes_Apu* );
|
extern Multi_Buffer* set_apu( class Buffer*, Apu* );
|
||||||
auto_init();
|
auto_init();
|
||||||
return set_sample_rate( rate, set_apu( buf, &emu.impl->apu ) );
|
return set_sample_rate( rate, set_apu( buf, &emu.impl->apu ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * Nes_Emu::set_sample_rate( long rate, class Nes_Effects_Buffer* buf )
|
const char * Emu::set_sample_rate( long rate, class Nes_Effects_Buffer* buf )
|
||||||
{
|
{
|
||||||
extern Multi_Buffer* set_apu( class Nes_Effects_Buffer*, Nes_Apu* );
|
extern Multi_Buffer* set_apu( class Nes_Effects_Buffer*, Apu* );
|
||||||
auto_init();
|
auto_init();
|
||||||
return set_sample_rate( rate, set_apu( buf, &emu.impl->apu ) );
|
return set_sample_rate( rate, set_apu( buf, &emu.impl->apu ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sound
|
// Sound
|
||||||
|
|
||||||
void Nes_Emu::set_frame_rate( double rate )
|
void Emu::set_frame_rate( double rate )
|
||||||
{
|
{
|
||||||
sound_buf->clock_rate( (long) (1789773 / 60.0 * rate) );
|
sound_buf->clock_rate( (long) (1789773 / 60.0 * rate) );
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * Nes_Emu::set_sample_rate( long rate, Multi_Buffer* new_buf )
|
const char * Emu::set_sample_rate( long rate, Multi_Buffer* new_buf )
|
||||||
{
|
{
|
||||||
auto_init();
|
auto_init();
|
||||||
emu.impl->apu.volume( 1.0 ); // cancel any previous non-linearity
|
emu.impl->apu.volume( 1.0 ); // cancel any previous non-linearity
|
||||||
|
@ -216,13 +216,13 @@ const char * Nes_Emu::set_sample_rate( long rate, Multi_Buffer* new_buf )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * Nes_Emu::set_sample_rate( long rate )
|
const char * Emu::set_sample_rate( long rate )
|
||||||
{
|
{
|
||||||
if ( !default_sound_buf ) default_sound_buf = new Mono_Buffer;
|
if ( !default_sound_buf ) default_sound_buf = new Mono_Buffer;
|
||||||
return set_sample_rate( rate, default_sound_buf );
|
return set_sample_rate( rate, default_sound_buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Emu::set_equalizer( equalizer_t const& eq )
|
void Emu::set_equalizer( equalizer_t const& eq )
|
||||||
{
|
{
|
||||||
equalizer_ = eq;
|
equalizer_ = eq;
|
||||||
if ( cart() )
|
if ( cart() )
|
||||||
|
@ -234,14 +234,14 @@ void Nes_Emu::set_equalizer( equalizer_t const& eq )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Emu::enable_sound( bool enabled )
|
void Emu::enable_sound( bool enabled )
|
||||||
{
|
{
|
||||||
if ( enabled )
|
if ( enabled )
|
||||||
{
|
{
|
||||||
for ( int i = channel_count(); i-- > 0; )
|
for ( int i = channel_count(); i-- > 0; )
|
||||||
{
|
{
|
||||||
Blip_Buffer* buf = sound_buf->channel( i ).center;
|
Blip_Buffer* buf = sound_buf->channel( i ).center;
|
||||||
int mapper_index = i - Nes_Apu::osc_count;
|
int mapper_index = i - Apu::osc_count;
|
||||||
if ( mapper_index < 0 )
|
if ( mapper_index < 0 )
|
||||||
emu.impl->apu.osc_output( i, buf );
|
emu.impl->apu.osc_output( i, buf );
|
||||||
else
|
else
|
||||||
|
@ -251,12 +251,12 @@ void Nes_Emu::enable_sound( bool enabled )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
emu.impl->apu.output( NULL );
|
emu.impl->apu.output( NULL );
|
||||||
for ( int i = channel_count() - Nes_Apu::osc_count; i-- > 0; )
|
for ( int i = channel_count() - Apu::osc_count; i-- > 0; )
|
||||||
emu.mapper->set_channel_buf( i, NULL );
|
emu.mapper->set_channel_buf( i, NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Emu::fade_samples( blip_sample_t* p, int size, int step )
|
void Emu::fade_samples( blip_sample_t* p, int size, int step )
|
||||||
{
|
{
|
||||||
if ( size >= sound_fade_size )
|
if ( size >= sound_fade_size )
|
||||||
{
|
{
|
||||||
|
@ -276,7 +276,7 @@ void Nes_Emu::fade_samples( blip_sample_t* p, int size, int step )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long Nes_Emu::read_samples( short* out, long out_size )
|
long Emu::read_samples( short* out, long out_size )
|
||||||
{
|
{
|
||||||
long count = sound_buf->read_samples( out, out_size );
|
long count = sound_buf->read_samples( out, out_size );
|
||||||
if ( fade_sound_in )
|
if ( fade_sound_in )
|
||||||
|
@ -296,7 +296,7 @@ long Nes_Emu::read_samples( short* out, long out_size )
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Emu::rgb_t const Nes_Emu::nes_colors [color_table_size] =
|
Emu::rgb_t const Emu::nes_colors [color_table_size] =
|
||||||
{
|
{
|
||||||
// generated with nes_ntsc default settings
|
// generated with nes_ntsc default settings
|
||||||
{102,102,102},{ 0, 42,136},{ 20, 18,168},{ 59, 0,164},
|
{102,102,102},{ 0, 42,136},{ 20, 18,168},{ 59, 0,164},
|
||||||
|
@ -430,14 +430,14 @@ Nes_Emu::rgb_t const Nes_Emu::nes_colors [color_table_size] =
|
||||||
{136,190,197},{184,184,184},{ 0, 0, 0},{ 0, 0, 0}
|
{136,190,197},{184,184,184},{ 0, 0, 0},{ 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Nes_Emu::SaveAudioBufferState()
|
void Emu::SaveAudioBufferState()
|
||||||
{
|
{
|
||||||
extra_fade_sound_in = fade_sound_in;
|
extra_fade_sound_in = fade_sound_in;
|
||||||
extra_fade_sound_out = fade_sound_out;
|
extra_fade_sound_out = fade_sound_out;
|
||||||
extra_sound_buf_changed_count = sound_buf_changed_count;
|
extra_sound_buf_changed_count = sound_buf_changed_count;
|
||||||
sound_buf->SaveAudioBufferState();
|
sound_buf->SaveAudioBufferState();
|
||||||
}
|
}
|
||||||
void Nes_Emu::RestoreAudioBufferState()
|
void Emu::RestoreAudioBufferState()
|
||||||
{
|
{
|
||||||
fade_sound_in = extra_fade_sound_in;
|
fade_sound_in = extra_fade_sound_in;
|
||||||
fade_sound_out = extra_fade_sound_out;
|
fade_sound_out = extra_fade_sound_out;
|
|
@ -2,22 +2,22 @@
|
||||||
|
|
||||||
// NES video game console emulator with snapshot support
|
// NES video game console emulator with snapshot support
|
||||||
|
|
||||||
// Nes_Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include "Nes_Cart.hpp"
|
#include "cart.hpp"
|
||||||
#include "Nes_Core.hpp"
|
#include "core.hpp"
|
||||||
#include "apu/Multi_Buffer.hpp"
|
#include "apu/Multi_Buffer.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Nes_State;
|
class State;
|
||||||
|
|
||||||
class Nes_Emu
|
class Emu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nes_Emu();
|
Emu();
|
||||||
virtual ~Nes_Emu();
|
virtual ~Emu();
|
||||||
|
|
||||||
// Basic setup
|
// Basic setup
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ class Nes_Emu
|
||||||
// Size and depth of graphics buffer required for rendering. Note that this
|
// Size and depth of graphics buffer required for rendering. Note that this
|
||||||
// is larger than the actual image, with a temporary area around the edge
|
// is larger than the actual image, with a temporary area around the edge
|
||||||
// that gets filled with junk.
|
// that gets filled with junk.
|
||||||
static const uint16_t buffer_width = Nes_Ppu::buffer_width;
|
static const uint16_t buffer_width = Ppu::buffer_width;
|
||||||
uint16_t buffer_height() const { return buffer_height_; }
|
uint16_t buffer_height() const { return buffer_height_; }
|
||||||
static const uint8_t bits_per_pixel = 8;
|
static const uint8_t bits_per_pixel = 8;
|
||||||
|
|
||||||
|
@ -90,10 +90,10 @@ class Nes_Emu
|
||||||
// Use already-loaded cartridge. Retains pointer, so it must be kept around until
|
// Use already-loaded cartridge. Retains pointer, so it must be kept around until
|
||||||
// closed. A cartridge can be shared among multiple emulators. After opening,
|
// closed. A cartridge can be shared among multiple emulators. After opening,
|
||||||
// cartridge's CHR data shouldn't be modified since a copy is cached internally.
|
// cartridge's CHR data shouldn't be modified since a copy is cached internally.
|
||||||
void set_cart(Nes_Cart const *);
|
void set_cart(Cart const *);
|
||||||
|
|
||||||
// Pointer to current cartridge, or NULL if none is loaded
|
// Pointer to current cartridge, or NULL if none is loaded
|
||||||
Nes_Cart const *cart() const { return emu.cart; }
|
Cart const *cart() const { return emu.cart; }
|
||||||
|
|
||||||
// Emulate powering NES off and then back on. If full_reset is false, emulates
|
// Emulate powering NES off and then back on. If full_reset is false, emulates
|
||||||
// pressing the reset button only, which doesn't affect memory, otherwise
|
// pressing the reset button only, which doesn't affect memory, otherwise
|
||||||
|
@ -108,7 +108,7 @@ class Nes_Emu
|
||||||
// Sound
|
// Sound
|
||||||
|
|
||||||
// Set sample rate and use a custom sound buffer instead of the default
|
// Set sample rate and use a custom sound buffer instead of the default
|
||||||
// mono buffer, i.e. Nes_Buffer, Effects_Buffer, etc..
|
// mono buffer, i.e. Buffer, Effects_Buffer, etc..
|
||||||
const char *set_sample_rate(long rate, Multi_Buffer *);
|
const char *set_sample_rate(long rate, Multi_Buffer *);
|
||||||
|
|
||||||
// Adjust effective frame rate by changing how many samples are generated each frame.
|
// Adjust effective frame rate by changing how many samples are generated each frame.
|
||||||
|
@ -219,7 +219,7 @@ class Nes_Emu
|
||||||
|
|
||||||
// End of public interface
|
// End of public interface
|
||||||
public:
|
public:
|
||||||
const char *set_sample_rate(long rate, class Nes_Buffer *);
|
const char *set_sample_rate(long rate, class Buffer *);
|
||||||
const char *set_sample_rate(long rate, class Nes_Effects_Buffer *);
|
const char *set_sample_rate(long rate, class Nes_Effects_Buffer *);
|
||||||
void irq_changed() { emu.irq_changed(); }
|
void irq_changed() { emu.irq_changed(); }
|
||||||
|
|
||||||
|
@ -230,14 +230,14 @@ class Nes_Emu
|
||||||
bool fade_sound_out;
|
bool fade_sound_out;
|
||||||
virtual const char *init_();
|
virtual const char *init_();
|
||||||
|
|
||||||
virtual void loading_state(Nes_State const &) {}
|
virtual void loading_state(State const &) {}
|
||||||
long timestamp() const { return emu.nes.frame_count; }
|
long timestamp() const { return emu.nes.frame_count; }
|
||||||
void set_timestamp(long t) { emu.nes.frame_count = t; }
|
void set_timestamp(long t) { emu.nes.frame_count = t; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Nes_Emu(const Nes_Emu &);
|
Emu(const Emu &);
|
||||||
Nes_Emu &operator=(const Nes_Emu &);
|
Emu &operator=(const Emu &);
|
||||||
|
|
||||||
// sound
|
// sound
|
||||||
Multi_Buffer *default_sound_buf;
|
Multi_Buffer *default_sound_buf;
|
||||||
|
@ -254,8 +254,8 @@ class Nes_Emu
|
||||||
char *host_pixels;
|
char *host_pixels;
|
||||||
int host_palette_size;
|
int host_palette_size;
|
||||||
frame_t single_frame;
|
frame_t single_frame;
|
||||||
Nes_Cart private_cart;
|
Cart private_cart;
|
||||||
Nes_Core emu; // large; keep at end
|
Core emu; // large; keep at end
|
||||||
|
|
||||||
bool init_called;
|
bool init_called;
|
||||||
const char *auto_init();
|
const char *auto_init();
|
||||||
|
@ -269,18 +269,18 @@ class Nes_Emu
|
||||||
void RestoreAudioBufferState();
|
void RestoreAudioBufferState();
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Nes_Emu::set_pixels(void *p, long n)
|
inline void Emu::set_pixels(void *p, long n)
|
||||||
{
|
{
|
||||||
host_pixels = (char *)p + n;
|
host_pixels = (char *)p + n;
|
||||||
emu.ppu.host_row_bytes = n;
|
emu.ppu.host_row_bytes = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t const *Nes_Emu::chr_mem()
|
inline uint8_t const *Emu::chr_mem()
|
||||||
{
|
{
|
||||||
return cart()->chr_size() ? (uint8_t *)cart()->chr() : emu.ppu.impl->chr_ram;
|
return cart()->chr_size() ? (uint8_t *)cart()->chr() : emu.ppu.impl->chr_ram;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline long Nes_Emu::chr_size() const
|
inline long Emu::chr_size() const
|
||||||
{
|
{
|
||||||
return cart()->chr_size() ? cart()->chr_size() : emu.ppu.chr_addr_size;
|
return cart()->chr_size() ? cart()->chr_size() : emu.ppu.chr_addr_size;
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
#include "Nes_Core.hpp"
|
#include "core.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
|
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
|
||||||
|
@ -79,7 +79,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
Nes_Mapper::Nes_Mapper()
|
Mapper::Mapper()
|
||||||
{
|
{
|
||||||
emu_ = NULL;
|
emu_ = NULL;
|
||||||
static char c;
|
static char c;
|
||||||
|
@ -87,13 +87,13 @@ Nes_Mapper::Nes_Mapper()
|
||||||
state_size = 0;
|
state_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Mapper::~Nes_Mapper()
|
Mapper::~Mapper()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets mirroring, maps first 8K CHR in, first and last 16K of PRG,
|
// Sets mirroring, maps first 8K CHR in, first and last 16K of PRG,
|
||||||
// intercepts writes to upper half of memory, and clears registered state.
|
// intercepts writes to upper half of memory, and clears registered state.
|
||||||
void Nes_Mapper::default_reset_state()
|
void Mapper::default_reset_state()
|
||||||
{
|
{
|
||||||
int mirroring = cart_->mirroring();
|
int mirroring = cart_->mirroring();
|
||||||
if (mirroring & 8)
|
if (mirroring & 8)
|
||||||
|
@ -113,7 +113,7 @@ void Nes_Mapper::default_reset_state()
|
||||||
memset(state, 0, state_size);
|
memset(state, 0, state_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::reset()
|
void Mapper::reset()
|
||||||
{
|
{
|
||||||
default_reset_state();
|
default_reset_state();
|
||||||
reset_state();
|
reset_state();
|
||||||
|
@ -134,19 +134,19 @@ int mapper_state_t::read(void *p, unsigned long s) const
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::save_state(mapper_state_t &out)
|
void Mapper::save_state(mapper_state_t &out)
|
||||||
{
|
{
|
||||||
out.write(state, state_size);
|
out.write(state, state_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::load_state(mapper_state_t const &in)
|
void Mapper::load_state(mapper_state_t const &in)
|
||||||
{
|
{
|
||||||
default_reset_state();
|
default_reset_state();
|
||||||
read_state(in);
|
read_state(in);
|
||||||
apply_mapping();
|
apply_mapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::read_state(mapper_state_t const &in)
|
void Mapper::read_state(mapper_state_t const &in)
|
||||||
{
|
{
|
||||||
memset(state, 0, state_size);
|
memset(state, 0, state_size);
|
||||||
in.read(state, state_size);
|
in.read(state, state_size);
|
||||||
|
@ -155,29 +155,29 @@ void Nes_Mapper::read_state(mapper_state_t const &in)
|
||||||
|
|
||||||
// Timing
|
// Timing
|
||||||
|
|
||||||
void Nes_Mapper::irq_changed() { emu_->irq_changed(); }
|
void Mapper::irq_changed() { emu_->irq_changed(); }
|
||||||
|
|
||||||
nes_time_t Nes_Mapper::next_irq(nes_time_t) { return no_irq; }
|
nes_time_t Mapper::next_irq(nes_time_t) { return no_irq; }
|
||||||
|
|
||||||
void Nes_Mapper::a12_clocked() {}
|
void Mapper::a12_clocked() {}
|
||||||
|
|
||||||
void Nes_Mapper::run_until(nes_time_t) {}
|
void Mapper::run_until(nes_time_t) {}
|
||||||
|
|
||||||
void Nes_Mapper::end_frame(nes_time_t) {}
|
void Mapper::end_frame(nes_time_t) {}
|
||||||
|
|
||||||
bool Nes_Mapper::ppu_enabled() const { return emu().ppu.w2001 & 0x08; }
|
bool Mapper::ppu_enabled() const { return emu().ppu.w2001 & 0x08; }
|
||||||
|
|
||||||
// Sound
|
// Sound
|
||||||
|
|
||||||
int Nes_Mapper::channel_count() const { return 0; }
|
int Mapper::channel_count() const { return 0; }
|
||||||
|
|
||||||
void Nes_Mapper::set_channel_buf(int, Blip_Buffer *) {}
|
void Mapper::set_channel_buf(int, Blip_Buffer *) {}
|
||||||
|
|
||||||
void Nes_Mapper::set_treble(blip_eq_t const &) {}
|
void Mapper::set_treble(blip_eq_t const &) {}
|
||||||
|
|
||||||
// Memory mapping
|
// Memory mapping
|
||||||
|
|
||||||
void Nes_Mapper::set_prg_bank(nes_addr_t addr, bank_size_t bs, int bank)
|
void Mapper::set_prg_bank(nes_addr_t addr, bank_size_t bs, int bank)
|
||||||
{
|
{
|
||||||
int bank_size = 1 << bs;
|
int bank_size = 1 << bs;
|
||||||
|
|
||||||
|
@ -194,42 +194,42 @@ void Nes_Mapper::set_prg_bank(nes_addr_t addr, bank_size_t bs, int bank)
|
||||||
emu().enable_prg_6000();
|
emu().enable_prg_6000();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::set_chr_bank(nes_addr_t addr, bank_size_t bs, int bank)
|
void Mapper::set_chr_bank(nes_addr_t addr, bank_size_t bs, int bank)
|
||||||
{
|
{
|
||||||
emu().ppu.render_until(emu().clock());
|
emu().ppu.render_until(emu().clock());
|
||||||
emu().ppu.set_chr_bank(addr, 1 << bs, bank << bs);
|
emu().ppu.set_chr_bank(addr, 1 << bs, bank << bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::set_chr_bank_ex(nes_addr_t addr, bank_size_t bs, int bank)
|
void Mapper::set_chr_bank_ex(nes_addr_t addr, bank_size_t bs, int bank)
|
||||||
{
|
{
|
||||||
emu().ppu.render_until(emu().clock());
|
emu().ppu.render_until(emu().clock());
|
||||||
emu().ppu.set_chr_bank_ex(addr, 1 << bs, bank << bs);
|
emu().ppu.set_chr_bank_ex(addr, 1 << bs, bank << bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::mirror_manual(int page0, int page1, int page2, int page3)
|
void Mapper::mirror_manual(int page0, int page1, int page2, int page3)
|
||||||
{
|
{
|
||||||
emu().ppu.render_bg_until(emu().clock());
|
emu().ppu.render_bg_until(emu().clock());
|
||||||
emu().ppu.set_nt_banks(page0, page1, page2, page3);
|
emu().ppu.set_nt_banks(page0, page1, page2, page3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::intercept_reads(nes_addr_t addr, unsigned size)
|
void Mapper::intercept_reads(nes_addr_t addr, unsigned size)
|
||||||
{
|
{
|
||||||
emu().add_mapper_intercept(addr, size, true, false);
|
emu().add_mapper_intercept(addr, size, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::intercept_writes(nes_addr_t addr, unsigned size)
|
void Mapper::intercept_writes(nes_addr_t addr, unsigned size)
|
||||||
{
|
{
|
||||||
emu().add_mapper_intercept(addr, size, false, true);
|
emu().add_mapper_intercept(addr, size, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Mapper::enable_sram(bool enabled, bool read_only)
|
void Mapper::enable_sram(bool enabled, bool read_only)
|
||||||
{
|
{
|
||||||
emu_->enable_sram(enabled, read_only);
|
emu_->enable_sram(enabled, read_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Mapper *Nes_Mapper::getMapperFromCode(const int mapperCode)
|
Mapper *Mapper::getMapperFromCode(const int mapperCode)
|
||||||
{
|
{
|
||||||
Nes_Mapper *mapper = nullptr;
|
Mapper *mapper = nullptr;
|
||||||
|
|
||||||
// Now checking if the detected mapper code is supported
|
// Now checking if the detected mapper code is supported
|
||||||
if (mapperCode == 0) mapper = new Mapper000();
|
if (mapperCode == 0) mapper = new Mapper000();
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// NES mapper interface
|
// NES mapper interface
|
||||||
// Nes_Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include "Nes_Cart.hpp"
|
|
||||||
#include "Nes_Cpu.hpp"
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include "cart.hpp"
|
||||||
|
#include "cpu.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Blip_Buffer;
|
class Blip_Buffer;
|
||||||
class blip_eq_t;
|
class blip_eq_t;
|
||||||
class Nes_Core;
|
class Core;
|
||||||
|
|
||||||
// Increase this (and let me know) if your mapper requires more state. This only
|
// Increase this (and let me know) if your mapper requires more state. This only
|
||||||
// sets the size of the in-memory buffer; it doesn't affect the file format at all.
|
// sets the size of the in-memory buffer; it doesn't affect the file format at all.
|
||||||
|
@ -30,10 +30,10 @@ struct mapper_state_t
|
||||||
int read(void *p, unsigned long s) const;
|
int read(void *p, unsigned long s) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Nes_Mapper
|
class Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Nes_Mapper();
|
virtual ~Mapper();
|
||||||
|
|
||||||
// Reset mapper to power-up state.
|
// Reset mapper to power-up state.
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
|
@ -94,7 +94,7 @@ class Nes_Mapper
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Services provided for derived mapper classes
|
// Services provided for derived mapper classes
|
||||||
Nes_Mapper();
|
Mapper();
|
||||||
|
|
||||||
// Register state data to automatically save and load. Be sure the binary
|
// Register state data to automatically save and load. Be sure the binary
|
||||||
// layout is suitable for use in a file, including any byte-order issues.
|
// layout is suitable for use in a file, including any byte-order issues.
|
||||||
|
@ -106,12 +106,12 @@ class Nes_Mapper
|
||||||
|
|
||||||
// Cause CPU writes within given address range to call mapper's write() function.
|
// Cause CPU writes within given address range to call mapper's write() function.
|
||||||
// Might map a larger address range, which the mapper can ignore and pass to
|
// Might map a larger address range, which the mapper can ignore and pass to
|
||||||
// Nes_Mapper::write(). The range 0x8000-0xffff is always intercepted by the mapper.
|
// Mapper::write(). The range 0x8000-0xffff is always intercepted by the mapper.
|
||||||
void intercept_writes(nes_addr_t addr, unsigned size);
|
void intercept_writes(nes_addr_t addr, unsigned size);
|
||||||
|
|
||||||
// Cause CPU reads within given address range to call mapper's read() function.
|
// Cause CPU reads within given address range to call mapper's read() function.
|
||||||
// Might map a larger address range, which the mapper can ignore and pass to
|
// Might map a larger address range, which the mapper can ignore and pass to
|
||||||
// Nes_Mapper::read(). CPU opcode/operand reads and low-memory reads always
|
// Mapper::read(). CPU opcode/operand reads and low-memory reads always
|
||||||
// go directly to memory and cannot be intercepted.
|
// go directly to memory and cannot be intercepted.
|
||||||
void intercept_reads(nes_addr_t addr, unsigned size);
|
void intercept_reads(nes_addr_t addr, unsigned size);
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ class Nes_Mapper
|
||||||
bool ppu_enabled() const;
|
bool ppu_enabled() const;
|
||||||
|
|
||||||
// Cartridge being emulated
|
// Cartridge being emulated
|
||||||
Nes_Cart const &cart() const { return *cart_; }
|
Cart const &cart() const { return *cart_; }
|
||||||
|
|
||||||
// Must be called when next_irq()'s return value is earlier than previous,
|
// Must be called when next_irq()'s return value is earlier than previous,
|
||||||
// current CPU run can be stopped earlier. Best to call whenever time may
|
// current CPU run can be stopped earlier. Best to call whenever time may
|
||||||
|
@ -166,7 +166,7 @@ class Nes_Mapper
|
||||||
int handle_bus_conflict(nes_addr_t addr, int data);
|
int handle_bus_conflict(nes_addr_t addr, int data);
|
||||||
|
|
||||||
// Reference to emulator that uses this mapper.
|
// Reference to emulator that uses this mapper.
|
||||||
Nes_Core &emu() const { return *emu_; }
|
Core &emu() const { return *emu_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Services derived classes provide
|
// Services derived classes provide
|
||||||
|
@ -181,8 +181,8 @@ class Nes_Mapper
|
||||||
// End of general interface
|
// End of general interface
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Nes_Cart const *cart_;
|
Cart const *cart_;
|
||||||
Nes_Core *emu_;
|
Core *emu_;
|
||||||
|
|
||||||
// Apply current mapping state to hardware. Called after reading mapper state
|
// Apply current mapping state to hardware. Called after reading mapper state
|
||||||
// from a snapshot.
|
// from a snapshot.
|
||||||
|
@ -190,23 +190,23 @@ class Nes_Mapper
|
||||||
|
|
||||||
void default_reset_state();
|
void default_reset_state();
|
||||||
|
|
||||||
static Nes_Mapper *getMapperFromCode(const int mapperCode);
|
static Mapper *getMapperFromCode(const int mapperCode);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int Nes_Mapper::handle_bus_conflict(nes_addr_t addr, int data) { return data; }
|
inline int Mapper::handle_bus_conflict(nes_addr_t addr, int data) { return data; }
|
||||||
inline void Nes_Mapper::mirror_horiz(int p) { mirror_manual(p, p, p ^ 1, p ^ 1); }
|
inline void Mapper::mirror_horiz(int p) { mirror_manual(p, p, p ^ 1, p ^ 1); }
|
||||||
inline void Nes_Mapper::mirror_vert(int p) { mirror_manual(p, p ^ 1, p, p ^ 1); }
|
inline void Mapper::mirror_vert(int p) { mirror_manual(p, p ^ 1, p, p ^ 1); }
|
||||||
inline void Nes_Mapper::mirror_single(int p) { mirror_manual(p, p, p, p); }
|
inline void Mapper::mirror_single(int p) { mirror_manual(p, p, p, p); }
|
||||||
inline void Nes_Mapper::mirror_full() { mirror_manual(0, 1, 2, 3); }
|
inline void Mapper::mirror_full() { mirror_manual(0, 1, 2, 3); }
|
||||||
|
|
||||||
inline void Nes_Mapper::register_state(void *p, unsigned s)
|
inline void Mapper::register_state(void *p, unsigned s)
|
||||||
{
|
{
|
||||||
state = p;
|
state = p;
|
||||||
state_size = s;
|
state_size = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Nes_Mapper::write_intercepted(nes_time_t, nes_addr_t, int) { return false; }
|
inline bool Mapper::write_intercepted(nes_time_t, nes_addr_t, int) { return false; }
|
||||||
|
|
||||||
inline int Nes_Mapper::read(nes_time_t, nes_addr_t) { return -1; } // signal to caller
|
inline int Mapper::read(nes_time_t, nes_addr_t) { return -1; } // signal to caller
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickNES
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Common simple mappers
|
// Common simple mappers
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper000 : public Nes_Mapper
|
class Mapper000 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper000() {}
|
Mapper000() {}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -29,7 +29,7 @@ struct mmc1_state_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(mmc1_state_t) == 6);
|
static_assert(sizeof(mmc1_state_t) == 6);
|
||||||
|
|
||||||
class Mapper001 : public Nes_Mapper, mmc1_state_t
|
class Mapper001 : public Mapper, mmc1_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper001()
|
Mapper001()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Common simple mappers
|
// Common simple mappers
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace quickerNES
|
||||||
|
|
||||||
// UNROM
|
// UNROM
|
||||||
|
|
||||||
class Mapper002 : public Nes_Mapper
|
class Mapper002 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Common simple mappers
|
// Common simple mappers
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace quickerNES
|
||||||
|
|
||||||
// CNROM
|
// CNROM
|
||||||
|
|
||||||
class Mapper003 : public Nes_Mapper
|
class Mapper003 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
#include "Nes_Core.hpp"
|
#include "core.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
|
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
|
||||||
|
@ -24,8 +24,8 @@ namespace quickerNES
|
||||||
// 264 or less breaks Gargoyle's Quest II
|
// 264 or less breaks Gargoyle's Quest II
|
||||||
// 267 or less breaks Magician
|
// 267 or less breaks Magician
|
||||||
int const irq_fine_tune = 268;
|
int const irq_fine_tune = 268;
|
||||||
nes_time_t const first_scanline = 20 * Nes_Ppu::scanline_len + irq_fine_tune;
|
nes_time_t const first_scanline = 20 * Ppu::scanline_len + irq_fine_tune;
|
||||||
nes_time_t const last_scanline = first_scanline + 240 * Nes_Ppu::scanline_len;
|
nes_time_t const last_scanline = first_scanline + 240 * Ppu::scanline_len;
|
||||||
|
|
||||||
// MMC3
|
// MMC3
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ struct mmc3_state_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(mmc3_state_t) == 15);
|
static_assert(sizeof(mmc3_state_t) == 15);
|
||||||
|
|
||||||
class Mapper004 : public Nes_Mapper, mmc3_state_t
|
class Mapper004 : public Mapper, mmc3_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper004()
|
Mapper004()
|
||||||
|
@ -144,7 +144,7 @@ class Mapper004 : public Nes_Mapper, mmc3_state_t
|
||||||
{
|
{
|
||||||
if (bg_enabled)
|
if (bg_enabled)
|
||||||
clock_counter();
|
clock_counter();
|
||||||
next_time += Nes_Ppu::scanline_len;
|
next_time += Ppu::scanline_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
// NES MMC5 mapper, currently only tailored for Castlevania 3 (U)
|
// NES MMC5 mapper, currently only tailored for Castlevania 3 (U)
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Nes_Core.hpp"
|
#include "core.hpp"
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ static_assert(sizeof(mmc5_state_t) == 0x31);
|
||||||
|
|
||||||
// MMC5
|
// MMC5
|
||||||
|
|
||||||
class Mapper005 : public Nes_Mapper, mmc5_state_t
|
class Mapper005 : public Mapper, mmc5_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper005()
|
Mapper005()
|
||||||
|
@ -57,7 +57,7 @@ class Mapper005 : public Nes_Mapper, mmc5_state_t
|
||||||
|
|
||||||
virtual void read_state(mapper_state_t const &in)
|
virtual void read_state(mapper_state_t const &in)
|
||||||
{
|
{
|
||||||
Nes_Mapper::read_state(in);
|
Mapper::read_state(in);
|
||||||
irq_time = no_irq;
|
irq_time = no_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Common simple mappers
|
// Common simple mappers
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace quickerNES
|
||||||
|
|
||||||
// AOROM
|
// AOROM
|
||||||
|
|
||||||
class Mapper007 : public Nes_Mapper
|
class Mapper007 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace quickerNES
|
||||||
|
|
||||||
// MMC2
|
// MMC2
|
||||||
|
|
||||||
class Mapper009 : public Nes_Mapper
|
class Mapper009 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t regs[6]; // A,B,C,D,E,F
|
uint8_t regs[6]; // A,B,C,D,E,F
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace quickerNES
|
||||||
|
|
||||||
// MMC4
|
// MMC4
|
||||||
|
|
||||||
class Mapper010 : public Nes_Mapper
|
class Mapper010 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t regs[6]; // A,B,C,D,E,F
|
uint8_t regs[6]; // A,B,C,D,E,F
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Optional less-common simple mappers
|
// Optional less-common simple mappers
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace quickerNES
|
||||||
|
|
||||||
// Color Dreams
|
// Color Dreams
|
||||||
|
|
||||||
class Mapper011 : public Nes_Mapper
|
class Mapper011 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ static_assert(sizeof(Mapper015_state_t) == 5);
|
||||||
|
|
||||||
// K-1029, K-1030P
|
// K-1029, K-1030P
|
||||||
|
|
||||||
class Mapper015 : public Nes_Mapper, Mapper015_state_t
|
class Mapper015 : public Mapper, Mapper015_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper015()
|
Mapper015()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Namco 106 mapper
|
// Namco 106 mapper
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "apu/namco/apu.hpp"
|
#include "apu/namco/apu.hpp"
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
@ -35,7 +35,7 @@ static_assert(sizeof(namco106_state_t) == 20 + sizeof(namco_state_t));
|
||||||
|
|
||||||
// Namco106
|
// Namco106
|
||||||
|
|
||||||
class Mapper019 : public Nes_Mapper, namco106_state_t
|
class Mapper019 : public Mapper, namco106_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper019()
|
Mapper019()
|
||||||
|
@ -128,7 +128,7 @@ class Mapper019 : public Nes_Mapper, namco106_state_t
|
||||||
return irq_ctr >> 8;
|
return irq_ctr >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Nes_Mapper::read(time, addr);
|
return Mapper::read(time, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool write_intercepted(nes_time_t time, nes_addr_t addr, int data)
|
virtual bool write_intercepted(nes_time_t time, nes_addr_t addr, int data)
|
||||||
|
@ -186,16 +186,16 @@ class Mapper019 : public Nes_Mapper, namco106_state_t
|
||||||
void save_state(mapper_state_t &out)
|
void save_state(mapper_state_t &out)
|
||||||
{
|
{
|
||||||
sound.save_state(&sound_state);
|
sound.save_state(&sound_state);
|
||||||
Nes_Mapper::save_state(out);
|
Mapper::save_state(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_state(mapper_state_t const &in)
|
void read_state(mapper_state_t const &in)
|
||||||
{
|
{
|
||||||
Nes_Mapper::read_state(in);
|
Mapper::read_state(in);
|
||||||
sound.load_state(sound_state);
|
sound.load_state(sound_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Namco_Apu sound;
|
Namco_Apu sound;
|
||||||
nes_time_t last_time;
|
nes_time_t last_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct vrc2_state_t
|
||||||
static_assert(sizeof(vrc2_state_t) == 18);
|
static_assert(sizeof(vrc2_state_t) == 18);
|
||||||
|
|
||||||
template <bool type_a, bool type_b>
|
template <bool type_a, bool type_b>
|
||||||
class Mapper_VRC2_4 : public Nes_Mapper, vrc2_state_t
|
class Mapper_VRC2_4 : public Mapper, vrc2_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper_VRC2_4()
|
Mapper_VRC2_4()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Konami VRC6 mapper
|
// Konami VRC6 mapper
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "apu/vrc6/apu.hpp"
|
#include "apu/vrc6/apu.hpp"
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
@ -44,7 +44,7 @@ struct vrc6_state_t
|
||||||
static_assert(sizeof(vrc6_state_t) == 26 + sizeof(vrc6_apu_state_t));
|
static_assert(sizeof(vrc6_state_t) == 26 + sizeof(vrc6_apu_state_t));
|
||||||
|
|
||||||
template <int swapMask>
|
template <int swapMask>
|
||||||
class Mapper_Vrc6 : public Nes_Mapper, vrc6_state_t
|
class Mapper_Vrc6 : public Mapper, vrc6_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper_Vrc6()
|
Mapper_Vrc6()
|
||||||
|
@ -69,7 +69,7 @@ class Mapper_Vrc6 : public Nes_Mapper, vrc6_state_t
|
||||||
virtual void save_state(mapper_state_t &out)
|
virtual void save_state(mapper_state_t &out)
|
||||||
{
|
{
|
||||||
sound.save_state(&sound_state);
|
sound.save_state(&sound_state);
|
||||||
Nes_Mapper::save_state(out);
|
Mapper::save_state(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply_mapping()
|
virtual void apply_mapping()
|
||||||
|
@ -139,7 +139,7 @@ class Mapper_Vrc6 : public Nes_Mapper, vrc6_state_t
|
||||||
write_irq(time, addr, data);
|
write_irq(time, addr, data);
|
||||||
}
|
}
|
||||||
int swap_mask;
|
int swap_mask;
|
||||||
Nes_Vrc6_Apu sound;
|
Vrc6_Apu sound;
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
timer_period = 113 * 4 + 3
|
timer_period = 113 * 4 + 3
|
||||||
|
@ -147,7 +147,7 @@ class Mapper_Vrc6 : public Nes_Mapper, vrc6_state_t
|
||||||
|
|
||||||
void read_state(mapper_state_t const &in)
|
void read_state(mapper_state_t const &in)
|
||||||
{
|
{
|
||||||
Nes_Mapper::read_state(in);
|
Mapper::read_state(in);
|
||||||
|
|
||||||
// to do: eliminate when format is updated
|
// to do: eliminate when format is updated
|
||||||
// old-style registers
|
// old-style registers
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Konami VRC6 mapper
|
// Konami VRC6 mapper
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper030 : public Nes_Mapper
|
class Mapper030 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper030() {}
|
Mapper030() {}
|
||||||
|
|
|
@ -39,7 +39,7 @@ static_assert(sizeof(mapper32_state_t) == 12);
|
||||||
|
|
||||||
// Irem_G101
|
// Irem_G101
|
||||||
|
|
||||||
class Mapper032 : public Nes_Mapper, mapper32_state_t
|
class Mapper032 : public Mapper, mapper32_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper032()
|
Mapper032()
|
||||||
|
|
|
@ -38,7 +38,7 @@ static_assert(sizeof(tc0190_state_t) == 9);
|
||||||
|
|
||||||
// TaitoTC0190
|
// TaitoTC0190
|
||||||
|
|
||||||
class Mapper033 : public Nes_Mapper, tc0190_state_t
|
class Mapper033 : public Mapper, tc0190_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper033()
|
Mapper033()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Optional less-common simple mappers
|
// Optional less-common simple mappers
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper034 : public Nes_Mapper
|
class Mapper034 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper060 : public Nes_Mapper
|
class Mapper060 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper060()
|
Mapper060()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Optional less-common simple mappers
|
// Optional less-common simple mappers
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper066 : public Nes_Mapper
|
class Mapper066 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Sunsoft FME-7 mapper
|
// Sunsoft FME-7 mapper
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/libs/
|
// Emu 0.7.0. http://www.slack.net/~ant/libs/
|
||||||
|
|
||||||
#include "apu/fme7/apu.hpp"
|
#include "apu/fme7/apu.hpp"
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
@ -37,7 +37,7 @@ static_assert(sizeof(fme7_state_t) == 18 + sizeof(fme7_apu_state_t));
|
||||||
|
|
||||||
// Fme7
|
// Fme7
|
||||||
|
|
||||||
class Mapper069 : public Nes_Mapper, fme7_state_t
|
class Mapper069 : public Mapper, fme7_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper069()
|
Mapper069()
|
||||||
|
@ -62,12 +62,12 @@ class Mapper069 : public Nes_Mapper, fme7_state_t
|
||||||
virtual void save_state(mapper_state_t &out)
|
virtual void save_state(mapper_state_t &out)
|
||||||
{
|
{
|
||||||
sound.save_state(&sound_state);
|
sound.save_state(&sound_state);
|
||||||
Nes_Mapper::save_state(out);
|
Mapper::save_state(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void read_state(mapper_state_t const &in)
|
virtual void read_state(mapper_state_t const &in)
|
||||||
{
|
{
|
||||||
Nes_Mapper::read_state(in);
|
Mapper::read_state(in);
|
||||||
sound.load_state(sound_state);
|
sound.load_state(sound_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ class Mapper069 : public Nes_Mapper, fme7_state_t
|
||||||
}
|
}
|
||||||
|
|
||||||
nes_time_t last_time;
|
nes_time_t last_time;
|
||||||
Nes_Fme7_Apu sound;
|
Fme7_Apu sound;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickNES
|
|
@ -31,7 +31,7 @@ namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
template <int mapperId>
|
template <int mapperId>
|
||||||
class Mapper_74x161x162x32 : public Nes_Mapper
|
class Mapper_74x161x162x32 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper_74x161x162x32()
|
Mapper_74x161x162x32()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Optional less-common simple mappers
|
// Optional less-common simple mappers
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper071 : public Nes_Mapper
|
class Mapper071 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t regs[3];
|
uint8_t regs[3];
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ struct vrc3_state_t
|
||||||
|
|
||||||
// VRC3
|
// VRC3
|
||||||
|
|
||||||
class Mapper073 : public Nes_Mapper, vrc3_state_t
|
class Mapper073 : public Mapper, vrc3_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper073()
|
Mapper073()
|
||||||
|
|
|
@ -33,7 +33,7 @@ static_assert(sizeof(vrc1_state_t) == 8);
|
||||||
|
|
||||||
// VRC1
|
// VRC1
|
||||||
|
|
||||||
class Mapper075 : public Nes_Mapper, vrc1_state_t
|
class Mapper075 : public Mapper, vrc1_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper075()
|
Mapper075()
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper078 : public Nes_Mapper
|
class Mapper078 : public Mapper
|
||||||
{
|
{
|
||||||
// lower 8 bits are the reg at 8000:ffff
|
// lower 8 bits are the reg at 8000:ffff
|
||||||
// next two bits are autodetecting type
|
// next two bits are autodetecting type
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
template <bool multicart>
|
template <bool multicart>
|
||||||
class Mapper_AveNina : public Nes_Mapper
|
class Mapper_AveNina : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper_AveNina()
|
Mapper_AveNina()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Nes_Emu 0.5.4. http://www.slack.net/~ant/
|
// Emu 0.5.4. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "apu/vrc7/apu.hpp"
|
#include "apu/vrc7/apu.hpp"
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
@ -40,7 +40,7 @@ static_assert(sizeof(vrc7_state_t) == 20 + sizeof(vrc7_snapshot_t));
|
||||||
|
|
||||||
// Vrc7
|
// Vrc7
|
||||||
|
|
||||||
class Mapper085 : public Nes_Mapper, vrc7_state_t
|
class Mapper085 : public Mapper, vrc7_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper085()
|
Mapper085()
|
||||||
|
@ -58,12 +58,12 @@ class Mapper085 : public Nes_Mapper, vrc7_state_t
|
||||||
virtual void save_state(mapper_state_t &out)
|
virtual void save_state(mapper_state_t &out)
|
||||||
{
|
{
|
||||||
sound.save_snapshot(&sound_state);
|
sound.save_snapshot(&sound_state);
|
||||||
Nes_Mapper::save_state(out);
|
Mapper::save_state(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void load_state(mapper_state_t const &in)
|
virtual void load_state(mapper_state_t const &in)
|
||||||
{
|
{
|
||||||
Nes_Mapper::load_state(in);
|
Mapper::load_state(in);
|
||||||
sound.load_snapshot(sound_state, in.size);
|
sound.load_snapshot(sound_state, in.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ class Mapper085 : public Nes_Mapper, vrc7_state_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Vrc7 sound;
|
Vrc7 sound;
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
timer_period = 113 * 4 + 3
|
timer_period = 113 * 4 + 3
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Optional less-common simple mappers
|
// Optional less-common simple mappers
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper087 : public Nes_Mapper
|
class Mapper087 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t bank;
|
uint8_t bank;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct namco_34x3_state_t
|
||||||
static_assert(sizeof(namco_34x3_state_t) == 10);
|
static_assert(sizeof(namco_34x3_state_t) == 10);
|
||||||
|
|
||||||
template <bool _is154>
|
template <bool _is154>
|
||||||
class Mapper_Namco_34x3 : public Nes_Mapper, namco_34x3_state_t
|
class Mapper_Namco_34x3 : public Mapper, namco_34x3_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper_Namco_34x3()
|
Mapper_Namco_34x3()
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper089 : public Nes_Mapper
|
class Mapper089 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper089()
|
Mapper089()
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper093 : public Nes_Mapper
|
class Mapper093 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper093()
|
Mapper093()
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper094 : public Nes_Mapper
|
class Mapper094 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper094()
|
Mapper094()
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper097 : public Nes_Mapper
|
class Mapper097 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper097()
|
Mapper097()
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper140 : public Nes_Mapper
|
class Mapper140 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper140()
|
Mapper140()
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct m156_state_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(m156_state_t) == 9);
|
static_assert(sizeof(m156_state_t) == 9);
|
||||||
|
|
||||||
class Mapper156 : public Nes_Mapper, m156_state_t
|
class Mapper156 : public Mapper, m156_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper156()
|
Mapper156()
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper180 : public Nes_Mapper
|
class Mapper180 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper180()
|
Mapper180()
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper184 : public Nes_Mapper
|
class Mapper184 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper184()
|
Mapper184()
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper190 : public Nes_Mapper
|
class Mapper190 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper190()
|
Mapper190()
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper193 : public Nes_Mapper
|
class Mapper193 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper193()
|
Mapper193()
|
||||||
|
|
|
@ -40,7 +40,7 @@ static_assert(sizeof(namco_34xx_state_t) == 10);
|
||||||
|
|
||||||
// Namco_34xx
|
// Namco_34xx
|
||||||
|
|
||||||
class Mapper206 : public Nes_Mapper, namco_34xx_state_t
|
class Mapper206 : public Mapper, namco_34xx_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper206()
|
Mapper206()
|
||||||
|
|
|
@ -38,7 +38,7 @@ static_assert(sizeof(taito_x1005_state_t) == 11);
|
||||||
|
|
||||||
// TaitoX1005
|
// TaitoX1005
|
||||||
|
|
||||||
class Mapper207 : public Nes_Mapper, taito_x1005_state_t
|
class Mapper207 : public Mapper, taito_x1005_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper207()
|
Mapper207()
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
// Optional less-common simple mappers
|
// Optional less-common simple mappers
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "mappers/mapper.hpp"
|
#include "mappers/mapper.hpp"
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper232 : public Nes_Mapper
|
class Mapper232 : public Mapper
|
||||||
{
|
{
|
||||||
uint8_t regs[2];
|
uint8_t regs[2];
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper240 : public Nes_Mapper
|
class Mapper240 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper240()
|
Mapper240()
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper241 : public Nes_Mapper
|
class Mapper241 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper241()
|
Mapper241()
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct mapper244_state_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(mapper244_state_t) == 2);
|
static_assert(sizeof(mapper244_state_t) == 2);
|
||||||
|
|
||||||
class Mapper244 : public Nes_Mapper, mapper244_state_t
|
class Mapper244 : public Mapper, mapper244_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper244()
|
Mapper244()
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Mapper246 : public Nes_Mapper
|
class Mapper246 : public Mapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mapper246()
|
Mapper246()
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
quickerNESAPUSrc = [
|
quickerNESAPUSrc = [
|
||||||
'apu/apu.cpp',
|
'apu/apu.cpp',
|
||||||
'apu/Nes_Oscs.cpp',
|
'apu/oscs.cpp',
|
||||||
'apu/Nes_Buffer.cpp',
|
'apu/buffer.cpp',
|
||||||
'apu/Blip_Buffer.cpp',
|
'apu/Blip_Buffer.cpp',
|
||||||
'apu/Effects_Buffer.cpp',
|
'apu/NESEffectsBuffer.cpp',
|
||||||
'apu/Nes_Effects_Buffer.cpp',
|
'apu/effectsBuffer.cpp',
|
||||||
'apu/Multi_Buffer.cpp',
|
'apu/Multi_Buffer.cpp',
|
||||||
'apu/namco/apu.cpp',
|
'apu/namco/apu.cpp',
|
||||||
'apu/vrc6/apu.cpp',
|
'apu/vrc6/apu.cpp',
|
||||||
|
@ -17,15 +17,15 @@ quickerNESAPUSrc = [
|
||||||
]
|
]
|
||||||
|
|
||||||
quickerNESPPUSrc = [
|
quickerNESPPUSrc = [
|
||||||
'ppu/Nes_Ppu.cpp',
|
'ppu/ppu.cpp',
|
||||||
'ppu/Nes_Ppu_Impl.cpp',
|
'ppu/ppuImpl.cpp',
|
||||||
'ppu/Nes_Ppu_Rendering.cpp',
|
'ppu/ppuRendering.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
quickerNESSrc = quickerNESAPUSrc + quickerNESPPUSrc + [
|
quickerNESSrc = quickerNESAPUSrc + quickerNESPPUSrc + [
|
||||||
'mappers/mapper.cpp',
|
'mappers/mapper.cpp',
|
||||||
'Nes_Emu.cpp',
|
'emu.cpp',
|
||||||
'Nes_Cpu.cpp'
|
'cpu.cpp'
|
||||||
]
|
]
|
||||||
|
|
||||||
# quickerNES Core Configuration
|
# quickerNES Core Configuration
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
|
|
||||||
// Timing and behavior of PPU
|
// Timing and behavior of PPU
|
||||||
|
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "Nes_Ppu.hpp"
|
#include "ppu.hpp"
|
||||||
#include "Nes_Core.hpp"
|
#include "core.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
// Timing
|
// Timing
|
||||||
|
|
||||||
ppu_time_t const scanline_len = Nes_Ppu::scanline_len;
|
ppu_time_t const scanline_len = Ppu::scanline_len;
|
||||||
|
|
||||||
// if non-zero, report sprite max at fixed time rather than calculating it
|
// if non-zero, report sprite max at fixed time rather than calculating it
|
||||||
nes_time_t const fixed_sprite_max_time = 0; // 1 * ((21 + 164) * scanline_len + 100) / ppu_overclock;
|
nes_time_t const fixed_sprite_max_time = 0; // 1 * ((21 + 164) * scanline_len + 100) / ppu_overclock;
|
||||||
|
@ -47,7 +47,7 @@ nes_time_t const earliest_vbl_end_time = max_frame_length / ppu_overclock - 10;
|
||||||
|
|
||||||
// Scanline rendering
|
// Scanline rendering
|
||||||
|
|
||||||
void Nes_Ppu::render_bg_until_(nes_time_t cpu_time)
|
void Ppu::render_bg_until_(nes_time_t cpu_time)
|
||||||
{
|
{
|
||||||
ppu_time_t time = ppu_time(cpu_time);
|
ppu_time_t time = ppu_time(cpu_time);
|
||||||
ppu_time_t const frame_duration = scanline_len * 261;
|
ppu_time_t const frame_duration = scanline_len * 261;
|
||||||
|
@ -121,7 +121,7 @@ void Nes_Ppu::render_bg_until_(nes_time_t cpu_time)
|
||||||
next_bg_time = nes_time(next_ppu_time);
|
next_bg_time = nes_time(next_ppu_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu::render_until_(nes_time_t time)
|
void Ppu::render_until_(nes_time_t time)
|
||||||
{
|
{
|
||||||
// render bg scanlines then render sprite scanlines up to wherever bg was rendered to
|
// render bg scanlines then render sprite scanlines up to wherever bg was rendered to
|
||||||
|
|
||||||
|
@ -141,14 +141,14 @@ void Nes_Ppu::render_until_(nes_time_t time)
|
||||||
|
|
||||||
// Frame events
|
// Frame events
|
||||||
|
|
||||||
inline void Nes_Ppu::end_vblank()
|
inline void Ppu::end_vblank()
|
||||||
{
|
{
|
||||||
// clear VBL, sprite hit, and max sprites flags first time after 20 scanlines
|
// clear VBL, sprite hit, and max sprites flags first time after 20 scanlines
|
||||||
r2002 &= end_vbl_mask;
|
r2002 &= end_vbl_mask;
|
||||||
end_vbl_mask = ~0;
|
end_vbl_mask = ~0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Ppu::run_end_frame(nes_time_t time)
|
inline void Ppu::run_end_frame(nes_time_t time)
|
||||||
{
|
{
|
||||||
if (!frame_ended)
|
if (!frame_ended)
|
||||||
{
|
{
|
||||||
|
@ -169,13 +169,13 @@ inline void Nes_Ppu::run_end_frame(nes_time_t time)
|
||||||
|
|
||||||
// Sprite max
|
// Sprite max
|
||||||
|
|
||||||
inline void Nes_Ppu::invalidate_sprite_max_()
|
inline void Ppu::invalidate_sprite_max_()
|
||||||
{
|
{
|
||||||
next_sprite_max_run = earliest_sprite_max / ppu_overclock;
|
next_sprite_max_run = earliest_sprite_max / ppu_overclock;
|
||||||
sprite_max_set_time = 0;
|
sprite_max_set_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu::run_sprite_max_(nes_time_t cpu_time)
|
void Ppu::run_sprite_max_(nes_time_t cpu_time)
|
||||||
{
|
{
|
||||||
end_vblank(); // might get run outside $2002 handler
|
end_vblank(); // might get run outside $2002 handler
|
||||||
|
|
||||||
|
@ -204,13 +204,13 @@ void Nes_Ppu::run_sprite_max_(nes_time_t cpu_time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Ppu::run_sprite_max(nes_time_t t)
|
inline void Ppu::run_sprite_max(nes_time_t t)
|
||||||
{
|
{
|
||||||
if (!fixed_sprite_max_time && t > next_sprite_max_run)
|
if (!fixed_sprite_max_time && t > next_sprite_max_run)
|
||||||
run_sprite_max_(t);
|
run_sprite_max_(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Ppu::invalidate_sprite_max(nes_time_t t)
|
inline void Ppu::invalidate_sprite_max(nes_time_t t)
|
||||||
{
|
{
|
||||||
if (!fixed_sprite_max_time && !(r2002 & 0x20))
|
if (!fixed_sprite_max_time && !(r2002 & 0x20))
|
||||||
{
|
{
|
||||||
|
@ -221,7 +221,7 @@ inline void Nes_Ppu::invalidate_sprite_max(nes_time_t t)
|
||||||
|
|
||||||
// Sprite 0 hit
|
// Sprite 0 hit
|
||||||
|
|
||||||
inline int Nes_Ppu_Impl::first_opaque_sprite_line()
|
inline int Ppu_Impl::first_opaque_sprite_line()
|
||||||
{
|
{
|
||||||
// advance earliest time if sprite has blank lines at beginning
|
// advance earliest time if sprite has blank lines at beginning
|
||||||
uint8_t const *p = map_chr(sprite_tile_index(spr_ram) * 16);
|
uint8_t const *p = map_chr(sprite_tile_index(spr_ram) * 16);
|
||||||
|
@ -241,7 +241,7 @@ inline int Nes_Ppu_Impl::first_opaque_sprite_line()
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu::update_sprite_hit(nes_time_t cpu_time)
|
void Ppu::update_sprite_hit(nes_time_t cpu_time)
|
||||||
{
|
{
|
||||||
ppu_time_t earliest = earliest_sprite_hit + spr_ram[0] * scanline_len + spr_ram[3];
|
ppu_time_t earliest = earliest_sprite_hit + spr_ram[0] * scanline_len + spr_ram[3];
|
||||||
// ppu_time_t latest = earliest + sprite_height() * scanline_len;
|
// ppu_time_t latest = earliest + sprite_height() * scanline_len;
|
||||||
|
@ -300,7 +300,7 @@ void Nes_Ppu::update_sprite_hit(nes_time_t cpu_time)
|
||||||
|
|
||||||
// $2002
|
// $2002
|
||||||
|
|
||||||
inline void Nes_Ppu::query_until(nes_time_t time)
|
inline void Ppu::query_until(nes_time_t time)
|
||||||
{
|
{
|
||||||
end_vblank();
|
end_vblank();
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ inline void Nes_Ppu::query_until(nes_time_t time)
|
||||||
r2002 |= (w2001 << 1 & 0x20) | (w2001 << 2 & 0x20);
|
r2002 |= (w2001 << 1 & 0x20) | (w2001 << 2 & 0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Nes_Ppu::read_2002(nes_time_t time)
|
int Ppu::read_2002(nes_time_t time)
|
||||||
{
|
{
|
||||||
nes_time_t next = next_status_event;
|
nes_time_t next = next_status_event;
|
||||||
next_status_event = vbl_end_time;
|
next_status_event = vbl_end_time;
|
||||||
|
@ -369,7 +369,7 @@ int Nes_Ppu::read_2002(nes_time_t time)
|
||||||
return (result & 0xE0) | (open_bus & 0x1F);
|
return (result & 0xE0) | (open_bus & 0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu::dma_sprites(nes_time_t time, void const *in)
|
void Ppu::dma_sprites(nes_time_t time, void const *in)
|
||||||
{
|
{
|
||||||
// dprintf( "%d sprites written\n", time );
|
// dprintf( "%d sprites written\n", time );
|
||||||
render_until(time);
|
render_until(time);
|
||||||
|
@ -382,7 +382,7 @@ void Nes_Ppu::dma_sprites(nes_time_t time, void const *in)
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
|
|
||||||
inline int Nes_Ppu_Impl::read_2007(int addr)
|
inline int Ppu_Impl::read_2007(int addr)
|
||||||
{
|
{
|
||||||
int result = r2007;
|
int result = r2007;
|
||||||
if (addr < 0x2000)
|
if (addr < 0x2000)
|
||||||
|
@ -400,7 +400,7 @@ inline int Nes_Ppu_Impl::read_2007(int addr)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Nes_Ppu::read(unsigned addr, nes_time_t time)
|
int Ppu::read(unsigned addr, nes_time_t time)
|
||||||
{
|
{
|
||||||
switch (addr & 7)
|
switch (addr & 7)
|
||||||
{
|
{
|
||||||
|
@ -447,7 +447,7 @@ int Nes_Ppu::read(unsigned addr, nes_time_t time)
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
|
|
||||||
void Nes_Ppu::write(nes_time_t time, unsigned addr, int data)
|
void Ppu::write(nes_time_t time, unsigned addr, int data)
|
||||||
{
|
{
|
||||||
switch (addr & 7)
|
switch (addr & 7)
|
||||||
{
|
{
|
||||||
|
@ -571,7 +571,7 @@ void Nes_Ppu::write(nes_time_t time, unsigned addr, int data)
|
||||||
|
|
||||||
// Frame begin/end
|
// Frame begin/end
|
||||||
|
|
||||||
nes_time_t Nes_Ppu::begin_frame(ppu_time_t timestamp)
|
nes_time_t Ppu::begin_frame(ppu_time_t timestamp)
|
||||||
{
|
{
|
||||||
// current time
|
// current time
|
||||||
int cpu_timestamp = timestamp / ppu_overclock;
|
int cpu_timestamp = timestamp / ppu_overclock;
|
||||||
|
@ -616,7 +616,7 @@ nes_time_t Nes_Ppu::begin_frame(ppu_time_t timestamp)
|
||||||
return cpu_timestamp;
|
return cpu_timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu_time_t Nes_Ppu::end_frame(nes_time_t end_time)
|
ppu_time_t Ppu::end_frame(nes_time_t end_time)
|
||||||
{
|
{
|
||||||
render_bg_until(end_time);
|
render_bg_until(end_time);
|
||||||
render_until(end_time);
|
render_until(end_time);
|
||||||
|
@ -644,14 +644,14 @@ ppu_time_t Nes_Ppu::end_frame(nes_time_t end_time)
|
||||||
return (end_time - frame_length_) * ppu_overclock + frame_length_extra;
|
return (end_time - frame_length_) * ppu_overclock + frame_length_extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu::poke_open_bus(nes_time_t time, int data, int mask)
|
void Ppu::poke_open_bus(nes_time_t time, int data, int mask)
|
||||||
{
|
{
|
||||||
open_bus = (open_bus & ~mask) | (data & mask);
|
open_bus = (open_bus & ~mask) | (data & mask);
|
||||||
if (mask & 0x1F) decay_low = time + scanline_len * 100 / ppu_overclock;
|
if (mask & 0x1F) decay_low = time + scanline_len * 100 / ppu_overclock;
|
||||||
if (mask & 0xE0) decay_high = time + scanline_len * 100 / ppu_overclock;
|
if (mask & 0xE0) decay_high = time + scanline_len * 100 / ppu_overclock;
|
||||||
}
|
}
|
||||||
|
|
||||||
nes_time_t Nes_Ppu::earliest_open_bus_decay()
|
nes_time_t Ppu::earliest_open_bus_decay()
|
||||||
{
|
{
|
||||||
return (decay_low < decay_high) ? decay_low : decay_high;
|
return (decay_low < decay_high) ? decay_low : decay_high;
|
||||||
}
|
}
|
|
@ -1,28 +1,28 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// NES PPU emulator
|
// NES PPU emulator
|
||||||
// Nes_Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include "Nes_Ppu_Rendering.hpp"
|
#include "ppuRendering.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Nes_Mapper;
|
class Mapper;
|
||||||
class Nes_Core;
|
class Core;
|
||||||
|
|
||||||
typedef long nes_time_t;
|
typedef long nes_time_t;
|
||||||
typedef long ppu_time_t; // ppu_time_t = nes_time_t * ppu_overclock
|
typedef long ppu_time_t; // ppu_time_t = nes_time_t * ppu_overclock
|
||||||
|
|
||||||
ppu_time_t const ppu_overclock = 3; // PPU clocks for each CPU clock
|
ppu_time_t const ppu_overclock = 3; // PPU clocks for each CPU clock
|
||||||
|
|
||||||
class Nes_Ppu : public Nes_Ppu_Rendering
|
class Ppu : public Ppu_Rendering
|
||||||
{
|
{
|
||||||
typedef Nes_Ppu_Rendering base;
|
typedef Ppu_Rendering base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Nes_Ppu(Nes_Core *);
|
Ppu(Core *);
|
||||||
|
|
||||||
// Begin PPU frame and return beginning CPU timestamp
|
// Begin PPU frame and return beginning CPU timestamp
|
||||||
nes_time_t begin_frame(ppu_time_t);
|
nes_time_t begin_frame(ppu_time_t);
|
||||||
|
@ -49,7 +49,7 @@ class Nes_Ppu : public Nes_Ppu_Rendering
|
||||||
int burst_phase;
|
int burst_phase;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Nes_Core &emu;
|
Core &emu;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -109,35 +109,35 @@ class Nes_Ppu : public Nes_Ppu_Rendering
|
||||||
void invalidate_sprite_max_();
|
void invalidate_sprite_max_();
|
||||||
void invalidate_sprite_max(nes_time_t);
|
void invalidate_sprite_max(nes_time_t);
|
||||||
|
|
||||||
friend int nes_cpu_read_likely_ppu(class Nes_Core *, unsigned, nes_time_t);
|
friend int nes_cpu_read_likely_ppu(class Core *, unsigned, nes_time_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Nes_Ppu::suspend_rendering()
|
inline void Ppu::suspend_rendering()
|
||||||
{
|
{
|
||||||
next_bg_time = indefinite_time;
|
next_bg_time = indefinite_time;
|
||||||
next_sprites_time = indefinite_time;
|
next_sprites_time = indefinite_time;
|
||||||
extra_clocks = 0;
|
extra_clocks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Nes_Ppu::Nes_Ppu(Nes_Core *e) : emu(*e)
|
inline Ppu::Ppu(Core *e) : emu(*e)
|
||||||
{
|
{
|
||||||
burst_phase = 0;
|
burst_phase = 0;
|
||||||
suspend_rendering();
|
suspend_rendering();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Ppu::render_until(nes_time_t t)
|
inline void Ppu::render_until(nes_time_t t)
|
||||||
{
|
{
|
||||||
if (t > next_sprites_time)
|
if (t > next_sprites_time)
|
||||||
render_until_(t);
|
render_until_(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Ppu::render_bg_until(nes_time_t t)
|
inline void Ppu::render_bg_until(nes_time_t t)
|
||||||
{
|
{
|
||||||
if (t > next_bg_time)
|
if (t > next_bg_time)
|
||||||
render_bg_until_(t);
|
render_bg_until_(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Ppu::update_open_bus(nes_time_t time)
|
inline void Ppu::update_open_bus(nes_time_t time)
|
||||||
{
|
{
|
||||||
if (time >= decay_low) open_bus &= ~0x1F;
|
if (time >= decay_low) open_bus &= ~0x1F;
|
||||||
if (time >= decay_high) open_bus &= ~0xE0;
|
if (time >= decay_high) open_bus &= ~0xE0;
|
|
@ -1,6 +1,6 @@
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Nes_Ppu_Impl.hpp"
|
#include "ppuImpl.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -31,7 +31,7 @@ inline void set_be32(void *p, unsigned long n)
|
||||||
|
|
||||||
#define SET_BE32(addr, data) set_be32(addr, data)
|
#define SET_BE32(addr, data) set_be32(addr, data)
|
||||||
|
|
||||||
Nes_Ppu_Impl::Nes_Ppu_Impl()
|
Ppu_Impl::Ppu_Impl()
|
||||||
{
|
{
|
||||||
impl = NULL;
|
impl = NULL;
|
||||||
chr_data = NULL;
|
chr_data = NULL;
|
||||||
|
@ -47,19 +47,19 @@ Nes_Ppu_Impl::Nes_Ppu_Impl()
|
||||||
mmc24_latched[1] = 0;
|
mmc24_latched[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nes_Ppu_Impl::~Nes_Ppu_Impl()
|
Ppu_Impl::~Ppu_Impl()
|
||||||
{
|
{
|
||||||
close_chr();
|
close_chr();
|
||||||
delete impl;
|
delete impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Impl::all_tiles_modified()
|
void Ppu_Impl::all_tiles_modified()
|
||||||
{
|
{
|
||||||
any_tiles_modified = true;
|
any_tiles_modified = true;
|
||||||
memset(modified_tiles, ~0, sizeof modified_tiles);
|
memset(modified_tiles, ~0, sizeof modified_tiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Nes_Ppu_Impl::open_chr(uint8_t const *new_chr, long chr_data_size)
|
const char *Ppu_Impl::open_chr(uint8_t const *new_chr, long chr_data_size)
|
||||||
{
|
{
|
||||||
close_chr();
|
close_chr();
|
||||||
|
|
||||||
|
@ -99,13 +99,13 @@ const char *Nes_Ppu_Impl::open_chr(uint8_t const *new_chr, long chr_data_size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Impl::close_chr()
|
void Ppu_Impl::close_chr()
|
||||||
{
|
{
|
||||||
delete[] tile_cache_mem;
|
delete[] tile_cache_mem;
|
||||||
tile_cache_mem = NULL;
|
tile_cache_mem = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Impl::set_chr_bank(int addr, int size, long data)
|
void Ppu_Impl::set_chr_bank(int addr, int size, long data)
|
||||||
{
|
{
|
||||||
if (data + size > chr_size)
|
if (data + size > chr_size)
|
||||||
data %= chr_size;
|
data %= chr_size;
|
||||||
|
@ -121,7 +121,7 @@ void Nes_Ppu_Impl::set_chr_bank(int addr, int size, long data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Impl::set_chr_bank_ex(int addr, int size, long data)
|
void Ppu_Impl::set_chr_bank_ex(int addr, int size, long data)
|
||||||
{
|
{
|
||||||
mmc24_enabled = true;
|
mmc24_enabled = true;
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ static uint8_t const initial_palette[0x20] =
|
||||||
{
|
{
|
||||||
0x0f, 0x01, 0x00, 0x01, 0x00, 0x02, 0x02, 0x0D, 0x08, 0x10, 0x08, 0x24, 0x00, 0x00, 0x04, 0x2C, 0x00, 0x01, 0x34, 0x03, 0x00, 0x04, 0x00, 0x14, 0x00, 0x3A, 0x00, 0x02, 0x00, 0x20, 0x2C, 0x08};
|
0x0f, 0x01, 0x00, 0x01, 0x00, 0x02, 0x02, 0x0D, 0x08, 0x10, 0x08, 0x24, 0x00, 0x00, 0x04, 0x2C, 0x00, 0x01, 0x34, 0x03, 0x00, 0x04, 0x00, 0x14, 0x00, 0x3A, 0x00, 0x02, 0x00, 0x20, 0x2C, 0x08};
|
||||||
|
|
||||||
void Nes_Ppu_Impl::reset(bool full_reset)
|
void Ppu_Impl::reset(bool full_reset)
|
||||||
{
|
{
|
||||||
w2000 = 0;
|
w2000 = 0;
|
||||||
w2001 = 0;
|
w2001 = 0;
|
||||||
|
@ -178,7 +178,7 @@ void Nes_Ppu_Impl::reset(bool full_reset)
|
||||||
memset(host_palette, 0, max_palette_size * sizeof *host_palette);
|
memset(host_palette, 0, max_palette_size * sizeof *host_palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Impl::capture_palette()
|
void Ppu_Impl::capture_palette()
|
||||||
{
|
{
|
||||||
if (palette_size + palette_increment <= max_palette_size)
|
if (palette_size + palette_increment <= max_palette_size)
|
||||||
{
|
{
|
||||||
|
@ -203,7 +203,7 @@ void Nes_Ppu_Impl::capture_palette()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Impl::run_hblank(int count)
|
void Ppu_Impl::run_hblank(int count)
|
||||||
{
|
{
|
||||||
long addr = (vram_addr & 0x7be0) + (vram_temp & 0x41f) + (count * 0x1000);
|
long addr = (vram_addr & 0x7be0) + (vram_temp & 0x41f) + (count * 0x1000);
|
||||||
if (w2001 & 0x08)
|
if (w2001 & 0x08)
|
||||||
|
@ -235,7 +235,7 @@ inline unsigned long reorder(unsigned long n)
|
||||||
return ((n << 14) | n);
|
return ((n << 14) | n);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Ppu_Impl::update_tile(int index)
|
inline void Ppu_Impl::update_tile(int index)
|
||||||
{
|
{
|
||||||
const uint8_t *in = chr_data + (index)*bytes_per_tile;
|
const uint8_t *in = chr_data + (index)*bytes_per_tile;
|
||||||
uint8_t *out = (uint8_t *)tile_cache[index];
|
uint8_t *out = (uint8_t *)tile_cache[index];
|
||||||
|
@ -274,14 +274,14 @@ inline void Nes_Ppu_Impl::update_tile(int index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Impl::rebuild_chr(unsigned long begin, unsigned long end)
|
void Ppu_Impl::rebuild_chr(unsigned long begin, unsigned long end)
|
||||||
{
|
{
|
||||||
unsigned end_index = (end + bytes_per_tile - 1) / bytes_per_tile;
|
unsigned end_index = (end + bytes_per_tile - 1) / bytes_per_tile;
|
||||||
for (unsigned index = begin / bytes_per_tile; index < end_index; index++)
|
for (unsigned index = begin / bytes_per_tile; index < end_index; index++)
|
||||||
update_tile(index);
|
update_tile(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Impl::update_tiles(int first_tile)
|
void Ppu_Impl::update_tiles(int first_tile)
|
||||||
{
|
{
|
||||||
int chunk = 0;
|
int chunk = 0;
|
||||||
do
|
do
|
||||||
|
@ -351,7 +351,7 @@ struct calc_sprite_max_scanlines
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
long Nes_Ppu_Impl::recalc_sprite_max(int scanline)
|
long Ppu_Impl::recalc_sprite_max(int scanline)
|
||||||
{
|
{
|
||||||
int const max_scanline_count = image_height;
|
int const max_scanline_count = image_height;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// NES PPU misc functions and setup
|
// NES PPU misc functions and setup
|
||||||
// Nes_Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ struct ppu_state_t
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ppu_state_t) == 20 + 0x20);
|
static_assert(sizeof(ppu_state_t) == 20 + 0x20);
|
||||||
|
|
||||||
class Nes_Ppu_Impl : public ppu_state_t
|
class Ppu_Impl : public ppu_state_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nes_Ppu_Impl();
|
Ppu_Impl();
|
||||||
~Nes_Ppu_Impl();
|
~Ppu_Impl();
|
||||||
|
|
||||||
void reset(bool full_reset);
|
void reset(bool full_reset);
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ class Nes_Ppu_Impl : public ppu_state_t
|
||||||
void run_hblank(int);
|
void run_hblank(int);
|
||||||
int sprite_height() const { return (w2000 >> 2 & 8) + 8; }
|
int sprite_height() const { return (w2000 >> 2 & 8) + 8; }
|
||||||
|
|
||||||
protected: // friend class Nes_Ppu; private:
|
protected: // friend class Ppu; private:
|
||||||
int addr_inc; // pre-calculated $2007 increment (based on w2001 & 0x04)
|
int addr_inc; // pre-calculated $2007 increment (based on w2001 & 0x04)
|
||||||
int read_2007(int addr);
|
int read_2007(int addr);
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ class Nes_Ppu_Impl : public ppu_state_t
|
||||||
long recalc_sprite_max(int scanline);
|
long recalc_sprite_max(int scanline);
|
||||||
int first_opaque_sprite_line();
|
int first_opaque_sprite_line();
|
||||||
|
|
||||||
protected: // friend class Nes_Ppu_Rendering; private:
|
protected: // friend class Ppu_Rendering; private:
|
||||||
unsigned long palette_offset;
|
unsigned long palette_offset;
|
||||||
int palette_changed;
|
int palette_changed;
|
||||||
void capture_palette();
|
void capture_palette();
|
||||||
|
@ -173,7 +173,7 @@ class Nes_Ppu_Impl : public ppu_state_t
|
||||||
void update_tile(int index);
|
void update_tile(int index);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Nes_Ppu_Impl::set_nt_banks(int bank0, int bank1, int bank2, int bank3)
|
inline void Ppu_Impl::set_nt_banks(int bank0, int bank1, int bank2, int bank3)
|
||||||
{
|
{
|
||||||
uint8_t *nt_ram = impl->nt_ram;
|
uint8_t *nt_ram = impl->nt_ram;
|
||||||
nt_banks[0] = &nt_ram[bank0 * 0x400];
|
nt_banks[0] = &nt_ram[bank0 * 0x400];
|
||||||
|
@ -182,14 +182,14 @@ inline void Nes_Ppu_Impl::set_nt_banks(int bank0, int bank1, int bank2, int bank
|
||||||
nt_banks[3] = &nt_ram[bank3 * 0x400];
|
nt_banks[3] = &nt_ram[bank3 * 0x400];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Nes_Ppu_Impl::map_palette(int addr)
|
inline int Ppu_Impl::map_palette(int addr)
|
||||||
{
|
{
|
||||||
if ((addr & 3) == 0)
|
if ((addr & 3) == 0)
|
||||||
addr &= 0x0f; // 0x10, 0x14, 0x18, 0x1c map to 0x00, 0x04, 0x08, 0x0c
|
addr &= 0x0f; // 0x10, 0x14, 0x18, 0x1c map to 0x00, 0x04, 0x08, 0x0c
|
||||||
return addr & 0x1f;
|
return addr & 0x1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Nes_Ppu_Impl::sprite_tile_index(uint8_t const *sprite) const
|
inline int Ppu_Impl::sprite_tile_index(uint8_t const *sprite) const
|
||||||
{
|
{
|
||||||
int tile = sprite[1] + (w2000 << 5 & 0x100);
|
int tile = sprite[1] + (w2000 << 5 & 0x100);
|
||||||
if (w2000 & 0x20)
|
if (w2000 & 0x20)
|
||||||
|
@ -197,7 +197,7 @@ inline int Nes_Ppu_Impl::sprite_tile_index(uint8_t const *sprite) const
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Nes_Ppu_Impl::write_2007(int data)
|
inline int Ppu_Impl::write_2007(int data)
|
||||||
{
|
{
|
||||||
int addr = vram_addr;
|
int addr = vram_addr;
|
||||||
uint8_t *chr_ram = this->chr_ram; // pre-read
|
uint8_t *chr_ram = this->chr_ram; // pre-read
|
||||||
|
@ -235,7 +235,7 @@ inline int Nes_Ppu_Impl::write_2007(int data)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Ppu_Impl::begin_frame()
|
inline void Ppu_Impl::begin_frame()
|
||||||
{
|
{
|
||||||
palette_changed = 0x18;
|
palette_changed = 0x18;
|
||||||
palette_size = 0;
|
palette_size = 0;
|
|
@ -1,6 +1,6 @@
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Nes_Ppu_Rendering.hpp"
|
#include "ppuRendering.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -21,8 +21,8 @@ namespace quickerNES
|
||||||
|
|
||||||
static unsigned zero = 0; // helps CodeWarrior optimizer when added to constants
|
static unsigned zero = 0; // helps CodeWarrior optimizer when added to constants
|
||||||
|
|
||||||
inline Nes_Ppu_Impl::cached_tile_t const &
|
inline Ppu_Impl::cached_tile_t const &
|
||||||
Nes_Ppu_Impl::get_sprite_tile(uint8_t const *sprite)
|
Ppu_Impl::get_sprite_tile(uint8_t const *sprite)
|
||||||
{
|
{
|
||||||
cached_tile_t *tiles = tile_cache;
|
cached_tile_t *tiles = tile_cache;
|
||||||
if (sprite[2] & 0x40)
|
if (sprite[2] & 0x40)
|
||||||
|
@ -31,19 +31,19 @@ Nes_Ppu_Impl::get_sprite_tile(uint8_t const *sprite)
|
||||||
|
|
||||||
// use index directly, since cached tile is same size as native tile
|
// use index directly, since cached tile is same size as native tile
|
||||||
static_assert(sizeof(cached_tile_t) == bytes_per_tile);
|
static_assert(sizeof(cached_tile_t) == bytes_per_tile);
|
||||||
return *(Nes_Ppu_Impl::cached_tile_t *)((uint8_t *)tiles + map_chr_addr(index * bytes_per_tile));
|
return *(Ppu_Impl::cached_tile_t *)((uint8_t *)tiles + map_chr_addr(index * bytes_per_tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Nes_Ppu_Impl::cached_tile_t const &Nes_Ppu_Impl::get_bg_tile(int index)
|
inline Ppu_Impl::cached_tile_t const &Ppu_Impl::get_bg_tile(int index)
|
||||||
{
|
{
|
||||||
// use index directly, since cached tile is same size as native tile
|
// use index directly, since cached tile is same size as native tile
|
||||||
static_assert(sizeof(cached_tile_t) == bytes_per_tile);
|
static_assert(sizeof(cached_tile_t) == bytes_per_tile);
|
||||||
return *(Nes_Ppu_Impl::cached_tile_t *)((uint8_t *)tile_cache + map_chr_addr(index * bytes_per_tile));
|
return *(Ppu_Impl::cached_tile_t *)((uint8_t *)tile_cache + map_chr_addr(index * bytes_per_tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill
|
// Fill
|
||||||
|
|
||||||
void Nes_Ppu_Rendering::fill_background(int count)
|
void Ppu_Rendering::fill_background(int count)
|
||||||
{
|
{
|
||||||
ptrdiff_t const next_line = scanline_row_bytes - image_width;
|
ptrdiff_t const next_line = scanline_row_bytes - image_width;
|
||||||
uint32_t *pixels = (uint32_t *)scanline_pixels;
|
uint32_t *pixels = (uint32_t *)scanline_pixels;
|
||||||
|
@ -72,7 +72,7 @@ void Nes_Ppu_Rendering::fill_background(int count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Rendering::clip_left(int count)
|
void Ppu_Rendering::clip_left(int count)
|
||||||
{
|
{
|
||||||
ptrdiff_t next_line = scanline_row_bytes;
|
ptrdiff_t next_line = scanline_row_bytes;
|
||||||
uint8_t *p = scanline_pixels;
|
uint8_t *p = scanline_pixels;
|
||||||
|
@ -86,7 +86,7 @@ void Nes_Ppu_Rendering::clip_left(int count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Rendering::save_left(int count)
|
void Ppu_Rendering::save_left(int count)
|
||||||
{
|
{
|
||||||
ptrdiff_t next_line = scanline_row_bytes;
|
ptrdiff_t next_line = scanline_row_bytes;
|
||||||
uint8_t *in = scanline_pixels;
|
uint8_t *in = scanline_pixels;
|
||||||
|
@ -103,7 +103,7 @@ void Nes_Ppu_Rendering::save_left(int count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Rendering::restore_left(int count)
|
void Ppu_Rendering::restore_left(int count)
|
||||||
{
|
{
|
||||||
ptrdiff_t next_line = scanline_row_bytes;
|
ptrdiff_t next_line = scanline_row_bytes;
|
||||||
uint8_t *out = scanline_pixels;
|
uint8_t *out = scanline_pixels;
|
||||||
|
@ -122,7 +122,7 @@ void Nes_Ppu_Rendering::restore_left(int count)
|
||||||
|
|
||||||
// Background
|
// Background
|
||||||
|
|
||||||
void Nes_Ppu_Rendering::draw_background_(int remain)
|
void Ppu_Rendering::draw_background_(int remain)
|
||||||
{
|
{
|
||||||
// Draws 'remain' background scanlines. Does not modify vram_addr.
|
// Draws 'remain' background scanlines. Does not modify vram_addr.
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ void Nes_Ppu_Rendering::draw_background_(int remain)
|
||||||
|
|
||||||
// Sprites
|
// Sprites
|
||||||
|
|
||||||
void Nes_Ppu_Rendering::draw_sprites_(int begin, int end)
|
void Ppu_Rendering::draw_sprites_(int begin, int end)
|
||||||
{
|
{
|
||||||
// Draws sprites on scanlines begin through end - 1. Handles clipping.
|
// Draws sprites on scanlines begin through end - 1. Handles clipping.
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ void Nes_Ppu_Rendering::draw_sprites_(int begin, int end)
|
||||||
int visible = sprite_height;
|
int visible = sprite_height;
|
||||||
|
|
||||||
#define CLIPPED 0
|
#define CLIPPED 0
|
||||||
#include "Nes_Ppu_Sprites.hpp"
|
#include "ppuSprites.hpp"
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -306,12 +306,12 @@ void Nes_Ppu_Rendering::draw_sprites_(int begin, int end)
|
||||||
// begin, end, top_minus_one + 1, skip, visible );
|
// begin, end, top_minus_one + 1, skip, visible );
|
||||||
|
|
||||||
#define CLIPPED 1
|
#define CLIPPED 1
|
||||||
#include "Nes_Ppu_Sprites.hpp"
|
#include "ppuSprites.hpp"
|
||||||
}
|
}
|
||||||
} while (index < 0x100);
|
} while (index < 0x100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Rendering::check_sprite_hit(int begin, int end)
|
void Ppu_Rendering::check_sprite_hit(int begin, int end)
|
||||||
{
|
{
|
||||||
// Checks for sprite 0 hit on scanlines begin through end - 1.
|
// Checks for sprite 0 hit on scanlines begin through end - 1.
|
||||||
// Updates sprite_hit_found. Background (but not sprites) must have
|
// Updates sprite_hit_found. Background (but not sprites) must have
|
||||||
|
@ -406,12 +406,12 @@ void Nes_Ppu_Rendering::check_sprite_hit(int begin, int end)
|
||||||
|
|
||||||
// Draw scanlines
|
// Draw scanlines
|
||||||
|
|
||||||
inline bool Nes_Ppu_Rendering::sprite_hit_possible(int scanline) const
|
inline bool Ppu_Rendering::sprite_hit_possible(int scanline) const
|
||||||
{
|
{
|
||||||
return !sprite_hit_found && spr_ram[0] <= scanline && (w2001 & 0x18) == 0x18;
|
return !sprite_hit_found && spr_ram[0] <= scanline && (w2001 & 0x18) == 0x18;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Rendering::draw_scanlines(int start, int count, uint8_t *pixels, long pitch, int mode)
|
void Ppu_Rendering::draw_scanlines(int start, int count, uint8_t *pixels, long pitch, int mode)
|
||||||
{
|
{
|
||||||
scanline_pixels = pixels + image_left;
|
scanline_pixels = pixels + image_left;
|
||||||
scanline_row_bytes = pitch;
|
scanline_row_bytes = pitch;
|
||||||
|
@ -475,7 +475,7 @@ void Nes_Ppu_Rendering::draw_scanlines(int start, int count, uint8_t *pixels, lo
|
||||||
scanline_pixels = NULL;
|
scanline_pixels = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nes_Ppu_Rendering::draw_background(int start, int count)
|
void Ppu_Rendering::draw_background(int start, int count)
|
||||||
{
|
{
|
||||||
// always capture palette at least once per frame
|
// always capture palette at least once per frame
|
||||||
if ((start + count >= 240 && !palette_size) || (w2001 & palette_changed))
|
if ((start + count >= 240 && !palette_size) || (w2001 & palette_changed))
|
|
@ -1,19 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// NES PPU emulator graphics rendering
|
// NES PPU emulator graphics rendering
|
||||||
// Nes_Emu 0.7.0
|
// Emu 0.7.0
|
||||||
|
|
||||||
#include "Nes_Ppu_Impl.hpp"
|
#include "ppuImpl.hpp"
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
{
|
{
|
||||||
|
|
||||||
class Nes_Ppu_Rendering : public Nes_Ppu_Impl
|
class Ppu_Rendering : public Ppu_Impl
|
||||||
{
|
{
|
||||||
typedef Nes_Ppu_Impl base;
|
typedef Ppu_Impl base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Nes_Ppu_Rendering();
|
Ppu_Rendering();
|
||||||
|
|
||||||
int sprite_limit;
|
int sprite_limit;
|
||||||
|
|
||||||
|
@ -50,13 +50,13 @@ class Nes_Ppu_Rendering : public Nes_Ppu_Impl
|
||||||
void check_sprite_hit(int begin, int end);
|
void check_sprite_hit(int begin, int end);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Nes_Ppu_Rendering::Nes_Ppu_Rendering()
|
inline Ppu_Rendering::Ppu_Rendering()
|
||||||
{
|
{
|
||||||
sprite_limit = 8;
|
sprite_limit = 8;
|
||||||
host_pixels = nullptr;
|
host_pixels = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Nes_Ppu_Rendering::draw_sprites(int start, int count)
|
inline void Ppu_Rendering::draw_sprites(int start, int count)
|
||||||
{
|
{
|
||||||
draw_scanlines(start, count, host_pixels + host_row_bytes * start, host_row_bytes, 2);
|
draw_scanlines(start, count, host_pixels + host_row_bytes * start, host_row_bytes, 2);
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Nes_Emu.hpp>
|
#include <quickerNES/emu.hpp>
|
||||||
#include <emuInstance.hpp>
|
#include <emuInstance.hpp>
|
||||||
|
|
||||||
namespace quickerNES
|
namespace quickerNES
|
||||||
|
@ -12,7 +12,7 @@ class QuickerNESInstance : public EmuInstance
|
||||||
QuickerNESInstance() : EmuInstance()
|
QuickerNESInstance() : EmuInstance()
|
||||||
{
|
{
|
||||||
// Creating new emulator
|
// Creating new emulator
|
||||||
_nes = new Nes_Emu;
|
_nes = new Emu;
|
||||||
|
|
||||||
// Allocating video buffer
|
// Allocating video buffer
|
||||||
video_buffer = (uint8_t *)malloc(image_width * image_height);
|
video_buffer = (uint8_t *)malloc(image_width * image_height);
|
||||||
|
@ -73,7 +73,7 @@ class QuickerNESInstance : public EmuInstance
|
||||||
uint8_t *video_buffer;
|
uint8_t *video_buffer;
|
||||||
|
|
||||||
// Emulator instance
|
// Emulator instance
|
||||||
Nes_Emu *_nes;
|
Emu *_nes;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quickNES
|
} // namespace quickNES
|
Loading…
Reference in New Issue