lsnes/ui/interface/nes/nes.cpp
2013-05-03 17:47:34 +03:00

146 lines
3.6 KiB
C++
Executable file

void InterfaceNES::initialize() {
NES::interface = this;
NES::system.init();
}
void InterfaceNES::setController(bool port, unsigned device) {
if(port == 0) config->nes.controllerPort1Device = device;
if(port == 1) config->nes.controllerPort2Device = device;
if(port == 0) switch(device) {
case 0: return NES::input.connect(0, NES::Input::Device::None);
case 1: return NES::input.connect(0, NES::Input::Device::Joypad);
}
if(port == 1) switch(device) {
case 0: return NES::input.connect(1, NES::Input::Device::None);
case 1: return NES::input.connect(1, NES::Input::Device::Joypad);
}
}
bool InterfaceNES::cartridgeLoaded() {
return NES::cartridge.loaded();
}
bool InterfaceNES::loadCartridge(const string &filename) {
uint8_t *data;
unsigned size;
if(interface->loadFile(filename, data, size) == false) return false;
interface->unloadCartridge();
interface->baseName = nall::basename(filename);
string markup;
markup.readfile({ interface->baseName, ".xml" });
NES::cartridge.load(markup, data, size);
NES::system.power();
delete[] data;
if(NES::cartridge.ram_size()) {
filemap fp;
if(fp.open(string{ interface->baseName, ".sav" }, filemap::mode::read)) {
memcpy(NES::cartridge.ram_data(), fp.data(), min(NES::cartridge.ram_size(), fp.size()));
}
}
interface->loadCartridge(::Interface::Mode::NES);
NES::video.generate(NES::Video::Format::RGB30);
return true;
}
void InterfaceNES::unloadCartridge() {
if(NES::cartridge.ram_size()) {
file::write({ interface->baseName, ".sav" }, NES::cartridge.ram_data(), NES::cartridge.ram_size());
}
NES::cartridge.unload();
interface->baseName = "";
}
//
void InterfaceNES::power() {
NES::system.power();
}
void InterfaceNES::reset() {
NES::system.reset();
}
void InterfaceNES::run() {
NES::system.run();
}
//
serializer InterfaceNES::serialize() {
NES::system.runtosave();
return NES::system.serialize();
}
bool InterfaceNES::unserialize(serializer &s) {
return NES::system.unserialize(s);
}
//
void InterfaceNES::setCheats(const lstring &list) {
NES::cheat.reset();
for(auto &code : list) {
lstring codelist;
codelist.split("+", code);
for(auto &part : codelist) {
unsigned addr, data, comp;
if(NES::Cheat::decode(part, addr, data, comp)) {
NES::cheat.append({ addr, data, comp });
}
}
}
NES::cheat.synchronize();
}
//
void InterfaceNES::videoRefresh(const uint16_t *data) {
static uint32_t output[256 * 240];
for(unsigned y = 0; y < 240; y++) {
const uint16_t *sp = data + y * 256;
uint32_t *dp = output + y * 256;
for(unsigned x = 0; x < 256; x++) {
uint32_t color = *sp++;
*dp++ = NES::video.palette[color];
}
}
if(config->video.maskOverscan) {
unsigned osw = config->video.maskOverscanHorizontal;
unsigned osh = config->video.maskOverscanVertical;
for(unsigned y = 0; y < 240; y++) {
uint32_t *dp = output + y * 256;
if(y < osh || y >= 240 - osh) {
memset(dp, 0, 256 * sizeof(uint32_t));
} else {
memset(dp + 0, 0, osw * sizeof(uint32_t));
memset(dp + 256 - osw, 0, osw * sizeof(uint32_t));
}
}
}
interface->videoRefresh(output, 256 * sizeof(uint32_t), 256, 240);
}
void InterfaceNES::audioSample(int16_t sample) {
signed samples[] = { sample };
dspaudio.sample(samples);
while(dspaudio.pending()) {
dspaudio.read(samples);
audio.sample(samples[0], samples[0]); //NES audio output is monaural; ruby only takes stereo audio
}
}
int16_t InterfaceNES::inputPoll(bool port, unsigned device, unsigned id) {
if(port == 0 && device == 0) return inputManager->nes.port1.gamepad.poll(id);
return 0;
}