Path: blob/master/libsnes/bsnes/target-libsnes/libsnes.cpp
2 views
#include "libsnes.hpp"1#include <snes/snes.hpp>23#include <nall/snes/cartridge.hpp>4#include <nall/gameboy/cartridge.hpp>56#include <queue>78#include <Windows.h>910using namespace nall;1112struct Interface : public SNES::Interface {13typedef SNES::Interface BaseType;1415snes_video_refresh_t pvideo_refresh;16snes_audio_sample_t paudio_sample;17snes_input_poll_t pinput_poll;18snes_input_state_t pinput_state;19snes_input_notify_t pinput_notify;20snes_path_request_t ppath_request;21snes_allocSharedMemory_t pallocSharedMemory;22snes_freeSharedMemory_t pfreeSharedMemory;23snes_trace_t ptrace;24string basename;25uint32_t *buffer;26uint32_t *palette;2728SnesCartridge cart;2930//zero 11-sep-201231time_t randomSeed() { return 0; }3233//zero 26-sep-201234std::queue<nall::string> messages;3536//zero 17-oct-201237int backdropColor;38int getBackdropColor()39{40return backdropColor;41}4243void videoRefresh(const uint32_t *data, bool hires, bool interlace, bool overscan) {44unsigned width = hires ? 512 : 256;45unsigned height = overscan ? 239 : 224;46unsigned pitch = 1024 >> interlace;47if(interlace) height <<= 1;48data += 9 * 1024; //skip front porch4950for(unsigned y = 0; y < height; y++) {51const uint32_t *sp = data + y * pitch;52uint32_t *dp = buffer + y * pitch;53for(unsigned x = 0; x < width; x++) {54*dp++ = palette[*sp++];55}56}5758if(pvideo_refresh) pvideo_refresh(buffer, width, height);59if(pinput_poll) pinput_poll();60}6162void audioSample(int16_t left, int16_t right) {63if(paudio_sample) return paudio_sample(left, right);64}6566//zero 27-sep-201267snes_scanlineStart_t pScanlineStart;68void scanlineStart(int line)69{70if(pScanlineStart) pScanlineStart((int)line);71}7273int16_t inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id) {74if(pinput_state) return pinput_state(port?1:0, (unsigned)device, index, id);75return 0;76}7778void inputNotify(int index) {79if (pinput_notify) pinput_notify(index);80}8182void message(const string &text) {83messages.push(text);84}8586void cpuTrace(const char *msg) {87if (ptrace)88ptrace((const char *)msg);89}9091string path(SNES::Cartridge::Slot slot, const string &hint)92{93if(ppath_request)94{95const char* path = ppath_request((int)slot, (const char*)hint);96return path;97}98return { basename, hint };99}100101102//zero 23-dec-2012103void* allocSharedMemory(const char* memtype, size_t amt, int initialByte = -1)104{105void* ret;106//if pallocSharedMemory isnt set up yet, we're going to have serious problems107ret = pallocSharedMemory(memtype,amt);108if(initialByte != -1)109{110for(unsigned i = 0; i < amt; i++) ((uint8*)ret)[i] = (uint8)initialByte;111}112return ret;113}114void freeSharedMemory(void* ptr)115{116if(!pfreeSharedMemory) return; //??117pfreeSharedMemory(ptr);118}119120Interface() :121pvideo_refresh(0),122paudio_sample(0),123pinput_poll(0),124pinput_state(0),125pinput_notify(0),126ppath_request(0),127pScanlineStart(0),128pallocSharedMemory(0),129pfreeSharedMemory(0),130backdropColor(-1),131ptrace(0),132cart(nullptr, 0)133{134buffer = new uint32_t[512 * 480];135palette = new uint32_t[16 * 32768];136memset(&cdlInfo,0,sizeof(cdlInfo));137}138139~Interface() {140delete[] buffer;141delete[] palette;142}143};144145void pwrap_init();146Interface *iface = nullptr;147namespace SNES {148SNES::Interface *interface()149{150if(iface != nullptr) return iface;151iface = new ::Interface();152pwrap_init();153return iface;154}155}156157const char* snes_library_id(void) {158static string version = {"bsnes v", Version};159return version;160}161162unsigned snes_library_revision_major(void) {163return 1;164}165166unsigned snes_library_revision_minor(void) {167return 3;168}169170void snes_set_allocSharedMemory(snes_allocSharedMemory_t cb)171{172iface->pallocSharedMemory = cb;173}174void snes_set_freeSharedMemory(snes_freeSharedMemory_t cb)175{176iface->pfreeSharedMemory = cb;177}178179void snes_set_video_refresh(snes_video_refresh_t video_refresh) {180iface->pvideo_refresh = video_refresh;181}182183void snes_set_color_lut(uint32_t * colors) {184for (int i = 0; i < 16 * 32768; i++)185iface->palette[i] = colors[i];186}187188void snes_set_audio_sample(snes_audio_sample_t audio_sample) {189iface->paudio_sample = audio_sample;190}191192void snes_set_input_poll(snes_input_poll_t input_poll) {193iface->pinput_poll = input_poll;194}195196void snes_set_input_state(snes_input_state_t input_state) {197iface->pinput_state = input_state;198}199200void snes_set_input_notify(snes_input_notify_t input_notify) {201iface->pinput_notify = input_notify;202}203204void snes_set_path_request(snes_path_request_t path_request)205{206iface->ppath_request = path_request;207}208209void snes_set_controller_port_device(bool port, unsigned device) {210SNES::input.connect(port, (SNES::Input::Device)device);211}212213void snes_set_cartridge_basename(const char *basename) {214iface->basename = basename;215}216217template<typename T> inline void reconstruct(T* t) {218t->~T();219memset(t,0,sizeof(*t));220new(t) T();221}222223void snes_init(void) {224225//force everything to get initialized, even though it probably already is226SNES::interface();227228//zero 01-sep-2014 - this is too slow. made rewind totally boring. made other edits to firmware chips to preserve their roms instead229//zero 22-may-2014 - why not this too, for the sake of completeness?230//reconstruct(&SNES::cartridge);231232//zero 01-dec-2012 - due to systematic variable initialization fails in bsnes components, these reconstructions are necessary,233//and the previous comment here which called this paranoid has been removed.234reconstruct(&SNES::icd2);235reconstruct(&SNES::nss);236reconstruct(&SNES::superfx);237reconstruct(&SNES::sa1);238reconstruct(&SNES::necdsp);239reconstruct(&SNES::hitachidsp);240reconstruct(&SNES::armdsp);241reconstruct(&SNES::bsxsatellaview);242reconstruct(&SNES::bsxcartridge);243reconstruct(&SNES::bsxflash);244reconstruct(&SNES::srtc); SNES::srtc.initialize();245reconstruct(&SNES::sdd1);246reconstruct(&SNES::spc7110); SNES::spc7110.initialize();247reconstruct(&SNES::obc1);248reconstruct(&SNES::msu1);249reconstruct(&SNES::link);250reconstruct(&SNES::video);251reconstruct(&SNES::audio);252253//zero 01-dec-2012 - forgot to do all these. massive desync chaos!254//remove these to make it easier to find initialization fails in the component power-ons / constructors / etc.255//or just forget about it. this snes_init gets called paranoidly frequently by bizhawk, so things should stay zeroed correctly256reconstruct(&SNES::cpu); SNES::cpu.initialize();257reconstruct(&SNES::smp); SNES::smp.initialize();258reconstruct(&SNES::dsp);259reconstruct(&SNES::ppu);260SNES::ppu.initialize();261SNES::system.init();262263//zero 26-aug-2013 - yup. still more264reconstruct(&GameBoy::cpu); GameBoy::cpu.initialize();265266SNES::input.connect(SNES::Controller::Port1, SNES::Input::Device::Joypad);267SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::Joypad);268}269270void snes_term(void) {271SNES::system.term();272}273274void snes_power(void) {275SNES::system.power();276}277278void snes_reset(void) {279SNES::system.reset();280}281282void snes_run(void) {283SNES::system.run();284}285286unsigned snes_serialize_size(void) {287return SNES::system.serialize_size();288}289290bool snes_serialize(uint8_t *data, unsigned size) {291SNES::system.runtosave();292serializer s = SNES::system.serialize();293if(s.size() > size) return false;294memcpy(data, s.data(), s.size());295return true;296}297298bool snes_unserialize(const uint8_t *data, unsigned size) {299serializer s(data, size);300return SNES::system.unserialize(s);301}302303struct CheatList {304bool enable;305string code;306CheatList() : enable(false) {}307};308309static linear_vector<CheatList> cheatList;310311void snes_cheat_reset(void) {312cheatList.reset();313GameBoy::cheat.reset();314GameBoy::cheat.synchronize();315SNES::cheat.reset();316SNES::cheat.synchronize();317}318319void snes_cheat_set(unsigned index, bool enable, const char *code) {320cheatList[index].enable = enable;321cheatList[index].code = code;322lstring list;323for(unsigned n = 0; n < cheatList.size(); n++) {324if(cheatList[n].enable) list.append(cheatList[n].code);325}326327if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) {328GameBoy::cheat.reset();329for(auto &code : list) {330lstring codelist;331codelist.split("+", code);332for(auto &part : codelist) {333unsigned addr, data, comp;334if(GameBoy::Cheat::decode(part, addr, data, comp)) {335GameBoy::cheat.append({ addr, data, comp });336}337}338}339GameBoy::cheat.synchronize();340return;341}342343SNES::cheat.reset();344for(auto &code : list) {345lstring codelist;346codelist.split("+", code);347for(auto &part : codelist) {348unsigned addr, data;349if(SNES::Cheat::decode(part, addr, data)) {350SNES::cheat.append({ addr, data });351}352}353}354SNES::cheat.synchronize();355}356357//zero 21-sep-2012358void snes_set_scanlineStart(snes_scanlineStart_t cb)359{360iface->pScanlineStart = cb;361}362363//zero 03-sep-2012364bool snes_check_cartridge(const uint8_t *rom_data, unsigned rom_size)365{366//tries to determine whether this rom is a snes rom - BUT THIS TRIES TO ACCEPT EVERYTHING! so we cant really use it367SnesCartridge temp(rom_data, rom_size);368return temp.type != SnesCartridge::TypeUnknown && temp.type != SnesCartridge::TypeGameBoy;369}370371//zero 05-sep-2012372int snes_peek_logical_register(int reg)373{374switch(reg)375{376//$2105377//zero 17-may-2014 TODO - enable these for other profiles378#if !defined(PROFILE_PERFORMANCE) && !defined(PROFILE_ACCURACY)379case SNES_REG_BG_MODE: return SNES::ppu.regs.bg_mode;380case SNES_REG_BG3_PRIORITY: return SNES::ppu.regs.bg3_priority;381case SNES_REG_BG1_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG1];382case SNES_REG_BG2_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG2];383case SNES_REG_BG3_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG3];384case SNES_REG_BG4_TILESIZE: return SNES::ppu.regs.bg_tilesize[SNES::PPU::BG4];385386//$2107387case SNES_REG_BG1_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG1]>>9;388case SNES_REG_BG1_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG1];389//$2108390case SNES_REG_BG2_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG2]>>9;391case SNES_REG_BG2_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG2];392//$2109393case SNES_REG_BG3_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG3]>>9;394case SNES_REG_BG3_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG3];395//$210A396case SNES_REG_BG4_SCADDR: return SNES::ppu.regs.bg_scaddr[SNES::PPU::BG4]>>9;397case SNES_REG_BG4_SCSIZE: return SNES::ppu.regs.bg_scsize[SNES::PPU::BG4];398//$210B399case SNES_REG_BG1_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG1]>>13;400case SNES_REG_BG2_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG2]>>13;401//$210C402case SNES_REG_BG3_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG3]>>13;403case SNES_REG_BG4_TDADDR: return SNES::ppu.regs.bg_tdaddr[SNES::PPU::BG4]>>13;404//$2133 SETINI405case SNES_REG_SETINI_MODE7_EXTBG: return SNES::ppu.regs.mode7_extbg?1:0;406case SNES_REG_SETINI_HIRES: return SNES::ppu.regs.pseudo_hires?1:0;407case SNES_REG_SETINI_OVERSCAN: return SNES::ppu.regs.overscan?1:0;408case SNES_REG_SETINI_OBJ_INTERLACE: return SNES::ppu.regs.oam_interlace?1:0;409case SNES_REG_SETINI_SCREEN_INTERLACE: return SNES::ppu.regs.interlace?1:0;410//$2130 CGWSEL411case SNES_REG_CGWSEL_COLORMASK: return SNES::ppu.regs.color_mask;412case SNES_REG_CGWSEL_COLORSUBMASK: return SNES::ppu.regs.colorsub_mask;413case SNES_REG_CGWSEL_ADDSUBMODE: return SNES::ppu.regs.addsub_mode?1:0;414case SNES_REG_CGWSEL_DIRECTCOLOR: return SNES::ppu.regs.direct_color?1:0;415//$2101 OBSEL416case SNES_REG_OBSEL_NAMEBASE: return SNES::ppu.regs.oam_tdaddr>>14;417case SNES_REG_OBSEL_NAMESEL: return SNES::ppu.regs.oam_nameselect;418case SNES_REG_OBSEL_SIZE: return SNES::ppu.regs.oam_basesize;419//$2131 CGADSUB420//enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 };421case SNES_REG_CGADSUB_MODE: return SNES::ppu.regs.color_mode;422case SNES_REG_CGADSUB_HALF: return SNES::ppu.regs.color_halve;423case SNES_REG_CGADSUB_BG4: return SNES::ppu.regs.color_enabled[3];424case SNES_REG_CGADSUB_BG3: return SNES::ppu.regs.color_enabled[2];425case SNES_REG_CGADSUB_BG2: return SNES::ppu.regs.color_enabled[1];426case SNES_REG_CGADSUB_BG1: return SNES::ppu.regs.color_enabled[0];427case SNES_REG_CGADSUB_OBJ: return SNES::ppu.regs.color_enabled[4];428case SNES_REG_CGADSUB_BACKDROP: return SNES::ppu.regs.color_enabled[5];429//$212C TM430case SNES_REG_TM_BG1: return SNES::ppu.regs.bg_enabled[0];431case SNES_REG_TM_BG2: return SNES::ppu.regs.bg_enabled[1];432case SNES_REG_TM_BG3: return SNES::ppu.regs.bg_enabled[2];433case SNES_REG_TM_BG4: return SNES::ppu.regs.bg_enabled[3];434case SNES_REG_TM_OBJ: return SNES::ppu.regs.bg_enabled[4];435//$212D TM436case SNES_REG_TS_BG1: return SNES::ppu.regs.bgsub_enabled[0];437case SNES_REG_TS_BG2: return SNES::ppu.regs.bgsub_enabled[1];438case SNES_REG_TS_BG3: return SNES::ppu.regs.bgsub_enabled[2];439case SNES_REG_TS_BG4: return SNES::ppu.regs.bgsub_enabled[3];440case SNES_REG_TS_OBJ: return SNES::ppu.regs.bgsub_enabled[4];441//Mode7 regs442case SNES_REG_M7SEL_REPEAT: return SNES::ppu.regs.mode7_repeat;443case SNES_REG_M7SEL_HFLIP: return SNES::ppu.regs.mode7_vflip;444case SNES_REG_M7SEL_VFLIP: return SNES::ppu.regs.mode7_hflip;445case SNES_REG_M7A: return SNES::ppu.regs.m7a;446case SNES_REG_M7B: return SNES::ppu.regs.m7b;447case SNES_REG_M7C: return SNES::ppu.regs.m7c;448case SNES_REG_M7D: return SNES::ppu.regs.m7d;449case SNES_REG_M7X: return SNES::ppu.regs.m7x;450case SNES_REG_M7Y: return SNES::ppu.regs.m7y;451//BG scroll regs452case SNES_REG_BG1HOFS: return SNES::ppu.regs.bg_hofs[0] & 0x3FF;453case SNES_REG_BG1VOFS: return SNES::ppu.regs.bg_vofs[0] & 0x3FF;454case SNES_REG_BG2HOFS: return SNES::ppu.regs.bg_hofs[1] & 0x3FF;455case SNES_REG_BG2VOFS: return SNES::ppu.regs.bg_vofs[1] & 0x3FF;456case SNES_REG_BG3HOFS: return SNES::ppu.regs.bg_hofs[2] & 0x3FF;457case SNES_REG_BG3VOFS: return SNES::ppu.regs.bg_vofs[2] & 0x3FF;458case SNES_REG_BG4HOFS: return SNES::ppu.regs.bg_hofs[3] & 0x3FF;459case SNES_REG_BG4VOFS: return SNES::ppu.regs.bg_vofs[3] & 0x3FF;460case SNES_REG_M7HOFS: return SNES::ppu.regs.m7_hofs & 0x1FFF; //rememebr to make these signed with <<19>>19461case SNES_REG_M7VOFS: return SNES::ppu.regs.m7_vofs & 0x1FFF; //rememebr to make these signed with <<19>>19462#endif463464}465return 0;466}467468bool snes_load_cartridge_normal(469const char *rom_xml, const uint8_t *rom_data, unsigned rom_size470) {471snes_cheat_reset();472if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);473iface->cart = SnesCartridge(rom_data, rom_size);474string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;475SNES::cartridge.load(SNES::Cartridge::Mode::Normal, { xmlrom });476SNES::system.power();477return true;478}479480bool snes_load_cartridge_bsx_slotted(481const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,482const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size483) {484snes_cheat_reset();485if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);486iface->cart = SnesCartridge(rom_data, rom_size);487string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;488if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size);489string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SnesCartridge(bsx_data, bsx_size).markup;490SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, xmlrom);491SNES::system.power();492return true;493}494495bool snes_load_cartridge_bsx(496const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,497const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size498) {499snes_cheat_reset();500if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);501iface->cart = SnesCartridge(rom_data, rom_size);502string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;503if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size);504string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SnesCartridge(bsx_data, bsx_size).markup;505SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, xmlrom);506SNES::system.power();507return true;508}509510bool snes_load_cartridge_sufami_turbo(511const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,512const char *sta_xml, const uint8_t *sta_data, unsigned sta_size,513const char *stb_xml, const uint8_t *stb_data, unsigned stb_size514) {515snes_cheat_reset();516if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);517iface->cart = SnesCartridge(rom_data, rom_size);518string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;519if(sta_data) SNES::sufamiturbo.slotA.rom.copy(sta_data, sta_size);520string xmlsta = (sta_xml && *sta_xml) ? string(sta_xml) : SnesCartridge(sta_data, sta_size).markup;521if(stb_data) SNES::sufamiturbo.slotB.rom.copy(stb_data, stb_size);522string xmlstb = (stb_xml && *stb_xml) ? string(stb_xml) : SnesCartridge(stb_data, stb_size).markup;523SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, xmlrom);524SNES::system.power();525return true;526}527528bool snes_load_cartridge_super_game_boy(529const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,530const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size531) {532snes_cheat_reset();533if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);534iface->cart = SnesCartridge(rom_data, rom_size);535string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : iface->cart.markup;536if(dmg_data) {537//GameBoyCartridge needs to modify dmg_data (for MMM01 emulation); so copy data538uint8_t *data = new uint8_t[dmg_size];539memcpy(data, dmg_data, dmg_size);540string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : GameBoyCartridge(data, dmg_size).markup;541GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, xmldmg, data, dmg_size);542delete[] data;543}544SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, xmlrom);545SNES::system.power();546return true;547}548549void snes_unload_cartridge(void) {550SNES::cartridge.unload();551}552553bool snes_get_region(void) {554return SNES::system.region() == SNES::System::Region::NTSC ? 0 : 1;555}556557char snes_get_mapper(void) {558return iface->cart.mapper;559}560561uint8_t* snes_get_memory_data(unsigned id) {562if(SNES::cartridge.loaded() == false) return 0;563564switch(id) {565case SNES_MEMORY_CARTRIDGE_RAM:566return SNES::cartridge.ram.data();567case SNES_MEMORY_CARTRIDGE_RTC:568if(SNES::cartridge.has_srtc()) return SNES::srtc.rtc;569if(SNES::cartridge.has_spc7110rtc()) return SNES::spc7110.rtc;570return 0;571case SNES_MEMORY_BSX_RAM:572if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;573return SNES::bsxcartridge.sram.data();574case SNES_MEMORY_BSX_PRAM:575if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;576return SNES::bsxcartridge.psram.data();577case SNES_MEMORY_SUFAMI_TURBO_A_RAM:578if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;579return SNES::sufamiturbo.slotA.ram.data();580case SNES_MEMORY_SUFAMI_TURBO_B_RAM:581if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;582return SNES::sufamiturbo.slotB.ram.data();583case SNES_MEMORY_GAME_BOY_CARTRAM:584if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;585return GameBoy::cartridge.ramdata;586//case SNES_MEMORY_GAME_BOY_RTC:587// if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;588// return GameBoy::cartridge.rtcdata;589case SNES_MEMORY_GAME_BOY_WRAM:590if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;591return GameBoy::cpu.wram;592case SNES_MEMORY_GAME_BOY_HRAM:593if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;594return GameBoy::cpu.hram;595596case SNES_MEMORY_WRAM:597return SNES::cpu.wram;598case SNES_MEMORY_APURAM:599return SNES::smp.apuram;600case SNES_MEMORY_VRAM:601return SNES::ppu.vram;602case SNES_MEMORY_OAM:603return SNES::ppu.oam;604case SNES_MEMORY_CGRAM:605return SNES::ppu.cgram;606607case SNES_MEMORY_CARTRIDGE_ROM:608return SNES::cartridge.rom.data();609}610611return 0;612}613614const char* snes_get_memory_id_name(unsigned id) {615if(SNES::cartridge.loaded() == false) return nullptr;616617switch(id) {618case SNES_MEMORY_CARTRIDGE_RAM:619return "CARTRIDGE_RAM";620case SNES_MEMORY_CARTRIDGE_RTC:621if(SNES::cartridge.has_srtc()) return "RTC";622if(SNES::cartridge.has_spc7110rtc()) return "SPC7110_RTC";623return nullptr;624case SNES_MEMORY_BSX_RAM:625if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;626return "BSX_SRAM";627case SNES_MEMORY_BSX_PRAM:628if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;629return "BSX_PSRAM";630case SNES_MEMORY_SUFAMI_TURBO_A_RAM:631if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;632return "SUFAMI_SLOTARAM";633case SNES_MEMORY_SUFAMI_TURBO_B_RAM:634if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;635return "SUFAMI_SLOTBRAM";636case SNES_MEMORY_GAME_BOY_CARTRAM:637if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;638//return GameBoy::cartridge.ramdata;639return "SGB_CARTRAM";640//case SNES_MEMORY_GAME_BOY_RTC:641// if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;642// return GameBoy::cartridge.rtcdata;643case SNES_MEMORY_GAME_BOY_WRAM:644if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;645//see notes in SetupMemoryDomains in bizhawk646return "SGB_WRAM";647case SNES_MEMORY_GAME_BOY_HRAM:648if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;649return "SGB_HRAM";650651case SNES_MEMORY_WRAM:652//return SNES::cpu.wram;653return "WRAM";654case SNES_MEMORY_APURAM:655//return SNES::smp.apuram;656return "APURAM";657case SNES_MEMORY_VRAM:658return "VRAM";659case SNES_MEMORY_OAM:660return "OAM";661case SNES_MEMORY_CGRAM:662return "CGRAM";663664case SNES_MEMORY_CARTRIDGE_ROM:665return "CARTRIDGE_ROM";666}667668return nullptr;669}670671unsigned snes_get_memory_size(unsigned id) {672if(SNES::cartridge.loaded() == false) return 0;673unsigned size = 0;674675switch(id) {676case SNES_MEMORY_CARTRIDGE_RAM:677size = SNES::cartridge.ram.size();678break;679case SNES_MEMORY_CARTRIDGE_RTC:680if(SNES::cartridge.has_srtc() || SNES::cartridge.has_spc7110rtc()) size = 20;681break;682case SNES_MEMORY_BSX_RAM:683if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;684size = SNES::bsxcartridge.sram.size();685break;686case SNES_MEMORY_BSX_PRAM:687if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;688size = SNES::bsxcartridge.psram.size();689break;690case SNES_MEMORY_SUFAMI_TURBO_A_RAM:691if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;692size = SNES::sufamiturbo.slotA.ram.size();693break;694case SNES_MEMORY_SUFAMI_TURBO_B_RAM:695if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;696size = SNES::sufamiturbo.slotB.ram.size();697break;698case SNES_MEMORY_GAME_BOY_CARTRAM:699if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;700size = GameBoy::cartridge.ramsize;701break;702//case SNES_MEMORY_GAME_BOY_RTC:703// if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;704// size = GameBoy::cartridge.rtcsize;705// break;706case SNES_MEMORY_GAME_BOY_WRAM:707if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;708//see notes in SetupMemoryDomains in bizhawk709size = 32768;710break;711case SNES_MEMORY_GAME_BOY_HRAM:712if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;713size = 128;714break;715716case SNES_MEMORY_WRAM:717size = 128 * 1024;718break;719case SNES_MEMORY_APURAM:720size = 64 * 1024;721break;722case SNES_MEMORY_VRAM:723size = 64 * 1024;724break;725case SNES_MEMORY_OAM:726size = 544;727break;728case SNES_MEMORY_CGRAM:729size = 512;730break;731732case SNES_MEMORY_CARTRIDGE_ROM:733size = SNES::cartridge.rom.size();734break;735}736737if(size == -1U) size = 0;738return size;739}740741uint8_t bus_read(unsigned addr) {742return SNES::bus.read(addr);743}744void bus_write(unsigned addr, uint8_t val) {745SNES::bus.write(addr, val);746}747748int snes_poll_message()749{750if(iface->messages.empty()) return -1;751return iface->messages.front().length();752}753void snes_dequeue_message(char* buffer)754{755int len = iface->messages.front().length();756memcpy(buffer,(const char*)iface->messages.front(),len);757iface->messages.pop();758}759760void snes_set_backdropColor(int color)761{762iface->backdropColor = color;763}764765void snes_set_trace_callback(snes_trace_t callback)766{767if (callback)768{769iface->wanttrace = true;770iface->ptrace = callback;771}772else773{774iface->wanttrace = false;775iface->ptrace = 0;776}777}778779