mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-23 01:51:36 +02:00
Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7f404e6edb | ||
|
47dffcae85 | ||
|
be625cc0fb | ||
|
4cb8b51606 | ||
|
87cb164f7c | ||
|
c1318961d8 | ||
|
791e64951b | ||
|
27af50099f | ||
|
fbd52c7e5f | ||
|
36795e8061 | ||
|
ec8350794a | ||
|
4545e7c62d | ||
|
3302398907 | ||
|
189e707594 | ||
|
9a8a54c75e | ||
|
d418eda97c | ||
|
5dbd5f4d0f | ||
|
d6001a2df4 | ||
|
bd61432322 | ||
|
0611fefefa | ||
|
6ac7b733bd | ||
|
a1e4c67a05 | ||
|
73ebe093b8 | ||
|
c3f9d421da | ||
|
689fc49047 | ||
|
cb97d98ad2 | ||
|
3cb04b101b | ||
|
5d273c5265 | ||
|
8703d57030 | ||
|
9ad8b7eaac | ||
|
76553756a2 | ||
|
4fd20f0ae0 | ||
|
bb4db22a7d | ||
|
67c13f749f | ||
|
616372e96b | ||
|
bba597fc6f | ||
|
abe639ea91 |
29
bsnes/Makefile
Executable file → Normal file
29
bsnes/Makefile
Executable file → Normal file
@@ -1,14 +1,17 @@
|
||||
include nall/Makefile
|
||||
|
||||
nes := nes
|
||||
snes := snes
|
||||
gb := gb
|
||||
gba := gba
|
||||
fc := fc
|
||||
sfc := sfc
|
||||
gb := gb
|
||||
gba := gba
|
||||
nds := nds
|
||||
|
||||
profile := accuracy
|
||||
target := ui
|
||||
target := ethos
|
||||
|
||||
# options += console
|
||||
# options += debugger
|
||||
# arch := win32
|
||||
# console := true
|
||||
|
||||
# compiler
|
||||
c := $(compiler) -std=gnu99
|
||||
@@ -34,7 +37,15 @@ ifeq ($(platform),x)
|
||||
link += -ldl -lX11 -lXext
|
||||
else ifeq ($(platform),osx)
|
||||
else ifeq ($(platform),win)
|
||||
link += $(if $(findstring console,$(options)),-mconsole,-mwindows)
|
||||
ifeq ($(arch),win32)
|
||||
flags += -m32
|
||||
link += -m32
|
||||
endif
|
||||
ifeq ($(console),true)
|
||||
link += -mconsole
|
||||
else
|
||||
link += -mwindows
|
||||
endif
|
||||
link += -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32
|
||||
link += -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||
else
|
||||
@@ -94,7 +105,7 @@ sync:
|
||||
rm -r phoenix/test
|
||||
|
||||
archive:
|
||||
if [ -f bsnes.tar.bz2 ]; then rm bsnes.tar.bz2; fi
|
||||
tar -cjf bsnes.tar.bz2 `ls`
|
||||
if [ -f bsnes.tar.xz ]; then rm bsnes.tar.xz; fi
|
||||
tar -cJf bsnes.tar.xz `ls`
|
||||
|
||||
help:;
|
||||
|
@@ -1,2 +0,0 @@
|
||||
@mingw32-make -j 8
|
||||
@pause
|
0
bsnes/data/bsnes.Manifest
Executable file → Normal file
0
bsnes/data/bsnes.Manifest
Executable file → Normal file
0
bsnes/data/bsnes.desktop
Executable file → Normal file
0
bsnes/data/bsnes.desktop
Executable file → Normal file
0
bsnes/data/bsnes.ico
Executable file → Normal file
0
bsnes/data/bsnes.ico
Executable file → Normal file
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
0
bsnes/data/bsnes.png
Executable file → Normal file
0
bsnes/data/bsnes.png
Executable file → Normal file
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
218557
bsnes/data/cheats.xml
Executable file → Normal file
218557
bsnes/data/cheats.xml
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
0
bsnes/data/laevateinn.hpp
Executable file → Normal file
0
bsnes/data/laevateinn.hpp
Executable file → Normal file
27
bsnes/base/base.hpp → bsnes/emulator/emulator.hpp
Executable file → Normal file
27
bsnes/base/base.hpp → bsnes/emulator/emulator.hpp
Executable file → Normal file
@@ -1,30 +1,37 @@
|
||||
#ifndef BASE_HPP
|
||||
#define BASE_HPP
|
||||
#ifndef EMULATOR_HPP
|
||||
#define EMULATOR_HPP
|
||||
|
||||
static const char Version[] = "088";
|
||||
namespace Emulator {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "091";
|
||||
static const char Author[] = "byuu";
|
||||
static const char License[] = "GPLv3";
|
||||
}
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/algorithm.hpp>
|
||||
#include <nall/any.hpp>
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/bitarray.hpp>
|
||||
#include <nall/directory.hpp>
|
||||
#include <nall/dl.hpp>
|
||||
#include <nall/dsp.hpp>
|
||||
#include <nall/endian.hpp>
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/moduloarray.hpp>
|
||||
#include <nall/priorityqueue.hpp>
|
||||
#include <nall/priority-queue.hpp>
|
||||
#include <nall/property.hpp>
|
||||
#include <nall/random.hpp>
|
||||
#include <nall/serializer.hpp>
|
||||
#include <nall/sha256.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
#include <nall/varint.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
#include <nall/stream/memory.hpp>
|
||||
#include <nall/stream/vector.hpp>
|
||||
using namespace nall;
|
||||
|
||||
#include "interface.hpp"
|
||||
|
||||
//debugging function hook:
|
||||
//no overhead (and no debugger invocation) if not compiled with -DDEBUGGER
|
||||
//wraps testing of function to allow invocation without a defined callback
|
||||
@@ -43,8 +50,8 @@ template<typename R, typename... P> struct hook<R (P...)> {
|
||||
hook(const hook &hook) { callback = hook.callback; }
|
||||
hook(void *function) { callback = function; }
|
||||
hook(R (*function)(P...)) { callback = function; }
|
||||
template<typename C> hook(R (C::*function)(P...), C *object) { callback = { function, object }; }
|
||||
template<typename C> hook(R (C::*function)(P...) const, C *object) { callback = { function, object }; }
|
||||
template<typename C> hook(R (C::*function)(P...), C *object) { callback = {function, object}; }
|
||||
template<typename C> hook(R (C::*function)(P...) const, C *object) { callback = {function, object}; }
|
||||
template<typename L> hook(const L& function) { callback = function; }
|
||||
|
||||
hook& operator=(const hook& hook) { callback = hook.callback; return *this; }
|
118
bsnes/emulator/interface.hpp
Normal file
118
bsnes/emulator/interface.hpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifndef EMULATOR_INTERFACE_HPP
|
||||
#define EMULATOR_INTERFACE_HPP
|
||||
|
||||
namespace Emulator {
|
||||
|
||||
struct Interface {
|
||||
struct Information {
|
||||
string name;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
bool overscan;
|
||||
double aspectRatio;
|
||||
bool resettable;
|
||||
struct Capability {
|
||||
bool states;
|
||||
bool cheats;
|
||||
} capability;
|
||||
} information;
|
||||
|
||||
struct Media {
|
||||
unsigned id;
|
||||
string name;
|
||||
string type;
|
||||
string load;
|
||||
};
|
||||
|
||||
vector<Media> media;
|
||||
|
||||
struct Device {
|
||||
unsigned id;
|
||||
unsigned portmask;
|
||||
string name;
|
||||
struct Input {
|
||||
unsigned id;
|
||||
unsigned type; //0 = digital, 1 = analog (relative), 2 = analog (absolute)
|
||||
string name;
|
||||
unsigned guid;
|
||||
};
|
||||
vector<Input> input;
|
||||
vector<unsigned> order;
|
||||
};
|
||||
|
||||
struct Port {
|
||||
unsigned id;
|
||||
string name;
|
||||
vector<Device> device;
|
||||
};
|
||||
vector<Port> port;
|
||||
|
||||
struct Bind {
|
||||
virtual void loadRequest(unsigned, const string&, const string&) {}
|
||||
virtual void loadRequest(unsigned, const string&) {}
|
||||
virtual void saveRequest(unsigned, const string&) {}
|
||||
virtual uint32_t videoColor(unsigned, uint16_t, uint16_t, uint16_t) { return 0u; }
|
||||
virtual void videoRefresh(const uint32_t*, unsigned, unsigned, unsigned) {}
|
||||
virtual void audioSample(int16_t, int16_t) {}
|
||||
virtual int16_t inputPoll(unsigned, unsigned, unsigned) { return 0; }
|
||||
virtual unsigned dipSettings(const XML::Node&) { return 0; }
|
||||
virtual string path(unsigned) { return ""; }
|
||||
virtual void notify(const string &text) { print(text, "\n"); }
|
||||
} *bind;
|
||||
|
||||
//callback bindings (provided by user interface)
|
||||
void loadRequest(unsigned id, const string &name, const string &type) { return bind->loadRequest(id, name, type); }
|
||||
void loadRequest(unsigned id, const string &path) { return bind->loadRequest(id, path); }
|
||||
void saveRequest(unsigned id, const string &path) { return bind->saveRequest(id, path); }
|
||||
uint32_t videoColor(unsigned source, uint16_t red, uint16_t green, uint16_t blue) { return bind->videoColor(source, red, green, blue); }
|
||||
void videoRefresh(const uint32_t *data, unsigned pitch, unsigned width, unsigned height) { return bind->videoRefresh(data, pitch, width, height); }
|
||||
void audioSample(int16_t lsample, int16_t rsample) { return bind->audioSample(lsample, rsample); }
|
||||
int16_t inputPoll(unsigned port, unsigned device, unsigned input) { return bind->inputPoll(port, device, input); }
|
||||
unsigned dipSettings(const XML::Node &node) { return bind->dipSettings(node); }
|
||||
string path(unsigned group) { return bind->path(group); }
|
||||
template<typename... Args> void notify(Args&... args) { return bind->notify({std::forward<Args>(args)...}); }
|
||||
|
||||
//information
|
||||
virtual double videoFrequency() = 0;
|
||||
virtual double audioFrequency() = 0;
|
||||
|
||||
//media interface
|
||||
virtual bool loaded() { return false; }
|
||||
virtual string sha256() { return ""; }
|
||||
virtual unsigned group(unsigned id) = 0;
|
||||
virtual void load(unsigned id, const string &manifest) {}
|
||||
virtual void save() {}
|
||||
virtual void load(unsigned id, const stream &memory, const string &markup = "") {}
|
||||
virtual void save(unsigned id, const stream &memory) {}
|
||||
virtual void unload() {}
|
||||
|
||||
//system interface
|
||||
virtual void connect(unsigned port, unsigned device) {}
|
||||
virtual void power() {}
|
||||
virtual void reset() {}
|
||||
virtual void run() {}
|
||||
|
||||
//time functions
|
||||
virtual bool rtc() { return false; }
|
||||
virtual void rtcsync() {}
|
||||
|
||||
//state functions
|
||||
virtual serializer serialize() = 0;
|
||||
virtual bool unserialize(serializer&) = 0;
|
||||
|
||||
//cheat functions
|
||||
virtual void cheatSet(const lstring& = lstring{}) {}
|
||||
|
||||
//utility functions
|
||||
virtual void paletteUpdate() {}
|
||||
|
||||
//debugger functions
|
||||
virtual bool tracerEnable(bool) { return false; }
|
||||
virtual void exportMemory() {}
|
||||
|
||||
Interface() : bind(nullptr) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
16
bsnes/fc/Makefile
Normal file
16
bsnes/fc/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
fc_objects := fc-interface fc-system fc-scheduler fc-input
|
||||
fc_objects += fc-memory fc-cartridge fc-cpu fc-apu fc-ppu
|
||||
fc_objects += fc-cheat fc-video
|
||||
objects += $(fc_objects)
|
||||
|
||||
obj/fc-interface.o: $(fc)/interface/interface.cpp $(call rwildcard,$(fc)/interface/)
|
||||
obj/fc-system.o: $(fc)/system/system.cpp $(call rwildcard,$(fc)/system/)
|
||||
obj/fc-scheduler.o: $(fc)/scheduler/scheduler.cpp $(call rwildcard,$(fc)/scheduler/)
|
||||
obj/fc-input.o: $(fc)/input/input.cpp $(call rwildcard,$(fc)/input/)
|
||||
obj/fc-memory.o: $(fc)/memory/memory.cpp $(call rwildcard,$(fc)/memory/)
|
||||
obj/fc-cartridge.o: $(fc)/cartridge/cartridge.cpp $(call rwildcard,$(fc)/cartridge/)
|
||||
obj/fc-cpu.o: $(fc)/cpu/cpu.cpp $(call rwildcard,$(fc)/cpu/)
|
||||
obj/fc-apu.o: $(fc)/apu/apu.cpp $(call rwildcard,$(fc)/apu/)
|
||||
obj/fc-ppu.o: $(fc)/ppu/ppu.cpp $(call rwildcard,$(fc)/ppu/)
|
||||
obj/fc-cheat.o: $(fc)/cheat/cheat.cpp $(call rwildcard,$(fc)/cheat/)
|
||||
obj/fc-video.o: $(fc)/video/video.cpp $(call rwildcard,$(fc)/video/)
|
6
bsnes/nes/apu/apu.cpp → bsnes/fc/apu/apu.cpp
Executable file → Normal file
6
bsnes/nes/apu/apu.cpp → bsnes/fc/apu/apu.cpp
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
#include "envelope.cpp"
|
||||
#include "sweep.cpp"
|
||||
@@ -60,7 +60,7 @@ void APU::main() {
|
||||
//output = filter.run_lopass(output);
|
||||
output = sclamp<16>(output);
|
||||
|
||||
interface->audioSample(output);
|
||||
interface->audioSample(output, output);
|
||||
|
||||
tick();
|
||||
}
|
0
bsnes/nes/apu/apu.hpp → bsnes/fc/apu/apu.hpp
Executable file → Normal file
0
bsnes/nes/apu/apu.hpp → bsnes/fc/apu/apu.hpp
Executable file → Normal file
0
bsnes/nes/apu/dmc.cpp → bsnes/fc/apu/dmc.cpp
Executable file → Normal file
0
bsnes/nes/apu/dmc.cpp → bsnes/fc/apu/dmc.cpp
Executable file → Normal file
0
bsnes/nes/apu/dmc.hpp → bsnes/fc/apu/dmc.hpp
Executable file → Normal file
0
bsnes/nes/apu/dmc.hpp → bsnes/fc/apu/dmc.hpp
Executable file → Normal file
0
bsnes/nes/apu/envelope.cpp → bsnes/fc/apu/envelope.cpp
Executable file → Normal file
0
bsnes/nes/apu/envelope.cpp → bsnes/fc/apu/envelope.cpp
Executable file → Normal file
0
bsnes/nes/apu/envelope.hpp → bsnes/fc/apu/envelope.hpp
Executable file → Normal file
0
bsnes/nes/apu/envelope.hpp → bsnes/fc/apu/envelope.hpp
Executable file → Normal file
0
bsnes/nes/apu/noise.cpp → bsnes/fc/apu/noise.cpp
Executable file → Normal file
0
bsnes/nes/apu/noise.cpp → bsnes/fc/apu/noise.cpp
Executable file → Normal file
0
bsnes/nes/apu/noise.hpp → bsnes/fc/apu/noise.hpp
Executable file → Normal file
0
bsnes/nes/apu/noise.hpp → bsnes/fc/apu/noise.hpp
Executable file → Normal file
0
bsnes/nes/apu/pulse.cpp → bsnes/fc/apu/pulse.cpp
Executable file → Normal file
0
bsnes/nes/apu/pulse.cpp → bsnes/fc/apu/pulse.cpp
Executable file → Normal file
0
bsnes/nes/apu/pulse.hpp → bsnes/fc/apu/pulse.hpp
Executable file → Normal file
0
bsnes/nes/apu/pulse.hpp → bsnes/fc/apu/pulse.hpp
Executable file → Normal file
0
bsnes/nes/apu/serialization.cpp → bsnes/fc/apu/serialization.cpp
Executable file → Normal file
0
bsnes/nes/apu/serialization.cpp → bsnes/fc/apu/serialization.cpp
Executable file → Normal file
0
bsnes/nes/apu/sweep.cpp → bsnes/fc/apu/sweep.cpp
Executable file → Normal file
0
bsnes/nes/apu/sweep.cpp → bsnes/fc/apu/sweep.cpp
Executable file → Normal file
0
bsnes/nes/apu/sweep.hpp → bsnes/fc/apu/sweep.hpp
Executable file → Normal file
0
bsnes/nes/apu/sweep.hpp → bsnes/fc/apu/sweep.hpp
Executable file → Normal file
0
bsnes/nes/apu/triangle.cpp → bsnes/fc/apu/triangle.cpp
Executable file → Normal file
0
bsnes/nes/apu/triangle.cpp → bsnes/fc/apu/triangle.cpp
Executable file → Normal file
0
bsnes/nes/apu/triangle.hpp → bsnes/fc/apu/triangle.hpp
Executable file → Normal file
0
bsnes/nes/apu/triangle.hpp → bsnes/fc/apu/triangle.hpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/bandai-fcg.cpp → bsnes/fc/cartridge/board/bandai-fcg.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/bandai-fcg.cpp → bsnes/fc/cartridge/board/bandai-fcg.cpp
Executable file → Normal file
@@ -111,7 +111,7 @@ void serialize(serializer &s) {
|
||||
s.integer(irq_latch);
|
||||
}
|
||||
|
||||
BandaiFCG(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
BandaiFCG(XML::Document &document) : Board(document) {
|
||||
}
|
||||
|
||||
};
|
174
bsnes/fc/cartridge/board/board.cpp
Normal file
174
bsnes/fc/cartridge/board/board.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
#include "bandai-fcg.cpp"
|
||||
#include "konami-vrc1.cpp"
|
||||
#include "konami-vrc2.cpp"
|
||||
#include "konami-vrc3.cpp"
|
||||
#include "konami-vrc4.cpp"
|
||||
#include "konami-vrc6.cpp"
|
||||
#include "konami-vrc7.cpp"
|
||||
#include "nes-axrom.cpp"
|
||||
#include "nes-bnrom.cpp"
|
||||
#include "nes-cnrom.cpp"
|
||||
#include "nes-exrom.cpp"
|
||||
#include "nes-fxrom.cpp"
|
||||
#include "nes-gxrom.cpp"
|
||||
#include "nes-hkrom.cpp"
|
||||
#include "nes-nrom.cpp"
|
||||
#include "nes-pxrom.cpp"
|
||||
#include "nes-sxrom.cpp"
|
||||
#include "nes-txrom.cpp"
|
||||
#include "nes-uxrom.cpp"
|
||||
#include "sunsoft-5b.cpp"
|
||||
|
||||
uint8 Board::Memory::read(unsigned addr) const {
|
||||
return data[mirror(addr, size)];
|
||||
}
|
||||
|
||||
void Board::Memory::write(unsigned addr, uint8 byte) {
|
||||
if(writable) data[mirror(addr, size)] = byte;
|
||||
}
|
||||
|
||||
unsigned Board::mirror(unsigned addr, unsigned size) {
|
||||
unsigned base = 0;
|
||||
if(size) {
|
||||
unsigned mask = 1 << 23;
|
||||
while(addr >= size) {
|
||||
while(!(addr & mask)) mask >>= 1;
|
||||
addr -= mask;
|
||||
if(size > mask) {
|
||||
size -= mask;
|
||||
base += mask;
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
base += addr;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
void Board::main() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
cartridge.clock += 12 * 4095;
|
||||
tick();
|
||||
}
|
||||
}
|
||||
|
||||
void Board::tick() {
|
||||
cartridge.clock += 12;
|
||||
if(cartridge.clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
|
||||
}
|
||||
|
||||
uint8 Board::chr_read(unsigned addr) {
|
||||
if(chrram.size) return chrram.data[mirror(addr, chrram.size)];
|
||||
if(chrrom.size) return chrrom.data[mirror(addr, chrrom.size)];
|
||||
return 0u;
|
||||
}
|
||||
|
||||
void Board::chr_write(unsigned addr, uint8 data) {
|
||||
if(chrram.size) chrram.data[mirror(addr, chrram.size)] = data;
|
||||
}
|
||||
|
||||
void Board::power() {
|
||||
}
|
||||
|
||||
void Board::reset() {
|
||||
}
|
||||
|
||||
void Board::serialize(serializer &s) {
|
||||
if(prgram.size) s.array(prgram.data, prgram.size);
|
||||
if(chrram.size) s.array(chrram.data, chrram.size);
|
||||
}
|
||||
|
||||
Board::Board(XML::Document &document) {
|
||||
cartridge.board = this;
|
||||
auto &cartridge = document["cartridge"];
|
||||
|
||||
information.type = cartridge["board"]["type"].data;
|
||||
information.battery = cartridge["prg"]["ram"]["nonvolatile"].data == "true";
|
||||
|
||||
auto &prom = cartridge["prg"]["rom"];
|
||||
auto &pram = cartridge["prg"]["ram"];
|
||||
auto &crom = cartridge["chr"]["rom"];
|
||||
auto &cram = cartridge["chr"]["ram"];
|
||||
|
||||
prgrom.size = numeral(prom["size"].data);
|
||||
prgram.size = numeral(pram["size"].data);
|
||||
chrrom.size = numeral(crom["size"].data);
|
||||
chrram.size = numeral(cram["size"].data);
|
||||
|
||||
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
|
||||
if(prgram.size) prgram.data = new uint8[prgram.size]();
|
||||
if(chrrom.size) chrrom.data = new uint8[chrrom.size]();
|
||||
if(chrram.size) chrram.data = new uint8[chrram.size]();
|
||||
|
||||
if(prom["name"].data) interface->loadRequest(ID::ProgramROM, prom["name"].data);
|
||||
if(pram["name"].data) interface->loadRequest(ID::ProgramRAM, pram["name"].data);
|
||||
if(crom["name"].data) interface->loadRequest(ID::CharacterROM, crom["name"].data);
|
||||
if(cram["name"].data) interface->loadRequest(ID::CharacterRAM, cram["name"].data);
|
||||
|
||||
if(pram["name"].data) Famicom::cartridge.memory.append({ID::ProgramRAM, pram["name"].data});
|
||||
if(cram["name"].data) Famicom::cartridge.memory.append({ID::CharacterRAM, cram["name"].data});
|
||||
|
||||
prgram.writable = true;
|
||||
chrram.writable = true;
|
||||
}
|
||||
|
||||
Board::~Board() {
|
||||
}
|
||||
|
||||
Board* Board::load(const string &manifest) {
|
||||
XML::Document document(manifest);
|
||||
string type = document["cartridge"]["board"]["type"].data;
|
||||
|
||||
if(type == "BANDAI-FCG" ) return new BandaiFCG(document);
|
||||
|
||||
if(type == "KONAMI-VRC-1") return new KonamiVRC1(document);
|
||||
if(type == "KONAMI-VRC-2") return new KonamiVRC2(document);
|
||||
if(type == "KONAMI-VRC-3") return new KonamiVRC3(document);
|
||||
if(type == "KONAMI-VRC-4") return new KonamiVRC4(document);
|
||||
if(type == "KONAMI-VRC-6") return new KonamiVRC6(document);
|
||||
if(type == "KONAMI-VRC-7") return new KonamiVRC7(document);
|
||||
|
||||
if(type == "NES-AMROM" ) return new NES_AxROM(document);
|
||||
if(type == "NES-ANROM" ) return new NES_AxROM(document);
|
||||
if(type == "NES-AN1ROM" ) return new NES_AxROM(document);
|
||||
if(type == "NES-AOROM" ) return new NES_AxROM(document);
|
||||
|
||||
if(type == "NES-BNROM" ) return new NES_BNROM(document);
|
||||
|
||||
if(type == "NES-CNROM" ) return new NES_CNROM(document);
|
||||
|
||||
if(type == "NES-EKROM" ) return new NES_ExROM(document);
|
||||
if(type == "NES-ELROM" ) return new NES_ExROM(document);
|
||||
if(type == "NES-ETROM" ) return new NES_ExROM(document);
|
||||
if(type == "NES-EWROM" ) return new NES_ExROM(document);
|
||||
|
||||
if(type == "NES-FJROM" ) return new NES_FxROM(document);
|
||||
if(type == "NES-FKROM" ) return new NES_FxROM(document);
|
||||
|
||||
if(type == "NES-GNROM" ) return new NES_GxROM(document);
|
||||
if(type == "NES-MHROM" ) return new NES_GxROM(document);
|
||||
|
||||
if(type == "NES-HKROM" ) return new NES_HKROM(document);
|
||||
|
||||
if(type == "NES-NROM-128") return new NES_NROM(document);
|
||||
if(type == "NES-NROM-256") return new NES_NROM(document);
|
||||
|
||||
if(type == "NES-PEEOROM" ) return new NES_PxROM(document);
|
||||
if(type == "NES-PNROM" ) return new NES_PxROM(document);
|
||||
|
||||
if(type == "NES-SNROM" ) return new NES_SxROM(document);
|
||||
if(type == "NES-SXROM" ) return new NES_SxROM(document);
|
||||
|
||||
if(type == "NES-TLROM" ) return new NES_TxROM(document);
|
||||
|
||||
if(type == "NES-UNROM" ) return new NES_UxROM(document);
|
||||
if(type == "NES-UOROM" ) return new NES_UxROM(document);
|
||||
|
||||
if(type == "SUNSOFT-5B" ) return new Sunsoft5B(document);
|
||||
|
||||
return nullptr;
|
||||
}
|
6
bsnes/nes/cartridge/board/board.hpp → bsnes/fc/cartridge/board/board.hpp
Executable file → Normal file
6
bsnes/nes/cartridge/board/board.hpp → bsnes/fc/cartridge/board/board.hpp
Executable file → Normal file
@@ -25,16 +25,14 @@ struct Board {
|
||||
|
||||
virtual inline void scanline(unsigned y) {}
|
||||
|
||||
virtual Memory& memory();
|
||||
|
||||
virtual void power();
|
||||
virtual void reset();
|
||||
|
||||
virtual void serialize(serializer&);
|
||||
Board(XML::Document &document, const uint8_t *data, unsigned size);
|
||||
Board(XML::Document &document);
|
||||
virtual ~Board();
|
||||
|
||||
static Board* load(const string &markup, const uint8_t *data, unsigned size);
|
||||
static Board* load(const string &manifest);
|
||||
|
||||
struct Information {
|
||||
string type;
|
2
bsnes/nes/cartridge/board/konami-vrc1.cpp → bsnes/fc/cartridge/board/konami-vrc1.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/konami-vrc1.cpp → bsnes/fc/cartridge/board/konami-vrc1.cpp
Executable file → Normal file
@@ -34,7 +34,7 @@ void serialize(serializer &s) {
|
||||
vrc1.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC1(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc1(*this) {
|
||||
KonamiVRC1(XML::Document &document) : Board(document), vrc1(*this) {
|
||||
}
|
||||
|
||||
};
|
2
bsnes/nes/cartridge/board/konami-vrc2.cpp → bsnes/fc/cartridge/board/konami-vrc2.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/konami-vrc2.cpp → bsnes/fc/cartridge/board/konami-vrc2.cpp
Executable file → Normal file
@@ -49,7 +49,7 @@ void serialize(serializer &s) {
|
||||
vrc2.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC2(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc2(*this) {
|
||||
KonamiVRC2(XML::Document &document) : Board(document), vrc2(*this) {
|
||||
settings.pinout.a0 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a0"].data);
|
||||
settings.pinout.a1 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a1"].data);
|
||||
}
|
2
bsnes/nes/cartridge/board/konami-vrc3.cpp → bsnes/fc/cartridge/board/konami-vrc3.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/konami-vrc3.cpp → bsnes/fc/cartridge/board/konami-vrc3.cpp
Executable file → Normal file
@@ -50,7 +50,7 @@ void serialize(serializer &s) {
|
||||
vrc3.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC3(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc3(*this) {
|
||||
KonamiVRC3(XML::Document &document) : Board(document), vrc3(*this) {
|
||||
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/konami-vrc4.cpp → bsnes/fc/cartridge/board/konami-vrc4.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/konami-vrc4.cpp → bsnes/fc/cartridge/board/konami-vrc4.cpp
Executable file → Normal file
@@ -53,7 +53,7 @@ void serialize(serializer &s) {
|
||||
vrc4.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC4(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc4(*this) {
|
||||
KonamiVRC4(XML::Document &document) : Board(document), vrc4(*this) {
|
||||
settings.pinout.a0 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a0"].data);
|
||||
settings.pinout.a1 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a1"].data);
|
||||
}
|
2
bsnes/nes/cartridge/board/konami-vrc6.cpp → bsnes/fc/cartridge/board/konami-vrc6.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/konami-vrc6.cpp → bsnes/fc/cartridge/board/konami-vrc6.cpp
Executable file → Normal file
@@ -36,7 +36,7 @@ void main() { vrc6.main(); }
|
||||
void power() { vrc6.power(); }
|
||||
void reset() { vrc6.reset(); }
|
||||
|
||||
KonamiVRC6(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc6(*this) {
|
||||
KonamiVRC6(XML::Document &document) : Board(document), vrc6(*this) {
|
||||
}
|
||||
|
||||
};
|
2
bsnes/nes/cartridge/board/konami-vrc7.cpp → bsnes/fc/cartridge/board/konami-vrc7.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/konami-vrc7.cpp → bsnes/fc/cartridge/board/konami-vrc7.cpp
Executable file → Normal file
@@ -41,7 +41,7 @@ void serialize(serializer &s) {
|
||||
vrc7.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC7(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc7(*this) {
|
||||
KonamiVRC7(XML::Document &document) : Board(document), vrc7(*this) {
|
||||
}
|
||||
|
||||
};
|
2
bsnes/nes/cartridge/board/nes-axrom.cpp → bsnes/fc/cartridge/board/nes-axrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-axrom.cpp → bsnes/fc/cartridge/board/nes-axrom.cpp
Executable file → Normal file
@@ -45,7 +45,7 @@ void serialize(serializer &s) {
|
||||
s.integer(mirror_select);
|
||||
}
|
||||
|
||||
NES_AxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
NES_AxROM(XML::Document &document) : Board(document) {
|
||||
}
|
||||
|
||||
};
|
2
bsnes/nes/cartridge/board/nes-bnrom.cpp → bsnes/fc/cartridge/board/nes-bnrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-bnrom.cpp → bsnes/fc/cartridge/board/nes-bnrom.cpp
Executable file → Normal file
@@ -45,7 +45,7 @@ void serialize(serializer &s) {
|
||||
s.integer(prg_bank);
|
||||
}
|
||||
|
||||
NES_BNROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
NES_BNROM(XML::Document &document) : Board(document) {
|
||||
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/nes-cnrom.cpp → bsnes/fc/cartridge/board/nes-cnrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-cnrom.cpp → bsnes/fc/cartridge/board/nes-cnrom.cpp
Executable file → Normal file
@@ -47,7 +47,7 @@ void serialize(serializer &s) {
|
||||
s.integer(chr_bank);
|
||||
}
|
||||
|
||||
NES_CNROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
NES_CNROM(XML::Document &document) : Board(document) {
|
||||
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/nes-exrom.cpp → bsnes/fc/cartridge/board/nes-exrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-exrom.cpp → bsnes/fc/cartridge/board/nes-exrom.cpp
Executable file → Normal file
@@ -46,7 +46,7 @@ void serialize(serializer &s) {
|
||||
mmc5.serialize(s);
|
||||
}
|
||||
|
||||
NES_ExROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), mmc5(*this) {
|
||||
NES_ExROM(XML::Document &document) : Board(document), mmc5(*this) {
|
||||
revision = Revision::ELROM;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/nes-fxrom.cpp → bsnes/fc/cartridge/board/nes-fxrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-fxrom.cpp → bsnes/fc/cartridge/board/nes-fxrom.cpp
Executable file → Normal file
@@ -84,7 +84,7 @@ void serialize(serializer &s) {
|
||||
s.array(latch);
|
||||
}
|
||||
|
||||
NES_FxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
NES_FxROM(XML::Document &document) : Board(document) {
|
||||
revision = Revision::FKROM;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/nes-gxrom.cpp → bsnes/fc/cartridge/board/nes-gxrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-gxrom.cpp → bsnes/fc/cartridge/board/nes-gxrom.cpp
Executable file → Normal file
@@ -54,7 +54,7 @@ void serialize(serializer &s) {
|
||||
s.integer(chr_bank);
|
||||
}
|
||||
|
||||
NES_GxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
NES_GxROM(XML::Document &document) : Board(document) {
|
||||
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/nes-hkrom.cpp → bsnes/fc/cartridge/board/nes-hkrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-hkrom.cpp → bsnes/fc/cartridge/board/nes-hkrom.cpp
Executable file → Normal file
@@ -42,7 +42,7 @@ void serialize(serializer &s) {
|
||||
mmc6.serialize(s);
|
||||
}
|
||||
|
||||
NES_HKROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), mmc6(*this) {
|
||||
NES_HKROM(XML::Document &document) : Board(document), mmc6(*this) {
|
||||
}
|
||||
|
||||
};
|
2
bsnes/nes/cartridge/board/nes-nrom.cpp → bsnes/fc/cartridge/board/nes-nrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-nrom.cpp → bsnes/fc/cartridge/board/nes-nrom.cpp
Executable file → Normal file
@@ -36,7 +36,7 @@ void serialize(serializer &s) {
|
||||
Board::serialize(s);
|
||||
}
|
||||
|
||||
NES_NROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
NES_NROM(XML::Document &document) : Board(document) {
|
||||
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/nes-pxrom.cpp → bsnes/fc/cartridge/board/nes-pxrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-pxrom.cpp → bsnes/fc/cartridge/board/nes-pxrom.cpp
Executable file → Normal file
@@ -90,7 +90,7 @@ void serialize(serializer &s) {
|
||||
s.array(latch);
|
||||
}
|
||||
|
||||
NES_PxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
NES_PxROM(XML::Document &document) : Board(document) {
|
||||
revision = Revision::PNROM;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/nes-sxrom.cpp → bsnes/fc/cartridge/board/nes-sxrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-sxrom.cpp → bsnes/fc/cartridge/board/nes-sxrom.cpp
Executable file → Normal file
@@ -94,7 +94,7 @@ void serialize(serializer &s) {
|
||||
mmc1.serialize(s);
|
||||
}
|
||||
|
||||
NES_SxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), mmc1(*this) {
|
||||
NES_SxROM(XML::Document &document) : Board(document), mmc1(*this) {
|
||||
revision = Revision::SXROM;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/nes-txrom.cpp → bsnes/fc/cartridge/board/nes-txrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-txrom.cpp → bsnes/fc/cartridge/board/nes-txrom.cpp
Executable file → Normal file
@@ -60,7 +60,7 @@ void serialize(serializer &s) {
|
||||
mmc3.serialize(s);
|
||||
}
|
||||
|
||||
NES_TxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), mmc3(*this) {
|
||||
NES_TxROM(XML::Document &document) : Board(document), mmc3(*this) {
|
||||
revision = Revision::TLROM;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/nes-uxrom.cpp → bsnes/fc/cartridge/board/nes-uxrom.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/nes-uxrom.cpp → bsnes/fc/cartridge/board/nes-uxrom.cpp
Executable file → Normal file
@@ -48,7 +48,7 @@ void serialize(serializer &s) {
|
||||
s.integer(prg_bank);
|
||||
}
|
||||
|
||||
NES_UxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
NES_UxROM(XML::Document &document) : Board(document) {
|
||||
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
2
bsnes/nes/cartridge/board/sunsoft-5b.cpp → bsnes/fc/cartridge/board/sunsoft-5b.cpp
Executable file → Normal file
2
bsnes/nes/cartridge/board/sunsoft-5b.cpp → bsnes/fc/cartridge/board/sunsoft-5b.cpp
Executable file → Normal file
@@ -220,7 +220,7 @@ void serialize(serializer &s) {
|
||||
pulse[2].serialize(s);
|
||||
}
|
||||
|
||||
Sunsoft5B(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
|
||||
Sunsoft5B(XML::Document &document) : Board(document) {
|
||||
}
|
||||
|
||||
};
|
36
bsnes/nes/cartridge/cartridge.cpp → bsnes/fc/cartridge/cartridge.cpp
Executable file → Normal file
36
bsnes/nes/cartridge/cartridge.cpp → bsnes/fc/cartridge/cartridge.cpp
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
#include "chip/chip.cpp"
|
||||
#include "board/board.cpp"
|
||||
@@ -14,18 +14,23 @@ void Cartridge::main() {
|
||||
board->main();
|
||||
}
|
||||
|
||||
void Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
|
||||
information.markup = markup;
|
||||
void Cartridge::load(const string &manifest) {
|
||||
information.markup = manifest;
|
||||
|
||||
if((size & 0xff) == 0) {
|
||||
sha256 = nall::sha256(data, size);
|
||||
board = Board::load(markup, data, size);
|
||||
} else {
|
||||
sha256 = nall::sha256(data + 16, size - 16);
|
||||
board = Board::load(markup, data + 16, size - 16);
|
||||
}
|
||||
Board::load(manifest); //this call will set Cartridge::board if successful
|
||||
if(board == nullptr) return;
|
||||
|
||||
sha256_ctx sha;
|
||||
uint8 hash[32];
|
||||
sha256_init(&sha);
|
||||
sha256_chunk(&sha, board->prgrom.data, board->prgrom.size);
|
||||
sha256_chunk(&sha, board->chrrom.data, board->chrrom.size);
|
||||
sha256_final(&sha);
|
||||
sha256_hash(&sha, hash);
|
||||
string result;
|
||||
for(auto &byte : hash) result.append(hex<2>(byte));
|
||||
sha256 = result;
|
||||
|
||||
system.load();
|
||||
loaded = true;
|
||||
}
|
||||
@@ -33,14 +38,7 @@ void Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
|
||||
void Cartridge::unload() {
|
||||
if(loaded == false) return;
|
||||
loaded = false;
|
||||
}
|
||||
|
||||
unsigned Cartridge::ram_size() {
|
||||
return board->memory().size;
|
||||
}
|
||||
|
||||
uint8* Cartridge::ram_data() {
|
||||
return board->memory().data;
|
||||
memory.reset();
|
||||
}
|
||||
|
||||
void Cartridge::power() {
|
11
bsnes/nes/cartridge/cartridge.hpp → bsnes/fc/cartridge/cartridge.hpp
Executable file → Normal file
11
bsnes/nes/cartridge/cartridge.hpp → bsnes/fc/cartridge/cartridge.hpp
Executable file → Normal file
@@ -5,12 +5,9 @@ struct Cartridge : Thread, property<Cartridge> {
|
||||
static void Main();
|
||||
void main();
|
||||
|
||||
void load(const string &markup, const uint8_t *data, unsigned size);
|
||||
void load(const string &manifest);
|
||||
void unload();
|
||||
|
||||
unsigned ram_size();
|
||||
uint8* ram_data();
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
@@ -21,6 +18,12 @@ struct Cartridge : Thread, property<Cartridge> {
|
||||
string markup;
|
||||
} information;
|
||||
|
||||
struct Memory {
|
||||
unsigned id;
|
||||
string name;
|
||||
};
|
||||
vector<Memory> memory;
|
||||
|
||||
void serialize(serializer&);
|
||||
Cartridge();
|
||||
|
0
bsnes/nes/cartridge/chip/chip.cpp → bsnes/fc/cartridge/chip/chip.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/chip.cpp → bsnes/fc/cartridge/chip/chip.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/chip.hpp → bsnes/fc/cartridge/chip/chip.hpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/chip.hpp → bsnes/fc/cartridge/chip/chip.hpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/mmc1.cpp → bsnes/fc/cartridge/chip/mmc1.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/mmc1.cpp → bsnes/fc/cartridge/chip/mmc1.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/mmc3.cpp → bsnes/fc/cartridge/chip/mmc3.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/mmc3.cpp → bsnes/fc/cartridge/chip/mmc3.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/mmc5.cpp → bsnes/fc/cartridge/chip/mmc5.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/mmc5.cpp → bsnes/fc/cartridge/chip/mmc5.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/mmc6.cpp → bsnes/fc/cartridge/chip/mmc6.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/mmc6.cpp → bsnes/fc/cartridge/chip/mmc6.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc1.cpp → bsnes/fc/cartridge/chip/vrc1.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc1.cpp → bsnes/fc/cartridge/chip/vrc1.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc2.cpp → bsnes/fc/cartridge/chip/vrc2.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc2.cpp → bsnes/fc/cartridge/chip/vrc2.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc3.cpp → bsnes/fc/cartridge/chip/vrc3.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc3.cpp → bsnes/fc/cartridge/chip/vrc3.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc4.cpp → bsnes/fc/cartridge/chip/vrc4.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc4.cpp → bsnes/fc/cartridge/chip/vrc4.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc6.cpp → bsnes/fc/cartridge/chip/vrc6.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc6.cpp → bsnes/fc/cartridge/chip/vrc6.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc7.cpp → bsnes/fc/cartridge/chip/vrc7.cpp
Executable file → Normal file
0
bsnes/nes/cartridge/chip/vrc7.cpp → bsnes/fc/cartridge/chip/vrc7.cpp
Executable file → Normal file
4
bsnes/nes/cheat/cheat.cpp → bsnes/fc/cheat/cheat.cpp
Executable file → Normal file
4
bsnes/nes/cheat/cheat.cpp → bsnes/fc/cheat/cheat.cpp
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
Cheat cheat;
|
||||
|
2
bsnes/nes/cheat/cheat.hpp → bsnes/fc/cheat/cheat.hpp
Executable file → Normal file
2
bsnes/nes/cheat/cheat.hpp → bsnes/fc/cheat/cheat.hpp
Executable file → Normal file
@@ -4,7 +4,7 @@ struct CheatCode {
|
||||
unsigned comp;
|
||||
};
|
||||
|
||||
struct Cheat : public linear_vector<CheatCode> {
|
||||
struct Cheat : public vector<CheatCode> {
|
||||
static bool decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp);
|
||||
|
||||
void synchronize();
|
70
bsnes/nes/cpu/cpu.cpp → bsnes/fc/cpu/cpu.cpp
Executable file → Normal file
70
bsnes/nes/cpu/cpu.cpp → bsnes/fc/cpu/cpu.cpp
Executable file → Normal file
@@ -1,40 +1,30 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
#include "core/core.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
#include "timing.cpp"
|
||||
#include "serialization.cpp"
|
||||
CPU cpu;
|
||||
|
||||
void CPU::Main() {
|
||||
cpu.main();
|
||||
}
|
||||
|
||||
void CPU::main() {
|
||||
//trace = true;
|
||||
//FILE *fp = fopen("/home/byuu/Desktop/log.txt", "wb");
|
||||
|
||||
unsigned lpc = 0xffff;
|
||||
void CPU::Enter() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
if(status.interrupt_pending) {
|
||||
interrupt();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(trace) {
|
||||
if(lpc != regs.pc) { print(disassemble(), "\n"); } lpc = regs.pc;
|
||||
//if(lpc != regs.pc) { fprintf(fp, "%s\n", (const char*)disassemble()); fflush(fp); } lpc = regs.pc;
|
||||
}
|
||||
|
||||
op_exec();
|
||||
cpu.main();
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::main() {
|
||||
if(status.interrupt_pending) {
|
||||
interrupt();
|
||||
return;
|
||||
}
|
||||
|
||||
exec();
|
||||
}
|
||||
|
||||
void CPU::add_clocks(unsigned clocks) {
|
||||
apu.clock -= clocks;
|
||||
if(apu.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(apu.thread);
|
||||
@@ -47,11 +37,7 @@ void CPU::add_clocks(unsigned clocks) {
|
||||
}
|
||||
|
||||
void CPU::power() {
|
||||
regs.a = 0x00;
|
||||
regs.x = 0x00;
|
||||
regs.y = 0x00;
|
||||
regs.s = 0x00;
|
||||
regs.p = 0x04;
|
||||
R6502::power();
|
||||
|
||||
for(unsigned addr = 0; addr < 0x0800; addr++) ram[addr] = 0xff;
|
||||
ram[0x0008] = 0xf7;
|
||||
@@ -61,11 +47,8 @@ void CPU::power() {
|
||||
}
|
||||
|
||||
void CPU::reset() {
|
||||
create(CPU::Main, 21477272);
|
||||
|
||||
regs.mdr = 0x00;
|
||||
regs.s -= 3;
|
||||
regs.p.i = 1;
|
||||
R6502::reset();
|
||||
create(CPU::Enter, 21477272);
|
||||
|
||||
regs.pc = bus.read(0xfffc) << 0;
|
||||
regs.pc |= bus.read(0xfffd) << 8;
|
||||
@@ -87,16 +70,8 @@ void CPU::reset() {
|
||||
status.controller_port1 = 0;
|
||||
}
|
||||
|
||||
uint8 CPU::mdr() const {
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void CPU::set_rdy_line(bool line) {
|
||||
status.rdy_line = line;
|
||||
}
|
||||
|
||||
void CPU::set_rdy_addr(optional<uint16> addr) {
|
||||
status.rdy_addr = addr;
|
||||
uint8 CPU::debugger_read(uint16 addr) {
|
||||
return bus.read(addr);
|
||||
}
|
||||
|
||||
uint8 CPU::ram_read(uint16 addr) {
|
||||
@@ -132,11 +107,4 @@ void CPU::write(uint16 addr, uint8 data) {
|
||||
return apu.write(addr, data);
|
||||
}
|
||||
|
||||
void CPU::oam_dma() {
|
||||
for(unsigned n = 0; n < 256; n++) {
|
||||
uint8 data = op_read((status.oam_dma_page << 8) + n);
|
||||
op_write(0x2004, data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
28
bsnes/nes/cpu/cpu.hpp → bsnes/fc/cpu/cpu.hpp
Executable file → Normal file
28
bsnes/nes/cpu/cpu.hpp → bsnes/fc/cpu/cpu.hpp
Executable file → Normal file
@@ -1,6 +1,4 @@
|
||||
struct CPU : Thread {
|
||||
#include "core/core.hpp"
|
||||
#include "memory/memory.hpp"
|
||||
struct CPU : Processor::R6502, Thread {
|
||||
uint8 ram[0x0800];
|
||||
|
||||
struct Status {
|
||||
@@ -21,16 +19,14 @@ struct CPU : Thread {
|
||||
unsigned controller_port1;
|
||||
} status;
|
||||
|
||||
static void Main();
|
||||
static void Enter();
|
||||
void main();
|
||||
void add_clocks(unsigned clocks);
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mdr() const;
|
||||
void set_rdy_line(bool);
|
||||
void set_rdy_addr(optional<uint16>);
|
||||
uint8 debugger_read(uint16 addr);
|
||||
|
||||
uint8 ram_read(uint16 addr);
|
||||
void ram_write(uint16 addr, uint8 data);
|
||||
@@ -38,12 +34,22 @@ struct CPU : Thread {
|
||||
uint8 read(uint16 addr);
|
||||
void write(uint16 addr, uint8 data);
|
||||
|
||||
void oam_dma();
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
//internal:
|
||||
bool trace;
|
||||
//timing.cpp
|
||||
uint8 op_read(uint16 addr);
|
||||
void op_write(uint16 addr, uint8 data);
|
||||
void last_cycle();
|
||||
void nmi(uint16 &vector);
|
||||
|
||||
void oam_dma();
|
||||
|
||||
void set_nmi_line(bool);
|
||||
void set_irq_line(bool);
|
||||
void set_irq_apu_line(bool);
|
||||
|
||||
void set_rdy_line(bool);
|
||||
void set_rdy_addr(optional<uint16>);
|
||||
};
|
||||
|
||||
extern CPU cpu;
|
20
bsnes/nes/cpu/serialization.cpp → bsnes/fc/cpu/serialization.cpp
Executable file → Normal file
20
bsnes/nes/cpu/serialization.cpp → bsnes/fc/cpu/serialization.cpp
Executable file → Normal file
@@ -1,27 +1,9 @@
|
||||
void CPU::serialize(serializer &s) {
|
||||
R6502::serialize(s);
|
||||
Thread::serialize(s);
|
||||
|
||||
s.array(ram);
|
||||
|
||||
s.integer(regs.mdr);
|
||||
s.integer(regs.pc);
|
||||
s.integer(regs.a);
|
||||
s.integer(regs.x);
|
||||
s.integer(regs.y);
|
||||
s.integer(regs.s);
|
||||
s.integer(regs.p.n);
|
||||
s.integer(regs.p.v);
|
||||
s.integer(regs.p.d);
|
||||
s.integer(regs.p.i);
|
||||
s.integer(regs.p.z);
|
||||
s.integer(regs.p.c);
|
||||
|
||||
s.integer(abs.w);
|
||||
s.integer(iabs.w);
|
||||
s.integer(rd);
|
||||
s.integer(zp);
|
||||
s.integer(aa);
|
||||
|
||||
s.integer(status.interrupt_pending);
|
||||
s.integer(status.nmi_pending);
|
||||
s.integer(status.nmi_line);
|
63
bsnes/fc/cpu/timing.cpp
Normal file
63
bsnes/fc/cpu/timing.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
uint8 CPU::op_read(uint16 addr) {
|
||||
if(status.oam_dma_pending) {
|
||||
status.oam_dma_pending = false;
|
||||
op_read(addr);
|
||||
oam_dma();
|
||||
}
|
||||
|
||||
while(status.rdy_line == 0) {
|
||||
regs.mdr = bus.read(status.rdy_addr ? status.rdy_addr() : addr);
|
||||
add_clocks(12);
|
||||
}
|
||||
|
||||
regs.mdr = bus.read(addr);
|
||||
add_clocks(12);
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void CPU::op_write(uint16 addr, uint8 data) {
|
||||
bus.write(addr, regs.mdr = data);
|
||||
add_clocks(12);
|
||||
}
|
||||
|
||||
void CPU::last_cycle() {
|
||||
status.interrupt_pending = ((status.irq_line | status.irq_apu_line) & ~regs.p.i) | status.nmi_pending;
|
||||
}
|
||||
|
||||
void CPU::nmi(uint16 &vector) {
|
||||
if(status.nmi_pending) {
|
||||
status.nmi_pending = false;
|
||||
vector = 0xfffa;
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::oam_dma() {
|
||||
for(unsigned n = 0; n < 256; n++) {
|
||||
uint8 data = op_read((status.oam_dma_page << 8) + n);
|
||||
op_write(0x2004, data);
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::set_nmi_line(bool line) {
|
||||
//edge-sensitive (0->1)
|
||||
if(!status.nmi_line && line) status.nmi_pending = true;
|
||||
status.nmi_line = line;
|
||||
}
|
||||
|
||||
void CPU::set_irq_line(bool line) {
|
||||
//level-sensitive
|
||||
status.irq_line = line;
|
||||
}
|
||||
|
||||
void CPU::set_irq_apu_line(bool line) {
|
||||
//level-sensitive
|
||||
status.irq_apu_line = line;
|
||||
}
|
||||
|
||||
void CPU::set_rdy_line(bool line) {
|
||||
status.rdy_line = line;
|
||||
}
|
||||
|
||||
void CPU::set_rdy_addr(optional<uint16> addr) {
|
||||
status.rdy_addr = addr;
|
||||
}
|
37
bsnes/nes/nes.hpp → bsnes/fc/fc.hpp
Executable file → Normal file
37
bsnes/nes/nes.hpp → bsnes/fc/fc.hpp
Executable file → Normal file
@@ -1,17 +1,18 @@
|
||||
#ifndef NES_HPP
|
||||
#define NES_HPP
|
||||
#ifndef FC_HPP
|
||||
#define FC_HPP
|
||||
|
||||
#include <base/base.hpp>
|
||||
#include <emulator/emulator.hpp>
|
||||
#include <processor/r6502/r6502.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
namespace Info {
|
||||
static const char Name[] = "bnes";
|
||||
static const unsigned SerializerVersion = 1;
|
||||
static const unsigned SerializerVersion = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
bnes - NES emulator
|
||||
bnes - Famicom emulator
|
||||
authors: byuu, Ryphecha
|
||||
license: GPLv3
|
||||
project started: 2011-09-05
|
||||
@@ -19,7 +20,7 @@ namespace NES {
|
||||
|
||||
#include <libco/libco.h>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
struct Thread {
|
||||
cothread_t thread;
|
||||
unsigned frequency;
|
||||
@@ -45,17 +46,17 @@ namespace NES {
|
||||
}
|
||||
};
|
||||
|
||||
#include <nes/system/system.hpp>
|
||||
#include <nes/scheduler/scheduler.hpp>
|
||||
#include <nes/input/input.hpp>
|
||||
#include <nes/memory/memory.hpp>
|
||||
#include <nes/cartridge/cartridge.hpp>
|
||||
#include <nes/cpu/cpu.hpp>
|
||||
#include <nes/apu/apu.hpp>
|
||||
#include <nes/ppu/ppu.hpp>
|
||||
#include <nes/cheat/cheat.hpp>
|
||||
#include <nes/video/video.hpp>
|
||||
#include <nes/interface/interface.hpp>
|
||||
#include <fc/system/system.hpp>
|
||||
#include <fc/scheduler/scheduler.hpp>
|
||||
#include <fc/input/input.hpp>
|
||||
#include <fc/memory/memory.hpp>
|
||||
#include <fc/cartridge/cartridge.hpp>
|
||||
#include <fc/cpu/cpu.hpp>
|
||||
#include <fc/apu/apu.hpp>
|
||||
#include <fc/ppu/ppu.hpp>
|
||||
#include <fc/cheat/cheat.hpp>
|
||||
#include <fc/video/video.hpp>
|
||||
#include <fc/interface/interface.hpp>
|
||||
}
|
||||
|
||||
#endif
|
4
bsnes/nes/input/input.cpp → bsnes/fc/input/input.cpp
Executable file → Normal file
4
bsnes/nes/input/input.cpp → bsnes/fc/input/input.cpp
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
#include "serialization.cpp"
|
||||
Input input;
|
2
bsnes/nes/input/input.hpp → bsnes/fc/input/input.hpp
Executable file → Normal file
2
bsnes/nes/input/input.hpp → bsnes/fc/input/input.hpp
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
struct Input {
|
||||
enum class Device : unsigned {
|
||||
None,
|
||||
Joypad,
|
||||
None,
|
||||
};
|
||||
|
||||
void latch(bool data);
|
0
bsnes/nes/input/serialization.cpp → bsnes/fc/input/serialization.cpp
Executable file → Normal file
0
bsnes/nes/input/serialization.cpp → bsnes/fc/input/serialization.cpp
Executable file → Normal file
155
bsnes/fc/interface/interface.cpp
Normal file
155
bsnes/fc/interface/interface.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace Famicom {
|
||||
|
||||
Interface *interface = nullptr;
|
||||
|
||||
double Interface::videoFrequency() {
|
||||
return 21477272.0 / (262.0 * 1364.0 - 4.0);
|
||||
}
|
||||
|
||||
double Interface::audioFrequency() {
|
||||
return 21477272.0 / 12.0;
|
||||
}
|
||||
|
||||
bool Interface::loaded() {
|
||||
return cartridge.loaded();
|
||||
}
|
||||
|
||||
string Interface::sha256() {
|
||||
return cartridge.sha256();
|
||||
}
|
||||
|
||||
unsigned Interface::group(unsigned id) {
|
||||
switch(id) {
|
||||
case ID::ProgramROM:
|
||||
case ID::ProgramRAM:
|
||||
case ID::CharacterROM:
|
||||
case ID::CharacterRAM:
|
||||
return 1;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
void Interface::load(unsigned id, const string &manifest) {
|
||||
cartridge.load(manifest);
|
||||
}
|
||||
|
||||
void Interface::save() {
|
||||
for(auto &memory : cartridge.memory) {
|
||||
saveRequest(memory.id, memory.name);
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::load(unsigned id, const stream &stream, const string &manifest) {
|
||||
if(id == ID::ProgramROM) {
|
||||
stream.read(cartridge.board->prgrom.data, min(cartridge.board->prgrom.size, stream.size()));
|
||||
}
|
||||
|
||||
if(id == ID::ProgramRAM) {
|
||||
stream.read(cartridge.board->prgram.data, min(cartridge.board->prgram.size, stream.size()));
|
||||
}
|
||||
|
||||
if(id == ID::CharacterROM) {
|
||||
stream.read(cartridge.board->chrrom.data, min(cartridge.board->chrrom.size, stream.size()));
|
||||
}
|
||||
|
||||
if(id == ID::CharacterRAM) {
|
||||
stream.read(cartridge.board->chrram.data, min(cartridge.board->chrram.size, stream.size()));
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::save(unsigned id, const stream &stream) {
|
||||
if(id == ID::ProgramRAM) {
|
||||
stream.write(cartridge.board->prgram.data, cartridge.board->prgram.size);
|
||||
}
|
||||
|
||||
if(id == ID::CharacterRAM) {
|
||||
stream.write(cartridge.board->chrram.data, cartridge.board->chrram.size);
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::unload() {
|
||||
save();
|
||||
cartridge.unload();
|
||||
}
|
||||
|
||||
void Interface::power() {
|
||||
system.power();
|
||||
}
|
||||
|
||||
void Interface::reset() {
|
||||
system.reset();
|
||||
}
|
||||
|
||||
void Interface::run() {
|
||||
system.run();
|
||||
}
|
||||
|
||||
serializer Interface::serialize() {
|
||||
system.runtosave();
|
||||
return system.serialize();
|
||||
}
|
||||
|
||||
bool Interface::unserialize(serializer &s) {
|
||||
return system.unserialize(s);
|
||||
}
|
||||
|
||||
void Interface::cheatSet(const lstring &list) {
|
||||
cheat.reset();
|
||||
for(auto &code : list) {
|
||||
lstring codelist = code.split("+");
|
||||
for(auto &part : codelist) {
|
||||
unsigned addr, data, comp;
|
||||
if(Cheat::decode(part, addr, data, comp)) cheat.append({addr, data, comp});
|
||||
}
|
||||
}
|
||||
cheat.synchronize();
|
||||
}
|
||||
|
||||
void Interface::paletteUpdate() {
|
||||
video.generate_palette();
|
||||
}
|
||||
|
||||
Interface::Interface() {
|
||||
interface = this;
|
||||
|
||||
information.name = "Famicom";
|
||||
information.width = 256;
|
||||
information.height = 240;
|
||||
information.overscan = true;
|
||||
information.aspectRatio = 8.0 / 7.0;
|
||||
information.resettable = true;
|
||||
information.capability.states = true;
|
||||
information.capability.cheats = true;
|
||||
|
||||
media.append({ID::Famicom, "Famicom", "fc"});
|
||||
|
||||
{
|
||||
Device device{0, ID::Port1 | ID::Port2, "Controller"};
|
||||
device.input.append({0, 0, "A" });
|
||||
device.input.append({1, 0, "B" });
|
||||
device.input.append({2, 0, "Select"});
|
||||
device.input.append({3, 0, "Start" });
|
||||
device.input.append({4, 0, "Up" });
|
||||
device.input.append({5, 0, "Down" });
|
||||
device.input.append({6, 0, "Left" });
|
||||
device.input.append({7, 0, "Right" });
|
||||
device.order = {4, 5, 6, 7, 1, 0, 2, 3};
|
||||
this->device.append(device);
|
||||
}
|
||||
|
||||
port.append({0, "Port 1"});
|
||||
port.append({1, "Port 2"});
|
||||
|
||||
for(auto &device : this->device) {
|
||||
for(auto &port : this->port) {
|
||||
if(device.portmask & (1 << port.id)) {
|
||||
port.device.append(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
58
bsnes/fc/interface/interface.hpp
Normal file
58
bsnes/fc/interface/interface.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef FC_HPP
|
||||
namespace Famicom {
|
||||
#endif
|
||||
|
||||
struct ID {
|
||||
enum : unsigned {
|
||||
System,
|
||||
Famicom,
|
||||
};
|
||||
|
||||
enum : unsigned {
|
||||
ProgramROM,
|
||||
ProgramRAM,
|
||||
CharacterROM,
|
||||
CharacterRAM,
|
||||
};
|
||||
|
||||
enum : unsigned {
|
||||
Port1 = 1,
|
||||
Port2 = 2,
|
||||
};
|
||||
};
|
||||
|
||||
struct Interface : Emulator::Interface {
|
||||
double videoFrequency();
|
||||
double audioFrequency();
|
||||
|
||||
bool loaded();
|
||||
string sha256();
|
||||
unsigned group(unsigned id);
|
||||
void load(unsigned id, const string &manifest);
|
||||
void save();
|
||||
void load(unsigned id, const stream &stream, const string &manifest = "");
|
||||
void save(unsigned id, const stream &stream);
|
||||
void unload();
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
void run();
|
||||
|
||||
serializer serialize();
|
||||
bool unserialize(serializer&);
|
||||
|
||||
void cheatSet(const lstring&);
|
||||
|
||||
void paletteUpdate();
|
||||
|
||||
Interface();
|
||||
|
||||
private:
|
||||
vector<Device> device;
|
||||
};
|
||||
|
||||
extern Interface *interface;
|
||||
|
||||
#ifndef FC_HPP
|
||||
}
|
||||
#endif
|
4
bsnes/nes/memory/memory.cpp → bsnes/fc/memory/memory.cpp
Executable file → Normal file
4
bsnes/nes/memory/memory.cpp → bsnes/fc/memory/memory.cpp
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
Bus bus;
|
||||
|
0
bsnes/nes/memory/memory.hpp → bsnes/fc/memory/memory.hpp
Executable file → Normal file
0
bsnes/nes/memory/memory.hpp → bsnes/fc/memory/memory.hpp
Executable file → Normal file
9
bsnes/nes/ppu/ppu.cpp → bsnes/fc/ppu/ppu.cpp
Executable file → Normal file
9
bsnes/nes/ppu/ppu.cpp → bsnes/fc/ppu/ppu.cpp
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
#include "serialization.cpp"
|
||||
PPU ppu;
|
||||
@@ -47,7 +47,6 @@ void PPU::scanline() {
|
||||
|
||||
void PPU::frame() {
|
||||
status.field ^= 1;
|
||||
interface->videoRefresh(buffer);
|
||||
scheduler.exit(Scheduler::ExitReason::FrameEvent);
|
||||
}
|
||||
|
||||
@@ -282,7 +281,7 @@ void PPU::scrolly_increment() {
|
||||
//
|
||||
|
||||
void PPU::raster_pixel() {
|
||||
uint16 *output = buffer + status.ly * 256;
|
||||
uint32 *output = buffer + status.ly * 256;
|
||||
|
||||
unsigned mask = 0x8000 >> (status.xaddr + (status.lx & 7));
|
||||
unsigned palette = 0, object_palette = 0;
|
||||
@@ -325,7 +324,7 @@ void PPU::raster_pixel() {
|
||||
}
|
||||
|
||||
if(raster_enable() == false) palette = 0;
|
||||
output[status.lx] = (status.emphasis << 6) | cgram_read(palette);
|
||||
output[status.lx] = video.palette[(status.emphasis << 6) | cgram_read(palette)];
|
||||
}
|
||||
|
||||
void PPU::raster_sprite() {
|
2
bsnes/nes/ppu/ppu.hpp → bsnes/fc/ppu/ppu.hpp
Executable file → Normal file
2
bsnes/nes/ppu/ppu.hpp → bsnes/fc/ppu/ppu.hpp
Executable file → Normal file
@@ -98,7 +98,7 @@ struct PPU : Thread {
|
||||
} oam[8], soam[8];
|
||||
} raster;
|
||||
|
||||
uint16 buffer[256 * 262];
|
||||
uint32 buffer[256 * 262];
|
||||
uint8 ciram[2048];
|
||||
uint8 cgram[32];
|
||||
uint8 oam[256];
|
0
bsnes/nes/ppu/serialization.cpp → bsnes/fc/ppu/serialization.cpp
Executable file → Normal file
0
bsnes/nes/ppu/serialization.cpp → bsnes/fc/ppu/serialization.cpp
Executable file → Normal file
4
bsnes/nes/scheduler/scheduler.cpp → bsnes/fc/scheduler/scheduler.cpp
Executable file → Normal file
4
bsnes/nes/scheduler/scheduler.cpp → bsnes/fc/scheduler/scheduler.cpp
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
Scheduler scheduler;
|
||||
|
0
bsnes/nes/scheduler/scheduler.hpp → bsnes/fc/scheduler/scheduler.hpp
Executable file → Normal file
0
bsnes/nes/scheduler/scheduler.hpp → bsnes/fc/scheduler/scheduler.hpp
Executable file → Normal file
20
bsnes/nes/system/serialization.cpp → bsnes/fc/system/serialization.cpp
Executable file → Normal file
20
bsnes/nes/system/serialization.cpp → bsnes/fc/system/serialization.cpp
Executable file → Normal file
@@ -1,13 +1,14 @@
|
||||
serializer System::serialize() {
|
||||
serializer s(serialize_size);
|
||||
|
||||
unsigned signature = 0x31545342, version = Info::SerializerVersion, crc32 = 0;
|
||||
char description[512];
|
||||
unsigned signature = 0x31545342, version = Info::SerializerVersion;
|
||||
char hash[64], description[512];
|
||||
memcpy(&hash, (const char*)cartridge.sha256(), 64);
|
||||
memset(&description, 0, sizeof description);
|
||||
|
||||
s.integer(signature);
|
||||
s.integer(version);
|
||||
s.integer(crc32);
|
||||
s.array(hash);
|
||||
s.array(description);
|
||||
|
||||
serialize_all(s);
|
||||
@@ -15,17 +16,16 @@ serializer System::serialize() {
|
||||
}
|
||||
|
||||
bool System::unserialize(serializer &s) {
|
||||
unsigned signature, version, crc32;
|
||||
char description[512];
|
||||
unsigned signature, version;
|
||||
char hash[64], description[512];
|
||||
|
||||
s.integer(signature);
|
||||
s.integer(version);
|
||||
s.integer(crc32);
|
||||
s.array(hash);
|
||||
s.array(description);
|
||||
|
||||
if(signature != 0x31545342) return false;
|
||||
if(version != Info::SerializerVersion) return false;
|
||||
//if(crc32 != 0) return false;
|
||||
|
||||
power();
|
||||
serialize_all(s);
|
||||
@@ -47,12 +47,12 @@ void System::serialize_all(serializer &s) {
|
||||
void System::serialize_init() {
|
||||
serializer s;
|
||||
|
||||
unsigned signature = 0, version = 0, crc32 = 0;
|
||||
char description[512];
|
||||
unsigned signature = 0, version = 0;
|
||||
char hash[64], description[512];
|
||||
|
||||
s.integer(signature);
|
||||
s.integer(version);
|
||||
s.integer(crc32);
|
||||
s.array(hash);
|
||||
s.array(description);
|
||||
|
||||
serialize_all(s);
|
11
bsnes/nes/system/system.cpp → bsnes/fc/system/system.cpp
Executable file → Normal file
11
bsnes/nes/system/system.cpp → bsnes/fc/system/system.cpp
Executable file → Normal file
@@ -1,12 +1,15 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
#include "serialization.cpp"
|
||||
System system;
|
||||
|
||||
void System::run() {
|
||||
scheduler.enter();
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
|
||||
interface->videoRefresh(ppu.buffer, 4 * 256, 256, 240);
|
||||
}
|
||||
}
|
||||
|
||||
void System::runtosave() {
|
||||
@@ -32,7 +35,9 @@ void System::runthreadtosave() {
|
||||
while(true) {
|
||||
scheduler.enter();
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break;
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent);
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
|
||||
interface->videoRefresh(ppu.buffer, 4 * 256, 256, 240);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
0
bsnes/nes/system/system.hpp → bsnes/fc/system/system.hpp
Executable file → Normal file
0
bsnes/nes/system/system.hpp → bsnes/fc/system/system.hpp
Executable file → Normal file
58
bsnes/nes/video/video.cpp → bsnes/fc/video/video.cpp
Executable file → Normal file
58
bsnes/nes/video/video.cpp → bsnes/fc/video/video.cpp
Executable file → Normal file
@@ -1,11 +1,23 @@
|
||||
#include <nes/nes.hpp>
|
||||
#include <fc/fc.hpp>
|
||||
|
||||
#define VIDEO_CPP
|
||||
namespace NES {
|
||||
namespace Famicom {
|
||||
|
||||
Video video;
|
||||
|
||||
unsigned Video::palette30(
|
||||
void Video::generate_palette() {
|
||||
for(unsigned n = 0; n < (1 << 9); n++) palette[n] = generate_color(n, 2.0, 0.0, 1.0, 1.0, 1.8);
|
||||
}
|
||||
|
||||
Video::Video() {
|
||||
palette = new unsigned[1 << 9];
|
||||
}
|
||||
|
||||
Video::~Video() {
|
||||
delete[] palette;
|
||||
}
|
||||
|
||||
uint32_t Video::generate_color(
|
||||
unsigned n, double saturation, double hue,
|
||||
double contrast, double brightness, double gamma
|
||||
) {
|
||||
@@ -46,43 +58,11 @@ unsigned Video::palette30(
|
||||
q *= saturation;
|
||||
|
||||
auto gammaAdjust = [=](double f) { return f < 0.0 ? 0.0 : std::pow(f, 2.2 / gamma); };
|
||||
unsigned r = 1023.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q);
|
||||
unsigned g = 1023.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q);
|
||||
unsigned b = 1023.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q);
|
||||
return (uclamp<10>(r) << 20) + (uclamp<10>(g) << 10) + (uclamp<10>(b) << 0);
|
||||
}
|
||||
unsigned r = 65535.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q);
|
||||
unsigned g = 65535.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q);
|
||||
unsigned b = 65535.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q);
|
||||
|
||||
void Video::generate(Format format) {
|
||||
for(unsigned n = 0; n < (1 << 9); n++) palette[n] = palette30(n, 2.0, 0.0, 1.0, 1.0, 1.8);
|
||||
|
||||
if(format == Format::RGB24) {
|
||||
for(unsigned n = 0; n < (1 << 9); n++) {
|
||||
unsigned color = palette[n];
|
||||
palette[n] = ((color >> 6) & 0xff0000) + ((color >> 4) & 0x00ff00) + ((color >> 2) & 0x0000ff);
|
||||
}
|
||||
}
|
||||
|
||||
if(format == Format::RGB16) {
|
||||
for(unsigned n = 0; n < (1 << 9); n++) {
|
||||
unsigned color = palette[n];
|
||||
palette[n] = ((color >> 14) & 0xf800) + ((color >> 9) & 0x07e0) + ((color >> 5) & 0x001f);
|
||||
}
|
||||
}
|
||||
|
||||
if(format == Format::RGB15) {
|
||||
for(unsigned n = 0; n < (1 << 9); n++) {
|
||||
unsigned color = palette[n];
|
||||
palette[n] = ((color >> 15) & 0x7c00) + ((color >> 10) & 0x03e0) + ((color >> 5) & 0x001f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Video::Video() {
|
||||
palette = new unsigned[1 << 9];
|
||||
}
|
||||
|
||||
Video::~Video() {
|
||||
delete[] palette;
|
||||
return interface->videoColor(n, uclamp<16>(r), uclamp<16>(g), uclamp<16>(b));
|
||||
}
|
||||
|
||||
}
|
12
bsnes/fc/video/video.hpp
Normal file
12
bsnes/fc/video/video.hpp
Normal file
@@ -0,0 +1,12 @@
|
||||
struct Video {
|
||||
unsigned *palette;
|
||||
void generate_palette();
|
||||
|
||||
Video();
|
||||
~Video();
|
||||
|
||||
private:
|
||||
uint32_t generate_color(unsigned, double, double, double, double, double);
|
||||
};
|
||||
|
||||
extern Video video;
|
6
bsnes/gb/Makefile
Executable file → Normal file
6
bsnes/gb/Makefile
Executable file → Normal file
@@ -1,8 +1,6 @@
|
||||
options += gameboy
|
||||
|
||||
gb_objects := gb-interface gb-system gb-scheduler
|
||||
gb_objects += gb-memory gb-cartridge
|
||||
gb_objects += gb-cpu gb-apu gb-lcd
|
||||
gb_objects += gb-cpu gb-ppu gb-apu
|
||||
gb_objects += gb-cheat gb-video
|
||||
objects += $(gb_objects)
|
||||
|
||||
@@ -12,7 +10,7 @@ obj/gb-scheduler.o: $(gb)/scheduler/scheduler.cpp $(call rwildcard,$(gb)/schedul
|
||||
obj/gb-cartridge.o: $(gb)/cartridge/cartridge.cpp $(call rwildcard,$(gb)/cartridge/)
|
||||
obj/gb-memory.o: $(gb)/memory/memory.cpp $(call rwildcard,$(gb)/memory/)
|
||||
obj/gb-cpu.o: $(gb)/cpu/cpu.cpp $(call rwildcard,$(gb)/cpu/)
|
||||
obj/gb-ppu.o: $(gb)/ppu/ppu.cpp $(call rwildcard,$(gb)/ppu/)
|
||||
obj/gb-apu.o: $(gb)/apu/apu.cpp $(call rwildcard,$(gb)/apu/)
|
||||
obj/gb-lcd.o: $(gb)/lcd/lcd.cpp $(call rwildcard,$(gb)/lcd/)
|
||||
obj/gb-cheat.o: $(gb)/cheat/cheat.cpp $(call rwildcard,$(gb)/cheat/)
|
||||
obj/gb-video.o: $(gb)/video/video.cpp $(call rwildcard,$(gb)/video/)
|
||||
|
6
bsnes/gb/apu/apu.cpp
Executable file → Normal file
6
bsnes/gb/apu/apu.cpp
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
#include <gb/gb.hpp>
|
||||
|
||||
#define APU_CPP
|
||||
namespace GB {
|
||||
namespace GameBoy {
|
||||
|
||||
#include "square1/square1.cpp"
|
||||
#include "square2/square2.cpp"
|
||||
@@ -46,9 +46,9 @@ void APU::main() {
|
||||
noise.run();
|
||||
master.run();
|
||||
|
||||
interface->audioSample(master.center, master.left, master.right);
|
||||
interface->audioSample(master.left, master.right);
|
||||
|
||||
clock += 1 * cpu.frequency;
|
||||
clock += cpu.frequency;
|
||||
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(scheduler.active_thread = cpu.thread);
|
||||
}
|
||||
}
|
||||
|
0
bsnes/gb/apu/apu.hpp
Executable file → Normal file
0
bsnes/gb/apu/apu.hpp
Executable file → Normal file
0
bsnes/gb/apu/master/master.cpp
Executable file → Normal file
0
bsnes/gb/apu/master/master.cpp
Executable file → Normal file
0
bsnes/gb/apu/master/master.hpp
Executable file → Normal file
0
bsnes/gb/apu/master/master.hpp
Executable file → Normal file
0
bsnes/gb/apu/noise/noise.cpp
Executable file → Normal file
0
bsnes/gb/apu/noise/noise.cpp
Executable file → Normal file
0
bsnes/gb/apu/noise/noise.hpp
Executable file → Normal file
0
bsnes/gb/apu/noise/noise.hpp
Executable file → Normal file
0
bsnes/gb/apu/serialization.cpp
Executable file → Normal file
0
bsnes/gb/apu/serialization.cpp
Executable file → Normal file
0
bsnes/gb/apu/square1/square1.cpp
Executable file → Normal file
0
bsnes/gb/apu/square1/square1.cpp
Executable file → Normal file
0
bsnes/gb/apu/square1/square1.hpp
Executable file → Normal file
0
bsnes/gb/apu/square1/square1.hpp
Executable file → Normal file
0
bsnes/gb/apu/square2/square2.cpp
Executable file → Normal file
0
bsnes/gb/apu/square2/square2.cpp
Executable file → Normal file
0
bsnes/gb/apu/square2/square2.hpp
Executable file → Normal file
0
bsnes/gb/apu/square2/square2.hpp
Executable file → Normal file
0
bsnes/gb/apu/wave/wave.cpp
Executable file → Normal file
0
bsnes/gb/apu/wave/wave.cpp
Executable file → Normal file
0
bsnes/gb/apu/wave/wave.hpp
Executable file → Normal file
0
bsnes/gb/apu/wave/wave.hpp
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user