Supporting arkanoidNES
This commit is contained in:
parent
9f164b4a58
commit
29beac9732
|
@ -79,13 +79,13 @@ error_t HQNState::advanceFrame(bool sleep)
|
||||||
SDL_Delay(wantTicks - ticks);
|
SDL_Delay(wantTicks - ticks);
|
||||||
}
|
}
|
||||||
// m_frameTime = wantTicks - m_prevFrame;
|
// m_frameTime = wantTicks - m_prevFrame;
|
||||||
error_t result = m_emu->emulate_frame(joypad[0], joypad[1]);
|
// error_t result = m_emu->emulate_frame(joypad[0], joypad[1]);
|
||||||
if (m_listener)
|
if (m_listener)
|
||||||
m_listener->onAdvanceFrame(this);
|
m_listener->onAdvanceFrame(this);
|
||||||
ticks = SDL_GetTicks();
|
ticks = SDL_GetTicks();
|
||||||
m_frameTime = ticks - m_prevFrame;
|
m_frameTime = ticks - m_prevFrame;
|
||||||
m_prevFrame = ticks;
|
m_prevFrame = ticks;
|
||||||
return result;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HQNState::setFramerate(int fps)
|
void HQNState::setFramerate(int fps)
|
||||||
|
|
|
@ -20,6 +20,8 @@ struct input_t
|
||||||
bool reset = false;
|
bool reset = false;
|
||||||
port_t port1 = 0;
|
port_t port1 = 0;
|
||||||
port_t port2 = 0;
|
port_t port2 = 0;
|
||||||
|
port_t arkanoidLatch = 0;
|
||||||
|
uint8_t arkanoidFire = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InputParser
|
class InputParser
|
||||||
|
@ -30,9 +32,14 @@ class InputParser
|
||||||
none,
|
none,
|
||||||
joypad,
|
joypad,
|
||||||
fourscore1,
|
fourscore1,
|
||||||
fourscore2
|
fourscore2,
|
||||||
|
arkanoidNES,
|
||||||
|
arkanoidFamicom
|
||||||
};
|
};
|
||||||
|
|
||||||
|
controller_t _controller1Type;
|
||||||
|
controller_t _controller2Type;
|
||||||
|
|
||||||
InputParser(const nlohmann::json &config)
|
InputParser(const nlohmann::json &config)
|
||||||
{
|
{
|
||||||
// Parsing controller 1 type
|
// Parsing controller 1 type
|
||||||
|
@ -59,6 +66,16 @@ class InputParser
|
||||||
_controller1Type = controller_t::fourscore2;
|
_controller1Type = controller_t::fourscore2;
|
||||||
isTypeRecognized = true;
|
isTypeRecognized = true;
|
||||||
}
|
}
|
||||||
|
if (controller1Type == "ArkanoidNES")
|
||||||
|
{
|
||||||
|
_controller1Type = controller_t::arkanoidNES;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
|
if (controller1Type == "ArkanoidFamicom")
|
||||||
|
{
|
||||||
|
_controller1Type = controller_t::arkanoidFamicom;
|
||||||
|
isTypeRecognized = true;
|
||||||
|
}
|
||||||
if (isTypeRecognized == false) JAFFAR_THROW_LOGIC("Controller 1 type not recognized: '%s'\n", controller1Type.c_str());
|
if (isTypeRecognized == false) JAFFAR_THROW_LOGIC("Controller 1 type not recognized: '%s'\n", controller1Type.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,10 +122,12 @@ class InputParser
|
||||||
parseConsoleInputs(input.reset, input.power, ss, inputString);
|
parseConsoleInputs(input.reset, input.power, ss, inputString);
|
||||||
|
|
||||||
// Parsing controller 1 inputs
|
// Parsing controller 1 inputs
|
||||||
parseControllerInputs(_controller1Type, input.port1, ss, inputString);
|
if (_controller1Type == arkanoidNES) parseArkanoidInput(input, ss, inputString);
|
||||||
|
if (_controller1Type == arkanoidFamicom) parseArkanoidInput(input, ss, inputString);
|
||||||
|
if (_controller1Type == joypad || _controller1Type == fourscore1) parseControllerInputs(_controller1Type, input.port1, ss, inputString);
|
||||||
|
|
||||||
// Parsing controller 1 inputs
|
// Parsing controller 2 inputs
|
||||||
parseControllerInputs(_controller2Type, input.port2, ss, inputString);
|
if (_controller2Type == joypad || _controller2Type == fourscore2) parseControllerInputs(_controller2Type, input.port2, ss, inputString);
|
||||||
|
|
||||||
// End separator
|
// End separator
|
||||||
if (ss.get() != '|') reportBadInputString(inputString);
|
if (ss.get() != '|') reportBadInputString(inputString);
|
||||||
|
@ -175,6 +194,55 @@ class InputParser
|
||||||
if (c == 'A') code |= 0b00000001;
|
if (c == 'A') code |= 0b00000001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void parseArkanoidInput(input_t& input, std::istringstream& ss, const std::string& inputString)
|
||||||
|
{
|
||||||
|
uint8_t potentiometer = 0;
|
||||||
|
uint8_t fire = 0;
|
||||||
|
|
||||||
|
// Controller separator
|
||||||
|
if (ss.get() != '|') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
if (ss.get() != ' ') reportBadInputString(inputString);
|
||||||
|
if (ss.get() != ' ') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
char c = ss.get(); // Hundreds
|
||||||
|
if (c != ' ' && c < 48 && c > 57) reportBadInputString(inputString);
|
||||||
|
if (c != ' ') potentiometer += 100 * ( (uint8_t)c - 48 );
|
||||||
|
|
||||||
|
c = ss.get(); // Tenths
|
||||||
|
if (c != ' ' && c < 48 && c > 57) reportBadInputString(inputString);
|
||||||
|
if (c != ' ') potentiometer += 10 * ( (uint8_t)c - 48 );
|
||||||
|
|
||||||
|
c = ss.get(); // Units
|
||||||
|
if (c != ' ' && c < 48 && c > 57) reportBadInputString(inputString);
|
||||||
|
if (c != ' ') potentiometer += (uint8_t)c - 48;
|
||||||
|
|
||||||
|
// Comma
|
||||||
|
if (ss.get() != ',') reportBadInputString(inputString);
|
||||||
|
|
||||||
|
// Fire
|
||||||
|
|
||||||
|
c = ss.get();
|
||||||
|
if (c != '.' && c != 'F') reportBadInputString(inputString);
|
||||||
|
if (c == 'F') fire = 1;
|
||||||
|
|
||||||
|
// Fire is encoded in port 1
|
||||||
|
input.arkanoidFire = fire;
|
||||||
|
|
||||||
|
// Potentiometer is encoded in port 2 - MSB and adding one bit for signalling the presence of the potentiometer, subtracted from 173
|
||||||
|
uint8_t subtracter = 171 - potentiometer;
|
||||||
|
|
||||||
|
input.arkanoidLatch = 0;
|
||||||
|
if ((subtracter & 128) > 0) input.arkanoidLatch += 1;
|
||||||
|
if ((subtracter & 64) > 0) input.arkanoidLatch += 2;
|
||||||
|
if ((subtracter & 32) > 0) input.arkanoidLatch += 4;
|
||||||
|
if ((subtracter & 16) > 0) input.arkanoidLatch += 8;
|
||||||
|
if ((subtracter & 8) > 0) input.arkanoidLatch += 16;
|
||||||
|
if ((subtracter & 4) > 0) input.arkanoidLatch += 32;
|
||||||
|
if ((subtracter & 2) > 0) input.arkanoidLatch += 64;
|
||||||
|
if ((subtracter & 1) > 0) input.arkanoidLatch += 128;
|
||||||
|
}
|
||||||
|
|
||||||
static void parseControllerInputs(const controller_t type, port_t &port, std::istringstream &ss, const std::string &inputString)
|
static void parseControllerInputs(const controller_t type, port_t &port, std::istringstream &ss, const std::string &inputString)
|
||||||
{
|
{
|
||||||
// If no controller assigned then, its port is all zeroes.
|
// If no controller assigned then, its port is all zeroes.
|
||||||
|
@ -254,9 +322,6 @@ class InputParser
|
||||||
if (c == '.') reset = false;
|
if (c == '.') reset = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
controller_t _controller1Type;
|
|
||||||
controller_t _controller2Type;
|
|
||||||
|
|
||||||
}; // class InputParser
|
}; // class InputParser
|
||||||
|
|
||||||
} // namespace jaffar
|
} // namespace jaffar
|
|
@ -84,7 +84,6 @@ class NESInstanceBase
|
||||||
// Flag to determine whether to enable/disable rendering
|
// Flag to determine whether to enable/disable rendering
|
||||||
bool _doRendering = true;
|
bool _doRendering = true;
|
||||||
|
|
||||||
private:
|
|
||||||
// Input parser instance
|
// Input parser instance
|
||||||
std::unique_ptr<jaffar::InputParser> _inputParser;
|
std::unique_ptr<jaffar::InputParser> _inputParser;
|
||||||
};
|
};
|
||||||
|
|
|
@ -97,7 +97,7 @@ int main(int argc, char *argv[])
|
||||||
if (status == false) JAFFAR_THROW_LOGIC("[ERROR] Could not find or read from sequence file: %s\n", sequenceFilePath.c_str());
|
if (status == false) JAFFAR_THROW_LOGIC("[ERROR] Could not find or read from sequence file: %s\n", sequenceFilePath.c_str());
|
||||||
|
|
||||||
// Building sequence information
|
// Building sequence information
|
||||||
const auto sequence = jaffarCommon::string::split(inputSequence, ' ');
|
const auto sequence = jaffarCommon::string::split(inputSequence, '\n');
|
||||||
|
|
||||||
// Initializing terminal
|
// Initializing terminal
|
||||||
jaffarCommon::logger::initializeTerminal();
|
jaffarCommon::logger::initializeTerminal();
|
||||||
|
@ -182,6 +182,7 @@ int main(int argc, char *argv[])
|
||||||
jaffarCommon::logger::log("[] Current Step #: %lu / %lu\n", currentStep + 1, sequenceLength);
|
jaffarCommon::logger::log("[] Current Step #: %lu / %lu\n", currentStep + 1, sequenceLength);
|
||||||
jaffarCommon::logger::log("[] Input: %s\n", inputString.c_str());
|
jaffarCommon::logger::log("[] Input: %s\n", inputString.c_str());
|
||||||
jaffarCommon::logger::log("[] State Hash: 0x%lX%lX\n", hash.first, hash.second);
|
jaffarCommon::logger::log("[] State Hash: 0x%lX%lX\n", hash.first, hash.second);
|
||||||
|
jaffarCommon::logger::log("[] Paddle X: %u\n", e.getLowMem()[0x11A]);
|
||||||
|
|
||||||
// Only print commands if not in reproduce mode
|
// Only print commands if not in reproduce mode
|
||||||
if (isReproduce == false) jaffarCommon::logger::log("[] Commands: n: -1 m: +1 | h: -10 | j: +10 | y: -100 | u: +100 | k: -1000 | i: +1000 | s: quicksave | p: play | q: quit\n");
|
if (isReproduce == false) jaffarCommon::logger::log("[] Commands: n: -1 m: +1 | h: -10 | j: +10 | y: -100 | u: +100 | k: -1000 | i: +1000 | s: quicksave | p: play | q: quit\n");
|
||||||
|
|
|
@ -58,13 +58,13 @@ struct nes_state_lite_t
|
||||||
uint8_t frame_count; // number of frames emulated since power-up
|
uint8_t frame_count; // number of frames emulated since power-up
|
||||||
};
|
};
|
||||||
|
|
||||||
struct joypad_state_t
|
struct input_state_t
|
||||||
{
|
{
|
||||||
uint32_t joypad_latches[2]; // joypad 1 & 2 shift registers
|
uint32_t joypad_latches[2]; // input_state 1 & 2 shift registers
|
||||||
|
uint32_t arkanoid_latch; // arkanoid latch
|
||||||
|
uint8_t arkanoid_fire; // arkanoid latch
|
||||||
uint8_t w4016; // strobe
|
uint8_t w4016; // strobe
|
||||||
uint8_t unused[3];
|
|
||||||
};
|
};
|
||||||
static_assert(sizeof(joypad_state_t) == 12);
|
|
||||||
|
|
||||||
struct cpu_state_t
|
struct cpu_state_t
|
||||||
{
|
{
|
||||||
|
@ -98,13 +98,22 @@ class Core : private Cpu
|
||||||
bool CHRRBlockEnabled = true;
|
bool CHRRBlockEnabled = true;
|
||||||
bool SRAMBlockEnabled = true;
|
bool SRAMBlockEnabled = true;
|
||||||
|
|
||||||
|
// APU and Joypad
|
||||||
|
enum controllerType_t
|
||||||
|
{
|
||||||
|
none_t,
|
||||||
|
joypad_t,
|
||||||
|
arkanoidNES_t,
|
||||||
|
arkanoidFamicom_t,
|
||||||
|
};
|
||||||
|
|
||||||
Core() : ppu(this)
|
Core() : ppu(this)
|
||||||
{
|
{
|
||||||
cart = NULL;
|
cart = NULL;
|
||||||
impl = NULL;
|
impl = NULL;
|
||||||
mapper = NULL;
|
mapper = NULL;
|
||||||
memset(&nes, 0, sizeof nes);
|
memset(&nes, 0, sizeof nes);
|
||||||
memset(&joypad, 0, sizeof joypad);
|
memset(&input_state, 0, sizeof input_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Core()
|
~Core()
|
||||||
|
@ -206,8 +215,8 @@ class Core : private Cpu
|
||||||
// CTRL Block
|
// CTRL Block
|
||||||
if (CTRLBlockEnabled == true)
|
if (CTRLBlockEnabled == true)
|
||||||
{
|
{
|
||||||
const auto inputDataSize = sizeof(joypad_state_t);
|
const auto inputDataSize = sizeof(input_state_t);
|
||||||
const auto inputData = (uint8_t *)&joypad;
|
const auto inputData = (uint8_t *)&input_state;
|
||||||
serializer.pushContiguous(inputData, inputDataSize);
|
serializer.pushContiguous(inputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,8 +332,8 @@ class Core : private Cpu
|
||||||
// CTRL Block
|
// CTRL Block
|
||||||
if (CTRLBlockEnabled == true)
|
if (CTRLBlockEnabled == true)
|
||||||
{
|
{
|
||||||
const auto outputData = (uint8_t *)&joypad;
|
const auto outputData = (uint8_t *)&input_state;
|
||||||
const auto inputDataSize = sizeof(joypad_state_t);
|
const auto inputDataSize = sizeof(input_state_t);
|
||||||
deserializer.popContiguous(outputData, inputDataSize);
|
deserializer.popContiguous(outputData, inputDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,8 +558,10 @@ class Core : private Cpu
|
||||||
if (!cart->has_battery_ram() || erase_battery_ram)
|
if (!cart->has_battery_ram() || erase_battery_ram)
|
||||||
memset(impl->sram, 0xFF, impl->sram_size);
|
memset(impl->sram, 0xFF, impl->sram_size);
|
||||||
|
|
||||||
joypad.joypad_latches[0] = 0;
|
input_state.joypad_latches[0] = 0;
|
||||||
joypad.joypad_latches[1] = 0;
|
input_state.joypad_latches[1] = 0;
|
||||||
|
input_state.arkanoid_latch = 0;
|
||||||
|
input_state.arkanoid_fire = 0;
|
||||||
|
|
||||||
nes.frame_count = 0;
|
nes.frame_count = 0;
|
||||||
}
|
}
|
||||||
|
@ -572,7 +583,7 @@ class Core : private Cpu
|
||||||
error_count = 0;
|
error_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nes_time_t emulate_frame(uint32_t joypad1, uint32_t joypad2)
|
nes_time_t emulate_frame(uint32_t joypad1, uint32_t joypad2, uint32_t arkanoid_latch, uint8_t arkanoid_fire)
|
||||||
{
|
{
|
||||||
#ifdef _QUICKERNES_DETECT_JOYPAD_READS
|
#ifdef _QUICKERNES_DETECT_JOYPAD_READS
|
||||||
joypad_read_count = 0;
|
joypad_read_count = 0;
|
||||||
|
@ -580,6 +591,8 @@ class Core : private Cpu
|
||||||
|
|
||||||
current_joypad[0] = joypad1;
|
current_joypad[0] = joypad1;
|
||||||
current_joypad[1] = joypad2;
|
current_joypad[1] = joypad2;
|
||||||
|
current_arkanoid_latch = arkanoid_latch;
|
||||||
|
current_arkanoid_fire = arkanoid_fire;
|
||||||
|
|
||||||
cpu_time_offset = ppu.begin_frame(nes.timestamp) - 1;
|
cpu_time_offset = ppu.begin_frame(nes.timestamp) - 1;
|
||||||
ppu_2002_time = 0;
|
ppu_2002_time = 0;
|
||||||
|
@ -649,6 +662,8 @@ class Core : private Cpu
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32_t current_joypad[2];
|
uint32_t current_joypad[2];
|
||||||
|
uint32_t current_arkanoid_latch;
|
||||||
|
uint8_t current_arkanoid_fire;
|
||||||
Cart const *cart;
|
Cart const *cart;
|
||||||
Mapper *mapper;
|
Mapper *mapper;
|
||||||
nes_state_t nes;
|
nes_state_t nes;
|
||||||
|
@ -697,27 +712,74 @@ class Core : private Cpu
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// APU and Joypad
|
|
||||||
joypad_state_t joypad;
|
controllerType_t _controllerType = controllerType_t::none_t;
|
||||||
|
|
||||||
|
input_state_t input_state;
|
||||||
|
|
||||||
|
void setControllerType(controllerType_t type) { _controllerType = type; }
|
||||||
|
|
||||||
int read_io(nes_addr_t addr)
|
int read_io(nes_addr_t addr)
|
||||||
{
|
{
|
||||||
if ((addr & 0xFFFE) == 0x4016)
|
if ((addr & 0xFFFE) == 0x4016)
|
||||||
{
|
{
|
||||||
// For performance's sake, this counter is only kept on demand
|
// For performance's sake, this counter is only kept on demand
|
||||||
#ifdef _QUICKERNES_DETECT_JOYPAD_READS
|
#ifdef _QUICKERNES_DETECT_JOYPAD_READS
|
||||||
joypad_read_count++;
|
joypad_read_count++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// to do: to aid with recording, doesn't emulate transparent latch,
|
// If write flag is put into w4016, reading from it returns nothing
|
||||||
// so a game that held strobe at 1 and read $4016 or $4017 would not get
|
if (input_state.w4016 & 1) return 0;
|
||||||
// the current A status as occurs on a NES
|
|
||||||
if (joypad.w4016 & 1) return 0;
|
// Proceed depending on input type
|
||||||
const uint8_t result = joypad.joypad_latches[addr & 1] & 1;
|
switch(_controllerType)
|
||||||
joypad.joypad_latches[addr & 1] >>= 1;
|
{
|
||||||
return result;
|
case controllerType_t::joypad_t:
|
||||||
|
{
|
||||||
|
const uint8_t result = input_state.joypad_latches[addr & 1] & 1;
|
||||||
|
input_state.joypad_latches[addr & 1] >>= 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
case controllerType_t::arkanoidNES_t:
|
||||||
|
{
|
||||||
|
if (addr == 0x4017)
|
||||||
|
{
|
||||||
|
// latch 0 encodes fire, latch 1 encodes potentiometer
|
||||||
|
const uint8_t result = (input_state.arkanoid_latch & 1) * 16 + current_arkanoid_fire * 8;
|
||||||
|
|
||||||
|
// Advancing latch 1
|
||||||
|
input_state.arkanoid_latch >>= 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case controllerType_t::arkanoidFamicom_t:
|
||||||
|
{
|
||||||
|
if (addr == 0x4016)
|
||||||
|
{
|
||||||
|
// latch 0 encodes fire
|
||||||
|
const uint8_t result = (input_state.joypad_latches[0] & 1) * 2;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr == 0x4017)
|
||||||
|
{
|
||||||
|
// latch 1 encodes potentiometer
|
||||||
|
const uint8_t result = (input_state.joypad_latches[1] & 1) * 2;
|
||||||
|
|
||||||
|
// Advancing latch 1
|
||||||
|
input_state.joypad_latches[1] >>= 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (addr == Apu::status_addr)
|
if (addr == Apu::status_addr)
|
||||||
return impl->apu.read_status(clock());
|
return impl->apu.read_status(clock());
|
||||||
|
|
||||||
|
@ -734,16 +796,18 @@ class Core : private Cpu
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// joypad strobe
|
// input_state strobe
|
||||||
if (addr == 0x4016)
|
if (addr == 0x4016)
|
||||||
{
|
{
|
||||||
// if strobe goes low, latch data
|
// if strobe goes low, latch data
|
||||||
if (joypad.w4016 & 1 & ~data)
|
if (input_state.w4016 & 1 & ~data)
|
||||||
{
|
{
|
||||||
joypad.joypad_latches[0] = current_joypad[0];
|
input_state.joypad_latches[0] = current_joypad[0];
|
||||||
joypad.joypad_latches[1] = current_joypad[1];
|
input_state.joypad_latches[1] = current_joypad[1];
|
||||||
|
input_state.arkanoid_latch = current_arkanoid_latch;
|
||||||
|
input_state.arkanoid_fire = current_arkanoid_fire;
|
||||||
}
|
}
|
||||||
joypad.w4016 = data;
|
input_state.w4016 = data;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,16 +104,16 @@ void Emu::set_palette_range(int begin, int end)
|
||||||
host_palette_size = end - emu.ppu.palette_begin;
|
host_palette_size = end - emu.ppu.palette_begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Emu::emulate_skip_frame(uint32_t joypad1, uint32_t joypad2)
|
const char *Emu::emulate_skip_frame(uint32_t joypad1, uint32_t joypad2, uint32_t arkanoid_latch, uint8_t arkanoid_fire)
|
||||||
{
|
{
|
||||||
char *old_host_pixels = host_pixels;
|
char *old_host_pixels = host_pixels;
|
||||||
host_pixels = NULL;
|
host_pixels = NULL;
|
||||||
emu.emulate_frame(joypad1, joypad2);
|
emu.emulate_frame(joypad1, joypad2, arkanoid_latch, arkanoid_fire);
|
||||||
host_pixels = old_host_pixels;
|
host_pixels = old_host_pixels;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Emu::emulate_frame(uint32_t joypad1, uint32_t joypad2)
|
const char *Emu::emulate_frame(uint32_t joypad1, uint32_t joypad2, uint32_t arkanoid_latch, uint8_t arkanoid_fire)
|
||||||
{
|
{
|
||||||
emu.ppu.host_pixels = NULL;
|
emu.ppu.host_pixels = NULL;
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ const char *Emu::emulate_frame(uint32_t joypad1, uint32_t joypad2)
|
||||||
if (sound_buf->samples_avail())
|
if (sound_buf->samples_avail())
|
||||||
clear_sound_buf();
|
clear_sound_buf();
|
||||||
|
|
||||||
nes_time_t frame_len = emu.emulate_frame(joypad1, joypad2);
|
nes_time_t frame_len = emu.emulate_frame(joypad1, joypad2, arkanoid_latch, arkanoid_fire);
|
||||||
sound_buf->end_frame(frame_len, false);
|
sound_buf->end_frame(frame_len, false);
|
||||||
|
|
||||||
f = frame_;
|
f = frame_;
|
||||||
|
@ -159,7 +159,7 @@ const char *Emu::emulate_frame(uint32_t joypad1, uint32_t joypad2)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
emu.ppu.max_palette_size = 0;
|
emu.ppu.max_palette_size = 0;
|
||||||
emu.emulate_frame(joypad1, joypad2);
|
emu.emulate_frame(joypad1, joypad2, arkanoid_latch, arkanoid_fire);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -54,15 +54,17 @@ class Emu
|
||||||
void enableStateBlock(const std::string &block) { emu.enableStateBlock(block); };
|
void enableStateBlock(const std::string &block) { emu.enableStateBlock(block); };
|
||||||
void disableStateBlock(const std::string &block) { emu.disableStateBlock(block); };
|
void disableStateBlock(const std::string &block) { emu.disableStateBlock(block); };
|
||||||
|
|
||||||
|
void setControllerType(Core::controllerType_t type) { emu.setControllerType(type); }
|
||||||
|
|
||||||
// Basic emulation
|
// Basic emulation
|
||||||
|
|
||||||
// Emulate one video frame using joypad1 and joypad2 as input. Afterwards, image
|
// Emulate one video frame using joypad1 and joypad2 as input. Afterwards, image
|
||||||
// and sound are available for output using the accessors below.
|
// and sound are available for output using the accessors below.
|
||||||
virtual const char *emulate_frame(uint32_t joypad1, uint32_t joypad2 = 0);
|
virtual const char *emulate_frame(uint32_t joypad1, uint32_t joypad2, uint32_t arkanoid_latch, uint8_t arkanoid_fire);
|
||||||
|
|
||||||
// Emulate one video frame using joypad1 and joypad2 as input, but skips drawing.
|
// Emulate one video frame using joypad1 and joypad2 as input, but skips drawing.
|
||||||
// Afterwards, audio is available for output using the accessors below.
|
// Afterwards, audio is available for output using the accessors below.
|
||||||
virtual const char *emulate_skip_frame(uint32_t joypad1, uint32_t joypad2 = 0);
|
virtual const char *emulate_skip_frame(uint32_t joypad1, uint32_t joypad2, uint32_t arkanoid_latch, uint8_t arkanoid_fire);
|
||||||
|
|
||||||
// Maximum size of palette that can be generated
|
// Maximum size of palette that can be generated
|
||||||
static const uint16_t max_palette_size = 256;
|
static const uint16_t max_palette_size = 256;
|
||||||
|
|
|
@ -8,7 +8,12 @@ typedef quickerNES::Emu emulator_t;
|
||||||
class NESInstance final : public NESInstanceBase
|
class NESInstance final : public NESInstanceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NESInstance(const nlohmann::json &config) : NESInstanceBase(config) {}
|
NESInstance(const nlohmann::json &config) : NESInstanceBase(config)
|
||||||
|
{
|
||||||
|
_nes.setControllerType(quickerNES::Core::controllerType_t::joypad_t);
|
||||||
|
if (_inputParser->_controller1Type == jaffar::InputParser::controller_t::arkanoidFamicom) _nes.setControllerType(quickerNES::Core::controllerType_t::arkanoidFamicom_t);
|
||||||
|
if (_inputParser->_controller1Type == jaffar::InputParser::controller_t::arkanoidNES) _nes.setControllerType(quickerNES::Core::controllerType_t::arkanoidNES_t);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *getLowMem() const override { return _nes.get_low_mem(); };
|
uint8_t *getLowMem() const override { return _nes.get_low_mem(); };
|
||||||
size_t getLowMemSize() const override { return _nes.get_low_mem_size(); };
|
size_t getLowMemSize() const override { return _nes.get_low_mem_size(); };
|
||||||
|
@ -53,8 +58,8 @@ class NESInstance final : public NESInstanceBase
|
||||||
|
|
||||||
void advanceState(const jaffar::input_t &input) override
|
void advanceState(const jaffar::input_t &input) override
|
||||||
{
|
{
|
||||||
if (_doRendering == true) _nes.emulate_frame(input.port1, input.port2);
|
if (_doRendering == true) _nes.emulate_frame(input.port1, input.port2, input.arkanoidLatch, input.arkanoidFire);
|
||||||
if (_doRendering == false) _nes.emulate_skip_frame(input.port1, input.port2);
|
if (_doRendering == false) _nes.emulate_skip_frame(input.port1, input.port2, input.arkanoidLatch, input.arkanoidFire);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"Rom File": "roms/Arkanoid (U) [!].nes",
|
||||||
|
"Expected ROM SHA1": "B2B30C4F30DD853C215C17B0C67CFE63D61A3062",
|
||||||
|
"Initial State File": "",
|
||||||
|
"Sequence File": "arkanoid.arkNESController.sol",
|
||||||
|
"Disable State Blocks": [ "SRAM", "CHRR", "NTAB", "SPRT", "MAPR", "CTRL", "APUR" ],
|
||||||
|
"Controller 1 Type": "Joypad",
|
||||||
|
"Controller 2 Type": "None",
|
||||||
|
"Differential Compression":
|
||||||
|
{
|
||||||
|
"Enabled": false,
|
||||||
|
"Max Differences": 2200,
|
||||||
|
"Use Zlib": true
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue