Restyling
This commit is contained in:
parent
dec1772b7e
commit
d8513ef867
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <utils.hpp>
|
||||
#include "sha1/sha1.hpp"
|
||||
#include <utils.hpp>
|
||||
|
||||
#define _LOW_MEM_SIZE 0x800
|
||||
#define _HIGH_MEM_SIZE 0x2000
|
||||
|
@ -14,7 +14,6 @@ static const uint16_t image_height = 240;
|
|||
class EmuInstance
|
||||
{
|
||||
public:
|
||||
|
||||
typedef uint8_t inputType;
|
||||
|
||||
// Deleting default constructors
|
||||
|
@ -65,14 +64,38 @@ class EmuInstance
|
|||
std::string moveString = "|..|........|";
|
||||
#endif
|
||||
|
||||
if (move & 0b00010000) moveString += 'U'; else moveString += '.';
|
||||
if (move & 0b00100000) moveString += 'D'; else moveString += '.';
|
||||
if (move & 0b01000000) moveString += 'L'; else moveString += '.';
|
||||
if (move & 0b10000000) moveString += 'R'; else moveString += '.';
|
||||
if (move & 0b00001000) moveString += 'S'; else moveString += '.';
|
||||
if (move & 0b00000100) moveString += 's'; else moveString += '.';
|
||||
if (move & 0b00000010) moveString += 'B'; else moveString += '.';
|
||||
if (move & 0b00000001) moveString += 'A'; else moveString += '.';
|
||||
if (move & 0b00010000)
|
||||
moveString += 'U';
|
||||
else
|
||||
moveString += '.';
|
||||
if (move & 0b00100000)
|
||||
moveString += 'D';
|
||||
else
|
||||
moveString += '.';
|
||||
if (move & 0b01000000)
|
||||
moveString += 'L';
|
||||
else
|
||||
moveString += '.';
|
||||
if (move & 0b10000000)
|
||||
moveString += 'R';
|
||||
else
|
||||
moveString += '.';
|
||||
if (move & 0b00001000)
|
||||
moveString += 'S';
|
||||
else
|
||||
moveString += '.';
|
||||
if (move & 0b00000100)
|
||||
moveString += 's';
|
||||
else
|
||||
moveString += '.';
|
||||
if (move & 0b00000010)
|
||||
moveString += 'B';
|
||||
else
|
||||
moveString += '.';
|
||||
if (move & 0b00000001)
|
||||
moveString += 'A';
|
||||
else
|
||||
moveString += '.';
|
||||
|
||||
moveString += "|";
|
||||
return moveString;
|
||||
|
@ -161,7 +184,6 @@ inline void loadROMFile(const std::string& romFilePath)
|
|||
virtual void *getInternalEmulatorPointer() const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
EmuInstance() = default;
|
||||
|
||||
// Storage for the light state size
|
||||
|
@ -174,7 +196,6 @@ inline void loadROMFile(const std::string& romFilePath)
|
|||
bool _doRendering = true;
|
||||
|
||||
private:
|
||||
|
||||
// Storage for the ROM data
|
||||
std::string _romData;
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include "emuInstance.hpp"
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
#include <utils.hpp>
|
||||
#include <hqn/hqn.h>
|
||||
#include <hqn/hqn_gui_controller.h>
|
||||
#include "emuInstance.hpp"
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <utils.hpp>
|
||||
|
||||
#define _INVERSE_FRAME_RATE 16667
|
||||
|
||||
|
@ -23,7 +23,6 @@ struct stepData_t
|
|||
class PlaybackInstance
|
||||
{
|
||||
public:
|
||||
|
||||
void addStep(const std::string &input)
|
||||
{
|
||||
stepData_t step;
|
||||
|
@ -223,9 +222,7 @@ const std::string getStateInput(const size_t stepId) const
|
|||
return step.input;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Internal sequence information
|
||||
std::vector<stepData_t> _stepSequence;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include <cstdlib>
|
||||
#include "argparse/argparse.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "emuInstance.hpp"
|
||||
#include "playbackInstance.hpp"
|
||||
#include "utils.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef _USE_QUICKNES
|
||||
#include "quickNESInstance.hpp"
|
||||
|
@ -40,8 +40,14 @@ int main(int argc, char *argv[])
|
|||
.implicit_value(true);
|
||||
|
||||
// Try to parse arguments
|
||||
try { program.parse_args(argc, argv); }
|
||||
catch (const std::runtime_error &err) { EXIT_WITH_ERROR("%s\n%s", err.what(), program.help().str().c_str()); }
|
||||
try
|
||||
{
|
||||
program.parse_args(argc, argv);
|
||||
}
|
||||
catch (const std::runtime_error &err)
|
||||
{
|
||||
EXIT_WITH_ERROR("%s\n%s", err.what(), program.help().str().c_str());
|
||||
}
|
||||
|
||||
// Getting ROM file path
|
||||
std::string romFilePath = program.get<std::string>("romFile");
|
||||
|
@ -186,4 +192,3 @@ int main(int argc, char *argv[])
|
|||
// Ending ncurses window
|
||||
finalizeTerminal();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
#include "Nes_Mapper.h"
|
||||
|
||||
template <bool _is152>
|
||||
class Mapper_74x161x162x32 : public Nes_Mapper {
|
||||
class Mapper_74x161x162x32 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper_74x161x162x32()
|
||||
{
|
||||
|
|
|
@ -13,7 +13,6 @@ extern void register_mapper_70();
|
|||
class QuickNESInstance : public EmuInstance
|
||||
{
|
||||
public:
|
||||
|
||||
QuickNESInstance() : EmuInstance()
|
||||
{
|
||||
// Creating new emulator
|
||||
|
@ -73,7 +72,6 @@ class QuickNESInstance : public EmuInstance
|
|||
void *getInternalEmulatorPointer() const override { return _nes; }
|
||||
|
||||
private:
|
||||
|
||||
inline size_t getStateSizeImpl() const override
|
||||
{
|
||||
uint8_t *data = (uint8_t *)malloc(_DUMMY_SIZE);
|
||||
|
|
|
@ -15,16 +15,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
class Nes_Cart {
|
||||
class Nes_Cart
|
||||
{
|
||||
public:
|
||||
|
||||
Nes_Cart() = default;
|
||||
|
||||
struct ines_header_t {
|
||||
struct ines_header_t
|
||||
{
|
||||
uint8_t signature[4];
|
||||
uint8_t prg_count; // number of 16K PRG banks
|
||||
uint8_t chr_count; // number of 8K CHR banks
|
||||
|
@ -40,7 +41,11 @@ void load_ines( const uint8_t* buffer )
|
|||
ines_header_t h;
|
||||
|
||||
size_t bufferPos = 0;
|
||||
{ size_t copySize = sizeof(ines_header_t); memcpy(&h, &buffer[bufferPos], copySize); bufferPos += copySize; }
|
||||
{
|
||||
size_t copySize = sizeof(ines_header_t);
|
||||
memcpy(&h, &buffer[bufferPos], copySize);
|
||||
bufferPos += copySize;
|
||||
}
|
||||
if (h.zero[7]) h.flags2 = 0;
|
||||
set_mapper(h.flags, h.flags2);
|
||||
|
||||
|
@ -55,8 +60,16 @@ void load_ines( const uint8_t* buffer )
|
|||
prg_ = (uint8_t *)p;
|
||||
chr_ = &prg_[prg_size_];
|
||||
|
||||
{ size_t copySize = prg_size(); memcpy(prg(), &buffer[bufferPos], copySize); bufferPos += copySize; }
|
||||
{ size_t copySize = chr_size(); memcpy(chr(), &buffer[bufferPos], copySize); bufferPos += copySize; }
|
||||
{
|
||||
size_t copySize = prg_size();
|
||||
memcpy(prg(), &buffer[bufferPos], copySize);
|
||||
bufferPos += copySize;
|
||||
}
|
||||
{
|
||||
size_t copySize = chr_size();
|
||||
memcpy(chr(), &buffer[bufferPos], copySize);
|
||||
bufferPos += copySize;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool has_battery_ram() const { return mapper & 0x02; }
|
||||
|
@ -97,4 +110,3 @@ private:
|
|||
long chr_size_;
|
||||
unsigned mapper;
|
||||
};
|
||||
|
||||
|
|
|
@ -15,13 +15,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// Nes_Emu 0.7.0
|
||||
|
||||
|
||||
#include "Nes_Cpu.hpp"
|
||||
#include "apu/apu.hpp"
|
||||
#include "mappers/mapper.hpp"
|
||||
#include "ppu/Nes_Ppu.hpp"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include "apu/apu.hpp"
|
||||
#include "Nes_Cpu.hpp"
|
||||
#include "ppu/Nes_Ppu.hpp"
|
||||
#include "mappers/mapper.hpp"
|
||||
|
||||
class Nes_Cart;
|
||||
|
||||
|
@ -66,10 +65,11 @@ struct cpu_state_t
|
|||
};
|
||||
static_assert(sizeof(cpu_state_t) == 8);
|
||||
|
||||
class Nes_Core : private Nes_Cpu {
|
||||
class Nes_Core : private Nes_Cpu
|
||||
{
|
||||
typedef Nes_Cpu cpu;
|
||||
public:
|
||||
|
||||
public:
|
||||
Nes_Core() : ppu(this)
|
||||
{
|
||||
cart = NULL;
|
||||
|
@ -222,17 +222,22 @@ public:
|
|||
|
||||
headerCode = "NESS"; // NESS Block
|
||||
blockSize = 0xFFFFFFFF;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
|
||||
headerCode = "TIME"; // TIME Block
|
||||
nes_state_t state = nes;
|
||||
state.timestamp *= 5;
|
||||
blockSize = sizeof(nes_state_t);
|
||||
dataSource = (void *)&state;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
headerCode = "CPUR"; // CPUR Block
|
||||
cpu_state_t s;
|
||||
|
@ -245,70 +250,97 @@ public:
|
|||
s.p = r.status;
|
||||
blockSize = sizeof(cpu_state_t);
|
||||
dataSource = (void *)&s;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
headerCode = "PPUR"; // PPUR Block
|
||||
blockSize = sizeof(ppu_state_t);
|
||||
dataSource = (void *)&ppu;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
headerCode = "APUR"; // APUR Block
|
||||
Nes_Apu::apu_state_t apuState;
|
||||
impl->apu.save_state(&apuState);
|
||||
blockSize = sizeof(Nes_Apu::apu_state_t);
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &apuState, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &apuState, blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
headerCode = "CTRL"; // CTRL Block
|
||||
blockSize = sizeof(joypad_state_t);
|
||||
dataSource = (void *)&joypad;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
headerCode = "MAPR"; // MAPR Block
|
||||
blockSize = mapper->state_size;
|
||||
dataSource = (void *)mapper->state;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
headerCode = "LRAM"; // LRAM Block
|
||||
blockSize = low_ram_size;
|
||||
dataSource = (void *)low_mem;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
headerCode = "SPRT"; // SPRT Block
|
||||
blockSize = Nes_Ppu::spr_ram_size;
|
||||
dataSource = (void *)ppu.spr_ram;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
headerCode = "NTAB"; // NTAB Block
|
||||
size_t nametable_size = 0x800;
|
||||
if (ppu.nt_banks[3] >= &ppu.impl->nt_ram[0xC00]) nametable_size = 0x1000;
|
||||
blockSize = nametable_size;
|
||||
dataSource = (void *)ppu.impl->nt_ram;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
if (ppu.chr_is_writable)
|
||||
{
|
||||
headerCode = "CHRR"; // CHRR Block
|
||||
blockSize = ppu.chr_size;
|
||||
dataSource = (void *)ppu.impl->chr_ram;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
}
|
||||
|
||||
if (sram_present)
|
||||
|
@ -316,15 +348,20 @@ public:
|
|||
headerCode = "SRAM"; // SRAM Block
|
||||
blockSize = impl->sram_size;
|
||||
dataSource = (void *)impl->sram;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize); pos += blockSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], dataSource, blockSize);
|
||||
pos += blockSize;
|
||||
}
|
||||
|
||||
headerCode = "gend"; // gend Block
|
||||
blockSize = 0;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize); pos += headerSize;
|
||||
memcpy(&buffer[pos], headerCode.data(), headerSize);
|
||||
pos += headerSize;
|
||||
memcpy(&buffer[pos], &blockSize, headerSize);
|
||||
pos += headerSize;
|
||||
|
||||
return pos; // Bytes written
|
||||
}
|
||||
|
@ -348,7 +385,8 @@ public:
|
|||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
blockSize = sizeof(nes_state_t);
|
||||
memcpy(&nesState, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy(&nesState, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
nes = nesState;
|
||||
nes.timestamp /= 5;
|
||||
|
||||
|
@ -357,7 +395,8 @@ public:
|
|||
blockSize = sizeof(cpu_state_t);
|
||||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
memcpy((void*) &s, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy((void *)&s, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
r.pc = s.pc;
|
||||
r.sp = s.s;
|
||||
r.a = s.a;
|
||||
|
@ -369,7 +408,8 @@ public:
|
|||
blockSize = sizeof(ppu_state_t);
|
||||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
memcpy((void*) &ppu, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy((void *)&ppu, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
// APUR Block
|
||||
Nes_Apu::apu_state_t apuState;
|
||||
|
@ -385,27 +425,31 @@ public:
|
|||
blockSize = sizeof(joypad_state_t);
|
||||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
memcpy((void*) &joypad, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy((void *)&joypad, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
// MAPR Block
|
||||
mapper->default_reset_state();
|
||||
blockSize = mapper->state_size;
|
||||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
memcpy((void*) mapper->state, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy((void *)mapper->state, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
mapper->apply_mapping();
|
||||
|
||||
// LRAM Block
|
||||
blockSize = low_ram_size;
|
||||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
memcpy((void*) low_mem, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy((void *)low_mem, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
// SPRT Block
|
||||
blockSize = Nes_Ppu::spr_ram_size;
|
||||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
memcpy((void*) ppu.spr_ram, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy((void *)ppu.spr_ram, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
// NTAB Block
|
||||
size_t nametable_size = 0x800;
|
||||
|
@ -413,7 +457,8 @@ public:
|
|||
blockSize = nametable_size;
|
||||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
memcpy((void*) ppu.impl->nt_ram, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy((void *)ppu.impl->nt_ram, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
|
||||
if (ppu.chr_is_writable)
|
||||
{
|
||||
|
@ -421,7 +466,8 @@ public:
|
|||
blockSize = ppu.chr_size;
|
||||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
memcpy((void*) ppu.impl->chr_ram, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy((void *)ppu.impl->chr_ram, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
}
|
||||
|
||||
if (sram_present)
|
||||
|
@ -430,7 +476,8 @@ public:
|
|||
blockSize = impl->sram_size;
|
||||
pos += headerSize;
|
||||
pos += headerSize;
|
||||
memcpy((void*) impl->sram, &buffer[pos], blockSize); pos += blockSize;
|
||||
memcpy((void *)impl->sram, &buffer[pos], blockSize);
|
||||
pos += blockSize;
|
||||
enable_sram(true);
|
||||
}
|
||||
|
||||
|
@ -526,7 +573,6 @@ public:
|
|||
disable_rendering();
|
||||
}
|
||||
|
||||
|
||||
void irq_changed()
|
||||
{
|
||||
cpu_set_irq_time(earliest_irq(cpu_time()));
|
||||
|
@ -537,11 +583,16 @@ public:
|
|||
cpu_set_end_time(earliest_event(cpu_time()));
|
||||
}
|
||||
|
||||
public: private: friend class Nes_Emu;
|
||||
public:
|
||||
private:
|
||||
friend class Nes_Emu;
|
||||
|
||||
struct impl_t
|
||||
{
|
||||
enum { sram_size = 0x2000 };
|
||||
enum
|
||||
{
|
||||
sram_size = 0x2000
|
||||
};
|
||||
uint8_t sram[sram_size];
|
||||
Nes_Apu apu;
|
||||
|
||||
|
@ -584,7 +635,6 @@ private:
|
|||
return ppu.frame_length();
|
||||
}
|
||||
|
||||
|
||||
inline nes_time_t earliest_event(nes_time_t present)
|
||||
{
|
||||
// PPU frame
|
||||
|
@ -678,7 +728,6 @@ private:
|
|||
((Nes_Core *)emu)->irq_changed();
|
||||
}
|
||||
|
||||
|
||||
// CPU
|
||||
unsigned sram_readable;
|
||||
unsigned sram_writable;
|
||||
|
@ -798,10 +847,14 @@ private:
|
|||
cpu::reduce_limit(n);
|
||||
}
|
||||
|
||||
public: private: friend class Nes_Ppu;
|
||||
public:
|
||||
private:
|
||||
friend class Nes_Ppu;
|
||||
void set_ppu_2002_time(nes_time_t t) { ppu_2002_time = t - 1 - cpu_time_offset; }
|
||||
|
||||
public: private: friend class Nes_Mapper;
|
||||
public:
|
||||
private:
|
||||
friend class Nes_Mapper;
|
||||
|
||||
void enable_prg_6000()
|
||||
{
|
||||
|
@ -845,7 +898,9 @@ public: private: friend class Nes_Mapper;
|
|||
}
|
||||
}
|
||||
|
||||
public: private: friend class Nes_Cpu;
|
||||
public:
|
||||
private:
|
||||
friend class Nes_Cpu;
|
||||
int cpu_read_ppu(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);
|
||||
|
@ -974,13 +1029,17 @@ inline void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time )
|
|||
#define NES_CPU_READ(cpu, addr, time) \
|
||||
static_cast<Nes_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); \
|
||||
}
|
||||
|
||||
#define NES_CPU_WRITE( cpu, addr, data, time ){\
|
||||
if ( addr < 0x800 ) cpu->low_mem [addr] = data;\
|
||||
else if ( addr == 0x2007 ) static_cast<Nes_Core&>(*cpu).cpu_write_2007( data );\
|
||||
else static_cast<Nes_Core&>(*cpu).cpu_write( addr, data, time );\
|
||||
#define NES_CPU_WRITE(cpu, addr, data, time) \
|
||||
{ \
|
||||
if (addr < 0x800) \
|
||||
cpu->low_mem[addr] = data; \
|
||||
else if (addr == 0x2007) \
|
||||
static_cast<Nes_Core &>(*cpu).cpu_write_2007(data); \
|
||||
else \
|
||||
static_cast<Nes_Core &>(*cpu).cpu_write(addr, data, time); \
|
||||
}
|
||||
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
typedef long nes_time_t; // clock cycle count
|
||||
typedef unsigned nes_addr_t; // 16-bit address
|
||||
|
||||
class Nes_Cpu {
|
||||
class Nes_Cpu
|
||||
{
|
||||
public:
|
||||
|
||||
// NES 6502 registers. *Not* kept updated during a call to run().
|
||||
struct registers_t {
|
||||
struct registers_t
|
||||
{
|
||||
uint16_t pc; // Should be more than 16 bits to allow overflow detection -- but I (eien86) removed it to maximize performance.
|
||||
uint8_t a;
|
||||
uint8_t x;
|
||||
|
@ -23,9 +24,18 @@ public:
|
|||
|
||||
// Map code memory (memory accessed via the program counter). Start and size
|
||||
// must be multiple of page_size.
|
||||
enum { page_bits = 11 };
|
||||
enum { page_count = 0x10000 >> page_bits };
|
||||
enum { page_size = 1L << page_bits };
|
||||
enum
|
||||
{
|
||||
page_bits = 11
|
||||
};
|
||||
enum
|
||||
{
|
||||
page_count = 0x10000 >> page_bits
|
||||
};
|
||||
enum
|
||||
{
|
||||
page_size = 1L << page_bits
|
||||
};
|
||||
|
||||
// Clear registers, unmap memory, and map code pages to unmapped_page.
|
||||
void reset(void const *unmapped_page = 0);
|
||||
|
@ -50,7 +60,8 @@ public:
|
|||
}
|
||||
|
||||
// Reasons that run() returns
|
||||
enum result_t {
|
||||
enum result_t
|
||||
{
|
||||
result_cycles, // Requested number of cycles (or more) were executed
|
||||
result_sei, // I flag just set and IRQ time would generate IRQ now
|
||||
result_cli, // I flag just cleared but IRQ should occur *after* next instr
|
||||
|
@ -83,10 +94,16 @@ public:
|
|||
unsigned long error_count() const { return error_count_; }
|
||||
|
||||
// If PC exceeds 0xFFFF and encounters page_wrap_opcode, it will be silently wrapped.
|
||||
enum { page_wrap_opcode = 0xF2 };
|
||||
enum
|
||||
{
|
||||
page_wrap_opcode = 0xF2
|
||||
};
|
||||
|
||||
// One of the many opcodes that are undefined and stop CPU emulation.
|
||||
enum { bad_opcode = 0xD2 };
|
||||
enum
|
||||
{
|
||||
bad_opcode = 0xD2
|
||||
};
|
||||
|
||||
uint8_t const *code_map[page_count + 1];
|
||||
nes_time_t clock_limit;
|
||||
|
@ -95,7 +112,10 @@ public:
|
|||
nes_time_t end_time_;
|
||||
unsigned long error_count_;
|
||||
|
||||
enum { irq_inhibit = 0x04 };
|
||||
enum
|
||||
{
|
||||
irq_inhibit = 0x04
|
||||
};
|
||||
|
||||
inline void update_clock_limit()
|
||||
{
|
||||
|
@ -115,9 +135,4 @@ public:
|
|||
{
|
||||
return (uint8_t *)code_map[addr >> page_bits] + addr;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,13 +4,14 @@
|
|||
|
||||
// Nes_Emu 0.7.0
|
||||
|
||||
#include "apu/Multi_Buffer.hpp"
|
||||
#include "Nes_Cart.hpp"
|
||||
#include "Nes_Core.hpp"
|
||||
#include "apu/Multi_Buffer.hpp"
|
||||
|
||||
class Nes_State;
|
||||
|
||||
class Nes_Emu {
|
||||
class Nes_Emu
|
||||
{
|
||||
public:
|
||||
Nes_Emu();
|
||||
virtual ~Nes_Emu();
|
||||
|
@ -115,7 +116,8 @@ public:
|
|||
int channel_count() const { return channel_count_; }
|
||||
|
||||
// Frequency equalizer parameters
|
||||
struct equalizer_t {
|
||||
struct equalizer_t
|
||||
{
|
||||
double treble; // 5.0 = extra-crisp, -200.0 = muffled
|
||||
long bass; // 0 = deep, 20000 = tinny
|
||||
};
|
||||
|
@ -146,18 +148,28 @@ public:
|
|||
// Graphics
|
||||
|
||||
// Number of frames generated per second
|
||||
enum { frame_rate = 60 };
|
||||
enum
|
||||
{
|
||||
frame_rate = 60
|
||||
};
|
||||
|
||||
// Size of fixed NES color table (including the 8 color emphasis modes)
|
||||
enum { color_table_size = 8 * 64 };
|
||||
enum
|
||||
{
|
||||
color_table_size = 8 * 64
|
||||
};
|
||||
|
||||
// NES color lookup table based on standard NTSC TV decoder. Use nes_ntsc.h to
|
||||
// generate a palette with custom parameters.
|
||||
struct rgb_t { unsigned char red, green, blue; };
|
||||
struct rgb_t
|
||||
{
|
||||
unsigned char red, green, blue;
|
||||
};
|
||||
static rgb_t const nes_colors[color_table_size];
|
||||
|
||||
// Hide/show/enhance sprites. Sprite mode does not affect emulation accuracy.
|
||||
enum sprite_mode_t {
|
||||
enum sprite_mode_t
|
||||
{
|
||||
sprites_hidden = 0,
|
||||
sprites_visible = 8, // limit of 8 sprites per scanline as on NES (default)
|
||||
sprites_enhanced = 64 // unlimited sprites per scanline (no flickering)
|
||||
|
@ -167,7 +179,10 @@ public:
|
|||
// Set range of host palette entries to use in graphics buffer; default uses
|
||||
// all of them. Begin will be rounded up to next multiple of palette_alignment.
|
||||
// Use frame().palette_begin to find the adjusted beginning entry used.
|
||||
enum { palette_alignment = 64 };
|
||||
enum
|
||||
{
|
||||
palette_alignment = 64
|
||||
};
|
||||
void set_palette_range(int begin, int end = 256);
|
||||
|
||||
// Access to emulated memory, for viewer/cheater/debugger
|
||||
|
@ -182,11 +197,17 @@ public:
|
|||
long nametable_size() const { return 0x1000; }
|
||||
|
||||
// Built-in 2K memory
|
||||
enum { low_mem_size = 0x800 };
|
||||
enum
|
||||
{
|
||||
low_mem_size = 0x800
|
||||
};
|
||||
uint8_t *low_mem() { return emu.low_mem; }
|
||||
|
||||
// Optional 8K memory
|
||||
enum { high_mem_size = 0x2000 };
|
||||
enum
|
||||
{
|
||||
high_mem_size = 0x2000
|
||||
};
|
||||
uint8_t *high_mem() { return emu.impl->sram; }
|
||||
|
||||
// Sprite memory
|
||||
|
@ -198,8 +219,8 @@ public:
|
|||
const char *set_sample_rate(long rate, class Nes_Buffer *);
|
||||
const char *set_sample_rate(long rate, class Nes_Effects_Buffer *);
|
||||
void irq_changed() { emu.irq_changed(); }
|
||||
private:
|
||||
|
||||
private:
|
||||
frame_t *frame_;
|
||||
int buffer_height_;
|
||||
bool fade_sound_in;
|
||||
|
@ -239,6 +260,7 @@ private:
|
|||
bool extra_fade_sound_in;
|
||||
bool extra_fade_sound_out;
|
||||
unsigned extra_sound_buf_changed_count;
|
||||
|
||||
public:
|
||||
void SaveAudioBufferState();
|
||||
void RestoreAudioBufferState();
|
||||
|
@ -259,4 +281,3 @@ inline long Nes_Emu::chr_size() const
|
|||
{
|
||||
return cart()->chr_size() ? cart()->chr_size() : emu.ppu.chr_addr_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
|
||||
// Blip_Buffer 0.4.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "Blip_Buffer.hpp"
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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
|
||||
|
@ -149,8 +148,7 @@ void Blip_Buffer::remove_samples( long count )
|
|||
|
||||
// Blip_Synth_
|
||||
|
||||
Blip_Synth_::Blip_Synth_( short* p, int w ) :
|
||||
impulses( p ),
|
||||
Blip_Synth_::Blip_Synth_(short *p, int w) : impulses(p),
|
||||
width(w)
|
||||
{
|
||||
volume_unit_ = 0.0;
|
||||
|
|
|
@ -11,9 +11,13 @@ typedef long blip_time_t;
|
|||
|
||||
// Output samples are 16-bit signed, with a range of -32768 to 32767
|
||||
typedef short blip_sample_t;
|
||||
enum { blip_sample_max = 32767 };
|
||||
enum
|
||||
{
|
||||
blip_sample_max = 32767
|
||||
};
|
||||
|
||||
class Blip_Buffer {
|
||||
class Blip_Buffer
|
||||
{
|
||||
public:
|
||||
// Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
|
||||
// to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
|
||||
|
@ -80,6 +84,7 @@ public:
|
|||
blip_resampled_time_t resampled_duration(int t) const { return t * factor_; }
|
||||
blip_resampled_time_t resampled_time(blip_time_t t) const { return t * factor_ + offset_; }
|
||||
blip_resampled_time_t clock_rate_factor(long clock_rate) const;
|
||||
|
||||
public:
|
||||
Blip_Buffer();
|
||||
~Blip_Buffer();
|
||||
|
@ -88,16 +93,19 @@ public:
|
|||
typedef blip_resampled_time_t resampled_time_t;
|
||||
const char *sample_rate(long r) { return set_sample_rate(r); }
|
||||
const char *sample_rate(long r, int msec) { return set_sample_rate(r, msec); }
|
||||
|
||||
private:
|
||||
// noncopyable
|
||||
Blip_Buffer(const Blip_Buffer &);
|
||||
Blip_Buffer &operator=(const Blip_Buffer &);
|
||||
|
||||
public:
|
||||
typedef long buf_t_;
|
||||
unsigned long factor_;
|
||||
blip_resampled_time_t offset_;
|
||||
buf_t_ *buffer_;
|
||||
long buffer_size_;
|
||||
|
||||
private:
|
||||
long reader_accum;
|
||||
int bass_shift;
|
||||
|
@ -113,6 +121,7 @@ private:
|
|||
int extra_length;
|
||||
long extra_reader_accum;
|
||||
blip_resampled_time_t extra_offset;
|
||||
|
||||
public:
|
||||
void SaveAudioBufferState();
|
||||
void RestoreAudioBufferState();
|
||||
|
@ -141,13 +150,15 @@ public:
|
|||
int const blip_res = 1 << BLIP_PHASE_BITS;
|
||||
class blip_eq_t;
|
||||
|
||||
class Blip_Synth_ {
|
||||
class Blip_Synth_
|
||||
{
|
||||
double volume_unit_;
|
||||
short *const impulses;
|
||||
int const width;
|
||||
long kernel_unit;
|
||||
int impulses_size() const { return blip_res / 2 * width + 1; }
|
||||
void adjust_impulse();
|
||||
|
||||
public:
|
||||
Blip_Buffer *buf;
|
||||
int last_amp;
|
||||
|
@ -167,7 +178,8 @@ const int blip_high_quality = 16;
|
|||
// by finding the difference between the maximum and minimum expected
|
||||
// amplitudes (max - min).
|
||||
template <int quality, int range>
|
||||
class Blip_Synth {
|
||||
class Blip_Synth
|
||||
{
|
||||
public:
|
||||
// Set overall volume of waveform
|
||||
void volume(double v) { impl.volume_unit(v * (1.0 / (range < 0 ? -range : range))); }
|
||||
|
@ -177,7 +189,11 @@ public:
|
|||
|
||||
// Get/set Blip_Buffer used for output
|
||||
Blip_Buffer *output() const { return impl.buf; }
|
||||
void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
|
||||
void output(Blip_Buffer *b)
|
||||
{
|
||||
impl.buf = b;
|
||||
impl.last_amp = 0;
|
||||
}
|
||||
|
||||
// Update amplitude of waveform at given time. Using this requires a separate
|
||||
// Blip_Synth for each waveform.
|
||||
|
@ -195,15 +211,18 @@ public:
|
|||
void offset_resampled(blip_resampled_time_t, int delta, Blip_Buffer *) const;
|
||||
|
||||
// Same as offset(), except code is inlined for higher performance
|
||||
void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
|
||||
void offset_inline(blip_time_t t, int delta, Blip_Buffer *buf) const
|
||||
{
|
||||
offset_resampled(t * buf->factor_ + buf->offset_, delta, buf);
|
||||
}
|
||||
void offset_inline( blip_time_t t, int delta ) const {
|
||||
void offset_inline(blip_time_t t, int delta) const
|
||||
{
|
||||
offset_resampled(t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf);
|
||||
}
|
||||
|
||||
public:
|
||||
Blip_Synth() : impl(impulses, quality) {}
|
||||
|
||||
private:
|
||||
typedef short imp_t;
|
||||
imp_t impulses[blip_res * (quality / 2) + 1];
|
||||
|
@ -211,7 +230,8 @@ private:
|
|||
};
|
||||
|
||||
// Low-pass equalization parameters
|
||||
class blip_eq_t {
|
||||
class blip_eq_t
|
||||
{
|
||||
public:
|
||||
// Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
|
||||
// treble, small positive values (0 to 5.0) increase treble.
|
||||
|
@ -232,7 +252,8 @@ private:
|
|||
int const blip_sample_bits = 30;
|
||||
|
||||
// Optimized inline sample reader for custom sample formats and mixing of Blip_Buffer samples
|
||||
class Blip_Reader {
|
||||
class Blip_Reader
|
||||
{
|
||||
public:
|
||||
// Begin reading samples from buffer. Returns value to pass to next() (can
|
||||
// be ignored if default bass_freq is acceptable).
|
||||
|
@ -256,32 +277,35 @@ private:
|
|||
long accum;
|
||||
};
|
||||
|
||||
|
||||
// End of public interface
|
||||
|
||||
|
||||
// Compatibility with older version
|
||||
const long blip_unscaled = 65535;
|
||||
const int blip_low_quality = blip_med_quality;
|
||||
const int blip_best_quality = blip_high_quality;
|
||||
|
||||
#define BLIP_FWD( i ) { \
|
||||
#define BLIP_FWD(i) \
|
||||
{ \
|
||||
long t0 = i0 * delta + buf[fwd + i]; \
|
||||
long t1 = imp[blip_res * (i + 1)] * delta + buf[fwd + 1 + i]; \
|
||||
i0 = imp[blip_res * (i + 2)]; \
|
||||
buf[fwd + i] = t0; \
|
||||
buf [fwd + 1 + i] = t1; }
|
||||
buf[fwd + 1 + i] = t1; \
|
||||
}
|
||||
|
||||
#define BLIP_REV( r ) { \
|
||||
#define BLIP_REV(r) \
|
||||
{ \
|
||||
long t0 = i0 * delta + buf[rev - r]; \
|
||||
long t1 = imp[blip_res * r] * delta + buf[rev + 1 - r]; \
|
||||
i0 = imp[blip_res * (r - 1)]; \
|
||||
buf[rev - r] = t0; \
|
||||
buf [rev + 1 - r] = t1; }
|
||||
buf[rev + 1 - r] = t1; \
|
||||
}
|
||||
|
||||
template <int quality, int range>
|
||||
inline void Blip_Synth<quality, range>::offset_resampled(blip_resampled_time_t time,
|
||||
int delta, Blip_Buffer* blip_buf ) const
|
||||
int delta,
|
||||
Blip_Buffer *blip_buf) const
|
||||
{
|
||||
// Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
|
||||
// need for a longer buffer as set by set_sample_rate().
|
||||
|
@ -333,10 +357,8 @@ void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
|
|||
offset_resampled(t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf);
|
||||
}
|
||||
|
||||
inline blip_eq_t::blip_eq_t( double t ) :
|
||||
treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
|
||||
inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
|
||||
treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
|
||||
inline blip_eq_t::blip_eq_t(double t) : treble(t), rolloff_freq(0), sample_rate(44100), cutoff_freq(0) {}
|
||||
inline blip_eq_t::blip_eq_t(double t, long rf, long sr, long cf) : treble(t), rolloff_freq(rf), sample_rate(sr), cutoff_freq(cf) {}
|
||||
|
||||
inline int Blip_Buffer::length() const { return length_; }
|
||||
inline long Blip_Buffer::samples_avail() const { return (long)(offset_ >> BLIP_BUFFER_ACCURACY); }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <cstring>
|
||||
#include "Effects_Buffer.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/* 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
|
||||
|
@ -161,9 +161,13 @@ void Effects_Buffer::config( const config_t& cfg )
|
|||
|
||||
int reverb_sample_delay = int(1.0 / 1000 * config_.reverb_delay * sample_rate());
|
||||
chans.reverb_delay_l = pin_range(reverb_size -
|
||||
(reverb_sample_delay - delay_offset) * 2, reverb_size - 2, 0 );
|
||||
(reverb_sample_delay - delay_offset) * 2,
|
||||
reverb_size - 2,
|
||||
0);
|
||||
chans.reverb_delay_r = pin_range(reverb_size + 1 -
|
||||
(reverb_sample_delay + delay_offset) * 2, reverb_size - 1, 1 );
|
||||
(reverb_sample_delay + delay_offset) * 2,
|
||||
reverb_size - 1,
|
||||
1);
|
||||
|
||||
int echo_sample_delay = int(1.0 / 1000 * config_.echo_delay * sample_rate());
|
||||
chans.echo_delay_l = pin_range(echo_size - 1 - (echo_sample_delay - delay_offset),
|
||||
|
@ -188,7 +192,6 @@ void Effects_Buffer::config( const config_t& cfg )
|
|||
o.right = &bufs[6];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -336,8 +339,10 @@ void Effects_Buffer::mix_mono( blip_sample_t* out, long count )
|
|||
|
||||
void Effects_Buffer::mix_stereo(blip_sample_t *out, long count)
|
||||
{
|
||||
Blip_Reader l; l.begin( bufs [1] );
|
||||
Blip_Reader r; r.begin( bufs [2] );
|
||||
Blip_Reader l;
|
||||
l.begin(bufs[1]);
|
||||
Blip_Reader r;
|
||||
r.begin(bufs[2]);
|
||||
Blip_Reader c;
|
||||
int shift = c.begin(bufs[0]);
|
||||
|
||||
|
@ -369,8 +374,10 @@ void Effects_Buffer::mix_stereo( blip_sample_t* out, long count )
|
|||
|
||||
void Effects_Buffer::mix_mono_enhanced(blip_sample_t *out, long count)
|
||||
{
|
||||
Blip_Reader sq1; sq1.begin( bufs [0] );
|
||||
Blip_Reader sq2; sq2.begin( bufs [1] );
|
||||
Blip_Reader sq1;
|
||||
sq1.begin(bufs[0]);
|
||||
Blip_Reader sq2;
|
||||
sq2.begin(bufs[1]);
|
||||
Blip_Reader center;
|
||||
int shift = center.begin(bufs[2]);
|
||||
|
||||
|
@ -401,10 +408,8 @@ void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out, long count )
|
|||
int sum3_s = center.read();
|
||||
center.next(shift);
|
||||
|
||||
int left = new_reverb_l + sum3_s + FMUL( chans.echo_level,
|
||||
echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
|
||||
int right = new_reverb_r + sum3_s + FMUL( chans.echo_level,
|
||||
echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
|
||||
int left = new_reverb_l + sum3_s + FMUL(chans.echo_level, echo_buf[(echo_pos + chans.echo_delay_l) & echo_mask]);
|
||||
int right = new_reverb_r + sum3_s + FMUL(chans.echo_level, echo_buf[(echo_pos + chans.echo_delay_r) & echo_mask]);
|
||||
|
||||
echo_buf[echo_pos] = sum3_s;
|
||||
echo_pos = (echo_pos + 1) & echo_mask;
|
||||
|
@ -430,12 +435,18 @@ void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out, long count )
|
|||
|
||||
void Effects_Buffer::mix_enhanced(blip_sample_t *out, long count)
|
||||
{
|
||||
Blip_Reader l1; l1.begin( bufs [3] );
|
||||
Blip_Reader r1; r1.begin( bufs [4] );
|
||||
Blip_Reader l2; l2.begin( bufs [5] );
|
||||
Blip_Reader r2; r2.begin( bufs [6] );
|
||||
Blip_Reader sq1; sq1.begin( bufs [0] );
|
||||
Blip_Reader sq2; sq2.begin( bufs [1] );
|
||||
Blip_Reader l1;
|
||||
l1.begin(bufs[3]);
|
||||
Blip_Reader r1;
|
||||
r1.begin(bufs[4]);
|
||||
Blip_Reader l2;
|
||||
l2.begin(bufs[5]);
|
||||
Blip_Reader r2;
|
||||
r2.begin(bufs[6]);
|
||||
Blip_Reader sq1;
|
||||
sq1.begin(bufs[0]);
|
||||
Blip_Reader sq2;
|
||||
sq2.begin(bufs[1]);
|
||||
Blip_Reader center;
|
||||
int shift = center.begin(bufs[2]);
|
||||
|
||||
|
@ -469,10 +480,8 @@ void Effects_Buffer::mix_enhanced( blip_sample_t* out, long count )
|
|||
int sum3_s = center.read();
|
||||
center.next(shift);
|
||||
|
||||
int left = new_reverb_l + sum3_s + l2.read() + FMUL( chans.echo_level,
|
||||
echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
|
||||
int right = new_reverb_r + sum3_s + r2.read() + FMUL( chans.echo_level,
|
||||
echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
|
||||
int left = new_reverb_l + sum3_s + l2.read() + FMUL(chans.echo_level, echo_buf[(echo_pos + chans.echo_delay_l) & echo_mask]);
|
||||
int right = new_reverb_r + sum3_s + r2.read() + FMUL(chans.echo_level, echo_buf[(echo_pos + chans.echo_delay_r) & echo_mask]);
|
||||
|
||||
l2.next(shift);
|
||||
r2.next(shift);
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
// Multi-channel effects buffer with panning, echo and reverb
|
||||
// Game_Music_Emu 0.3.0
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Multi_Buffer.hpp"
|
||||
#include <stdint.h>
|
||||
|
||||
// Effects_Buffer uses several buffers and outputs stereo sample pairs.
|
||||
class Effects_Buffer : public Multi_Buffer {
|
||||
class Effects_Buffer : public Multi_Buffer
|
||||
{
|
||||
public:
|
||||
// If center_only is true, only center buffers are created and
|
||||
// less memory is used.
|
||||
|
@ -22,7 +23,8 @@ public:
|
|||
// 4 echo -
|
||||
|
||||
// Channel configuration
|
||||
struct config_t {
|
||||
struct config_t
|
||||
{
|
||||
double pan_1; // -1.0 = left, 0.0 = center, 1.0 = right
|
||||
double pan_2;
|
||||
double echo_delay; // msec
|
||||
|
@ -48,12 +50,19 @@ public:
|
|||
void end_frame(blip_time_t, bool was_stereo = true);
|
||||
long read_samples(blip_sample_t *, long);
|
||||
long samples_avail() const;
|
||||
|
||||
private:
|
||||
typedef long fixed_t;
|
||||
|
||||
enum { max_buf_count = 7 };
|
||||
enum
|
||||
{
|
||||
max_buf_count = 7
|
||||
};
|
||||
Blip_Buffer bufs[max_buf_count];
|
||||
enum { chan_count = 5 };
|
||||
enum
|
||||
{
|
||||
chan_count = 5
|
||||
};
|
||||
channel_t channels[chan_count];
|
||||
config_t config_;
|
||||
long stereo_remain;
|
||||
|
@ -66,7 +75,8 @@ private:
|
|||
int reverb_pos;
|
||||
int echo_pos;
|
||||
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
fixed_t pan_1_levels[2];
|
||||
fixed_t pan_2_levels[2];
|
||||
int echo_delay_l;
|
||||
|
@ -83,7 +93,7 @@ private:
|
|||
void mix_mono_enhanced(blip_sample_t *, long);
|
||||
};
|
||||
|
||||
inline Effects_Buffer::channel_t Effects_Buffer::channel( int i ) {
|
||||
inline Effects_Buffer::channel_t Effects_Buffer::channel(int i)
|
||||
{
|
||||
return channels[i % chan_count];
|
||||
}
|
||||
|
||||
|
|
|
@ -174,7 +174,8 @@ long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
|
|||
}
|
||||
|
||||
// to do: this might miss opportunities for optimization
|
||||
if ( !bufs [0].samples_avail() ) {
|
||||
if (!bufs[0].samples_avail())
|
||||
{
|
||||
was_stereo = stereo_added;
|
||||
stereo_added = false;
|
||||
}
|
||||
|
@ -246,7 +247,8 @@ void Stereo_Buffer::mix_mono( blip_sample_t* out, long count )
|
|||
out[1] = s;
|
||||
out += 2;
|
||||
|
||||
if ( (int16_t) s != s ) {
|
||||
if ((int16_t)s != s)
|
||||
{
|
||||
s = 0x7FFF - (s >> 24);
|
||||
out[-2] = s;
|
||||
out[-1] = s;
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
// Interface to one or more Blip_Buffers mapped to one or more channels
|
||||
// consisting of left, center, and right buffers.
|
||||
class Multi_Buffer {
|
||||
class Multi_Buffer
|
||||
{
|
||||
public:
|
||||
Multi_Buffer(int samples_per_frame);
|
||||
virtual ~Multi_Buffer() {}
|
||||
|
@ -17,7 +18,8 @@ public:
|
|||
virtual const char *set_channel_count(int);
|
||||
|
||||
// Get indexed channel, from 0 to channel count - 1
|
||||
struct channel_t {
|
||||
struct channel_t
|
||||
{
|
||||
Blip_Buffer *center;
|
||||
Blip_Buffer *left;
|
||||
Blip_Buffer *right;
|
||||
|
@ -52,6 +54,7 @@ public:
|
|||
|
||||
protected:
|
||||
void channels_changed() { channels_changed_count_++; }
|
||||
|
||||
private:
|
||||
// noncopyable
|
||||
Multi_Buffer(const Multi_Buffer &);
|
||||
|
@ -62,17 +65,21 @@ private:
|
|||
int length_;
|
||||
int const samples_per_frame_;
|
||||
unsigned channels_changed_count_save_;
|
||||
|
||||
protected:
|
||||
void SaveAudioBufferStatePrivate();
|
||||
void RestoreAudioBufferStatePrivate();
|
||||
|
||||
public:
|
||||
virtual void SaveAudioBufferState() = 0;
|
||||
virtual void RestoreAudioBufferState() = 0;
|
||||
};
|
||||
|
||||
// Uses a single buffer and outputs mono samples.
|
||||
class Mono_Buffer : public Multi_Buffer {
|
||||
class Mono_Buffer : public Multi_Buffer
|
||||
{
|
||||
Blip_Buffer buf;
|
||||
|
||||
public:
|
||||
Mono_Buffer();
|
||||
~Mono_Buffer();
|
||||
|
@ -95,7 +102,8 @@ public:
|
|||
};
|
||||
|
||||
// Uses three buffers (one for center) and outputs stereo sample pairs.
|
||||
class Stereo_Buffer : public Multi_Buffer {
|
||||
class Stereo_Buffer : public Multi_Buffer
|
||||
{
|
||||
public:
|
||||
Stereo_Buffer();
|
||||
~Stereo_Buffer();
|
||||
|
@ -117,7 +125,10 @@ public:
|
|||
long read_samples(blip_sample_t *, long);
|
||||
|
||||
private:
|
||||
enum { buf_count = 3 };
|
||||
enum
|
||||
{
|
||||
buf_count = 3
|
||||
};
|
||||
Blip_Buffer bufs[buf_count];
|
||||
channel_t chan;
|
||||
bool stereo_added;
|
||||
|
@ -131,8 +142,10 @@ private:
|
|||
};
|
||||
|
||||
// Silent_Buffer generates no samples, useful where no sound is wanted
|
||||
class Silent_Buffer : public Multi_Buffer {
|
||||
class Silent_Buffer : public Multi_Buffer
|
||||
{
|
||||
channel_t chan;
|
||||
|
||||
public:
|
||||
Silent_Buffer();
|
||||
|
||||
|
@ -149,7 +162,6 @@ public:
|
|||
virtual void RestoreAudioBufferState();
|
||||
};
|
||||
|
||||
|
||||
// End of public interface
|
||||
|
||||
inline const char *Multi_Buffer::set_sample_rate(long rate, int msec)
|
||||
|
@ -183,4 +195,3 @@ inline void Mono_Buffer::bass_freq( int freq ) { buf.bass_freq( freq ); }
|
|||
inline long Mono_Buffer::read_samples(blip_sample_t *p, long s) { return buf.read_samples(p, s); }
|
||||
|
||||
inline long Mono_Buffer::samples_avail() const { return buf.samples_avail(); }
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ details. You should have received a copy of the GNU Lesser General Public
|
|||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
// Nes_Buffer
|
||||
|
||||
Nes_Buffer::Nes_Buffer() : Multi_Buffer(1) {}
|
||||
|
@ -194,7 +193,6 @@ long Nes_Nonlinearizer::make_nonlinear( Blip_Buffer& buf, long count )
|
|||
count = avail;
|
||||
if (count && enabled)
|
||||
{
|
||||
|
||||
Blip_Buffer::buf_t_ *p = buf.buffer_;
|
||||
long accum = this->accum;
|
||||
long prev = this->prev;
|
||||
|
|
|
@ -8,10 +8,17 @@
|
|||
|
||||
class Nes_Apu;
|
||||
|
||||
class Nes_Nonlinearizer {
|
||||
class Nes_Nonlinearizer
|
||||
{
|
||||
private:
|
||||
enum { table_bits = 11 };
|
||||
enum { table_size = 1 << table_bits };
|
||||
enum
|
||||
{
|
||||
table_bits = 11
|
||||
};
|
||||
enum
|
||||
{
|
||||
table_size = 1 << table_bits
|
||||
};
|
||||
int16_t table[table_size];
|
||||
Nes_Apu *apu;
|
||||
long accum;
|
||||
|
@ -19,6 +26,7 @@ private:
|
|||
|
||||
long extra_accum;
|
||||
long extra_prev;
|
||||
|
||||
public:
|
||||
Nes_Nonlinearizer();
|
||||
bool enabled;
|
||||
|
@ -30,7 +38,8 @@ public:
|
|||
void RestoreAudioBufferState();
|
||||
};
|
||||
|
||||
class Nes_Buffer : public Multi_Buffer {
|
||||
class Nes_Buffer : public Multi_Buffer
|
||||
{
|
||||
public:
|
||||
Nes_Buffer();
|
||||
~Nes_Buffer();
|
||||
|
@ -61,6 +70,7 @@ private:
|
|||
Blip_Buffer tnd;
|
||||
Nes_Nonlinearizer nonlin;
|
||||
friend Multi_Buffer *set_apu(Nes_Buffer *, Nes_Apu *);
|
||||
|
||||
public:
|
||||
virtual void SaveAudioBufferState();
|
||||
virtual void RestoreAudioBufferState();
|
||||
|
|
|
@ -15,8 +15,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
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
Nes_Effects_Buffer::Nes_Effects_Buffer() :
|
||||
Effects_Buffer( true ) // nes never uses stereo channels
|
||||
Nes_Effects_Buffer::Nes_Effects_Buffer() : Effects_Buffer(true) // nes never uses stereo channels
|
||||
{
|
||||
config_t c;
|
||||
c.effects_enabled = false;
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
// Effects_Buffer with non-linear sound
|
||||
// Nes_Emu 0.7.0
|
||||
|
||||
#include "Nes_Buffer.hpp"
|
||||
#include "Effects_Buffer.hpp"
|
||||
#include "Nes_Buffer.hpp"
|
||||
|
||||
// Effects_Buffer uses several buffers and outputs stereo sample pairs.
|
||||
class Nes_Effects_Buffer : public Effects_Buffer {
|
||||
class Nes_Effects_Buffer : public Effects_Buffer
|
||||
{
|
||||
public:
|
||||
Nes_Effects_Buffer();
|
||||
~Nes_Effects_Buffer();
|
||||
|
|
|
@ -25,12 +25,14 @@ void Nes_Osc::clock_length( int halt_mask )
|
|||
void Nes_Envelope::clock_envelope()
|
||||
{
|
||||
int period = regs[0] & 15;
|
||||
if ( reg_written [3] ) {
|
||||
if (reg_written[3])
|
||||
{
|
||||
reg_written[3] = false;
|
||||
env_delay = period;
|
||||
envelope = 15;
|
||||
}
|
||||
else if ( --env_delay < 0 ) {
|
||||
else if (--env_delay < 0)
|
||||
{
|
||||
env_delay = period;
|
||||
if (envelope | (regs[0] & 0x20))
|
||||
envelope = (envelope - 1) & 15;
|
||||
|
@ -39,7 +41,8 @@ void Nes_Envelope::clock_envelope()
|
|||
|
||||
int Nes_Envelope::volume() const
|
||||
{
|
||||
return length_counter == 0 ? 0 : (regs [0] & 0x10) ? (regs [0] & 15) : envelope;
|
||||
return length_counter == 0 ? 0 : (regs[0] & 0x10) ? (regs[0] & 15)
|
||||
: envelope;
|
||||
}
|
||||
|
||||
// Nes_Square
|
||||
|
@ -71,15 +74,15 @@ void Nes_Square::clock_sweep( int negative_adjust )
|
|||
}
|
||||
}
|
||||
|
||||
if ( reg_written [1] ) {
|
||||
if (reg_written[1])
|
||||
{
|
||||
reg_written[1] = false;
|
||||
sweep_delay = (sweep >> 4) & 7;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Nes_Square::maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period)
|
||||
{
|
||||
long remain = end_time - time;
|
||||
if (remain > 0)
|
||||
|
@ -109,7 +112,8 @@ void Nes_Square::run( nes_time_t time, nes_time_t end_time )
|
|||
const int volume = this->volume();
|
||||
if (volume == 0 || period < 8 || (period + offset) >= 0x800)
|
||||
{
|
||||
if ( last_amp ) {
|
||||
if (last_amp)
|
||||
{
|
||||
synth.offset(time, -last_amp, output);
|
||||
last_amp = 0;
|
||||
}
|
||||
|
@ -123,7 +127,8 @@ void Nes_Square::run( nes_time_t time, nes_time_t end_time )
|
|||
int duty_select = (regs[0] >> 6) & 3;
|
||||
int duty = 1 << duty_select; // 1, 2, 4, 2
|
||||
int amp = 0;
|
||||
if ( duty_select == 3 ) {
|
||||
if (duty_select == 3)
|
||||
{
|
||||
duty = 2; // negated 25%
|
||||
amp = volume;
|
||||
}
|
||||
|
@ -144,13 +149,13 @@ void Nes_Square::run( nes_time_t time, nes_time_t end_time )
|
|||
|
||||
do {
|
||||
phase = (phase + 1) & (phase_range - 1);
|
||||
if ( phase == 0 || phase == duty ) {
|
||||
if (phase == 0 || phase == duty)
|
||||
{
|
||||
delta = -delta;
|
||||
synth.offset_inline(time, delta, output);
|
||||
}
|
||||
time += timer_period;
|
||||
}
|
||||
while ( time < end_time );
|
||||
} while (time < end_time);
|
||||
|
||||
last_amp = (delta + volume) >> 1;
|
||||
this->phase = phase;
|
||||
|
@ -182,8 +187,7 @@ inline int Nes_Triangle::calc_amp() const
|
|||
}
|
||||
|
||||
// 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 Nes_Triangle::maintain_phase(nes_time_t time, nes_time_t end_time, nes_time_t timer_period)
|
||||
{
|
||||
long remain = end_time - time;
|
||||
if (remain > 0)
|
||||
|
@ -226,23 +230,25 @@ void Nes_Triangle::run( nes_time_t time, nes_time_t end_time )
|
|||
|
||||
int phase = this->phase;
|
||||
int volume = 1;
|
||||
if ( phase > phase_range ) {
|
||||
if (phase > phase_range)
|
||||
{
|
||||
phase -= phase_range;
|
||||
volume = -volume;
|
||||
}
|
||||
|
||||
do {
|
||||
if ( --phase == 0 ) {
|
||||
if (--phase == 0)
|
||||
{
|
||||
phase = phase_range;
|
||||
volume = -volume;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
synth.offset_inline(time, volume, output);
|
||||
}
|
||||
|
||||
time += timer_period;
|
||||
}
|
||||
while ( time < end_time );
|
||||
} while (time < end_time);
|
||||
|
||||
if (volume < 0)
|
||||
phase += phase_range;
|
||||
|
@ -277,7 +283,8 @@ void Nes_Dmc::recalc_irq()
|
|||
if (irq_enabled && length_counter)
|
||||
irq = apu->last_dmc_time + delay +
|
||||
((length_counter - 1) * 8 + bits_remain - 1) * nes_time_t(period) + 1;
|
||||
if ( irq != next_irq ) {
|
||||
if (irq != next_irq)
|
||||
{
|
||||
next_irq = irq;
|
||||
apu->irq_changed();
|
||||
}
|
||||
|
@ -308,10 +315,24 @@ int Nes_Dmc::count_reads( nes_time_t time, nes_time_t* last_read ) const
|
|||
|
||||
static const short dmc_period_table[2][16] = {
|
||||
{0x1ac, 0x17c, 0x154, 0x140, 0x11e, 0x0fe, 0x0e2, 0x0d6, // NTSC
|
||||
0x0be, 0x0a0, 0x08e, 0x080, 0x06a, 0x054, 0x048, 0x036},
|
||||
0x0be,
|
||||
0x0a0,
|
||||
0x08e,
|
||||
0x080,
|
||||
0x06a,
|
||||
0x054,
|
||||
0x048,
|
||||
0x036},
|
||||
|
||||
{0x18e, 0x161, 0x13c, 0x129, 0x10a, 0x0ec, 0x0d2, 0x0c7, // PAL (totally untested)
|
||||
0x0b1, 0x095, 0x084, 0x077, 0x062, 0x04e, 0x043, 0x032} // to do: verify PAL periods
|
||||
0x0b1,
|
||||
0x095,
|
||||
0x084,
|
||||
0x077,
|
||||
0x062,
|
||||
0x04e,
|
||||
0x043,
|
||||
0x032} // to do: verify PAL periods
|
||||
};
|
||||
|
||||
inline void Nes_Dmc::reload_sample()
|
||||
|
@ -322,14 +343,134 @@ inline void Nes_Dmc::reload_sample()
|
|||
|
||||
static const unsigned char dac_table[128] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14,
|
||||
15,15,16,17,18,19,20,20,21,22,23,24,24,25,26,27,
|
||||
27,28,29,30,31,31,32,33,33,34,35,36,36,37,38,38,
|
||||
39,40,41,41,42,43,43,44,45,45,46,47,47,48,48,49,
|
||||
50,50,51,52,52,53,53,54,55,55,56,56,57,58,58,59,
|
||||
59,60,60,61,61,62,63,63,64,64,65,65,66,66,67,67,
|
||||
68,68,69,70,70,71,71,72,72,73,73,74,74,75,75,75,
|
||||
76,76,77,77,78,78,79,79,80,80,81,81,82,82,82,83,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
31,
|
||||
31,
|
||||
32,
|
||||
33,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
36,
|
||||
37,
|
||||
38,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
43,
|
||||
44,
|
||||
45,
|
||||
45,
|
||||
46,
|
||||
47,
|
||||
47,
|
||||
48,
|
||||
48,
|
||||
49,
|
||||
50,
|
||||
50,
|
||||
51,
|
||||
52,
|
||||
52,
|
||||
53,
|
||||
53,
|
||||
54,
|
||||
55,
|
||||
55,
|
||||
56,
|
||||
56,
|
||||
57,
|
||||
58,
|
||||
58,
|
||||
59,
|
||||
59,
|
||||
60,
|
||||
60,
|
||||
61,
|
||||
61,
|
||||
62,
|
||||
63,
|
||||
63,
|
||||
64,
|
||||
64,
|
||||
65,
|
||||
65,
|
||||
66,
|
||||
66,
|
||||
67,
|
||||
67,
|
||||
68,
|
||||
68,
|
||||
69,
|
||||
70,
|
||||
70,
|
||||
71,
|
||||
71,
|
||||
72,
|
||||
72,
|
||||
73,
|
||||
73,
|
||||
74,
|
||||
74,
|
||||
75,
|
||||
75,
|
||||
75,
|
||||
76,
|
||||
76,
|
||||
77,
|
||||
77,
|
||||
78,
|
||||
78,
|
||||
79,
|
||||
79,
|
||||
80,
|
||||
80,
|
||||
81,
|
||||
81,
|
||||
82,
|
||||
82,
|
||||
82,
|
||||
83,
|
||||
};
|
||||
|
||||
void Nes_Dmc::write_register(int addr, int data)
|
||||
|
@ -370,10 +511,12 @@ void Nes_Dmc::fill_buffer()
|
|||
buf_full = true;
|
||||
if (--length_counter == 0)
|
||||
{
|
||||
if ( regs [0] & loop_flag ) {
|
||||
if (regs[0] & loop_flag)
|
||||
{
|
||||
reload_sample();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
apu->osc_enables &= ~0x10;
|
||||
irq_flag = irq_enabled;
|
||||
next_irq = Nes_Apu::no_irq;
|
||||
|
@ -414,7 +557,8 @@ void Nes_Dmc::run( nes_time_t time, nes_time_t end_time )
|
|||
{
|
||||
int step = (bits & 1) * 4 - 2;
|
||||
bits >>= 1;
|
||||
if ( unsigned (dac + step) <= 0x7F ) {
|
||||
if (unsigned(dac + step) <= 0x7F)
|
||||
{
|
||||
dac += step;
|
||||
synth.offset_inline(time, step, output);
|
||||
}
|
||||
|
@ -425,10 +569,12 @@ void Nes_Dmc::run( nes_time_t time, nes_time_t end_time )
|
|||
if (--bits_remain == 0)
|
||||
{
|
||||
bits_remain = 8;
|
||||
if ( !buf_full ) {
|
||||
if (!buf_full)
|
||||
{
|
||||
silence = true;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
silence = false;
|
||||
bits = buf;
|
||||
buf_full = false;
|
||||
|
@ -437,8 +583,7 @@ void Nes_Dmc::run( nes_time_t time, nes_time_t end_time )
|
|||
fill_buffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( time < end_time );
|
||||
} while (time < end_time);
|
||||
|
||||
this->dac = dac;
|
||||
this->last_amp = dac;
|
||||
|
@ -452,9 +597,7 @@ void Nes_Dmc::run( nes_time_t time, nes_time_t end_time )
|
|||
// Nes_Noise
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -492,7 +635,8 @@ void Nes_Noise::run( nes_time_t time, nes_time_t end_time )
|
|||
|
||||
// approximate noise cycling while muted, by shuffling up noise register
|
||||
// to do: precise muted noise cycling?
|
||||
if ( !(regs [2] & mode_flag) ) {
|
||||
if (!(regs[2] & mode_flag))
|
||||
{
|
||||
int feedback = (noise << 13) ^ (noise << 14);
|
||||
noise = (feedback & 0x4000) | (noise >> 1);
|
||||
}
|
||||
|
@ -513,7 +657,8 @@ void Nes_Noise::run( nes_time_t time, nes_time_t end_time )
|
|||
int feedback = (noise << tap) ^ (noise << 14);
|
||||
time += period;
|
||||
|
||||
if ( (noise + 1) & 2 ) {
|
||||
if ((noise + 1) & 2)
|
||||
{
|
||||
// bits 0 and 1 of noise differ
|
||||
delta = -delta;
|
||||
synth.offset_resampled(rtime, delta, output);
|
||||
|
@ -521,8 +666,7 @@ void Nes_Noise::run( nes_time_t time, nes_time_t end_time )
|
|||
|
||||
rtime += rperiod;
|
||||
noise = (feedback & 0x4000) | (noise >> 1);
|
||||
}
|
||||
while ( time < end_time );
|
||||
} while (time < end_time);
|
||||
|
||||
last_amp = (delta + volume) >> 1;
|
||||
this->noise = noise;
|
||||
|
|
|
@ -21,14 +21,17 @@ struct Nes_Osc
|
|||
int last_amp; // last amplitude oscillator was outputting
|
||||
|
||||
void clock_length(int halt_mask);
|
||||
int period() const {
|
||||
int period() const
|
||||
{
|
||||
return (regs[3] & 7) * 0x100 + (regs[2] & 0xff);
|
||||
}
|
||||
void reset() {
|
||||
void reset()
|
||||
{
|
||||
delay = 0;
|
||||
last_amp = 0;
|
||||
}
|
||||
int update_amp( int amp ) {
|
||||
int update_amp(int amp)
|
||||
{
|
||||
int delta = amp - last_amp;
|
||||
last_amp = amp;
|
||||
return delta;
|
||||
|
@ -42,7 +45,8 @@ struct Nes_Envelope : Nes_Osc
|
|||
|
||||
void clock_envelope();
|
||||
int volume() const;
|
||||
void reset() {
|
||||
void reset()
|
||||
{
|
||||
envelope = 0;
|
||||
env_delay = 0;
|
||||
Nes_Osc::reset();
|
||||
|
@ -52,9 +56,18 @@ struct Nes_Envelope : Nes_Osc
|
|||
// Nes_Square
|
||||
struct Nes_Square : Nes_Envelope
|
||||
{
|
||||
enum { negate_flag = 0x08 };
|
||||
enum { shift_mask = 0x07 };
|
||||
enum { phase_range = 8 };
|
||||
enum
|
||||
{
|
||||
negate_flag = 0x08
|
||||
};
|
||||
enum
|
||||
{
|
||||
shift_mask = 0x07
|
||||
};
|
||||
enum
|
||||
{
|
||||
phase_range = 8
|
||||
};
|
||||
int phase;
|
||||
int sweep_delay;
|
||||
|
||||
|
@ -65,18 +78,21 @@ struct Nes_Square : Nes_Envelope
|
|||
|
||||
void clock_sweep(int adjust);
|
||||
void run(nes_time_t, nes_time_t);
|
||||
void reset() {
|
||||
void reset()
|
||||
{
|
||||
sweep_delay = 0;
|
||||
Nes_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
|
||||
struct Nes_Triangle : Nes_Osc
|
||||
{
|
||||
enum { phase_range = 16 };
|
||||
enum
|
||||
{
|
||||
phase_range = 16
|
||||
};
|
||||
int phase;
|
||||
int linear_counter;
|
||||
Blip_Synth<blip_med_quality, 1> synth;
|
||||
|
@ -84,13 +100,13 @@ struct Nes_Triangle : Nes_Osc
|
|||
int calc_amp() const;
|
||||
void run(nes_time_t, nes_time_t);
|
||||
void clock_linear_counter();
|
||||
void reset() {
|
||||
void reset()
|
||||
{
|
||||
linear_counter = 0;
|
||||
phase = 1;
|
||||
Nes_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
|
||||
|
@ -100,7 +116,8 @@ struct Nes_Noise : Nes_Envelope
|
|||
Blip_Synth<blip_med_quality, 1> synth;
|
||||
|
||||
void run(nes_time_t, nes_time_t);
|
||||
void reset() {
|
||||
void reset()
|
||||
{
|
||||
noise = 1 << 14;
|
||||
Nes_Envelope::reset();
|
||||
}
|
||||
|
@ -118,7 +135,10 @@ struct Nes_Dmc : Nes_Osc
|
|||
bool buf_full;
|
||||
bool silence;
|
||||
|
||||
enum { loop_flag = 0x40 };
|
||||
enum
|
||||
{
|
||||
loop_flag = 0x40
|
||||
};
|
||||
|
||||
int dac;
|
||||
|
||||
|
@ -145,4 +165,3 @@ struct Nes_Dmc : Nes_Osc
|
|||
int count_reads(nes_time_t, nes_time_t *) const;
|
||||
nes_time_t next_read_time() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
int const amp_range = 15;
|
||||
|
||||
Nes_Apu::Nes_Apu() :
|
||||
square1( &square_synth ),
|
||||
Nes_Apu::Nes_Apu() : square1(&square_synth),
|
||||
square2(&square_synth)
|
||||
{
|
||||
dmc.apu = this;
|
||||
|
@ -112,14 +111,17 @@ void Nes_Apu::reset( bool pal_mode, int initial_dmc_dac )
|
|||
void Nes_Apu::irq_changed()
|
||||
{
|
||||
nes_time_t new_irq = dmc.next_irq;
|
||||
if ( dmc.irq_flag | irq_flag ) {
|
||||
if (dmc.irq_flag | irq_flag)
|
||||
{
|
||||
new_irq = 0;
|
||||
}
|
||||
else if ( new_irq > next_irq ) {
|
||||
else if (new_irq > next_irq)
|
||||
{
|
||||
new_irq = next_irq;
|
||||
}
|
||||
|
||||
if ( new_irq != earliest_irq_ ) {
|
||||
if (new_irq != earliest_irq_)
|
||||
{
|
||||
earliest_irq_ = new_irq;
|
||||
if (irq_notifier_)
|
||||
irq_notifier_(irq_data);
|
||||
|
@ -173,7 +175,8 @@ void Nes_Apu::run_until_( nes_time_t end_time )
|
|||
switch (frame++)
|
||||
{
|
||||
case 0:
|
||||
if ( !(frame_mode & 0xc0) ) {
|
||||
if (!(frame_mode & 0xc0))
|
||||
{
|
||||
next_irq = time + frame_period * 4 + 1;
|
||||
irq_flag = true;
|
||||
}
|
||||
|
@ -239,13 +242,16 @@ void Nes_Apu::end_frame( nes_time_t end_time )
|
|||
last_time -= end_time;
|
||||
last_dmc_time -= end_time;
|
||||
|
||||
if ( next_irq != no_irq ) {
|
||||
if (next_irq != no_irq)
|
||||
{
|
||||
next_irq -= end_time;
|
||||
}
|
||||
if ( dmc.next_irq != no_irq ) {
|
||||
if (dmc.next_irq != no_irq)
|
||||
{
|
||||
dmc.next_irq -= end_time;
|
||||
}
|
||||
if ( earliest_irq_ != no_irq ) {
|
||||
if (earliest_irq_ != no_irq)
|
||||
{
|
||||
earliest_irq_ -= end_time;
|
||||
if (earliest_irq_ < 0)
|
||||
earliest_irq_ = 0;
|
||||
|
@ -255,11 +261,7 @@ void Nes_Apu::end_frame( nes_time_t end_time )
|
|||
// registers
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -307,11 +309,13 @@ void Nes_Apu::write_register( nes_time_t time, nes_addr_t addr, int data )
|
|||
|
||||
int old_enables = osc_enables;
|
||||
osc_enables = data;
|
||||
if ( !(data & 0x10) ) {
|
||||
if (!(data & 0x10))
|
||||
{
|
||||
dmc.next_irq = no_irq;
|
||||
recalc_irq = true;
|
||||
}
|
||||
else if ( !(old_enables & 0x10) ) {
|
||||
else if (!(old_enables & 0x10))
|
||||
{
|
||||
dmc.start(); // dmc just enabled
|
||||
}
|
||||
|
||||
|
@ -356,7 +360,8 @@ int Nes_Apu::read_status( nes_time_t time )
|
|||
|
||||
run_until_(time);
|
||||
|
||||
if ( irq_flag ) {
|
||||
if (irq_flag)
|
||||
{
|
||||
irq_flag = false;
|
||||
irq_changed();
|
||||
}
|
||||
|
|
|
@ -3,14 +3,13 @@
|
|||
// NES 2A03 APU sound chip emulator
|
||||
// Nes_Snd_Emu 0.1.7
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdint>
|
||||
#include <climits>
|
||||
#include "Nes_Oscs.hpp"
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
|
||||
class Nes_Apu {
|
||||
class Nes_Apu
|
||||
{
|
||||
public:
|
||||
|
||||
typedef uint8_t env_t[3];
|
||||
/*struct env_t {
|
||||
uint8_t delay;
|
||||
|
@ -18,7 +17,8 @@ public:
|
|||
uint8_t written;
|
||||
};*/
|
||||
|
||||
struct apu_t {
|
||||
struct apu_t
|
||||
{
|
||||
uint8_t w40xx[0x14]; // $4000-$4013
|
||||
uint8_t w4015; // enables
|
||||
uint8_t w4017; // mode
|
||||
|
@ -27,7 +27,8 @@ public:
|
|||
uint8_t irq_flag;
|
||||
};
|
||||
|
||||
struct square_t {
|
||||
struct square_t
|
||||
{
|
||||
uint16_t delay;
|
||||
env_t env;
|
||||
uint8_t length_counter;
|
||||
|
@ -37,7 +38,8 @@ public:
|
|||
uint8_t unused2[1];
|
||||
};
|
||||
|
||||
struct triangle_t {
|
||||
struct triangle_t
|
||||
{
|
||||
uint16_t delay;
|
||||
uint8_t length_counter;
|
||||
uint8_t phase;
|
||||
|
@ -45,14 +47,16 @@ public:
|
|||
uint8_t linear_mode;
|
||||
};
|
||||
|
||||
struct noise_t {
|
||||
struct noise_t
|
||||
{
|
||||
uint16_t delay;
|
||||
env_t env;
|
||||
uint8_t length_counter;
|
||||
uint16_t shift_reg;
|
||||
};
|
||||
|
||||
struct dmc_t {
|
||||
struct dmc_t
|
||||
{
|
||||
uint16_t delay;
|
||||
uint16_t remain;
|
||||
uint16_t addr;
|
||||
|
@ -158,6 +162,7 @@ private:
|
|||
friend class Nes_Nonlinearizer;
|
||||
void enable_nonlinear(double volume);
|
||||
static double nonlinear_tnd_gain() { return 0.75; }
|
||||
|
||||
private:
|
||||
friend struct Nes_Dmc;
|
||||
|
||||
|
@ -231,7 +236,6 @@ inline nes_time_t Nes_Dmc::next_read_time() const
|
|||
|
||||
inline nes_time_t Nes_Apu::next_dmc_read_time() const { return dmc.next_read_time(); }
|
||||
|
||||
|
||||
template <int mode>
|
||||
struct apu_reflection
|
||||
{
|
||||
|
@ -288,7 +292,6 @@ struct apu_reflection
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
inline void Nes_Apu::save_state(apu_state_t *state) const
|
||||
{
|
||||
for (int i = 0; i < osc_count * 4; i++)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <cstring>
|
||||
#include "apu/fme7/apu.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/* 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
|
||||
|
@ -29,10 +29,7 @@ void Nes_Fme7_Apu::reset()
|
|||
unsigned char Nes_Fme7_Apu::amp_table[16] =
|
||||
{
|
||||
#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
|
||||
};
|
||||
|
||||
|
@ -85,8 +82,7 @@ void Nes_Fme7_Apu::run_until( blip_time_t end_time )
|
|||
delta = -delta;
|
||||
synth.offset_inline(time, delta, osc_output);
|
||||
time += period;
|
||||
}
|
||||
while ( time < end_time );
|
||||
} while (time < end_time);
|
||||
|
||||
oscs[index].last_amp = (delta + volume) >> 1;
|
||||
phases[index] = (delta > 0);
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
// Sunsoft FME-7 sound emulator
|
||||
// Nes_Emu 0.7.0
|
||||
|
||||
#include <cstdint>
|
||||
#include "apu/Blip_Buffer.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
struct fme7_apu_state_t
|
||||
{
|
||||
enum { reg_count = 14 };
|
||||
enum
|
||||
{
|
||||
reg_count = 14
|
||||
};
|
||||
uint8_t regs[reg_count];
|
||||
uint8_t phases[3]; // 0 or 1
|
||||
uint8_t latch;
|
||||
|
@ -16,7 +19,8 @@ struct fme7_apu_state_t
|
|||
};
|
||||
static_assert(sizeof(fme7_apu_state_t) == 24);
|
||||
|
||||
class Nes_Fme7_Apu : private fme7_apu_state_t {
|
||||
class Nes_Fme7_Apu : private fme7_apu_state_t
|
||||
{
|
||||
public:
|
||||
Nes_Fme7_Apu();
|
||||
|
||||
|
@ -25,16 +29,28 @@ public:
|
|||
void volume(double);
|
||||
void treble_eq(blip_eq_t const &);
|
||||
void output(Blip_Buffer *);
|
||||
enum { osc_count = 3 };
|
||||
enum
|
||||
{
|
||||
osc_count = 3
|
||||
};
|
||||
void osc_output(int index, Blip_Buffer *);
|
||||
void end_frame(blip_time_t);
|
||||
void save_state(fme7_apu_state_t *) const;
|
||||
void load_state(fme7_apu_state_t const &);
|
||||
|
||||
// Mask and addresses of registers
|
||||
enum { addr_mask = 0xe000 };
|
||||
enum { data_addr = 0xe000 };
|
||||
enum { latch_addr = 0xc000 };
|
||||
enum
|
||||
{
|
||||
addr_mask = 0xe000
|
||||
};
|
||||
enum
|
||||
{
|
||||
data_addr = 0xe000
|
||||
};
|
||||
enum
|
||||
{
|
||||
latch_addr = 0xc000
|
||||
};
|
||||
|
||||
// (addr & addr_mask) == latch_addr
|
||||
void write_latch(int);
|
||||
|
@ -50,13 +66,17 @@ private:
|
|||
|
||||
static unsigned char amp_table[16];
|
||||
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
Blip_Buffer *output;
|
||||
int last_amp;
|
||||
} oscs[osc_count];
|
||||
blip_time_t last_time;
|
||||
|
||||
enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff
|
||||
enum
|
||||
{
|
||||
amp_range = 192
|
||||
}; // can be any value; this gives best error/quality tradeoff
|
||||
Blip_Synth<blip_good_quality, 1> synth;
|
||||
|
||||
void run_until(blip_time_t);
|
||||
|
@ -128,4 +148,3 @@ inline void Nes_Fme7_Apu::load_state( fme7_apu_state_t const& in )
|
|||
// Run sound channels for 0 cycles for clean audio after loading state
|
||||
run_until(last_time);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/
|
||||
|
||||
#include "apu/Blip_Buffer.hpp"
|
||||
#include "apu/namco/apu.hpp"
|
||||
#include "apu/Blip_Buffer.hpp"
|
||||
|
||||
/* 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
|
||||
|
@ -133,8 +133,7 @@ void Nes_Namco_Apu::run_until( nes_time_t nes_end_time )
|
|||
time += period;
|
||||
if (wave_pos >= wave_size)
|
||||
wave_pos = 0;
|
||||
}
|
||||
while ( time < end_time );
|
||||
} while (time < end_time);
|
||||
|
||||
osc.wave_pos = wave_pos;
|
||||
osc.last_amp = last_amp;
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
// Namco 106 sound chip emulator
|
||||
// Nes_Snd_Emu 0.1.7
|
||||
|
||||
#include <cstdint>
|
||||
#include "apu/apu.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
struct namco_state_t
|
||||
{
|
||||
|
@ -16,7 +16,8 @@ struct namco_state_t
|
|||
};
|
||||
static_assert(sizeof(namco_state_t) == 172);
|
||||
|
||||
class Nes_Namco_Apu {
|
||||
class Nes_Namco_Apu
|
||||
{
|
||||
public:
|
||||
Nes_Namco_Apu();
|
||||
~Nes_Namco_Apu();
|
||||
|
@ -25,18 +26,27 @@ public:
|
|||
void volume(double);
|
||||
void treble_eq(const blip_eq_t &);
|
||||
void output(Blip_Buffer *);
|
||||
enum { osc_count = 8 };
|
||||
enum
|
||||
{
|
||||
osc_count = 8
|
||||
};
|
||||
void osc_output(int index, Blip_Buffer *);
|
||||
void reset();
|
||||
void end_frame(nes_time_t);
|
||||
|
||||
// Read/write data register is at 0x4800
|
||||
enum { data_reg_addr = 0x4800 };
|
||||
enum
|
||||
{
|
||||
data_reg_addr = 0x4800
|
||||
};
|
||||
void write_data(nes_time_t, int);
|
||||
int read_data();
|
||||
|
||||
// Write-only address register is at 0xF800
|
||||
enum { addr_reg_addr = 0xF800 };
|
||||
enum
|
||||
{
|
||||
addr_reg_addr = 0xF800
|
||||
};
|
||||
void write_addr(int);
|
||||
|
||||
// to do: implement save/restore
|
||||
|
@ -48,7 +58,8 @@ private:
|
|||
Nes_Namco_Apu(const Nes_Namco_Apu &);
|
||||
Nes_Namco_Apu &operator=(const Nes_Namco_Apu &);
|
||||
|
||||
struct Namco_Osc {
|
||||
struct Namco_Osc
|
||||
{
|
||||
long delay;
|
||||
Blip_Buffer *output;
|
||||
short last_amp;
|
||||
|
@ -60,7 +71,10 @@ private:
|
|||
nes_time_t last_time;
|
||||
int addr_reg;
|
||||
|
||||
enum { reg_count = 0x80 };
|
||||
enum
|
||||
{
|
||||
reg_count = 0x80
|
||||
};
|
||||
uint8_t reg[reg_count];
|
||||
Blip_Synth<blip_good_quality, 15> synth;
|
||||
|
||||
|
@ -94,4 +108,3 @@ inline void Nes_Namco_Apu::write_data( nes_time_t time, int data )
|
|||
run_until(time);
|
||||
access() = data;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,8 +146,7 @@ void Nes_Vrc6_Apu::run_square( Vrc6_Osc& osc, nes_time_t end_time )
|
|||
square_synth.offset(time, -volume, output);
|
||||
}
|
||||
time += period;
|
||||
}
|
||||
while ( time < end_time );
|
||||
} while (time < end_time);
|
||||
|
||||
osc.phase = phase;
|
||||
}
|
||||
|
@ -198,8 +197,7 @@ void Nes_Vrc6_Apu::run_saw( nes_time_t end_time )
|
|||
|
||||
time += period;
|
||||
amp = (amp + amp_step) & 0xFF;
|
||||
}
|
||||
while ( time < end_time );
|
||||
} while (time < end_time);
|
||||
|
||||
osc.phase = phase;
|
||||
osc.amp = amp;
|
||||
|
|
|
@ -4,13 +4,14 @@
|
|||
// Konami VRC6 sound chip emulator
|
||||
// Nes_Snd_Emu 0.1.7
|
||||
|
||||
#include <cstdint>
|
||||
#include "apu/apu.hpp"
|
||||
#include "apu/Blip_Buffer.hpp"
|
||||
#include "apu/apu.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
struct vrc6_apu_state_t;
|
||||
|
||||
class Nes_Vrc6_Apu {
|
||||
class Nes_Vrc6_Apu
|
||||
{
|
||||
public:
|
||||
Nes_Vrc6_Apu();
|
||||
~Nes_Vrc6_Apu();
|
||||
|
@ -20,7 +21,10 @@ public:
|
|||
void volume(double);
|
||||
void treble_eq(blip_eq_t const &);
|
||||
void output(Blip_Buffer *);
|
||||
enum { osc_count = 3 };
|
||||
enum
|
||||
{
|
||||
osc_count = 3
|
||||
};
|
||||
void osc_output(int index, Blip_Buffer *);
|
||||
void end_frame(nes_time_t);
|
||||
void save_state(vrc6_apu_state_t *) const;
|
||||
|
@ -29,9 +33,18 @@ public:
|
|||
// Oscillator 0 write-only registers are at $9000-$9002
|
||||
// Oscillator 1 write-only registers are at $A000-$A002
|
||||
// Oscillator 2 write-only registers are at $B000-$B002
|
||||
enum { reg_count = 3 };
|
||||
enum { base_addr = 0x9000 };
|
||||
enum { addr_step = 0x1000 };
|
||||
enum
|
||||
{
|
||||
reg_count = 3
|
||||
};
|
||||
enum
|
||||
{
|
||||
base_addr = 0x9000
|
||||
};
|
||||
enum
|
||||
{
|
||||
addr_step = 0x1000
|
||||
};
|
||||
void write_osc(nes_time_t, int osc, int reg, int data);
|
||||
|
||||
private:
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
#include "apu/vrc7/emu2413.hpp"
|
||||
#include <cstring>
|
||||
|
||||
#define BYTESWAP(xxxx) {uint32_t _temp = (uint32_t)(xxxx);\
|
||||
#define BYTESWAP(xxxx) \
|
||||
{ \
|
||||
uint32_t _temp = (uint32_t)(xxxx); \
|
||||
((uint8_t *)&(xxxx))[0] = (uint8_t)((_temp) >> 24); \
|
||||
((uint8_t *)&(xxxx))[1] = (uint8_t)((_temp) >> 16); \
|
||||
((uint8_t *)&(xxxx))[2] = (uint8_t)((_temp) >> 8); \
|
||||
|
|
|
@ -4,14 +4,15 @@
|
|||
// Konami VRC7 sound chip emulator
|
||||
// Nes_Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
|
||||
|
||||
#include <cstdint>
|
||||
#include "apu/vrc7/emu2413_state.hpp"
|
||||
#include "apu/Blip_Buffer.hpp"
|
||||
#include "apu/vrc7/emu2413_state.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
struct vrc7_snapshot_t;
|
||||
typedef long nes_time_t;
|
||||
|
||||
class Nes_Vrc7 {
|
||||
class Nes_Vrc7
|
||||
{
|
||||
public:
|
||||
Nes_Vrc7();
|
||||
~Nes_Vrc7();
|
||||
|
@ -21,7 +22,10 @@ public:
|
|||
void volume(double);
|
||||
void treble_eq(blip_eq_t const &);
|
||||
void output(Blip_Buffer *);
|
||||
enum { osc_count = 6 };
|
||||
enum
|
||||
{
|
||||
osc_count = 6
|
||||
};
|
||||
void osc_output(int index, Blip_Buffer *);
|
||||
void end_frame(nes_time_t);
|
||||
void save_snapshot(vrc7_snapshot_t *);
|
||||
|
@ -68,4 +72,3 @@ inline void Nes_Vrc7::osc_output( int i, Blip_Buffer* buf )
|
|||
{
|
||||
oscs[i].output = buf;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,10 +56,10 @@ if the origin of this software is not misrepresented.
|
|||
YM2143 data sheet
|
||||
|
||||
**************************************************************************************/
|
||||
#include "emu2413.hpp"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "emu2413.hpp"
|
||||
|
||||
static const unsigned char default_inst[15][8] = {
|
||||
/* 2019-03-19 VRC7 instrument patchset dumped by Nuke.YKT */
|
||||
|
@ -78,8 +78,7 @@ static const unsigned char default_inst[15][8] = {
|
|||
{0x71, 0x23, 0x11, 0x06, 0x65, 0x74, 0x18, 0x16},
|
||||
{0x01, 0x02, 0xD3, 0x05, 0xC9, 0x95, 0x03, 0x02},
|
||||
{0x61, 0x63, 0x0C, 0x00, 0x94, 0xC0, 0x33, 0xF6},
|
||||
{ 0x21, 0x72, 0x0D, 0x00, 0xC1, 0xD5, 0x56, 0x06 }
|
||||
};
|
||||
{0x21, 0x72, 0x0D, 0x00, 0xC1, 0xD5, 0x56, 0x06}};
|
||||
|
||||
#define EG2DB(d) ((d) * (e_int32)(EG_STEP / DB_STEP))
|
||||
#define TL2EG(d) ((d) * (e_int32)(TL_STEP / EG_STEP))
|
||||
|
@ -128,7 +127,15 @@ static const unsigned char default_inst[15][8] = {
|
|||
|
||||
/* Definition of envelope mode */
|
||||
enum
|
||||
{ SETTLE, ATTACK, DECAY, SUSHOLD, SUSTINE, RELEASE, FINISH };
|
||||
{
|
||||
SETTLE,
|
||||
ATTACK,
|
||||
DECAY,
|
||||
SUSHOLD,
|
||||
SUSTINE,
|
||||
RELEASE,
|
||||
FINISH
|
||||
};
|
||||
|
||||
/***************************************************
|
||||
|
||||
|
@ -153,7 +160,6 @@ static void makeAdjustTable (OPLL * opll)
|
|||
opll->AR_ADJUST_TABLE[i] = (e_uint16)((double)(1 << EG_BITS) - 1 - (1 << EG_BITS) * log((double)i) / log(128.));
|
||||
}
|
||||
|
||||
|
||||
/* Table for dB(0 -- (1<<DB_BITS)-1) to Liner(0 -- DB2LIN_AMP_WIDTH) */
|
||||
static void makeDB2LinTable(OPLL *opll)
|
||||
{
|
||||
|
@ -175,7 +181,6 @@ static e_int32 lin2db (double d)
|
|||
return Min(-(e_int32)(20.0 * log10(d) / DB_STEP), DB_MUTE - 1); /* 0 -- 127 */
|
||||
}
|
||||
|
||||
|
||||
/* Sin Table */
|
||||
static void makeSinTable(OPLL *opll)
|
||||
{
|
||||
|
@ -238,9 +243,7 @@ static void makeTllTable (OPLL *opll)
|
|||
#define dB2(x) ((x)*2)
|
||||
|
||||
static const double kltable[16] = {
|
||||
dB2 (0.000), dB2 (9.000), dB2 (12.000), dB2 (13.875), dB2 (15.000), dB2 (16.125), dB2 (16.875), dB2 (17.625),
|
||||
dB2 (18.000), dB2 (18.750), dB2 (19.125), dB2 (19.500), dB2 (19.875), dB2 (20.250), dB2 (20.625), dB2 (21.000)
|
||||
};
|
||||
dB2(0.000), dB2(9.000), dB2(12.000), dB2(13.875), dB2(15.000), dB2(16.125), dB2(16.875), dB2(17.625), dB2(18.000), dB2(18.750), dB2(19.125), dB2(19.500), dB2(19.875), dB2(20.250), dB2(20.625), dB2(21.000)};
|
||||
|
||||
e_int32 tmp;
|
||||
e_int32 fnum, block, TL, KL;
|
||||
|
@ -282,8 +285,7 @@ static const double attacktime[16][4] = {
|
|||
{0.84, 0.70, 0.60, 0.54},
|
||||
{0.50, 0.42, 0.34, 0.30},
|
||||
{0.28, 0.22, 0.18, 0.14},
|
||||
{0.00, 0.00, 0.00, 0.00}
|
||||
};
|
||||
{0.00, 0.00, 0.00, 0.00}};
|
||||
|
||||
static const double decaytime[16][4] = {
|
||||
{0, 0, 0, 0},
|
||||
|
@ -301,8 +303,7 @@ static const double decaytime[16][4] = {
|
|||
{10.22, 8.21, 6.84, 5.87},
|
||||
{5.11, 4.10, 3.42, 2.94},
|
||||
{2.55, 2.05, 1.71, 1.47},
|
||||
{1.27, 1.27, 1.27, 1.27}
|
||||
};
|
||||
{1.27, 1.27, 1.27, 1.27}};
|
||||
#endif
|
||||
|
||||
/* Rate Table for Attack */
|
||||
|
@ -321,7 +322,6 @@ static void makeDphaseARTable(OPLL * opll)
|
|||
attacktable[RM][RL] = EG_DP_WIDTH;
|
||||
else
|
||||
attacktable[RM][RL] = (e_uint32)((double)(1 << EG_DP_BITS) / (attacktime[RM][RL] * 3579545 / 72000));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -392,7 +392,6 @@ static void makeDphaseDRTable (OPLL * opll)
|
|||
|
||||
static void makeRksTable(OPLL *opll)
|
||||
{
|
||||
|
||||
e_int32 fnum8, block, KR;
|
||||
|
||||
for (fnum8 = 0; fnum8 < 2; fnum8++)
|
||||
|
@ -414,7 +413,6 @@ static void makeRksTable (OPLL *opll)
|
|||
|
||||
INLINE static e_uint32 calc_eg_dphase(OPLL *opll, OPLL_SLOT *slot)
|
||||
{
|
||||
|
||||
switch (slot->eg_mode)
|
||||
{
|
||||
case ATTACK:
|
||||
|
@ -453,9 +451,7 @@ INLINE static e_uint32 calc_eg_dphase (OPLL *opll, OPLL_SLOT * slot)
|
|||
|
||||
#define UPDATE_PG(S) (S)->dphase = opll->dphaseTable[(S)->fnum][(S)->block][(S)->patch.ML]
|
||||
#define UPDATE_TLL(S) \
|
||||
(((S)->type==0)?\
|
||||
((S)->tll = opll->tllTable[((S)->fnum)>>5][(S)->block][(S)->patch.TL][(S)->patch.KL]):\
|
||||
((S)->tll = opll->tllTable[((S)->fnum)>>5][(S)->block][(S)->volume][(S)->patch.KL]))
|
||||
(((S)->type == 0) ? ((S)->tll = opll->tllTable[((S)->fnum) >> 5][(S)->block][(S)->patch.TL][(S)->patch.KL]) : ((S)->tll = opll->tllTable[((S)->fnum) >> 5][(S)->block][(S)->volume][(S)->patch.KL]))
|
||||
#define UPDATE_RKS(S) (S)->rks = opll->rksTable[((S)->fnum) >> 8][(S)->block][(S)->patch.KR]
|
||||
#define UPDATE_WF(S) (S)->sintbl = opll->waveform[(S)->patch.WF]
|
||||
#define UPDATE_EG(S) (S)->eg_dphase = calc_eg_dphase(opll, S)
|
||||
|
@ -466,7 +462,6 @@ INLINE static e_uint32 calc_eg_dphase (OPLL *opll, OPLL_SLOT * slot)
|
|||
UPDATE_WF(S); \
|
||||
UPDATE_EG(S) /* EG should be updated last. */
|
||||
|
||||
|
||||
/* Slot key on */
|
||||
INLINE static void slotOn(OPLL_SLOT *slot)
|
||||
{
|
||||
|
@ -607,7 +602,6 @@ OPLL *OPLL_new (e_uint32 clk)
|
|||
return opll;
|
||||
}
|
||||
|
||||
|
||||
void OPLL_delete(OPLL *opll)
|
||||
{
|
||||
free(opll);
|
||||
|
@ -690,8 +684,6 @@ void OPLL_forceRefresh (OPLL * opll)
|
|||
#define wave2_8pi(e) ((e) << (2 + PG_BITS - SLOT_AMP_BITS))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Update AM, PM unit */
|
||||
static void update_ampm(OPLL *opll)
|
||||
{
|
||||
|
@ -721,15 +713,12 @@ static void calc_envelope(OPLL *opll, OPLL_SLOT * slot, e_int32 lfo)
|
|||
#define S2E(x) (SL2EG((e_int32)(x / SL_STEP)) << (EG_DP_BITS - EG_BITS))
|
||||
|
||||
static const e_uint32 SL[16] = {
|
||||
S2E (0.0), S2E (3.0), S2E (6.0), S2E (9.0), S2E (12.0), S2E (15.0), S2E (18.0), S2E (21.0),
|
||||
S2E (24.0), S2E (27.0), S2E (30.0), S2E (33.0), S2E (36.0), S2E (39.0), S2E (42.0), S2E (48.0)
|
||||
};
|
||||
S2E(0.0), S2E(3.0), S2E(6.0), S2E(9.0), S2E(12.0), S2E(15.0), S2E(18.0), S2E(21.0), S2E(24.0), S2E(27.0), S2E(30.0), S2E(33.0), S2E(36.0), S2E(39.0), S2E(42.0), S2E(48.0)};
|
||||
|
||||
e_uint32 egout;
|
||||
|
||||
switch (slot->eg_mode)
|
||||
{
|
||||
|
||||
case ATTACK:
|
||||
egout = opll->AR_ADJUST_TABLE[HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS)];
|
||||
slot->eg_phase += slot->eg_dphase;
|
||||
|
@ -843,7 +832,6 @@ INLINE static e_int32 calc_slot_mod(OPLL *opll, OPLL_SLOT * slot)
|
|||
slot->feedback = (slot->output[1] + slot->output[0]) >> 1;
|
||||
|
||||
return slot->feedback;
|
||||
|
||||
}
|
||||
|
||||
static INLINE e_int16 calc(OPLL *opll)
|
||||
|
@ -989,10 +977,8 @@ static void setInstrument(OPLL * opll, e_uint i, e_uint inst)
|
|||
carp->RR = (src[7] & 0xF);
|
||||
}
|
||||
|
||||
|
||||
void OPLL_writeReg(OPLL *opll, e_uint32 reg, e_uint32 data)
|
||||
{
|
||||
|
||||
e_int32 i, v, ch;
|
||||
|
||||
data = data & 0xff;
|
||||
|
@ -1152,7 +1138,6 @@ void OPLL_writeReg (OPLL * opll, e_uint32 reg, e_uint32 data)
|
|||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ typedef unsigned int e_uint32;
|
|||
#define SL_BITS 4
|
||||
#define SL_MUTE (1 << SL_BITS)
|
||||
|
||||
|
||||
/* Bits for Pitch and Amp modulator */
|
||||
#define PM_PG_BITS 8
|
||||
#define PM_PG_WIDTH (1 << PM_PG_BITS)
|
||||
|
@ -51,7 +50,6 @@ typedef unsigned int e_uint32;
|
|||
#define AM_DP_BITS 16
|
||||
#define AM_DP_WIDTH (1 << AM_DP_BITS)
|
||||
|
||||
|
||||
#ifdef EMU2413_DLL_EXPORTS
|
||||
#define EMU2413_API __declspec(dllexport)
|
||||
#elif defined(EMU2413_DLL_IMPORTS)
|
||||
|
@ -61,21 +59,26 @@ typedef unsigned int e_uint32;
|
|||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
|
||||
enum {OPLL_VRC7_TONE=0} ;
|
||||
enum
|
||||
{
|
||||
OPLL_VRC7_TONE = 0
|
||||
};
|
||||
|
||||
/* voice data */
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
e_uint32 TL, FB, EG, ML, AR, DR, SL, RR, KR, KL, AM, PM, WF;
|
||||
} OPLL_PATCH;
|
||||
|
||||
/* slot */
|
||||
typedef struct {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
OPLL_PATCH patch;
|
||||
|
||||
e_int32 type; /* 0 : modulator 1 : carrier */
|
||||
|
@ -108,8 +111,8 @@ typedef struct {
|
|||
#define OPLL_MASK_CH(x) (1 << (x))
|
||||
|
||||
/* opll */
|
||||
typedef struct {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
e_uint32 adr;
|
||||
e_int32 out;
|
||||
|
||||
|
@ -213,4 +216,3 @@ EMU2413_API e_uint32 OPLL_toggleMask(OPLL *, e_uint32 mask) ;
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <stdint.h>
|
||||
#include "emu2413_state.hpp"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
@ -34,15 +34,19 @@ void OPLL_serialize(const OPLL * opll, OPLL_STATE* state)
|
|||
}
|
||||
}
|
||||
|
||||
#define BYTESWAP(xxxx) {uint32_t _temp = (uint32_t)(xxxx);\
|
||||
#define BYTESWAP(xxxx) \
|
||||
{ \
|
||||
uint32_t _temp = (uint32_t)(xxxx); \
|
||||
((uint8_t *)&(xxxx))[0] = (uint8_t)((_temp) >> 24); \
|
||||
((uint8_t *)&(xxxx))[1] = (uint8_t)((_temp) >> 16); \
|
||||
((uint8_t *)&(xxxx))[2] = (uint8_t)((_temp) >> 8); \
|
||||
((uint8_t *)&(xxxx))[3] = (uint8_t)((_temp) >> 0); \
|
||||
}
|
||||
|
||||
|
||||
#define SET(xxxx,yyyy) { if ((xxxx) != (yyyy)) {\
|
||||
#define SET(xxxx, yyyy) \
|
||||
{ \
|
||||
if ((xxxx) != (yyyy)) \
|
||||
{ \
|
||||
(xxxx) = (yyyy); \
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
#include "emu2413.hpp"
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
e_int32 feedback;
|
||||
e_int32 output[2];
|
||||
e_uint32 phase;
|
||||
|
@ -13,7 +14,8 @@ typedef struct {
|
|||
e_uint32 egout;
|
||||
} OPLL_SLOT_STATE;
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
e_uint32 pm_phase;
|
||||
e_int32 am_phase;
|
||||
OPLL_SLOT_STATE slot[6 * 2];
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <cstring>
|
||||
#include "mappers/mapper.hpp"
|
||||
#include "Nes_Core.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/* 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
|
||||
|
@ -209,7 +209,6 @@ void Nes_Mapper::mirror_manual( int page0, int page1, int page2, int page3 )
|
|||
emu().ppu.set_nt_banks(page0, page1, page2, page3);
|
||||
}
|
||||
|
||||
|
||||
void Nes_Mapper::intercept_reads(nes_addr_t addr, unsigned size)
|
||||
{
|
||||
emu().add_mapper_intercept(addr, size, true, false);
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
// NES mapper interface
|
||||
// Nes_Emu 0.7.0
|
||||
|
||||
#include <climits>
|
||||
#include "Nes_Cart.hpp"
|
||||
#include "Nes_Cpu.hpp"
|
||||
#include <climits>
|
||||
|
||||
class Blip_Buffer;
|
||||
class blip_eq_t;
|
||||
|
@ -17,7 +17,8 @@ static unsigned const max_mapper_state_size = 512; //was 256, needed more for
|
|||
struct mapper_state_t
|
||||
{
|
||||
int size;
|
||||
union {
|
||||
union
|
||||
{
|
||||
double align;
|
||||
uint8_t data[max_mapper_state_size];
|
||||
};
|
||||
|
@ -26,7 +27,8 @@ struct mapper_state_t
|
|||
int read(void *p, unsigned long s) const;
|
||||
};
|
||||
|
||||
class Nes_Mapper {
|
||||
class Nes_Mapper
|
||||
{
|
||||
public:
|
||||
virtual ~Nes_Mapper();
|
||||
|
||||
|
@ -53,7 +55,10 @@ public:
|
|||
// Timing
|
||||
|
||||
// Time returned when current mapper state won't ever cause an IRQ
|
||||
enum { no_irq = LONG_MAX / 2 };
|
||||
enum
|
||||
{
|
||||
no_irq = LONG_MAX / 2
|
||||
};
|
||||
|
||||
// Time next IRQ will occur at
|
||||
virtual nes_time_t next_irq(nes_time_t present);
|
||||
|
@ -108,7 +113,8 @@ protected:
|
|||
void intercept_reads(nes_addr_t addr, unsigned size);
|
||||
|
||||
// Bank sizes for mapping
|
||||
enum bank_size_t { // 1 << bank_Xk = X * 1024
|
||||
enum bank_size_t
|
||||
{ // 1 << bank_Xk = X * 1024
|
||||
bank_1k = 10,
|
||||
bank_2k = 11,
|
||||
bank_4k = 12,
|
||||
|
@ -119,7 +125,10 @@ protected:
|
|||
|
||||
// Index of last PRG/CHR bank. Last_bank selects last bank, last_bank - 1
|
||||
// selects next-to-last bank, etc.
|
||||
enum { last_bank = -1 };
|
||||
enum
|
||||
{
|
||||
last_bank = -1
|
||||
};
|
||||
|
||||
// Map 'size' bytes from 'PRG + bank * size' to CPU address space starting at 'addr'
|
||||
void set_prg_bank(nes_addr_t addr, bank_size_t size, int bank);
|
||||
|
@ -163,15 +172,12 @@ protected:
|
|||
// apply_mapping().
|
||||
virtual void read_state(mapper_state_t const &);
|
||||
|
||||
|
||||
|
||||
// Called by default reset() before apply_mapping() is called.
|
||||
virtual void reset_state() {}
|
||||
|
||||
// End of general interface
|
||||
|
||||
public:
|
||||
|
||||
Nes_Cart const *cart_;
|
||||
Nes_Core *emu_;
|
||||
|
||||
|
@ -184,7 +190,6 @@ protected:
|
|||
static Nes_Mapper *getMapperFromCode(const int mapperCode);
|
||||
};
|
||||
|
||||
|
||||
inline int Nes_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 Nes_Mapper::mirror_vert(int p) { mirror_manual(p, p ^ 1, p, p ^ 1); }
|
||||
|
|
|
@ -19,7 +19,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// NROM
|
||||
|
||||
class Mapper000 : public Nes_Mapper {
|
||||
class Mapper000 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper000() {}
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ struct mmc1_state_t
|
|||
};
|
||||
static_assert(sizeof(mmc1_state_t) == 6);
|
||||
|
||||
class Mapper001 : public Nes_Mapper, mmc1_state_t {
|
||||
class Mapper001 : public Nes_Mapper, mmc1_state_t
|
||||
{
|
||||
public:
|
||||
Mapper001()
|
||||
{
|
||||
|
@ -75,7 +76,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void register_changed(int reg)
|
||||
{
|
||||
// Mirroring
|
||||
|
@ -122,5 +122,3 @@ public:
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -19,8 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// UNROM
|
||||
|
||||
class Mapper002 : public Nes_Mapper {
|
||||
class Mapper002 : public Nes_Mapper
|
||||
{
|
||||
uint8_t bank;
|
||||
|
||||
public:
|
||||
Mapper002()
|
||||
{
|
||||
|
@ -39,4 +41,3 @@ public:
|
|||
set_prg_bank(0x8000, bank_16k, data);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,8 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// CNROM
|
||||
|
||||
class Mapper003 : public Nes_Mapper {
|
||||
class Mapper003 : public Nes_Mapper
|
||||
{
|
||||
uint8_t bank;
|
||||
|
||||
public:
|
||||
Mapper003()
|
||||
{
|
||||
|
@ -38,4 +40,3 @@ public:
|
|||
set_chr_bank(0, bank_8k, bank & 7);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#include "mappers/mapper.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include "Nes_Core.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/* 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
|
||||
|
@ -39,7 +39,8 @@ struct mmc3_state_t
|
|||
};
|
||||
static_assert(sizeof(mmc3_state_t) == 15);
|
||||
|
||||
class Mapper004 : public Nes_Mapper, mmc3_state_t {
|
||||
class Mapper004 : public Nes_Mapper, mmc3_state_t
|
||||
{
|
||||
public:
|
||||
Mapper004()
|
||||
{
|
||||
|
@ -92,7 +93,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void a12_clocked()
|
||||
{
|
||||
clock_counter();
|
||||
|
@ -196,7 +196,8 @@ public:
|
|||
{
|
||||
switch (addr & 0xE001)
|
||||
{
|
||||
case 0x8000: {
|
||||
case 0x8000:
|
||||
{
|
||||
int changed = mode ^ data;
|
||||
mode = data;
|
||||
// avoid unnecessary bank updates
|
||||
|
@ -207,7 +208,8 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
case 0x8001: {
|
||||
case 0x8001:
|
||||
{
|
||||
int bank = mode & 7;
|
||||
banks[bank] = data;
|
||||
if (bank < 6)
|
||||
|
@ -249,4 +251,3 @@ public:
|
|||
nes_time_t next_time;
|
||||
int counter_just_clocked; // used only for debugging
|
||||
};
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <cstring>
|
||||
#include "mappers/mapper.hpp"
|
||||
#include "Nes_Core.hpp"
|
||||
#include "mappers/mapper.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/* 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
|
||||
|
@ -21,7 +21,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
struct mmc5_state_t
|
||||
{
|
||||
enum { reg_count = 0x30 };
|
||||
enum
|
||||
{
|
||||
reg_count = 0x30
|
||||
};
|
||||
uint8_t regs[0x30];
|
||||
uint8_t irq_enabled;
|
||||
};
|
||||
|
@ -29,7 +32,8 @@ static_assert( sizeof (mmc5_state_t) == 0x31 );
|
|||
|
||||
// MMC5
|
||||
|
||||
class Mapper005 : public Nes_Mapper, mmc5_state_t {
|
||||
class Mapper005 : public Nes_Mapper, mmc5_state_t
|
||||
{
|
||||
public:
|
||||
Mapper005()
|
||||
{
|
||||
|
@ -54,7 +58,10 @@ public:
|
|||
irq_time = no_irq;
|
||||
}
|
||||
|
||||
enum { regs_addr = 0x5100 };
|
||||
enum
|
||||
{
|
||||
regs_addr = 0x5100
|
||||
};
|
||||
|
||||
virtual nes_time_t next_irq(nes_time_t)
|
||||
{
|
||||
|
@ -73,8 +80,7 @@ public:
|
|||
switch (reg)
|
||||
{
|
||||
case 0x05:
|
||||
mirror_manual( data & 3, data >> 2 & 3,
|
||||
data >> 4 & 3, data >> 6 & 3 );
|
||||
mirror_manual(data & 3, data >> 2 & 3, data >> 4 & 3, data >> 6 & 3);
|
||||
break;
|
||||
|
||||
case 0x15:
|
||||
|
@ -128,10 +134,7 @@ public:
|
|||
void apply_mapping()
|
||||
{
|
||||
static unsigned char list[] = {
|
||||
0x05, 0x15, 0x16, 0x17,
|
||||
0x20, 0x21, 0x22, 0x23,
|
||||
0x28, 0x29, 0x2a, 0x2b
|
||||
};
|
||||
0x05, 0x15, 0x16, 0x17, 0x20, 0x21, 0x22, 0x23, 0x28, 0x29, 0x2a, 0x2b};
|
||||
|
||||
for (int i = 0; i < (int)sizeof list; i++)
|
||||
write_intercepted(0, regs_addr + list[i], regs[list[i]]);
|
||||
|
@ -142,6 +145,3 @@ public:
|
|||
|
||||
nes_time_t irq_time;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,8 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// AOROM
|
||||
|
||||
class Mapper007 : public Nes_Mapper {
|
||||
class Mapper007 : public Nes_Mapper
|
||||
{
|
||||
uint8_t bank;
|
||||
|
||||
public:
|
||||
Mapper007()
|
||||
{
|
||||
|
@ -46,5 +48,3 @@ public:
|
|||
set_prg_bank(0x8000, bank_32k, bank & 7);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include "mappers/mapper.hpp"
|
||||
#include <cstring>
|
||||
|
||||
// MMC2
|
||||
|
||||
|
@ -47,13 +47,30 @@ public:
|
|||
{
|
||||
switch (addr >> 12)
|
||||
{
|
||||
case 0xa: regs[0] = data; set_prg_bank(0x8000, bank_8k, data); break;
|
||||
case 0xb: regs[1] = data; set_chr_bank(0x0000, bank_4k, data); break;
|
||||
case 0xc: regs[2] = data; set_chr_bank_ex(0x0000, bank_4k, data); break;
|
||||
case 0xd: regs[3] = data; set_chr_bank(0x1000, bank_4k, data); break;
|
||||
case 0xe: regs[4] = data; set_chr_bank_ex(0x1000, bank_4k, data); break;
|
||||
case 0xf: regs[5] = data; mirror(data); break;
|
||||
case 0xa:
|
||||
regs[0] = data;
|
||||
set_prg_bank(0x8000, bank_8k, data);
|
||||
break;
|
||||
case 0xb:
|
||||
regs[1] = data;
|
||||
set_chr_bank(0x0000, bank_4k, data);
|
||||
break;
|
||||
case 0xc:
|
||||
regs[2] = data;
|
||||
set_chr_bank_ex(0x0000, bank_4k, data);
|
||||
break;
|
||||
case 0xd:
|
||||
regs[3] = data;
|
||||
set_chr_bank(0x1000, bank_4k, data);
|
||||
break;
|
||||
case 0xe:
|
||||
regs[4] = data;
|
||||
set_chr_bank_ex(0x1000, bank_4k, data);
|
||||
break;
|
||||
case 0xf:
|
||||
regs[5] = data;
|
||||
mirror(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include <cstring>
|
||||
#include "mappers/mapper.hpp"
|
||||
#include <cstring>
|
||||
|
||||
// MMC4
|
||||
|
||||
|
@ -45,12 +45,30 @@ public:
|
|||
{
|
||||
switch (addr >> 12)
|
||||
{
|
||||
case 0xa: regs[0] = data; set_prg_bank(0x8000, bank_16k, data); break;
|
||||
case 0xb: regs[1] = data; set_chr_bank(0x0000, bank_4k, data); break;
|
||||
case 0xc: regs[2] = data; set_chr_bank_ex(0x0000, bank_4k, data); break;
|
||||
case 0xd: regs[3] = data; set_chr_bank(0x1000, bank_4k, data); break;
|
||||
case 0xe: regs[4] = data; set_chr_bank_ex(0x1000, bank_4k, data); break;
|
||||
case 0xf: regs[5] = data; mirror(data); break;
|
||||
case 0xa:
|
||||
regs[0] = data;
|
||||
set_prg_bank(0x8000, bank_16k, data);
|
||||
break;
|
||||
case 0xb:
|
||||
regs[1] = data;
|
||||
set_chr_bank(0x0000, bank_4k, data);
|
||||
break;
|
||||
case 0xc:
|
||||
regs[2] = data;
|
||||
set_chr_bank_ex(0x0000, bank_4k, data);
|
||||
break;
|
||||
case 0xd:
|
||||
regs[3] = data;
|
||||
set_chr_bank(0x1000, bank_4k, data);
|
||||
break;
|
||||
case 0xe:
|
||||
regs[4] = data;
|
||||
set_chr_bank_ex(0x1000, bank_4k, data);
|
||||
break;
|
||||
case 0xf:
|
||||
regs[5] = data;
|
||||
mirror(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -19,8 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// Color Dreams
|
||||
|
||||
class Mapper011 : public Nes_Mapper {
|
||||
class Mapper011 : public Nes_Mapper
|
||||
{
|
||||
uint8_t bank;
|
||||
|
||||
public:
|
||||
Mapper011()
|
||||
{
|
||||
|
|
|
@ -29,7 +29,8 @@ static_assert( sizeof (Mapper015_state_t) == 5 );
|
|||
|
||||
// K-1029, K-1030P
|
||||
|
||||
class Mapper015 : public Nes_Mapper, Mapper015_state_t {
|
||||
class Mapper015 : public Nes_Mapper, Mapper015_state_t
|
||||
{
|
||||
public:
|
||||
Mapper015()
|
||||
{
|
||||
|
@ -89,4 +90,3 @@ public:
|
|||
|
||||
unsigned long int i;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "mappers/mapper.hpp"
|
||||
#include "apu/namco/apu.hpp"
|
||||
#include "mappers/mapper.hpp"
|
||||
|
||||
/* 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
|
||||
|
@ -32,7 +32,8 @@ static_assert( sizeof (namco106_state_t) == 20 + sizeof (namco_state_t) );
|
|||
|
||||
// Namco106
|
||||
|
||||
class Mapper019 : public Nes_Mapper, namco106_state_t {
|
||||
class Mapper019 : public Nes_Mapper, namco106_state_t
|
||||
{
|
||||
public:
|
||||
Mapper019()
|
||||
{
|
||||
|
@ -194,5 +195,3 @@ public:
|
|||
Nes_Namco_Apu sound;
|
||||
nes_time_t last_time;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ struct vrc2_state_t
|
|||
static_assert(sizeof(vrc2_state_t) == 18);
|
||||
|
||||
template <bool type_a, bool type_b>
|
||||
class Mapper_VRC2_4 : public Nes_Mapper, vrc2_state_t {
|
||||
class Mapper_VRC2_4 : public Nes_Mapper, vrc2_state_t
|
||||
{
|
||||
public:
|
||||
Mapper_VRC2_4()
|
||||
{
|
||||
|
@ -180,7 +181,10 @@ public:
|
|||
}
|
||||
|
||||
unsigned is22, reg1mask, reg2mask;
|
||||
enum { timer_period = 113 * 4 + 3 };
|
||||
enum
|
||||
{
|
||||
timer_period = 113 * 4 + 3
|
||||
};
|
||||
|
||||
private:
|
||||
void set_mirroring()
|
||||
|
@ -220,7 +224,8 @@ private:
|
|||
|
||||
template <bool type_a, bool type_b>
|
||||
void Mapper_VRC2_4<type_a, type_b>::write_irq(nes_time_t time,
|
||||
nes_addr_t addr, int data )
|
||||
nes_addr_t addr,
|
||||
int data)
|
||||
{
|
||||
// IRQ
|
||||
run_until(time);
|
||||
|
@ -246,5 +251,4 @@ void Mapper_VRC2_4<type_a, type_b>::write_irq( nes_time_t time,
|
|||
irq_changed();
|
||||
}
|
||||
|
||||
|
||||
typedef Mapper_VRC2_4<true, true> Mapper021;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
// Konami VRC6 mapper
|
||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <cstring>
|
||||
#include "mappers/mapper.hpp"
|
||||
#include "apu/vrc6/apu.hpp"
|
||||
#include "mappers/mapper.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/* 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
|
||||
|
@ -41,7 +41,8 @@ struct vrc6_state_t
|
|||
static_assert(sizeof(vrc6_state_t) == 26 + sizeof(vrc6_apu_state_t));
|
||||
|
||||
template <int swapMask>
|
||||
class Mapper_Vrc6 : public Nes_Mapper, vrc6_state_t {
|
||||
class Mapper_Vrc6 : public Nes_Mapper, vrc6_state_t
|
||||
{
|
||||
public:
|
||||
Mapper_Vrc6()
|
||||
{
|
||||
|
@ -136,8 +137,10 @@ public:
|
|||
}
|
||||
int swap_mask;
|
||||
Nes_Vrc6_Apu sound;
|
||||
enum { timer_period = 113 * 4 + 3 };
|
||||
|
||||
enum
|
||||
{
|
||||
timer_period = 113 * 4 + 3
|
||||
};
|
||||
|
||||
void read_state(mapper_state_t const &in)
|
||||
{
|
||||
|
@ -191,7 +194,8 @@ void write_bank( nes_addr_t addr, int data )
|
|||
set_prg_bank(0x8000, bank_16k, data);
|
||||
break;
|
||||
|
||||
case 0xb003: {
|
||||
case 0xb003:
|
||||
{
|
||||
mirroring = data;
|
||||
|
||||
// dprintf( "Change mirroring %d\n", data );
|
||||
|
@ -224,5 +228,4 @@ void write_bank( nes_addr_t addr, int data )
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
typedef Mapper_Vrc6<0> Mapper024;
|
|
@ -31,7 +31,8 @@
|
|||
|
||||
// Unrom512
|
||||
|
||||
class Mapper030 : public Nes_Mapper {
|
||||
class Mapper030 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper030() {}
|
||||
|
||||
|
@ -48,4 +49,3 @@ public:
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ static_assert( sizeof ( mapper32_state_t ) == 12 );
|
|||
|
||||
// Irem_G101
|
||||
|
||||
class Mapper032 : public Nes_Mapper, mapper32_state_t {
|
||||
class Mapper032 : public Nes_Mapper, mapper32_state_t
|
||||
{
|
||||
public:
|
||||
Mapper032()
|
||||
{
|
||||
|
@ -107,12 +108,17 @@ public:
|
|||
|
||||
switch (addr & 0xF007)
|
||||
{
|
||||
case 0xB000: case 0xB001: case 0xB002: case 0xB003:
|
||||
case 0xB004: case 0xB005: case 0xB006: case 0xB007:
|
||||
case 0xB000:
|
||||
case 0xB001:
|
||||
case 0xB002:
|
||||
case 0xB003:
|
||||
case 0xB004:
|
||||
case 0xB005:
|
||||
case 0xB006:
|
||||
case 0xB007:
|
||||
chr_bank[addr & 0x07] = data;
|
||||
set_chr_bank((addr & 0x07) << 10, bank_1k, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ static_assert( sizeof ( tc0190_state_t ) == 9 );
|
|||
|
||||
// TaitoTC0190
|
||||
|
||||
class Mapper033 : public Nes_Mapper, tc0190_state_t {
|
||||
class Mapper033 : public Nes_Mapper, tc0190_state_t
|
||||
{
|
||||
public:
|
||||
Mapper033()
|
||||
{
|
||||
|
@ -44,7 +45,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
@ -57,8 +59,10 @@ public:
|
|||
for (int i = 0; i < 4; i++)
|
||||
set_chr_bank(0x1000 + (i << 10), bank_1k, creg[2 + i]);
|
||||
|
||||
if ( mirr ) mirror_horiz();
|
||||
else mirror_vert();
|
||||
if (mirr)
|
||||
mirror_horiz();
|
||||
else
|
||||
mirror_vert();
|
||||
}
|
||||
|
||||
virtual void write(nes_time_t, nes_addr_t addr, int data)
|
||||
|
@ -69,20 +73,25 @@ public:
|
|||
preg[0] = data & 0x3F;
|
||||
mirr = data >> 6;
|
||||
set_prg_bank(0x8000, bank_8k, preg[0]);
|
||||
if ( mirr ) mirror_horiz();
|
||||
else mirror_vert();
|
||||
if (mirr)
|
||||
mirror_horiz();
|
||||
else
|
||||
mirror_vert();
|
||||
break;
|
||||
case 0x8001:
|
||||
preg[1] = data & 0x3F;
|
||||
set_prg_bank(0xA000, bank_8k, preg[1]);
|
||||
break;
|
||||
case 0x8002: case 0x8003:
|
||||
case 0x8002:
|
||||
case 0x8003:
|
||||
addr &= 0x01;
|
||||
creg[addr] = data;
|
||||
set_chr_bank(addr << 11, bank_2k, creg[addr]);
|
||||
break;
|
||||
case 0xA000: case 0xA001:
|
||||
case 0xA002: case 0xA003:
|
||||
case 0xA000:
|
||||
case 0xA001:
|
||||
case 0xA002:
|
||||
case 0xA003:
|
||||
addr &= 0x03;
|
||||
creg[2 + addr] = data;
|
||||
set_chr_bank(0x1000 | (addr << 10), bank_1k, creg[2 + addr]);
|
||||
|
|
|
@ -19,8 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// Nina-1 (Deadly Towers only)
|
||||
|
||||
class Mapper034 : public Nes_Mapper {
|
||||
class Mapper034 : public Nes_Mapper
|
||||
{
|
||||
uint8_t bank;
|
||||
|
||||
public:
|
||||
Mapper034()
|
||||
{
|
||||
|
@ -38,4 +40,3 @@ public:
|
|||
set_prg_bank(0x8000, bank_32k, bank);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
|
||||
// NROM-128 4-in-1 multicart
|
||||
|
||||
class Mapper060 : public Nes_Mapper {
|
||||
class Mapper060 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper060()
|
||||
{
|
||||
|
|
|
@ -19,8 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// GNROM
|
||||
|
||||
class Mapper066 : public Nes_Mapper {
|
||||
class Mapper066 : public Nes_Mapper
|
||||
{
|
||||
uint8_t bank;
|
||||
|
||||
public:
|
||||
Mapper066()
|
||||
{
|
||||
|
@ -46,4 +48,3 @@ public:
|
|||
set_chr_bank(0, bank_8k, bank & 3);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/libs/
|
||||
|
||||
#include "mappers/mapper.hpp"
|
||||
#include "apu/fme7/apu.hpp"
|
||||
#include "mappers/mapper.hpp"
|
||||
|
||||
/* Copyright (C) 2005 Chris Moeller */
|
||||
/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
|
||||
|
@ -34,7 +34,8 @@ static_assert( sizeof (fme7_state_t) == 18 + sizeof (fme7_apu_state_t) );
|
|||
|
||||
// Fme7
|
||||
|
||||
class Mapper069 : public Nes_Mapper, fme7_state_t {
|
||||
class Mapper069 : public Nes_Mapper, fme7_state_t
|
||||
{
|
||||
public:
|
||||
Mapper069()
|
||||
{
|
||||
|
@ -132,7 +133,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void write_irq(nes_time_t time, int index, int data)
|
||||
{
|
||||
run_until(time);
|
||||
|
@ -186,5 +186,3 @@ public:
|
|||
nes_time_t last_time;
|
||||
Nes_Fme7_Apu sound;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
// Mapper_74x161x162x32
|
||||
|
||||
template <int mapperId>
|
||||
class Mapper_74x161x162x32 : public Nes_Mapper {
|
||||
class Mapper_74x161x162x32 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper_74x161x162x32()
|
||||
{
|
||||
|
|
|
@ -19,8 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// Camerica
|
||||
|
||||
class Mapper071 : public Nes_Mapper {
|
||||
class Mapper071 : public Nes_Mapper
|
||||
{
|
||||
uint8_t regs[3];
|
||||
|
||||
public:
|
||||
Mapper071()
|
||||
{
|
||||
|
@ -48,7 +50,3 @@ public:
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ struct vrc3_state_t
|
|||
|
||||
// VRC3
|
||||
|
||||
class Mapper073 : public Nes_Mapper, vrc3_state_t {
|
||||
class Mapper073 : public Nes_Mapper, vrc3_state_t
|
||||
{
|
||||
public:
|
||||
Mapper073()
|
||||
{
|
||||
|
|
|
@ -30,7 +30,8 @@ static_assert( sizeof ( vrc1_state_t ) == 8 );
|
|||
|
||||
// VRC1
|
||||
|
||||
class Mapper075 : public Nes_Mapper, vrc1_state_t {
|
||||
class Mapper075 : public Nes_Mapper, vrc1_state_t
|
||||
{
|
||||
public:
|
||||
Mapper075()
|
||||
{
|
||||
|
@ -105,5 +106,3 @@ public:
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
// Holy Diver and Uchuusen - Cosmo Carrier.
|
||||
|
||||
class Mapper078 : public Nes_Mapper {
|
||||
class Mapper078 : public Nes_Mapper
|
||||
{
|
||||
// lower 8 bits are the reg at 8000:ffff
|
||||
// next two bits are autodetecting type
|
||||
// 0 = unknown 1 = cosmo carrier 2 = holy diver
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
#include "mappers/mapper.hpp"
|
||||
|
||||
template <bool multicart>
|
||||
class Mapper_AveNina : public Nes_Mapper {
|
||||
class Mapper_AveNina : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper_AveNina()
|
||||
{
|
||||
|
@ -82,8 +83,10 @@ void Mapper_AveNina< multicart >::write_regs()
|
|||
{
|
||||
set_prg_bank(0x8000, bank_32k, (regs >> 3) & 0x07);
|
||||
set_chr_bank(0x0000, bank_8k, ((regs >> 3) & 0x08) | (regs & 0x07));
|
||||
if ( regs & 0x80 ) mirror_vert();
|
||||
else mirror_horiz();
|
||||
if (regs & 0x80)
|
||||
mirror_vert();
|
||||
else
|
||||
mirror_horiz();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
// Nes_Emu 0.5.4. http://www.slack.net/~ant/
|
||||
|
||||
#include <cstring>
|
||||
#include "mappers/mapper.hpp"
|
||||
#include "apu/vrc7/apu.hpp"
|
||||
#include "mappers/mapper.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/* Copyright (C) 2004-2005 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
|
@ -37,7 +37,8 @@ static_assert( sizeof (vrc7_state_t) == 20 + sizeof (vrc7_snapshot_t) );
|
|||
|
||||
// Vrc7
|
||||
|
||||
class Mapper085 : public Nes_Mapper, vrc7_state_t {
|
||||
class Mapper085 : public Nes_Mapper, vrc7_state_t
|
||||
{
|
||||
public:
|
||||
Mapper085()
|
||||
{
|
||||
|
@ -194,7 +195,8 @@ public:
|
|||
{
|
||||
write_chr_bank(((addr >> 4) & 1) | (((addr - 0xa000) >> 11) & ~1), data);
|
||||
}
|
||||
else switch ( addr & 0xf010 )
|
||||
else
|
||||
switch (addr & 0xf010)
|
||||
{
|
||||
case 0x8000: write_prg_bank(0, data); break;
|
||||
case 0x8010: write_prg_bank(1, data); break;
|
||||
|
@ -205,13 +207,17 @@ public:
|
|||
break;
|
||||
|
||||
case 0x9010:
|
||||
if ( addr & 0x20 ) sound.write_data( time, data );
|
||||
else sound.write_reg( data );
|
||||
if (addr & 0x20)
|
||||
sound.write_data(time, data);
|
||||
else
|
||||
sound.write_reg(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Nes_Vrc7 sound;
|
||||
enum { timer_period = 113 * 4 + 3 };
|
||||
enum
|
||||
{
|
||||
timer_period = 113 * 4 + 3
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -18,8 +18,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// Jaleco/Konami/Taito
|
||||
|
||||
class Mapper087 : public Nes_Mapper {
|
||||
class Mapper087 : public Nes_Mapper
|
||||
{
|
||||
uint8_t bank;
|
||||
|
||||
public:
|
||||
Mapper087()
|
||||
{
|
||||
|
@ -44,4 +46,3 @@ public:
|
|||
|
||||
void write(nes_time_t, nes_addr_t, int) {}
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ struct namco_34x3_state_t
|
|||
static_assert(sizeof(namco_34x3_state_t) == 10);
|
||||
|
||||
template <bool _is154>
|
||||
class Mapper_Namco_34x3 : public Nes_Mapper, namco_34x3_state_t {
|
||||
class Mapper_Namco_34x3 : public Nes_Mapper, namco_34x3_state_t
|
||||
{
|
||||
public:
|
||||
Mapper_Namco_34x3()
|
||||
{
|
||||
|
@ -45,7 +46,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
@ -77,15 +79,20 @@ public:
|
|||
mode &= 0x07;
|
||||
switch (mode)
|
||||
{
|
||||
case 0: case 1:
|
||||
case 0:
|
||||
case 1:
|
||||
bank[mode] = data >> 1;
|
||||
set_chr_bank(0x0000 + (mode << 11), bank_2k, bank[mode]);
|
||||
break;
|
||||
case 2: case 3: case 4: case 5:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
bank[mode] = data | 0x40;
|
||||
set_chr_bank(0x1000 + ((mode - 2) << 10), bank_1k, bank[mode]);
|
||||
break;
|
||||
case 6: case 7:
|
||||
case 6:
|
||||
case 7:
|
||||
bank[mode] = data;
|
||||
set_prg_bank(0x8000 + ((mode - 6) << 13), bank_8k, bank[mode]);
|
||||
break;
|
||||
|
@ -101,7 +108,6 @@ public:
|
|||
|
||||
typedef Mapper_Namco_34x3<false> Mapper088;
|
||||
|
||||
|
||||
// void register_mapper_namco_34xx();
|
||||
// void register_mapper_namco_34xx()
|
||||
// {
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
// Sunsoft2b
|
||||
|
||||
class Mapper089 : public Nes_Mapper {
|
||||
class Mapper089 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper089()
|
||||
{
|
||||
|
@ -34,7 +35,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
// Sunsoft2a
|
||||
|
||||
class Mapper093 : public Nes_Mapper {
|
||||
class Mapper093 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper093()
|
||||
{
|
||||
|
@ -34,7 +35,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
|
||||
// Un1rom
|
||||
|
||||
class Mapper094 : public Nes_Mapper {
|
||||
class Mapper094 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper094()
|
||||
{
|
||||
|
@ -36,7 +37,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
// Irem_Tam_S1
|
||||
|
||||
class Mapper097 : public Nes_Mapper {
|
||||
class Mapper097 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper097()
|
||||
{
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
|
||||
// Jaleco_JF11
|
||||
|
||||
class Mapper140 : public Nes_Mapper {
|
||||
class Mapper140 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper140()
|
||||
{
|
||||
|
|
|
@ -11,7 +11,8 @@ struct m156_state_t
|
|||
};
|
||||
static_assert(sizeof(m156_state_t) == 9);
|
||||
|
||||
class Mapper156 : public Nes_Mapper, m156_state_t {
|
||||
class Mapper156 : public Nes_Mapper, m156_state_t
|
||||
{
|
||||
public:
|
||||
Mapper156()
|
||||
{
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
// UxROM (inverted)
|
||||
|
||||
class Mapper180 : public Nes_Mapper {
|
||||
class Mapper180 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper180()
|
||||
{
|
||||
|
@ -35,7 +36,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
// Sunsoft1
|
||||
|
||||
class Mapper184 : public Nes_Mapper {
|
||||
class Mapper184 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper184()
|
||||
{
|
||||
|
@ -34,7 +35,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
@ -56,8 +58,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void write(nes_time_t, nes_addr_t addr, int data)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t regs;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
// Magic Kid Googoo
|
||||
|
||||
class Mapper190: public Nes_Mapper {
|
||||
class Mapper190 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper190()
|
||||
{
|
||||
|
@ -52,4 +53,3 @@ public:
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
|
||||
// NTDEC's TC-112 mapper IC.
|
||||
|
||||
class Mapper193 : public Nes_Mapper {
|
||||
class Mapper193 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper193()
|
||||
{
|
||||
|
@ -37,7 +38,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
@ -50,7 +52,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void write(nes_time_t, nes_addr_t addr, int data)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool write_intercepted(nes_time_t, nes_addr_t addr, int data)
|
||||
{
|
||||
|
@ -71,4 +74,3 @@ public:
|
|||
|
||||
uint8_t regs[4];
|
||||
};
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@ static_assert( sizeof (namco_34xx_state_t) == 10 );
|
|||
|
||||
// Namco_34xx
|
||||
|
||||
class Mapper206 : public Nes_Mapper, namco_34xx_state_t {
|
||||
class Mapper206 : public Nes_Mapper, namco_34xx_state_t
|
||||
{
|
||||
public:
|
||||
Mapper206()
|
||||
{
|
||||
|
@ -46,7 +47,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
@ -72,15 +74,20 @@ public:
|
|||
mode &= 0x07;
|
||||
switch (mode)
|
||||
{
|
||||
case 0: case 1:
|
||||
case 0:
|
||||
case 1:
|
||||
bank[mode] = data >> 1;
|
||||
set_chr_bank(0x0000 + (mode << 11), bank_2k, bank[mode]);
|
||||
break;
|
||||
case 2: case 3: case 4: case 5:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
bank[mode] = data;
|
||||
set_chr_bank(0x1000 + ((mode - 2) << 10), bank_1k, bank[mode]);
|
||||
break;
|
||||
case 6: case 7:
|
||||
case 6:
|
||||
case 7:
|
||||
bank[mode] = data;
|
||||
set_prg_bank(0x8000 + ((mode - 6) << 13), bank_8k, bank[mode]);
|
||||
break;
|
||||
|
@ -89,4 +96,3 @@ public:
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ static_assert( sizeof (taito_x1005_state_t) == 11 );
|
|||
|
||||
// TaitoX1005
|
||||
|
||||
class Mapper207 : public Nes_Mapper, taito_x1005_state_t {
|
||||
class Mapper207 : public Nes_Mapper, taito_x1005_state_t
|
||||
{
|
||||
public:
|
||||
Mapper207()
|
||||
{
|
||||
|
@ -44,7 +45,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
@ -87,4 +89,3 @@ public:
|
|||
|
||||
virtual void write(nes_time_t, nes_addr_t addr, int data) {}
|
||||
};
|
||||
|
||||
|
|
|
@ -20,8 +20,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
// Quattro
|
||||
|
||||
class Mapper232 : public Nes_Mapper {
|
||||
class Mapper232 : public Nes_Mapper
|
||||
{
|
||||
uint8_t regs[2];
|
||||
|
||||
public:
|
||||
Mapper232()
|
||||
{
|
||||
|
@ -50,4 +52,3 @@ public:
|
|||
Mapper232::apply_mapping();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
// https://www.nesdev.org/wiki/INES_Mapper240
|
||||
|
||||
class Mapper240 : public Nes_Mapper {
|
||||
class Mapper240 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper240()
|
||||
{
|
||||
|
@ -44,7 +45,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void write(nes_time_t, nes_addr_t, int data)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool write_intercepted(nes_time_t, nes_addr_t addr, int data)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
// https://www.nesdev.org/wiki/INES_Mapper241
|
||||
|
||||
class Mapper241 : public Nes_Mapper {
|
||||
class Mapper241 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper241()
|
||||
{
|
||||
|
@ -33,7 +34,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
|
|
@ -34,7 +34,8 @@ struct mapper244_state_t
|
|||
};
|
||||
static_assert(sizeof(mapper244_state_t) == 2);
|
||||
|
||||
class Mapper244 : public Nes_Mapper, mapper244_state_t {
|
||||
class Mapper244 : public Nes_Mapper, mapper244_state_t
|
||||
{
|
||||
public:
|
||||
Mapper244()
|
||||
{
|
||||
|
@ -43,7 +44,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
// https://www.nesdev.org/wiki/INES_Mapper246
|
||||
|
||||
class Mapper246 : public Nes_Mapper {
|
||||
class Mapper246 : public Nes_Mapper
|
||||
{
|
||||
public:
|
||||
Mapper246()
|
||||
{
|
||||
|
@ -48,7 +49,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void write(nes_time_t, nes_addr_t addr, int data)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool write_intercepted(nes_time_t, nes_addr_t addr, int data)
|
||||
{
|
||||
|
@ -71,4 +73,3 @@ public:
|
|||
|
||||
uint8_t regs[8];
|
||||
};
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <cstring>
|
||||
#include "Nes_Ppu.hpp"
|
||||
#include "Nes_Core.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/* 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
|
||||
|
@ -234,8 +234,7 @@ inline int Nes_Ppu_Impl::first_opaque_sprite_line()
|
|||
}
|
||||
|
||||
p += 8;
|
||||
}
|
||||
while ( !--twice );
|
||||
} while (!--twice);
|
||||
return line;
|
||||
}
|
||||
|
||||
|
@ -323,8 +322,7 @@ int Nes_Ppu::read_2002( nes_time_t time )
|
|||
query_until(time);
|
||||
|
||||
next_status_event = next_sprite_hit_check;
|
||||
nes_time_t const next_max = fixed_sprite_max_time ?
|
||||
fixed_sprite_max_time : next_sprite_max_run;
|
||||
nes_time_t const next_max = fixed_sprite_max_time ? fixed_sprite_max_time : next_sprite_max_run;
|
||||
if (next_status_event > next_max)
|
||||
next_status_event = next_max;
|
||||
|
||||
|
@ -408,7 +406,8 @@ int Nes_Ppu::read( unsigned addr, nes_time_t time )
|
|||
return read_2002(time);
|
||||
|
||||
// sprite ram
|
||||
case 4: {
|
||||
case 4:
|
||||
{
|
||||
int result = spr_ram[w2003];
|
||||
if ((w2003 & 3) == 2)
|
||||
result &= 0xe3;
|
||||
|
@ -417,7 +416,8 @@ int Nes_Ppu::read( unsigned addr, nes_time_t time )
|
|||
}
|
||||
|
||||
// video ram
|
||||
case 7: {
|
||||
case 7:
|
||||
{
|
||||
render_bg_until(time);
|
||||
int addr = vram_addr;
|
||||
int new_addr = addr + addr_inc;
|
||||
|
@ -448,7 +448,8 @@ void Nes_Ppu::write( nes_time_t time, unsigned addr, int data )
|
|||
{
|
||||
switch (addr & 7)
|
||||
{
|
||||
case 0:{// control
|
||||
case 0:
|
||||
{ // control
|
||||
int changed = w2000 ^ data;
|
||||
|
||||
if (changed & 0x28)
|
||||
|
@ -483,7 +484,8 @@ void Nes_Ppu::write( nes_time_t time, unsigned addr, int data )
|
|||
break;
|
||||
}
|
||||
|
||||
case 1:{// sprites, bg enable
|
||||
case 1:
|
||||
{ // sprites, bg enable
|
||||
int changed = w2001 ^ data;
|
||||
|
||||
if (changed & 0xE1)
|
||||
|
|
|
@ -14,8 +14,10 @@ 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
|
||||
|
||||
class Nes_Ppu : public Nes_Ppu_Rendering {
|
||||
class Nes_Ppu : public Nes_Ppu_Rendering
|
||||
{
|
||||
typedef Nes_Ppu_Rendering base;
|
||||
|
||||
public:
|
||||
Nes_Ppu(Nes_Core *);
|
||||
|
||||
|
@ -44,10 +46,12 @@ public:
|
|||
int burst_phase;
|
||||
|
||||
private:
|
||||
|
||||
Nes_Core &emu;
|
||||
|
||||
enum { indefinite_time = LONG_MAX / 2 + 1 };
|
||||
enum
|
||||
{
|
||||
indefinite_time = LONG_MAX / 2 + 1
|
||||
};
|
||||
|
||||
void suspend_rendering();
|
||||
int read_(unsigned addr, nes_time_t); // note swapped arguments!
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <cstring>
|
||||
#include "Nes_Ppu_Impl.hpp"
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include "Nes_Ppu_Impl.hpp"
|
||||
#include <cstring>
|
||||
|
||||
/* 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
|
||||
|
@ -18,7 +18,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
||||
int const cache_line_size = 128; // tile cache is kept aligned to this boundary
|
||||
|
||||
inline void set_be32( void* p, unsigned long n ) {
|
||||
inline void set_be32(void *p, unsigned long n)
|
||||
{
|
||||
((unsigned char *)p)[0] = (unsigned char)(n >> 24);
|
||||
((unsigned char *)p)[1] = (unsigned char)(n >> 16);
|
||||
((unsigned char *)p)[2] = (unsigned char)(n >> 8);
|
||||
|
@ -41,7 +42,6 @@ Nes_Ppu_Impl::Nes_Ppu_Impl()
|
|||
mmc24_enabled = false;
|
||||
mmc24_latched[0] = 0;
|
||||
mmc24_latched[1] = 0;
|
||||
|
||||
}
|
||||
|
||||
Nes_Ppu_Impl::~Nes_Ppu_Impl()
|
||||
|
@ -143,9 +143,7 @@ void Nes_Ppu_Impl::set_chr_bank_ex( int addr, int size, long data )
|
|||
|
||||
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)
|
||||
{
|
||||
|
@ -304,14 +302,11 @@ void Nes_Ppu_Impl::update_tiles( int first_tile )
|
|||
if (modified & 1)
|
||||
update_tile(index);
|
||||
index++;
|
||||
} while ((modified >>= 1) != 0);
|
||||
}
|
||||
while ( (modified >>= 1) != 0 );
|
||||
} while (++chunk & 3);
|
||||
}
|
||||
}
|
||||
while ( ++chunk & 3 );
|
||||
}
|
||||
}
|
||||
while ( chunk < chr_tile_count / 8 );
|
||||
} while (chunk < chr_tile_count / 8);
|
||||
}
|
||||
|
||||
// Sprite max
|
||||
|
@ -428,8 +423,7 @@ long Nes_Ppu_Impl::recalc_sprite_max( int scanline )
|
|||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
while ( i < 0x100 );
|
||||
} while (i < 0x100);
|
||||
scanline++;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
struct ppu_state_t
|
||||
{
|
||||
uint8_t w2000; // control
|
||||
|
@ -26,7 +25,8 @@ struct ppu_state_t
|
|||
};
|
||||
static_assert(sizeof(ppu_state_t) == 20 + 0x20);
|
||||
|
||||
class Nes_Ppu_Impl : public ppu_state_t {
|
||||
class Nes_Ppu_Impl : public ppu_state_t
|
||||
{
|
||||
public:
|
||||
Nes_Ppu_Impl();
|
||||
~Nes_Ppu_Impl();
|
||||
|
@ -43,7 +43,10 @@ public:
|
|||
static const uint16_t image_left = 8;
|
||||
static const uint16_t buffer_width = image_width + 16;
|
||||
static const uint16_t buffer_height = image_height;
|
||||
enum { spr_ram_size = 0x100 };
|
||||
enum
|
||||
{
|
||||
spr_ram_size = 0x100
|
||||
};
|
||||
|
||||
uint8_t *nt_banks[4];
|
||||
bool chr_is_writable;
|
||||
|
@ -75,7 +78,8 @@ public:
|
|||
{
|
||||
uint8_t nt_ram[nt_ram_size];
|
||||
uint8_t chr_ram[chr_addr_size];
|
||||
union {
|
||||
union
|
||||
{
|
||||
uint32_t clip_buf[256 * 2];
|
||||
uint8_t mini_offscreen[buffer_width * mini_offscreen_height];
|
||||
};
|
||||
|
@ -88,14 +92,13 @@ public:
|
|||
uint16_t getSpriteRAMSize() { return spr_ram_size; }
|
||||
uint8_t spr_ram[spr_ram_size];
|
||||
void all_tiles_modified();
|
||||
protected:
|
||||
|
||||
protected:
|
||||
void begin_frame();
|
||||
void run_hblank(int);
|
||||
int sprite_height() const { return (w2000 >> 2 & 8) + 8; }
|
||||
|
||||
protected: // friend class Nes_Ppu; private:
|
||||
|
||||
int addr_inc; // pre-calculated $2007 increment (based on w2001 & 0x04)
|
||||
int read_2007(int addr);
|
||||
|
||||
|
@ -104,7 +107,6 @@ protected: //friend class Nes_Ppu; private:
|
|||
int first_opaque_sprite_line();
|
||||
|
||||
protected: // friend class Nes_Ppu_Rendering; private:
|
||||
|
||||
unsigned long palette_offset;
|
||||
int palette_changed;
|
||||
void capture_palette();
|
||||
|
@ -119,7 +121,6 @@ protected: //friend class Nes_Ppu_Rendering; private:
|
|||
uint8_t *get_nametable(int addr) { return nt_banks[addr >> 10 & 3]; };
|
||||
|
||||
private:
|
||||
|
||||
static int map_palette(int addr);
|
||||
int sprite_tile_index(uint8_t const *sprite) const;
|
||||
|
||||
|
@ -148,7 +149,6 @@ private:
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool mmc24_enabled;
|
||||
uint8_t mmc24_latched[2];
|
||||
|
||||
|
@ -161,7 +161,8 @@ private:
|
|||
cached_tile_t *tile_cache;
|
||||
cached_tile_t *flipped_tiles;
|
||||
uint8_t *tile_cache_mem;
|
||||
union {
|
||||
union
|
||||
{
|
||||
uint8_t modified_tiles[chr_tile_count / 8];
|
||||
uint32_t align_;
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
#include "Nes_Ppu_Rendering.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
/* 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
|
||||
|
@ -30,16 +30,14 @@ inline Nes_Ppu_Impl::cached_tile_t const&
|
|||
|
||||
// use index directly, since cached tile is same size as native 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 *(Nes_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)
|
||||
{
|
||||
// use index directly, since cached tile is same size as native 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 *(Nes_Ppu_Impl::cached_tile_t *)((uint8_t *)tile_cache + map_chr_addr(index * bytes_per_tile));
|
||||
}
|
||||
|
||||
// Fill
|
||||
|
@ -253,8 +251,7 @@ void Nes_Ppu_Rendering::draw_background_( int remain )
|
|||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while ( remain );
|
||||
} while (remain);
|
||||
}
|
||||
|
||||
// Sprites
|
||||
|
@ -310,8 +307,7 @@ void Nes_Ppu_Rendering::draw_sprites_( int begin, int end )
|
|||
#define CLIPPED 1
|
||||
#include "Nes_Ppu_Sprites.hpp"
|
||||
}
|
||||
}
|
||||
while ( index < 0x100 );
|
||||
} while (index < 0x100);
|
||||
}
|
||||
|
||||
void Nes_Ppu_Rendering::check_sprite_hit(int begin, int end)
|
||||
|
@ -399,14 +395,12 @@ void Nes_Ppu_Rendering::check_sprite_hit( int begin, int end )
|
|||
|
||||
return;
|
||||
}
|
||||
}
|
||||
while ( x++ < 7 );
|
||||
} while (x++ < 7);
|
||||
}
|
||||
if (skip > final)
|
||||
skip -= 2;
|
||||
skip++;
|
||||
}
|
||||
while ( skip != final );
|
||||
} while (skip != final);
|
||||
}
|
||||
|
||||
// Draw scanlines
|
||||
|
@ -416,8 +410,7 @@ inline bool Nes_Ppu_Rendering::sprite_hit_possible( int scanline ) const
|
|||
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 Nes_Ppu_Rendering::draw_scanlines(int start, int count, uint8_t *pixels, long pitch, int mode)
|
||||
{
|
||||
scanline_pixels = pixels + image_left;
|
||||
scanline_row_bytes = pitch;
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
|
||||
#include "Nes_Ppu_Impl.hpp"
|
||||
|
||||
class Nes_Ppu_Rendering : public Nes_Ppu_Impl {
|
||||
class Nes_Ppu_Rendering : public Nes_Ppu_Impl
|
||||
{
|
||||
typedef Nes_Ppu_Impl base;
|
||||
|
||||
public:
|
||||
Nes_Ppu_Rendering();
|
||||
|
||||
|
@ -16,13 +18,11 @@ public:
|
|||
long host_row_bytes;
|
||||
|
||||
protected:
|
||||
|
||||
long sprite_hit_found; // -1: sprite 0 didn't hit, 0: no hit so far, > 0: y * 341 + x
|
||||
void draw_background(int start, int count);
|
||||
void draw_sprites(int start, int count);
|
||||
|
||||
private:
|
||||
|
||||
void draw_scanlines(int start, int count, uint8_t *pixels, long pitch, int mode);
|
||||
void draw_background_(int count);
|
||||
|
||||
|
@ -37,7 +37,10 @@ private:
|
|||
void restore_left(int count);
|
||||
|
||||
// sprites
|
||||
enum { max_sprites = 64 };
|
||||
enum
|
||||
{
|
||||
max_sprites = 64
|
||||
};
|
||||
uint8_t sprite_scanlines[image_height]; // number of sprites on each scanline
|
||||
void draw_sprites_(int start, int count);
|
||||
bool sprite_hit_possible(int scanline) const;
|
||||
|
@ -54,4 +57,3 @@ inline void Nes_Ppu_Rendering::draw_sprites( int start, int count )
|
|||
{
|
||||
draw_scanlines(start, count, host_pixels + host_row_bytes * start, host_row_bytes, 2);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,13 @@ unsigned long offset = (sprite_2 & 3) * 0x04040404 + (this->palette_offset + 0x1
|
|||
unsigned long const mask = 0x03030303 + zero;
|
||||
unsigned long const maskgen = 0x80808080 + zero;
|
||||
|
||||
#define DRAW_PAIR( shift ) { \
|
||||
#define DRAW_PAIR(shift) \
|
||||
{ \
|
||||
int sprite_count = *scanlines; \
|
||||
CALC_FOUR(((uint32_t *)out)[0], (line >> (shift + 4)), out0) \
|
||||
CALC_FOUR(((uint32_t *)out)[1], (line >> shift), out1) \
|
||||
if ( sprite_count < this->max_sprites ) { \
|
||||
if (sprite_count < this->max_sprites) \
|
||||
{ \
|
||||
((uint32_t *)out)[0] = out0; \
|
||||
((uint32_t *)out)[1] = out1; \
|
||||
} \
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
class QuickerNESInstance : public EmuInstance
|
||||
{
|
||||
public:
|
||||
|
||||
QuickerNESInstance() : EmuInstance()
|
||||
{
|
||||
// Creating new emulator
|
||||
|
@ -57,7 +56,6 @@ class QuickerNESInstance : public EmuInstance
|
|||
void *getInternalEmulatorPointer() const override { return _nes; }
|
||||
|
||||
private:
|
||||
|
||||
inline size_t getStateSizeImpl() const override
|
||||
{
|
||||
return _nes->getStateSize();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include <sstream>
|
||||
#include <chrono>
|
||||
#include "argparse/argparse.hpp"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "sha1/sha1.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef _USE_QUICKNES
|
||||
#include "quickNESInstance.hpp"
|
||||
|
@ -31,8 +31,14 @@ int main(int argc, char *argv[])
|
|||
.default_value(std::string(""));
|
||||
|
||||
// Try to parse arguments
|
||||
try { program.parse_args(argc, argv); }
|
||||
catch (const std::runtime_error &err) { EXIT_WITH_ERROR("%s\n%s", err.what(), program.help().str().c_str()); }
|
||||
try
|
||||
{
|
||||
program.parse_args(argc, argv);
|
||||
}
|
||||
catch (const std::runtime_error &err)
|
||||
{
|
||||
EXIT_WITH_ERROR("%s\n%s", err.what(), program.help().str().c_str());
|
||||
}
|
||||
|
||||
// Getting test script file path
|
||||
std::string scriptFilePath = program.get<std::string>("scriptFile");
|
||||
|
@ -174,4 +180,3 @@ int main(int argc, char *argv[])
|
|||
// If reached this point, everything ran ok
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <metrohash128/metrohash128.h>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <stdarg.h>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <metrohash128/metrohash128.h>
|
||||
#include <vector>
|
||||
|
||||
// If we use NCurses, we need to use the appropriate printing function
|
||||
#ifdef NCURSES
|
||||
|
@ -82,10 +82,8 @@ void refreshTerminal()
|
|||
refresh();
|
||||
}
|
||||
|
||||
|
||||
#endif // NCURSES
|
||||
|
||||
|
||||
typedef _uint128_t hash_t;
|
||||
inline hash_t calculateMetroHash(uint8_t *data, size_t size)
|
||||
{
|
||||
|
@ -100,7 +98,8 @@ inline hash_t calculateMetroHash(uint8_t* data, size_t size)
|
|||
// Taken from stack overflow answer to https://stackoverflow.com/questions/236129/how-do-i-iterate-over-the-words-of-a-string
|
||||
// By Evan Teran
|
||||
|
||||
template <typename Out> inline void split(const std::string &s, char delim, Out result)
|
||||
template <typename Out>
|
||||
inline void split(const std::string &s, char delim, Out result)
|
||||
{
|
||||
std::istringstream iss(s);
|
||||
std::string item;
|
||||
|
@ -178,7 +177,8 @@ inline bool saveStringToFile(const std::string &src, const char *fileName)
|
|||
}
|
||||
|
||||
// Function to split a vector into n mostly fair chunks
|
||||
template <typename T> inline std::vector<T> splitVector(const T size, const T n)
|
||||
template <typename T>
|
||||
inline std::vector<T> splitVector(const T size, const T n)
|
||||
{
|
||||
std::vector<T> subSizes(n);
|
||||
|
||||
|
@ -196,7 +196,12 @@ inline std::string simplifyMove(const std::string& move)
|
|||
std::string simpleMove;
|
||||
|
||||
bool isEmptyMove = true;
|
||||
for (size_t i = 0; i < move.size(); i++) if (move[i] != '.' && move[i] != '|') { simpleMove += move[i]; isEmptyMove = false; }
|
||||
for (size_t i = 0; i < move.size(); i++)
|
||||
if (move[i] != '.' && move[i] != '|')
|
||||
{
|
||||
simpleMove += move[i];
|
||||
isEmptyMove = false;
|
||||
}
|
||||
if (isEmptyMove) return ".";
|
||||
return simpleMove;
|
||||
}
|
||||
|
@ -214,10 +219,17 @@ inline bool getBitFlag(const uint8_t value, const uint8_t idx)
|
|||
return false;
|
||||
}
|
||||
|
||||
inline size_t countButtonsPressedString(const std::string &input)
|
||||
{
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < input.size(); i++)
|
||||
if (input[i] != '.') count++;
|
||||
return count;
|
||||
};
|
||||
|
||||
inline size_t countButtonsPressedString(const std::string& input) { size_t count = 0; for (size_t i = 0; i < input.size(); i++) if (input[i] != '.') count++; return count; };
|
||||
|
||||
template<typename T> inline uint16_t countButtonsPressedNumber(const T& input) {
|
||||
template <typename T>
|
||||
inline uint16_t countButtonsPressedNumber(const T &input)
|
||||
{
|
||||
uint16_t count = 0;
|
||||
if (input & 0b0000000000000001) count++;
|
||||
if (input & 0b0000000000000010) count++;
|
||||
|
@ -238,5 +250,11 @@ template<typename T> inline uint16_t countButtonsPressedNumber(const T& input) {
|
|||
return count;
|
||||
};
|
||||
|
||||
static auto moveCountComparerString = [](const std::string& a, const std::string& b) { return countButtonsPressedString(a) < countButtonsPressedString(b); };
|
||||
static auto moveCountComparerNumber = [](const uint8_t a, const uint8_t b) { return countButtonsPressedNumber(a) < countButtonsPressedNumber(b); };
|
||||
static auto moveCountComparerString = [](const std::string &a, const std::string &b)
|
||||
{
|
||||
return countButtonsPressedString(a) < countButtonsPressedString(b);
|
||||
};
|
||||
static auto moveCountComparerNumber = [](const uint8_t a, const uint8_t b)
|
||||
{
|
||||
return countButtonsPressedNumber(a) < countButtonsPressedNumber(b);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue