mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-26 02:39:06 +02:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7b0e484c18 |
51
src/Makefile
51
src/Makefile
@@ -1,4 +1,5 @@
|
||||
include lib/nall/Makefile
|
||||
include lib/nall/Makefile-qt
|
||||
ui = ui_qt
|
||||
|
||||
################
|
||||
@@ -8,7 +9,7 @@ ui = ui_qt
|
||||
c := $(compiler)
|
||||
cpp := $(subst cc,++,$(compiler))
|
||||
flags := -O3 -fomit-frame-pointer -Ilib
|
||||
link := -s
|
||||
link :=
|
||||
|
||||
# profile-guided instrumentation:
|
||||
# flags += -fprofile-generate
|
||||
@@ -22,19 +23,31 @@ link := -s
|
||||
################
|
||||
|
||||
ifeq ($(platform),x)
|
||||
ruby := video.glx video.xv video.sdl
|
||||
link += -s
|
||||
|
||||
ruby := video.glx video.xv video.sdl video.qtimage
|
||||
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao
|
||||
ruby += input.sdl input.x
|
||||
|
||||
link += $(if $(findstring audio.openal,$(ruby)),-lopenal)
|
||||
else ifeq ($(platform),osx)
|
||||
ruby := video.qtimage
|
||||
ruby += audio.openal
|
||||
ruby += input.carbon
|
||||
|
||||
link += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL)
|
||||
else ifeq ($(platform),win)
|
||||
ruby := video.direct3d video.wgl video.directdraw video.gdi
|
||||
link += -mwindows
|
||||
# link += -mconsole
|
||||
link += -s -luuid -lkernel32 -luser32 -lgdi32 -lshell32
|
||||
# statically link Qt for Windows build
|
||||
link += -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||
|
||||
ruby := video.direct3d video.wgl video.directdraw video.gdi video.qtimage
|
||||
ruby += audio.directsound
|
||||
ruby += input.rawinput input.directinput
|
||||
|
||||
link += -mwindows
|
||||
# link += -mconsole
|
||||
link += -luuid -lkernel32 -luser32 -lgdi32 -lshell32
|
||||
# statically link Qt for Windows build
|
||||
link += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||
link += $(if $(findstring audio.openal,$(ruby)),-lopenal32)
|
||||
else
|
||||
unknown_platform: help;
|
||||
endif
|
||||
@@ -43,7 +56,8 @@ endif
|
||||
### ruby ###
|
||||
############
|
||||
|
||||
rubyflags = $(call ifhas,.sdl,$(ruby),`sdl-config --cflags`)
|
||||
rubyflags := $(call ifhas,.sdl,$(ruby),`sdl-config --cflags`)
|
||||
rubyflags += $(call ifhas,.qt,$(ruby),$(qtinc))
|
||||
|
||||
link += $(call ifhas,.sdl,$(ruby),`sdl-config --libs`)
|
||||
link += $(call ifhas,video.direct3d,$(ruby),-ld3d9)
|
||||
@@ -54,19 +68,18 @@ link += $(call ifhas,video.xv,$(ruby),-lXv)
|
||||
link += $(call ifhas,audio.alsa,$(ruby),-lasound)
|
||||
link += $(call ifhas,audio.ao,$(ruby),-lao)
|
||||
link += $(call ifhas,audio.directsound,$(ruby),-ldsound)
|
||||
link += $(call ifhas,audio.openal,$(ruby),$(if $(call streq,$(platform),x),-lopenal,-lopenal32))
|
||||
link += $(call ifhas,audio.pulseaudio,$(ruby),-lpulse-simple)
|
||||
link += $(call ifhas,input.directinput,$(ruby),-ldinput8 -ldxguid)
|
||||
link += $(call ifhas,input.rawinput,$(ruby),-lxinput -ldinput8 -ldxguid)
|
||||
link += $(call ifhas,input.rawinput,$(ruby),-ldinput8 -ldxguid)
|
||||
|
||||
####################
|
||||
### core objects ###
|
||||
####################
|
||||
|
||||
objects = libco ruby libreader libfilter string \
|
||||
system cartridge cheat \
|
||||
memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu \
|
||||
sgb sa1 bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||
objects := libco ruby libreader libfilter
|
||||
objects += system cartridge cheat
|
||||
objects += memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu
|
||||
objects += sgb superfx sa1 bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||
|
||||
ifeq ($(enable_gzip),true)
|
||||
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
||||
@@ -110,7 +123,6 @@ obj/libco.o: lib/libco/libco.c lib/libco/*
|
||||
$(c) -O3 -fomit-frame-pointer -static -Ilib -c $< -o $@
|
||||
obj/libreader.o: lib/libreader/libreader.cpp lib/libreader/*
|
||||
obj/libfilter.o: lib/libfilter/libfilter.cpp lib/libfilter/*
|
||||
obj/string.o: lib/nall/string.cpp lib/nall/*
|
||||
|
||||
#################
|
||||
### utilities ###
|
||||
@@ -167,6 +179,7 @@ obj/system.o: system/system.cpp $(call rwildcard,system/)
|
||||
#####################
|
||||
|
||||
obj/sgb.o : chip/sgb/sgb.cpp $(call rwildcard,chip/sgb/)
|
||||
obj/superfx.o: chip/superfx/superfx.cpp $(call rwildcard,chip/superfx/)
|
||||
obj/sa1.o : chip/sa1/sa1.cpp $(call rwildcard,chip/sa1/)
|
||||
obj/bsx.o : chip/bsx/bsx.cpp chip/bsx/*
|
||||
obj/srtc.o : chip/srtc/srtc.cpp chip/srtc/*
|
||||
@@ -216,7 +229,12 @@ obj/winout.o : lib/libjma/winout.cpp lib/libjma/*
|
||||
###############
|
||||
|
||||
build: ui_build $(objects)
|
||||
ifeq ($(platform),osx)
|
||||
test -d ../bsnes.app || mkdir -p ../bsnes.app/Contents/MacOS
|
||||
$(strip $(cpp) -o ../bsnes.app/Contents/MacOS/bsnes $(objects) $(link))
|
||||
else
|
||||
$(strip $(cpp) -o ../bsnes $(objects) $(link))
|
||||
endif
|
||||
|
||||
install:
|
||||
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
|
||||
@@ -250,4 +268,3 @@ help:
|
||||
@echo ""
|
||||
@echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true"
|
||||
@echo ""
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#define BSNES_VERSION "0.046"
|
||||
#define BSNES_VERSION "0.047"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define BUSCORE sBus
|
||||
@@ -41,4 +41,3 @@ typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
|
||||
#include "interface.hpp"
|
||||
|
||||
|
@@ -30,6 +30,7 @@ public:
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
ExHiROM,
|
||||
SuperFXROM,
|
||||
SA1ROM,
|
||||
SPC7110ROM,
|
||||
BSCLoROM,
|
||||
|
@@ -22,11 +22,8 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
||||
const uint8 company = data[index + Company];
|
||||
const uint8 region = data[index + CartRegion] & 0x7f;
|
||||
|
||||
if(data[index + RamSize] & 7) {
|
||||
info.ram_size = 1024 << (data[index + RamSize] & 7);
|
||||
} else {
|
||||
info.ram_size = 0;
|
||||
}
|
||||
if(info.ram_size == 1024) info.ram_size = 0; //no RAM present, eg RamSize == 0
|
||||
|
||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
|
||||
@@ -119,6 +116,9 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
|
||||
|
||||
if(mapper == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
|
||||
info.superfx = true;
|
||||
info.mapper = SuperFXROM;
|
||||
info.ram_size = 1024 << (data[index - 3] & 7);
|
||||
if(info.ram_size == 1024) info.ram_size = 0;
|
||||
}
|
||||
|
||||
if(mapper == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
|
||||
|
@@ -1,3 +1,5 @@
|
||||
@mingw32-make
|
||||
|
||||
::@mingw32-make enable_gzip=true enable_jma=true
|
||||
|
||||
@pause
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "sgb/sgb.hpp"
|
||||
#include "superfx/superfx.hpp"
|
||||
#include "sa1/sa1.hpp"
|
||||
#include "bsx/bsx.hpp"
|
||||
#include "srtc/srtc.hpp"
|
||||
|
@@ -36,5 +36,5 @@ void DSP3::write(unsigned addr, uint8 data) {
|
||||
DSP3i::dsp3_byte = data;
|
||||
DSP3i::DSP3SetByte();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
@@ -56,5 +56,5 @@ void DSP4::write(unsigned addr, uint8 data) {
|
||||
DSP4i::DSP4SetByte();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
@@ -75,4 +75,3 @@ OBC1::OBC1() {}
|
||||
OBC1::~OBC1() {}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -3,21 +3,16 @@
|
||||
SA1Bus sa1bus;
|
||||
|
||||
namespace memory {
|
||||
VectorSelectionPage vectorsp;
|
||||
StaticRAM iram(2048);
|
||||
MappedRAM &bwram = memory::cartram;
|
||||
CC1BWRAM cc1bwram;
|
||||
BitmapRAM bitmapram;
|
||||
static VectorSelectionPage vectorsp;
|
||||
static StaticRAM iram(2048);
|
||||
static MappedRAM &bwram = memory::cartram;
|
||||
static CC1BWRAM cc1bwram;
|
||||
static BitmapRAM bitmapram;
|
||||
}
|
||||
|
||||
void SA1Bus::init() {
|
||||
for(uint32_t i = 0x0000; i <= 0xffff; i++) {
|
||||
map(i << 8, memory::memory_unmapped, 0);
|
||||
}
|
||||
|
||||
for(uint16_t i = 0x2200; i <= 0x23ff; i++) {
|
||||
memory::mmio.map(i, sa1);
|
||||
}
|
||||
map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
||||
for(uint16_t i = 0x2200; i <= 0x23ff; i++) memory::mmio.map(i, sa1);
|
||||
|
||||
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
|
||||
map(MapDirect, 0x00, 0x3f, 0x2200, 0x23ff, memory::mmio);
|
||||
@@ -120,7 +115,7 @@ uint8_t BitmapRAM::read(unsigned addr) {
|
||||
//4bpp
|
||||
unsigned shift = addr & 1;
|
||||
addr = (addr >> 1) & (memory::cartram.size() - 1);
|
||||
switch(shift) {
|
||||
switch(shift) { default:
|
||||
case 0: return (memory::cartram.read(addr) >> 0) & 15;
|
||||
case 1: return (memory::cartram.read(addr) >> 4) & 15;
|
||||
}
|
||||
@@ -128,7 +123,7 @@ uint8_t BitmapRAM::read(unsigned addr) {
|
||||
//2bpp
|
||||
unsigned shift = addr & 3;
|
||||
addr = (addr >> 2) & (memory::cartram.size() - 1);
|
||||
switch(shift) {
|
||||
switch(shift) { default:
|
||||
case 0: return (memory::cartram.read(addr) >> 0) & 3;
|
||||
case 1: return (memory::cartram.read(addr) >> 2) & 3;
|
||||
case 2: return (memory::cartram.read(addr) >> 4) & 3;
|
||||
@@ -142,7 +137,7 @@ void BitmapRAM::write(unsigned addr, uint8_t data) {
|
||||
//4bpp
|
||||
uint8_t shift = addr & 1;
|
||||
addr = (addr >> 1) & (memory::cartram.size() - 1);
|
||||
switch(shift) {
|
||||
switch(shift) { default:
|
||||
case 0: data = (memory::cartram.read(addr) & 0xf0) | ((data & 15) << 0); break;
|
||||
case 1: data = (memory::cartram.read(addr) & 0x0f) | ((data & 15) << 4); break;
|
||||
}
|
||||
@@ -150,7 +145,7 @@ void BitmapRAM::write(unsigned addr, uint8_t data) {
|
||||
//2bpp
|
||||
uint8_t shift = addr & 3;
|
||||
addr = (addr >> 2) & (memory::cartram.size() - 1);
|
||||
switch(shift) {
|
||||
switch(shift) { default:
|
||||
case 0: data = (memory::cartram.read(addr) & 0xfc) | ((data & 3) << 0); break;
|
||||
case 1: data = (memory::cartram.read(addr) & 0xf3) | ((data & 3) << 2); break;
|
||||
case 2: data = (memory::cartram.read(addr) & 0xcf) | ((data & 3) << 4); break;
|
||||
|
@@ -21,11 +21,3 @@ struct BitmapRAM : Memory {
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern VectorSelectionPage vectorsp;
|
||||
extern StaticRAM iram;
|
||||
extern MappedRAM &bwram;
|
||||
extern CC1BWRAM cc1bwram;
|
||||
extern BitmapRAM bitmapram;
|
||||
}
|
||||
|
@@ -315,4 +315,3 @@ SA1::SA1() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -158,5 +158,5 @@ SDD1::SDD1() {
|
||||
SDD1::~SDD1() {
|
||||
delete[] buffer.data;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
@@ -63,4 +63,3 @@ void SuperGameBoy::reset() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -25,4 +25,3 @@ private:
|
||||
};
|
||||
|
||||
extern SuperGameBoy sgb;
|
||||
|
||||
|
@@ -674,4 +674,3 @@ SPC7110::SPC7110() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -229,4 +229,3 @@ SRTC::SRTC() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -88,5 +88,5 @@ void ST010::write(unsigned addr, uint8 data) {
|
||||
ram[0x0021] &= ~0x80;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
92
src/chip/superfx/bus/bus.cpp
Normal file
92
src/chip/superfx/bus/bus.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
SuperFXBus superfxbus;
|
||||
|
||||
namespace memory {
|
||||
static SuperFXGSUROM gsurom;
|
||||
static SuperFXGSURAM gsuram;
|
||||
static SuperFXCPUROM fxrom;
|
||||
static SuperFXCPURAM fxram;
|
||||
};
|
||||
|
||||
void SuperFXBus::init() {
|
||||
map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
||||
|
||||
map(MapLinear, 0x00, 0x3f, 0x0000, 0x7fff, memory::gsurom);
|
||||
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::gsurom);
|
||||
map(MapLinear, 0x40, 0x5f, 0x0000, 0xffff, memory::gsurom);
|
||||
map(MapLinear, 0x60, 0x7f, 0x0000, 0xffff, memory::gsuram);
|
||||
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::fxram, 0x0000, 0x2000);
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::fxrom);
|
||||
bus.map(MapLinear, 0x40, 0x5f, 0x0000, 0xffff, memory::fxrom);
|
||||
bus.map(MapLinear, 0x60, 0x7d, 0x0000, 0xffff, memory::fxram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::fxram, 0x0000, 0x2000);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::fxrom);
|
||||
bus.map(MapLinear, 0xc0, 0xdf, 0x0000, 0xffff, memory::fxrom);
|
||||
bus.map(MapLinear, 0xe0, 0xff, 0x0000, 0xffff, memory::fxram);
|
||||
}
|
||||
|
||||
//ROM / RAM access from the SuperFX CPU
|
||||
|
||||
unsigned SuperFXGSUROM::size() const {
|
||||
return memory::cartrom.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXGSUROM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ron) superfx.add_clocks(2);
|
||||
return memory::cartrom.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXGSUROM::write(unsigned addr, uint8_t data) {
|
||||
}
|
||||
|
||||
unsigned SuperFXGSURAM::size() const {
|
||||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXGSURAM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ran) superfx.add_clocks(2);
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXGSURAM::write(unsigned addr, uint8_t data) {
|
||||
while(!superfx.regs.scmr.ran) superfx.add_clocks(2);
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
//ROM / RAM access from the S-CPU
|
||||
|
||||
unsigned SuperFXCPUROM::size() const {
|
||||
return memory::cartrom.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXCPUROM::read(unsigned addr) {
|
||||
if(superfx.regs.sfr.g && superfx.regs.scmr.ron) {
|
||||
static const uint8_t data[16] = {
|
||||
0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
|
||||
0x00, 0x01, 0x08, 0x01, 0x00, 0x01, 0x0c, 0x01,
|
||||
};
|
||||
return data[addr & 15];
|
||||
}
|
||||
return memory::cartrom.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXCPUROM::write(unsigned addr, uint8_t data) {
|
||||
memory::cartrom.write(addr, data);
|
||||
}
|
||||
|
||||
unsigned SuperFXCPURAM::size() const {
|
||||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXCPURAM::read(unsigned addr) {
|
||||
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return cpu.regs.mdr;
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXCPURAM::write(unsigned addr, uint8_t data) {
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
#endif
|
27
src/chip/superfx/bus/bus.hpp
Normal file
27
src/chip/superfx/bus/bus.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
struct SuperFXBus : Bus {
|
||||
void init();
|
||||
};
|
||||
|
||||
struct SuperFXGSUROM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
};
|
||||
|
||||
struct SuperFXGSURAM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
};
|
||||
|
||||
struct SuperFXCPUROM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
};
|
||||
|
||||
struct SuperFXCPURAM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
};
|
121
src/chip/superfx/core/core.cpp
Normal file
121
src/chip/superfx/core/core.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
#include "opcodes.cpp"
|
||||
#include "opcode_table.cpp"
|
||||
|
||||
void SuperFX::exec_opcode() {
|
||||
#if 0
|
||||
if(!fp) fp = fopen("sfxtrace.log", "wb");
|
||||
char t[4096];
|
||||
disassemble_opcode(t);
|
||||
fprintf(fp, "%s ", t);
|
||||
for(unsigned i = 0; i < 16; i++) fprintf(fp, "r%u:%.4x ", i, (uint16_t)regs.r[i]);
|
||||
fprintf(fp, "\n");
|
||||
#endif
|
||||
|
||||
(this->*opcode_table[(regs.sfr & 0x0300) + peekpipe()])();
|
||||
if(r15_modified == false) regs.r[15]++;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::color(uint8_t source) {
|
||||
if(regs.por.highnibble) return (regs.colr & 0xf0) | (source >> 4);
|
||||
if(regs.por.freezehigh) return (regs.colr & 0xf0) | (source & 0x0f);
|
||||
return source;
|
||||
}
|
||||
|
||||
void SuperFX::plot(uint8_t x, uint8_t y) {
|
||||
uint8_t color = regs.colr;
|
||||
|
||||
if(regs.por.dither && regs.scmr.md != 3) {
|
||||
if((x ^ y) & 1) color >>= 4;
|
||||
color &= 0x0f;
|
||||
}
|
||||
|
||||
if(!regs.por.transparent) {
|
||||
if(regs.scmr.md == 3) {
|
||||
if(regs.por.freezehigh) {
|
||||
if((color & 0x0f) == 0) return;
|
||||
} else {
|
||||
if(color == 0) return;
|
||||
}
|
||||
} else {
|
||||
if((color & 0x0f) == 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t offset = (y << 5) + (x >> 3);
|
||||
if(offset != pixelcache[0].offset) {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
pixelcache[1] = pixelcache[0];
|
||||
pixelcache[0].bitpend = 0x00;
|
||||
pixelcache[0].offset = offset;
|
||||
}
|
||||
|
||||
x = (x & 7) ^ 7;
|
||||
pixelcache[0].data[x] = color;
|
||||
pixelcache[0].bitpend |= 1 << x;
|
||||
if(pixelcache[0].bitpend == 0xff) {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
pixelcache[1] = pixelcache[0];
|
||||
pixelcache[0].bitpend = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SuperFX::rpix(uint8_t x, uint8_t y) {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
pixelcache_flush(pixelcache[0]);
|
||||
|
||||
unsigned cn; //character number
|
||||
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
||||
case 0: cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3); break;
|
||||
case 1: cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3); break;
|
||||
case 2: cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3); break;
|
||||
case 3: cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3); break;
|
||||
}
|
||||
unsigned bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
||||
unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||
uint8_t data = 0x00;
|
||||
x = (x & 7) ^ 7;
|
||||
|
||||
for(unsigned n = 0; n < bpp; n++) {
|
||||
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
add_clocks(memory_access_speed);
|
||||
data |= ((superfxbus.read(addr + byte) >> x) & 1) << n;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void SuperFX::pixelcache_flush(pixelcache_t &cache) {
|
||||
if(cache.bitpend == 0x00) return;
|
||||
|
||||
uint8_t x = cache.offset << 3;
|
||||
uint8_t y = cache.offset >> 5;
|
||||
|
||||
unsigned cn; //character number
|
||||
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
||||
case 0: cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3); break;
|
||||
case 1: cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3); break;
|
||||
case 2: cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3); break;
|
||||
case 3: cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3); break;
|
||||
}
|
||||
unsigned bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
||||
unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||
|
||||
for(unsigned n = 0; n < bpp; n++) {
|
||||
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
uint8_t data = 0x00;
|
||||
for(unsigned x = 0; x < 8; x++) data |= ((cache.data[x] >> n) & 1) << x;
|
||||
if(cache.bitpend != 0xff) {
|
||||
add_clocks(memory_access_speed);
|
||||
data &= cache.bitpend;
|
||||
data |= superfxbus.read(addr + byte) & ~cache.bitpend;
|
||||
}
|
||||
add_clocks(memory_access_speed);
|
||||
superfxbus.write(addr + byte, data);
|
||||
}
|
||||
|
||||
cache.bitpend = 0x00;
|
||||
}
|
||||
|
||||
#endif
|
93
src/chip/superfx/core/core.hpp
Normal file
93
src/chip/superfx/core/core.hpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "registers.hpp"
|
||||
|
||||
void exec_opcode();
|
||||
uint8_t color(uint8_t source);
|
||||
void plot(uint8_t x, uint8_t y);
|
||||
uint8_t rpix(uint8_t x, uint8_t y);
|
||||
void pixelcache_flush(pixelcache_t &cache);
|
||||
|
||||
void (SuperFX::*opcode_table[1024])();
|
||||
void initialize_opcode_table();
|
||||
|
||||
//opcodes.cpp
|
||||
template<int> void op_adc_i();
|
||||
template<int> void op_adc_r();
|
||||
template<int> void op_add_i();
|
||||
template<int> void op_add_r();
|
||||
void op_alt1();
|
||||
void op_alt2();
|
||||
void op_alt3();
|
||||
template<int> void op_and_i();
|
||||
template<int> void op_and_r();
|
||||
void op_asr();
|
||||
void op_bge();
|
||||
void op_bcc();
|
||||
void op_bcs();
|
||||
void op_beq();
|
||||
template<int> void op_bic_i();
|
||||
template<int> void op_bic_r();
|
||||
void op_blt();
|
||||
void op_bmi();
|
||||
void op_bne();
|
||||
void op_bpl();
|
||||
void op_bra();
|
||||
void op_bvc();
|
||||
void op_bvs();
|
||||
void op_cache();
|
||||
void op_cmode();
|
||||
template<int> void op_cmp_r();
|
||||
void op_color();
|
||||
template<int> void op_dec_r();
|
||||
void op_div2();
|
||||
void op_fmult();
|
||||
template<int> void op_from_r();
|
||||
void op_getb();
|
||||
void op_getbl();
|
||||
void op_getbh();
|
||||
void op_getbs();
|
||||
void op_getc();
|
||||
void op_hib();
|
||||
template<int> void op_ibt_r();
|
||||
template<int> void op_inc_r();
|
||||
template<int> void op_iwt_r();
|
||||
template<int> void op_jmp_r();
|
||||
template<int> void op_ldb_ir();
|
||||
template<int> void op_ldw_ir();
|
||||
template<int> void op_link();
|
||||
template<int> void op_ljmp_r();
|
||||
template<int> void op_lm_r();
|
||||
template<int> void op_lms_r();
|
||||
void op_lmult();
|
||||
void op_lob();
|
||||
void op_loop();
|
||||
void op_lsr();
|
||||
void op_merge();
|
||||
template<int> void op_mult_i();
|
||||
template<int> void op_mult_r();
|
||||
void op_nop();
|
||||
void op_not();
|
||||
template<int> void op_or_i();
|
||||
template<int> void op_or_r();
|
||||
void op_plot();
|
||||
void op_ramb();
|
||||
void op_rol();
|
||||
void op_romb();
|
||||
void op_ror();
|
||||
void op_rpix();
|
||||
template<int> void op_sbc_r();
|
||||
void op_sbk();
|
||||
void op_sex();
|
||||
template<int> void op_sm_r();
|
||||
template<int> void op_sms_r();
|
||||
template<int> void op_stb_ir();
|
||||
void op_stop();
|
||||
template<int> void op_stw_ir();
|
||||
template<int> void op_sub_i();
|
||||
template<int> void op_sub_r();
|
||||
void op_swap();
|
||||
template<int> void op_to_r();
|
||||
template<int> void op_umult_i();
|
||||
template<int> void op_umult_r();
|
||||
template<int> void op_with_r();
|
||||
template<int> void op_xor_i();
|
||||
template<int> void op_xor_r();
|
270
src/chip/superfx/core/opcode_table.cpp
Normal file
270
src/chip/superfx/core/opcode_table.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
void SuperFX::initialize_opcode_table() {
|
||||
#define op4(id, name) \
|
||||
op(id+ 0, name< 1>) op(id+ 1, name< 2>) op(id+ 2, name< 3>) op(id+ 3, name< 4>)
|
||||
|
||||
#define op6(id, name) \
|
||||
op(id+ 0, name< 8>) op(id+ 1, name< 9>) op(id+ 2, name<10>) op(id+ 3, name<11>) \
|
||||
op(id+ 4, name<12>) op(id+ 5, name<13>)
|
||||
|
||||
#define op12(id, name) \
|
||||
op(id+ 0, name< 0>) op(id+ 1, name< 1>) op(id+ 2, name< 2>) op(id+ 3, name< 3>) \
|
||||
op(id+ 4, name< 4>) op(id+ 5, name< 5>) op(id+ 6, name< 6>) op(id+ 7, name< 7>) \
|
||||
op(id+ 8, name< 8>) op(id+ 9, name< 9>) op(id+10, name<10>) op(id+11, name<11>)
|
||||
|
||||
#define op15l(id, name) \
|
||||
op(id+ 0, name< 0>) op(id+ 1, name< 1>) op(id+ 2, name< 2>) op(id+ 3, name< 3>) \
|
||||
op(id+ 4, name< 4>) op(id+ 5, name< 5>) op(id+ 6, name< 6>) op(id+ 7, name< 7>) \
|
||||
op(id+ 8, name< 8>) op(id+ 9, name< 9>) op(id+10, name<10>) op(id+11, name<11>) \
|
||||
op(id+12, name<12>) op(id+13, name<13>) op(id+14, name<14>)
|
||||
|
||||
#define op15h(id, name) \
|
||||
op(id+ 0, name< 1>) op(id+ 1, name< 2>) op(id+ 2, name< 3>) op(id+ 3, name< 4>) \
|
||||
op(id+ 4, name< 5>) op(id+ 5, name< 6>) op(id+ 6, name< 7>) op(id+ 7, name< 8>) \
|
||||
op(id+ 8, name< 9>) op(id+ 9, name<10>) op(id+10, name<11>) op(id+11, name<12>) \
|
||||
op(id+12, name<13>) op(id+13, name<14>) op(id+14, name<15>)
|
||||
|
||||
#define op16(id, name) \
|
||||
op(id+ 0, name< 0>) op(id+ 1, name< 1>) op(id+ 2, name< 2>) op(id+ 3, name< 3>) \
|
||||
op(id+ 4, name< 4>) op(id+ 5, name< 5>) op(id+ 6, name< 6>) op(id+ 7, name< 7>) \
|
||||
op(id+ 8, name< 8>) op(id+ 9, name< 9>) op(id+10, name<10>) op(id+11, name<11>) \
|
||||
op(id+12, name<12>) op(id+13, name<13>) op(id+14, name<14>) op(id+15, name<15>)
|
||||
|
||||
//======
|
||||
// ALT0
|
||||
//======
|
||||
|
||||
#define op(id, name) opcode_table[ 0 + id] = &SuperFX::op_##name;
|
||||
op (0x00, stop)
|
||||
op (0x01, nop)
|
||||
op (0x02, cache)
|
||||
op (0x03, lsr)
|
||||
op (0x04, rol)
|
||||
op (0x05, bra)
|
||||
op (0x06, blt)
|
||||
op (0x07, bge)
|
||||
op (0x08, bne)
|
||||
op (0x09, beq)
|
||||
op (0x0a, bpl)
|
||||
op (0x0b, bmi)
|
||||
op (0x0c, bcc)
|
||||
op (0x0d, bcs)
|
||||
op (0x0e, bvc)
|
||||
op (0x0f, bvs)
|
||||
op16 (0x10, to_r)
|
||||
op16 (0x20, with_r)
|
||||
op12 (0x30, stw_ir)
|
||||
op (0x3c, loop)
|
||||
op (0x3d, alt1)
|
||||
op (0x3e, alt2)
|
||||
op (0x3f, alt3)
|
||||
op12 (0x40, ldw_ir)
|
||||
op (0x4c, plot)
|
||||
op (0x4d, swap)
|
||||
op (0x4e, color)
|
||||
op (0x4f, not)
|
||||
op16 (0x50, add_r)
|
||||
op16 (0x60, sub_r)
|
||||
op (0x70, merge)
|
||||
op15h(0x71, and_r)
|
||||
op16 (0x80, mult_r)
|
||||
op (0x90, sbk)
|
||||
op4 (0x91, link)
|
||||
op (0x95, sex)
|
||||
op (0x96, asr)
|
||||
op (0x97, ror)
|
||||
op6 (0x98, jmp_r)
|
||||
op (0x9e, lob)
|
||||
op (0x9f, fmult)
|
||||
op16 (0xa0, ibt_r)
|
||||
op16 (0xb0, from_r)
|
||||
op (0xc0, hib)
|
||||
op15h(0xc1, or_r)
|
||||
op15l(0xd0, inc_r)
|
||||
op (0xdf, getc)
|
||||
op15l(0xe0, dec_r)
|
||||
op (0xef, getb)
|
||||
op16 (0xf0, iwt_r)
|
||||
#undef op
|
||||
|
||||
//======
|
||||
// ALT1
|
||||
//======
|
||||
|
||||
#define op(id, name) opcode_table[256 + id] = &SuperFX::op_##name;
|
||||
op (0x00, stop)
|
||||
op (0x01, nop)
|
||||
op (0x02, cache)
|
||||
op (0x03, lsr)
|
||||
op (0x04, rol)
|
||||
op (0x05, bra)
|
||||
op (0x06, blt)
|
||||
op (0x07, bge)
|
||||
op (0x08, bne)
|
||||
op (0x09, beq)
|
||||
op (0x0a, bpl)
|
||||
op (0x0b, bmi)
|
||||
op (0x0c, bcc)
|
||||
op (0x0d, bcs)
|
||||
op (0x0e, bvc)
|
||||
op (0x0f, bvs)
|
||||
op16 (0x10, to_r)
|
||||
op16 (0x20, with_r)
|
||||
op12 (0x30, stb_ir)
|
||||
op (0x3c, loop)
|
||||
op (0x3d, alt1)
|
||||
op (0x3e, alt2)
|
||||
op (0x3f, alt3)
|
||||
op12 (0x40, ldb_ir)
|
||||
op (0x4c, rpix)
|
||||
op (0x4d, swap)
|
||||
op (0x4e, cmode)
|
||||
op (0x4f, not)
|
||||
op16 (0x50, adc_r)
|
||||
op16 (0x60, sbc_r)
|
||||
op (0x70, merge)
|
||||
op15h(0x71, bic_r)
|
||||
op16 (0x80, umult_r)
|
||||
op (0x90, sbk)
|
||||
op4 (0x91, link)
|
||||
op (0x95, sex)
|
||||
op (0x96, div2)
|
||||
op (0x97, ror)
|
||||
op6 (0x98, ljmp_r)
|
||||
op (0x9e, lob)
|
||||
op (0x9f, lmult)
|
||||
op16 (0xa0, lms_r)
|
||||
op16 (0xb0, from_r)
|
||||
op (0xc0, hib)
|
||||
op15h(0xc1, xor_r)
|
||||
op15l(0xd0, inc_r)
|
||||
op (0xdf, getc)
|
||||
op15l(0xe0, dec_r)
|
||||
op (0xef, getbh)
|
||||
op16 (0xf0, lm_r)
|
||||
#undef op
|
||||
|
||||
//======
|
||||
// ALT2
|
||||
//======
|
||||
|
||||
#define op(id, name) opcode_table[512 + id] = &SuperFX::op_##name;
|
||||
op (0x00, stop)
|
||||
op (0x01, nop)
|
||||
op (0x02, cache)
|
||||
op (0x03, lsr)
|
||||
op (0x04, rol)
|
||||
op (0x05, bra)
|
||||
op (0x06, blt)
|
||||
op (0x07, bge)
|
||||
op (0x08, bne)
|
||||
op (0x09, beq)
|
||||
op (0x0a, bpl)
|
||||
op (0x0b, bmi)
|
||||
op (0x0c, bcc)
|
||||
op (0x0d, bcs)
|
||||
op (0x0e, bvc)
|
||||
op (0x0f, bvs)
|
||||
op16 (0x10, to_r)
|
||||
op16 (0x20, with_r)
|
||||
op12 (0x30, stw_ir)
|
||||
op (0x3c, loop)
|
||||
op (0x3d, alt1)
|
||||
op (0x3e, alt2)
|
||||
op (0x3f, alt3)
|
||||
op12 (0x40, ldw_ir)
|
||||
op (0x4c, plot)
|
||||
op (0x4d, swap)
|
||||
op (0x4e, color)
|
||||
op (0x4f, not)
|
||||
op16 (0x50, add_i)
|
||||
op16 (0x60, sub_i)
|
||||
op (0x70, merge)
|
||||
op15h(0x71, and_i)
|
||||
op16 (0x80, mult_i)
|
||||
op (0x90, sbk)
|
||||
op4 (0x91, link)
|
||||
op (0x95, sex)
|
||||
op (0x96, asr)
|
||||
op (0x97, ror)
|
||||
op6 (0x98, jmp_r)
|
||||
op (0x9e, lob)
|
||||
op (0x9f, fmult)
|
||||
op16 (0xa0, sms_r)
|
||||
op16 (0xb0, from_r)
|
||||
op (0xc0, hib)
|
||||
op15h(0xc1, or_i)
|
||||
op15l(0xd0, inc_r)
|
||||
op (0xdf, ramb)
|
||||
op15l(0xe0, dec_r)
|
||||
op (0xef, getbl)
|
||||
op16 (0xf0, sm_r)
|
||||
#undef op
|
||||
|
||||
//======
|
||||
// ALT3
|
||||
//======
|
||||
|
||||
#define op(id, name) opcode_table[768 + id] = &SuperFX::op_##name;
|
||||
op (0x00, stop)
|
||||
op (0x01, nop)
|
||||
op (0x02, cache)
|
||||
op (0x03, lsr)
|
||||
op (0x04, rol)
|
||||
op (0x05, bra)
|
||||
op (0x06, blt)
|
||||
op (0x07, bge)
|
||||
op (0x08, bne)
|
||||
op (0x09, beq)
|
||||
op (0x0a, bpl)
|
||||
op (0x0b, bmi)
|
||||
op (0x0c, bcc)
|
||||
op (0x0d, bcs)
|
||||
op (0x0e, bvc)
|
||||
op (0x0f, bvs)
|
||||
op16 (0x10, to_r)
|
||||
op16 (0x20, with_r)
|
||||
op12 (0x30, stb_ir)
|
||||
op (0x3c, loop)
|
||||
op (0x3d, alt1)
|
||||
op (0x3e, alt2)
|
||||
op (0x3f, alt3)
|
||||
op12 (0x40, ldb_ir)
|
||||
op (0x4c, rpix)
|
||||
op (0x4d, swap)
|
||||
op (0x4e, cmode)
|
||||
op (0x4f, not)
|
||||
op16 (0x50, adc_i)
|
||||
op16 (0x60, cmp_r)
|
||||
op (0x70, merge)
|
||||
op15h(0x71, bic_i)
|
||||
op16 (0x80, umult_i)
|
||||
op (0x90, sbk)
|
||||
op4 (0x91, link)
|
||||
op (0x95, sex)
|
||||
op (0x96, div2)
|
||||
op (0x97, ror)
|
||||
op6 (0x98, ljmp_r)
|
||||
op (0x9e, lob)
|
||||
op (0x9f, lmult)
|
||||
op16 (0xa0, lms_r)
|
||||
op16 (0xb0, from_r)
|
||||
op (0xc0, hib)
|
||||
op15h(0xc1, xor_i)
|
||||
op15l(0xd0, inc_r)
|
||||
op (0xdf, romb)
|
||||
op15l(0xe0, dec_r)
|
||||
op (0xef, getbs)
|
||||
op16 (0xf0, lm_r)
|
||||
#undef op
|
||||
|
||||
#undef op4
|
||||
#undef op6
|
||||
#undef op12
|
||||
#undef op15l
|
||||
#undef op15h
|
||||
#undef op16
|
||||
}
|
||||
|
||||
#endif
|
661
src/chip/superfx/core/opcodes.cpp
Normal file
661
src/chip/superfx/core/opcodes.cpp
Normal file
@@ -0,0 +1,661 @@
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
//$00 stop
|
||||
void SuperFX::op_stop() {
|
||||
if(regs.cfgr.irq == 0) {
|
||||
regs.sfr.irq = 1;
|
||||
cpu.regs.irq = 1;
|
||||
}
|
||||
|
||||
regs.sfr.g = 0;
|
||||
regs.pipeline = 0x01;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$01 nop
|
||||
void SuperFX::op_nop() {
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$02 cache
|
||||
void SuperFX::op_cache() {
|
||||
if(regs.cbr != (regs.r[15] & 0xfff0)) {
|
||||
regs.cbr = regs.r[15] & 0xfff0;
|
||||
cache_flush();
|
||||
}
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$03 lsr
|
||||
void SuperFX::op_lsr() {
|
||||
regs.sfr.cy = (regs.sr() & 1);
|
||||
regs.dr() = regs.sr() >> 1;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$04 rol
|
||||
void SuperFX::op_rol() {
|
||||
bool carry = (regs.sr() & 0x8000);
|
||||
regs.dr() = (regs.sr() << 1) | regs.sfr.cy;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.cy = carry;
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$05 bra e
|
||||
void SuperFX::op_bra() {
|
||||
regs.r[15] += (int8_t)pipe();
|
||||
}
|
||||
|
||||
//$06 blt e
|
||||
void SuperFX::op_blt() {
|
||||
int e = (int8_t)pipe();
|
||||
if((regs.sfr.s ^ regs.sfr.ov) == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$07 bge e
|
||||
void SuperFX::op_bge() {
|
||||
int e = (int8_t)pipe();
|
||||
if((regs.sfr.s ^ regs.sfr.ov) == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$08 bne e
|
||||
void SuperFX::op_bne() {
|
||||
int e = (int8_t)pipe();
|
||||
if(regs.sfr.z == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$09 beq e
|
||||
void SuperFX::op_beq() {
|
||||
int e = (int8_t)pipe();
|
||||
if(regs.sfr.z == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0a bpl e
|
||||
void SuperFX::op_bpl() {
|
||||
int e = (int8_t)pipe();
|
||||
if(regs.sfr.s == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0b bmi e
|
||||
void SuperFX::op_bmi() {
|
||||
int e = (int8_t)pipe();
|
||||
if(regs.sfr.s == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0c bcc e
|
||||
void SuperFX::op_bcc() {
|
||||
int e = (int8_t)pipe();
|
||||
if(regs.sfr.cy == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0d bcs e
|
||||
void SuperFX::op_bcs() {
|
||||
int e = (int8_t)pipe();
|
||||
if(regs.sfr.cy == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0e bvc e
|
||||
void SuperFX::op_bvc() {
|
||||
int e = (int8_t)pipe();
|
||||
if(regs.sfr.ov == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0f bvs e
|
||||
void SuperFX::op_bvs() {
|
||||
int e = (int8_t)pipe();
|
||||
if(regs.sfr.ov == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$10-1f(b0): to rN
|
||||
//$10-1f(b1): move rN
|
||||
template<int n> void SuperFX::op_to_r() {
|
||||
if(regs.sfr.b == 0) {
|
||||
regs.dreg = ®s.r[n];
|
||||
} else {
|
||||
regs.r[n] = regs.sr();
|
||||
regs.reset();
|
||||
}
|
||||
}
|
||||
|
||||
//$20-2f: with rN
|
||||
template<int n> void SuperFX::op_with_r() {
|
||||
regs.sreg = ®s.r[n];
|
||||
regs.dreg = ®s.r[n];
|
||||
regs.sfr.b = 1;
|
||||
}
|
||||
|
||||
//$30-3b(alt0): stw (rN)
|
||||
template<int n> void SuperFX::op_stw_ir() {
|
||||
regs.ramaddr = regs.r[n];
|
||||
rambuffer_write(regs.ramaddr ^ 0, regs.sr() >> 0);
|
||||
rambuffer_write(regs.ramaddr ^ 1, regs.sr() >> 8);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$30-3b(alt1): stb (rN)
|
||||
template<int n> void SuperFX::op_stb_ir() {
|
||||
regs.ramaddr = regs.r[n];
|
||||
rambuffer_write(regs.ramaddr, regs.sr());
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$3c loop
|
||||
void SuperFX::op_loop() {
|
||||
regs.r[12]--;
|
||||
regs.sfr.s = (regs.r[12] & 0x8000);
|
||||
regs.sfr.z = (regs.r[12] == 0);
|
||||
if(!regs.sfr.z) regs.r[15] = regs.r[13];
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$3d alt1
|
||||
void SuperFX::op_alt1() {
|
||||
regs.sfr.b = 0;
|
||||
regs.sfr.alt1 = 1;
|
||||
}
|
||||
|
||||
//$3e alt2
|
||||
void SuperFX::op_alt2() {
|
||||
regs.sfr.b = 0;
|
||||
regs.sfr.alt2 = 1;
|
||||
}
|
||||
|
||||
//$3f alt3
|
||||
void SuperFX::op_alt3() {
|
||||
regs.sfr.b = 0;
|
||||
regs.sfr.alt1 = 1;
|
||||
regs.sfr.alt2 = 1;
|
||||
}
|
||||
|
||||
//$40-4b(alt0): ldw (rN)
|
||||
template<int n> void SuperFX::op_ldw_ir() {
|
||||
regs.ramaddr = regs.r[n];
|
||||
uint16_t data;
|
||||
data = rambuffer_read(regs.ramaddr ^ 0) << 0;
|
||||
data |= rambuffer_read(regs.ramaddr ^ 1) << 8;
|
||||
regs.dr() = data;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$40-4b(alt1): ldb (rN)
|
||||
template<int n> void SuperFX::op_ldb_ir() {
|
||||
regs.ramaddr = regs.r[n];
|
||||
regs.dr() = rambuffer_read(regs.ramaddr);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$4c(alt0): plot
|
||||
void SuperFX::op_plot() {
|
||||
plot(regs.r[1], regs.r[2]);
|
||||
regs.r[1]++;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$4c(alt1): rpix
|
||||
void SuperFX::op_rpix() {
|
||||
regs.dr() = rpix(regs.r[1], regs.r[2]);
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$4d: swap
|
||||
void SuperFX::op_swap() {
|
||||
regs.dr() = (regs.sr() >> 8) | (regs.sr() << 8);
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$4e(alt0): color
|
||||
void SuperFX::op_color() {
|
||||
regs.colr = color(regs.sr());
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$4e(alt1): cmode
|
||||
void SuperFX::op_cmode() {
|
||||
regs.por = regs.sr();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$4f: not
|
||||
void SuperFX::op_not() {
|
||||
regs.dr() = ~regs.sr();
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$50-5f(alt0): add rN
|
||||
template<int n> void SuperFX::op_add_r() {
|
||||
int r = regs.sr() + regs.r[n];
|
||||
regs.sfr.ov = ~(regs.sr() ^ regs.r[n]) & (regs.r[n] ^ r) & 0x8000;
|
||||
regs.sfr.s = (r & 0x8000);
|
||||
regs.sfr.cy = (r >= 0x10000);
|
||||
regs.sfr.z = ((uint16_t)r == 0);
|
||||
regs.dr() = r;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$50-5f(alt1): adc rN
|
||||
template<int n> void SuperFX::op_adc_r() {
|
||||
int r = regs.sr() + regs.r[n] + regs.sfr.cy;
|
||||
regs.sfr.ov = ~(regs.sr() ^ regs.r[n]) & (regs.r[n] ^ r) & 0x8000;
|
||||
regs.sfr.s = (r & 0x8000);
|
||||
regs.sfr.cy = (r >= 0x10000);
|
||||
regs.sfr.z = ((uint16_t)r == 0);
|
||||
regs.dr() = r;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$50-5f(alt2): add #N
|
||||
template<int n> void SuperFX::op_add_i() {
|
||||
int r = regs.sr() + n;
|
||||
regs.sfr.ov = ~(regs.sr() ^ n) & (n ^ r) & 0x8000;
|
||||
regs.sfr.s = (r & 0x8000);
|
||||
regs.sfr.cy = (r >= 0x10000);
|
||||
regs.sfr.z = ((uint16_t)r == 0);
|
||||
regs.dr() = r;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$50-5f(alt3): adc #N
|
||||
template<int n> void SuperFX::op_adc_i() {
|
||||
int r = regs.sr() + n + regs.sfr.cy;
|
||||
regs.sfr.ov = ~(regs.sr() ^ n) & (n ^ r) & 0x8000;
|
||||
regs.sfr.s = (r & 0x8000);
|
||||
regs.sfr.cy = (r >= 0x10000);
|
||||
regs.sfr.z = ((uint16_t)r == 0);
|
||||
regs.dr() = r;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$60-6f(alt0): sub rN
|
||||
template<int n> void SuperFX::op_sub_r() {
|
||||
int r = regs.sr() - regs.r[n];
|
||||
regs.sfr.ov = (regs.sr() ^ regs.r[n]) & (regs.sr() ^ r) & 0x8000;
|
||||
regs.sfr.s = (r & 0x8000);
|
||||
regs.sfr.cy = (r >= 0);
|
||||
regs.sfr.z = ((uint16_t)r == 0);
|
||||
regs.dr() = r;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$60-6f(alt1): sbc rN
|
||||
template<int n> void SuperFX::op_sbc_r() {
|
||||
int r = regs.sr() - regs.r[n] - !regs.sfr.cy;
|
||||
regs.sfr.ov = (regs.sr() ^ regs.r[n]) & (regs.sr() ^ r) & 0x8000;
|
||||
regs.sfr.s = (r & 0x8000);
|
||||
regs.sfr.cy = (r >= 0);
|
||||
regs.sfr.z = ((uint16_t)r == 0);
|
||||
regs.dr() = r;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$60-6f(alt2): sub #N
|
||||
template<int n> void SuperFX::op_sub_i() {
|
||||
int r = regs.sr() - n;
|
||||
regs.sfr.ov = (regs.sr() ^ n) & (regs.sr() ^ r) & 0x8000;
|
||||
regs.sfr.s = (r & 0x8000);
|
||||
regs.sfr.cy = (r >= 0);
|
||||
regs.sfr.z = ((uint16_t)r == 0);
|
||||
regs.dr() = r;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$60-6f(alt3): cmp rN
|
||||
template<int n> void SuperFX::op_cmp_r() {
|
||||
int r = regs.sr() - regs.r[n];
|
||||
regs.sfr.ov = (regs.sr() ^ regs.r[n]) & (regs.sr() ^ r) & 0x8000;
|
||||
regs.sfr.s = (r & 0x8000);
|
||||
regs.sfr.cy = (r >= 0);
|
||||
regs.sfr.z = ((uint16_t)r == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$70: merge
|
||||
void SuperFX::op_merge() {
|
||||
regs.dr() = (regs.r[7] & 0xff00) | (regs.r[8] >> 8);
|
||||
regs.sfr.ov = (regs.dr() & 0xc0c0);
|
||||
regs.sfr.s = (regs.dr() & 0x8080);
|
||||
regs.sfr.cy = (regs.dr() & 0xe0e0);
|
||||
regs.sfr.z = (regs.dr() & 0xf0f0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$71-7f(alt0): and rN
|
||||
template<int n> void SuperFX::op_and_r() {
|
||||
regs.dr() = regs.sr() & regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$71-7f(alt1): bic rN
|
||||
template<int n> void SuperFX::op_bic_r() {
|
||||
regs.dr() = regs.sr() & ~regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$71-7f(alt2): and #N
|
||||
template<int n> void SuperFX::op_and_i() {
|
||||
regs.dr() = regs.sr() & n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$71-7f(alt3): bic #N
|
||||
template<int n> void SuperFX::op_bic_i() {
|
||||
regs.dr() = regs.sr() & ~n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$80-8f(alt0): mult rN
|
||||
template<int n> void SuperFX::op_mult_r() {
|
||||
regs.dr() = (int8_t)regs.sr() * (int8_t)regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
if(!regs.cfgr.ms0) add_clocks(2);
|
||||
}
|
||||
|
||||
//$80-8f(alt1): umult rN
|
||||
template<int n> void SuperFX::op_umult_r() {
|
||||
regs.dr() = (uint8_t)regs.sr() * (uint8_t)regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
if(!regs.cfgr.ms0) add_clocks(2);
|
||||
}
|
||||
|
||||
//$80-8f(alt2): mult #N
|
||||
template<int n> void SuperFX::op_mult_i() {
|
||||
regs.dr() = (int8_t)regs.sr() * (int8_t)n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
if(!regs.cfgr.ms0) add_clocks(2);
|
||||
}
|
||||
|
||||
//$80-8f(alt3): umult #N
|
||||
template<int n> void SuperFX::op_umult_i() {
|
||||
regs.dr() = (uint8_t)regs.sr() * (uint8_t)n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
if(!regs.cfgr.ms0) add_clocks(2);
|
||||
}
|
||||
|
||||
//$90: sbk
|
||||
void SuperFX::op_sbk() {
|
||||
rambuffer_write(regs.ramaddr ^ 0, regs.sr() >> 0);
|
||||
rambuffer_write(regs.ramaddr ^ 1, regs.sr() >> 8);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$91-94: link #N
|
||||
template<int n> void SuperFX::op_link() {
|
||||
regs.r[11] = regs.r[15] + n;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$95: sex
|
||||
void SuperFX::op_sex() {
|
||||
regs.dr() = (int8_t)regs.sr();
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$96(alt0): asr
|
||||
void SuperFX::op_asr() {
|
||||
regs.sfr.cy = (regs.sr() & 1);
|
||||
regs.dr() = (int16_t)regs.sr() >> 1;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$96(alt1): div2
|
||||
void SuperFX::op_div2() {
|
||||
regs.sfr.cy = (regs.sr() & 1);
|
||||
regs.dr() = ((int16_t)regs.sr() >> 1) + ((regs.sr() + 1) >> 16);
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$97: ror
|
||||
void SuperFX::op_ror() {
|
||||
bool carry = (regs.sr() & 1);
|
||||
regs.dr() = (regs.sfr.cy << 15) | (regs.sr() >> 1);
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.cy = carry;
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$98-9d(alt0): jmp rN
|
||||
template<int n> void SuperFX::op_jmp_r() {
|
||||
regs.r[15] = regs.r[n];
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$98-9d(alt1): ljmp rN
|
||||
template<int n> void SuperFX::op_ljmp_r() {
|
||||
regs.pbr = regs.r[n];
|
||||
regs.r[15] = regs.sr();
|
||||
regs.cbr = regs.r[15] & 0xfff0;
|
||||
cache_flush();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$9e: lob
|
||||
void SuperFX::op_lob() {
|
||||
regs.dr() = regs.sr() & 0xff;
|
||||
regs.sfr.s = (regs.dr() & 0x80);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$9f(alt0): fmult
|
||||
void SuperFX::op_fmult() {
|
||||
uint32_t result = (int16_t)regs.sr() * (int16_t)regs.r[6];
|
||||
regs.dr() = result >> 16;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.cy = (result & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
add_clocks(4 + (regs.cfgr.ms0 << 2));
|
||||
}
|
||||
|
||||
//$9f(alt1): lmult
|
||||
void SuperFX::op_lmult() {
|
||||
uint32_t result = (int16_t)regs.sr() * (int16_t)regs.r[6];
|
||||
regs.r[4] = result;
|
||||
regs.dr() = result >> 16;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.cy = (result & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
add_clocks(4 + (regs.cfgr.ms0 << 2));
|
||||
}
|
||||
|
||||
//$a0-af(alt0): ibt rN,#pp
|
||||
template<int n> void SuperFX::op_ibt_r() {
|
||||
regs.r[n] = (int8_t)pipe();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$a0-af(alt1): lms rN,(yy)
|
||||
template<int n> void SuperFX::op_lms_r() {
|
||||
regs.ramaddr = pipe() << 1;
|
||||
uint16_t data;
|
||||
data = rambuffer_read(regs.ramaddr ^ 0) << 0;
|
||||
data |= rambuffer_read(regs.ramaddr ^ 1) << 8;
|
||||
regs.r[n] = data;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$a0-af(alt2): sms (yy),rN
|
||||
template<int n> void SuperFX::op_sms_r() {
|
||||
regs.ramaddr = pipe() << 1;
|
||||
rambuffer_write(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
||||
rambuffer_write(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$b0-bf(b0): from rN
|
||||
//$b0-bf(b1): moves rN
|
||||
template<int n> void SuperFX::op_from_r() {
|
||||
if(regs.sfr.b == 0) {
|
||||
regs.sreg = ®s.r[n];
|
||||
} else {
|
||||
regs.dr() = regs.r[n];
|
||||
regs.sfr.ov = (regs.dr() & 0x80);
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
}
|
||||
|
||||
//$c0: hib
|
||||
void SuperFX::op_hib() {
|
||||
regs.dr() = regs.sr() >> 8;
|
||||
regs.sfr.s = (regs.dr() & 0x80);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$c1-cf(alt0): or rN
|
||||
template<int n> void SuperFX::op_or_r() {
|
||||
regs.dr() = regs.sr() | regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$c1-cf(alt1): xor rN
|
||||
template<int n> void SuperFX::op_xor_r() {
|
||||
regs.dr() = regs.sr() ^ regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$c1-cf(alt2): or #N
|
||||
template<int n> void SuperFX::op_or_i() {
|
||||
regs.dr() = regs.sr() | n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$c1-cf(alt3): xor #N
|
||||
template<int n> void SuperFX::op_xor_i() {
|
||||
regs.dr() = regs.sr() ^ n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$d0-de: inc rN
|
||||
template<int n> void SuperFX::op_inc_r() {
|
||||
regs.r[n]++;
|
||||
regs.sfr.s = (regs.r[n] & 0x8000);
|
||||
regs.sfr.z = (regs.r[n] == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$df(alt0): getc
|
||||
void SuperFX::op_getc() {
|
||||
regs.colr = color(rombuffer_read());
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$df(alt2): ramb
|
||||
void SuperFX::op_ramb() {
|
||||
rambuffer_sync();
|
||||
regs.rambr = regs.sr();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$df(alt3): romb
|
||||
void SuperFX::op_romb() {
|
||||
rombuffer_sync();
|
||||
regs.rombr = regs.sr();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$e0-ee: dec rN
|
||||
template<int n> void SuperFX::op_dec_r() {
|
||||
regs.r[n]--;
|
||||
regs.sfr.s = (regs.r[n] & 0x8000);
|
||||
regs.sfr.z = (regs.r[n] == 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$ef(alt0): getb
|
||||
void SuperFX::op_getb() {
|
||||
regs.dr() = rombuffer_read();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$ef(alt1): getbh
|
||||
void SuperFX::op_getbh() {
|
||||
regs.dr() = (rombuffer_read() << 8) | (regs.sr() & 0x00ff);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$ef(alt2): getbl
|
||||
void SuperFX::op_getbl() {
|
||||
regs.dr() = (regs.sr() & 0xff00) | (rombuffer_read() << 0);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$ef(alt3): getbs
|
||||
void SuperFX::op_getbs() {
|
||||
regs.dr() = (int8_t)rombuffer_read();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$f0-ff(alt0): iwt rN,#xx
|
||||
template<int n> void SuperFX::op_iwt_r() {
|
||||
uint16_t data;
|
||||
data = pipe() << 0;
|
||||
data |= pipe() << 8;
|
||||
regs.r[n] = data;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$f0-ff(alt1): lm rN,(xx)
|
||||
template<int n> void SuperFX::op_lm_r() {
|
||||
regs.ramaddr = pipe() << 0;
|
||||
regs.ramaddr |= pipe() << 8;
|
||||
uint16_t data;
|
||||
data = rambuffer_read(regs.ramaddr ^ 0) << 0;
|
||||
data |= rambuffer_read(regs.ramaddr ^ 1) << 8;
|
||||
regs.r[n] = data;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
//$f0-ff(alt2): sm (xx),rN
|
||||
template<int n> void SuperFX::op_sm_r() {
|
||||
regs.ramaddr = pipe() << 0;
|
||||
regs.ramaddr |= pipe() << 8;
|
||||
rambuffer_write(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
||||
rambuffer_write(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
#endif
|
177
src/chip/superfx/core/registers.hpp
Normal file
177
src/chip/superfx/core/registers.hpp
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
|
||||
//accepts a callback binding so r14 writes can trigger ROM buffering transparently
|
||||
struct reg16_t : noncopyable {
|
||||
uint16_t data;
|
||||
function<void (uint16_t)> on_modify;
|
||||
|
||||
inline operator unsigned() const { return data; }
|
||||
inline uint16_t assign(uint16_t i) {
|
||||
if(on_modify) on_modify(i);
|
||||
else data = i;
|
||||
return data;
|
||||
}
|
||||
|
||||
inline unsigned operator++() { return assign(data + 1); }
|
||||
inline unsigned operator--() { return assign(data - 1); }
|
||||
inline unsigned operator++(int) { unsigned r = data; assign(data + 1); return r; }
|
||||
inline unsigned operator--(int) { unsigned r = data; assign(data - 1); return r; }
|
||||
inline unsigned operator = (unsigned i) { return assign(i); }
|
||||
inline unsigned operator |= (unsigned i) { return assign(data | i); }
|
||||
inline unsigned operator ^= (unsigned i) { return assign(data ^ i); }
|
||||
inline unsigned operator &= (unsigned i) { return assign(data & i); }
|
||||
inline unsigned operator <<= (unsigned i) { return assign(data << i); }
|
||||
inline unsigned operator >>= (unsigned i) { return assign(data >> i); }
|
||||
inline unsigned operator += (unsigned i) { return assign(data + i); }
|
||||
inline unsigned operator -= (unsigned i) { return assign(data - i); }
|
||||
inline unsigned operator *= (unsigned i) { return assign(data * i); }
|
||||
inline unsigned operator /= (unsigned i) { return assign(data / i); }
|
||||
inline unsigned operator %= (unsigned i) { return assign(data % i); }
|
||||
|
||||
inline unsigned operator = (const reg16_t& i) { return assign(i); }
|
||||
|
||||
reg16_t() : data(0) {}
|
||||
};
|
||||
|
||||
struct sfr_t {
|
||||
bool irq; //interrupt flag
|
||||
bool b; //WITH flag
|
||||
bool ih; //immediate higher 8-bit flag
|
||||
bool il; //immediate lower 8-bit flag
|
||||
bool alt2; //ALT2 mode
|
||||
bool alt1; //ALT2 instruction mode
|
||||
bool r; //ROM r14 read flag
|
||||
bool g; //GO flag
|
||||
bool ov; //overflow flag
|
||||
bool s; //sign flag
|
||||
bool cy; //carry flag
|
||||
bool z; //zero flag
|
||||
|
||||
operator uint16_t() const {
|
||||
return (irq << 15) | (b << 12) | (ih << 11) | (il << 10) | (alt2 << 9) | (alt1 << 8)
|
||||
| (r << 6) | (g << 5) | (ov << 4) | (s << 3) | (cy << 2) | (z << 1);
|
||||
}
|
||||
|
||||
sfr_t& operator=(uint16_t data) {
|
||||
irq = data & 0x8000;
|
||||
b = data & 0x1000;
|
||||
ih = data & 0x0800;
|
||||
il = data & 0x0400;
|
||||
alt2 = data & 0x0200;
|
||||
alt1 = data & 0x0100;
|
||||
r = data & 0x0040;
|
||||
g = data & 0x0020;
|
||||
ov = data & 0x0010;
|
||||
s = data & 0x0008;
|
||||
cy = data & 0x0004;
|
||||
z = data & 0x0002;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct scmr_t {
|
||||
unsigned ht;
|
||||
bool ron;
|
||||
bool ran;
|
||||
unsigned md;
|
||||
|
||||
operator uint8_t() const {
|
||||
return ((ht >> 1) << 5) | (ron << 4) | (ran << 3) | ((ht & 1) << 2) | (md);
|
||||
}
|
||||
|
||||
scmr_t& operator=(uint8_t data) {
|
||||
ht = (bool)(data & 0x20) << 1;
|
||||
ht |= (bool)(data & 0x04) << 0;
|
||||
ron = data & 0x10;
|
||||
ran = data & 0x08;
|
||||
md = data & 0x03;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct por_t {
|
||||
bool obj;
|
||||
bool freezehigh;
|
||||
bool highnibble;
|
||||
bool dither;
|
||||
bool transparent;
|
||||
|
||||
operator uint8_t() const {
|
||||
return (obj << 4) | (freezehigh << 3) | (highnibble << 2) | (dither << 1) | (transparent);
|
||||
}
|
||||
|
||||
por_t& operator=(uint8_t data) {
|
||||
obj = data & 0x10;
|
||||
freezehigh = data & 0x08;
|
||||
highnibble = data & 0x04;
|
||||
dither = data & 0x02;
|
||||
transparent = data & 0x01;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct cfgr_t {
|
||||
bool irq;
|
||||
bool ms0;
|
||||
|
||||
operator uint8_t() const {
|
||||
return (irq << 7) | (ms0 << 5);
|
||||
}
|
||||
|
||||
cfgr_t& operator=(uint8_t data) {
|
||||
irq = data & 0x80;
|
||||
ms0 = data & 0x20;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct regs_t {
|
||||
uint8_t pipeline;
|
||||
uint16_t ramaddr;
|
||||
|
||||
reg16_t r[16]; //general purpose registers
|
||||
sfr_t sfr; //status flag register
|
||||
uint8_t pbr; //program bank register
|
||||
uint8_t rombr; //game pack ROM bank register
|
||||
bool rambr; //game pack RAM bank register
|
||||
uint16_t cbr; //cache base register
|
||||
uint8_t scbr; //screen base register
|
||||
scmr_t scmr; //screen mode register
|
||||
uint8_t colr; //color register
|
||||
por_t por; //plot option register
|
||||
bool bramr; //back-up RAM register
|
||||
uint8_t vcr; //version code register
|
||||
cfgr_t cfgr; //config register
|
||||
bool clsr; //clock select register
|
||||
|
||||
unsigned romcl; //clock ticks until romdr is valid
|
||||
uint8_t romdr; //ROM buffer data register
|
||||
|
||||
unsigned ramcl; //clock ticks until ramdr is valid
|
||||
uint16_t ramar; //RAM buffer address register
|
||||
uint8_t ramdr; //RAM buffer data register
|
||||
|
||||
reg16_t *sreg, *dreg;
|
||||
reg16_t& sr() { return *sreg; } //source register (from)
|
||||
reg16_t& dr() { return *dreg; } //destination register (to)
|
||||
|
||||
void reset() {
|
||||
sfr.b = 0;
|
||||
sfr.alt1 = 0;
|
||||
sfr.alt2 = 0;
|
||||
|
||||
sreg = &r[0];
|
||||
dreg = &r[0];
|
||||
}
|
||||
} regs;
|
||||
|
||||
struct cache_t {
|
||||
uint8_t buffer[512];
|
||||
bool valid[32];
|
||||
} cache;
|
||||
|
||||
struct pixelcache_t {
|
||||
uint16_t offset;
|
||||
uint8_t bitpend;
|
||||
uint8_t data[8];
|
||||
} pixelcache[2];
|
275
src/chip/superfx/disasm/disasm.cpp
Normal file
275
src/chip/superfx/disasm/disasm.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
void SuperFX::disassemble_opcode(char *output) {
|
||||
*output = 0;
|
||||
|
||||
if(!regs.sfr.alt2) {
|
||||
if(!regs.sfr.alt1) {
|
||||
disassemble_alt0(output);
|
||||
} else {
|
||||
disassemble_alt1(output);
|
||||
}
|
||||
} else {
|
||||
if(!regs.sfr.alt1) {
|
||||
disassemble_alt2(output);
|
||||
} else {
|
||||
disassemble_alt3(output);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned length = strlen(output);
|
||||
while(length++ < 20) strcat(output, " ");
|
||||
}
|
||||
|
||||
#define case4(id) \
|
||||
case id+ 0: case id+ 1: case id+ 2: case id+ 3
|
||||
#define case6(id) \
|
||||
case id+ 0: case id+ 1: case id+ 2: case id+ 3: case id+ 4: case id+ 5
|
||||
#define case12(id) \
|
||||
case id+ 0: case id+ 1: case id+ 2: case id+ 3: case id+ 4: case id+ 5: case id+ 6: case id+ 7: \
|
||||
case id+ 8: case id+ 9: case id+10: case id+11
|
||||
#define case15(id) \
|
||||
case id+ 0: case id+ 1: case id+ 2: case id+ 3: case id+ 4: case id+ 5: case id+ 6: case id+ 7: \
|
||||
case id+ 8: case id+ 9: case id+10: case id+11: case id+12: case id+13: case id+14
|
||||
#define case16(id) \
|
||||
case id+ 0: case id+ 1: case id+ 2: case id+ 3: case id+ 4: case id+ 5: case id+ 6: case id+ 7: \
|
||||
case id+ 8: case id+ 9: case id+10: case id+11: case id+12: case id+13: case id+14: case id+15
|
||||
|
||||
#define op0 regs.pipeline
|
||||
#define op1 superfxbus.read((regs.pbr << 16) + regs.r[15] + 0)
|
||||
#define op2 superfxbus.read((regs.pbr << 16) + regs.r[15] + 1)
|
||||
|
||||
void SuperFX::disassemble_alt0(char *output) {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
case (0x01): sprintf(t, "nop"); break;
|
||||
case (0x02): sprintf(t, "cache"); break;
|
||||
case (0x03): sprintf(t, "lsr"); break;
|
||||
case (0x04): sprintf(t, "rol"); break;
|
||||
case (0x05): sprintf(t, "bra %+d", (int8_t)op1); break;
|
||||
case (0x06): sprintf(t, "blt %+d", (int8_t)op1); break;
|
||||
case (0x07): sprintf(t, "bge %+d", (int8_t)op1); break;
|
||||
case (0x08): sprintf(t, "bne %+d", (int8_t)op1); break;
|
||||
case (0x09): sprintf(t, "beq %+d", (int8_t)op1); break;
|
||||
case (0x0a): sprintf(t, "bpl %+d", (int8_t)op1); break;
|
||||
case (0x0b): sprintf(t, "bmi %+d", (int8_t)op1); break;
|
||||
case (0x0c): sprintf(t, "bcc %+d", (int8_t)op1); break;
|
||||
case (0x0d): sprintf(t, "bcs %+d", (int8_t)op1); break;
|
||||
case (0x0e): sprintf(t, "bvc %+d", (int8_t)op1); break;
|
||||
case (0x0f): sprintf(t, "bvs %+d", (int8_t)op1); break;
|
||||
case16(0x10): sprintf(t, "to r%u", op0 & 15); break;
|
||||
case16(0x20): sprintf(t, "with r%u", op0 & 15); break;
|
||||
case12(0x30): sprintf(t, "stw (r%u)", op0 & 15); break;
|
||||
case (0x3c): sprintf(t, "loop"); break;
|
||||
case (0x3d): sprintf(t, "alt1"); break;
|
||||
case (0x3e): sprintf(t, "alt2"); break;
|
||||
case (0x3f): sprintf(t, "alt3"); break;
|
||||
case12(0x40): sprintf(t, "ldw (r%u)", op0 & 15); break;
|
||||
case (0x4c): sprintf(t, "plot"); break;
|
||||
case (0x4d): sprintf(t, "swap"); break;
|
||||
case (0x4e): sprintf(t, "color"); break;
|
||||
case (0x4f): sprintf(t, "not"); break;
|
||||
case16(0x50): sprintf(t, "add r%u", op0 & 15); break;
|
||||
case16(0x60): sprintf(t, "sub r%u", op0 & 15); break;
|
||||
case (0x70): sprintf(t, "merge"); break;
|
||||
case15(0x71): sprintf(t, "and r%u", op0 & 15); break;
|
||||
case16(0x80): sprintf(t, "mult r%u", op0 & 15); break;
|
||||
case (0x90): sprintf(t, "sbk"); break;
|
||||
case4 (0x91): sprintf(t, "link #%u", op0 & 15); break;
|
||||
case (0x95): sprintf(t, "sex"); break;
|
||||
case (0x96): sprintf(t, "asr"); break;
|
||||
case (0x97): sprintf(t, "ror"); break;
|
||||
case6 (0x98): sprintf(t, "jmp r%u", op0 & 15); break;
|
||||
case (0x9e): sprintf(t, "lob"); break;
|
||||
case (0x9f): sprintf(t, "fmult"); break;
|
||||
case16(0xa0): sprintf(t, "ibt r%u,#$%.2x", op0 & 15, op1); break;
|
||||
case16(0xb0): sprintf(t, "from r%u", op0 & 15); break;
|
||||
case (0xc0): sprintf(t, "hib");
|
||||
case15(0xc1): sprintf(t, "or r%u", op0 & 15); break;
|
||||
case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break;
|
||||
case (0xdf): sprintf(t, "getc"); break;
|
||||
case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break;
|
||||
case (0xef): sprintf(t, "getb"); break;
|
||||
case16(0xf0): sprintf(t, "iwt r%u,#$%.2x%.2x", op0 & 15, op2, op1); break;
|
||||
}
|
||||
strcat(output, t);
|
||||
}
|
||||
|
||||
void SuperFX::disassemble_alt1(char *output) {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
case (0x01): sprintf(t, "nop"); break;
|
||||
case (0x02): sprintf(t, "cache"); break;
|
||||
case (0x03): sprintf(t, "lsr"); break;
|
||||
case (0x04): sprintf(t, "rol"); break;
|
||||
case (0x05): sprintf(t, "bra %+d", (int8_t)op1); break;
|
||||
case (0x06): sprintf(t, "blt %+d", (int8_t)op1); break;
|
||||
case (0x07): sprintf(t, "bge %+d", (int8_t)op1); break;
|
||||
case (0x08): sprintf(t, "bne %+d", (int8_t)op1); break;
|
||||
case (0x09): sprintf(t, "beq %+d", (int8_t)op1); break;
|
||||
case (0x0a): sprintf(t, "bpl %+d", (int8_t)op1); break;
|
||||
case (0x0b): sprintf(t, "bmi %+d", (int8_t)op1); break;
|
||||
case (0x0c): sprintf(t, "bcc %+d", (int8_t)op1); break;
|
||||
case (0x0d): sprintf(t, "bcs %+d", (int8_t)op1); break;
|
||||
case (0x0e): sprintf(t, "bvc %+d", (int8_t)op1); break;
|
||||
case (0x0f): sprintf(t, "bvs %+d", (int8_t)op1); break;
|
||||
case16(0x10): sprintf(t, "to r%u", op0 & 15); break;
|
||||
case16(0x20): sprintf(t, "with r%u", op0 & 15); break;
|
||||
case12(0x30): sprintf(t, "stb (r%u)", op0 & 15); break;
|
||||
case (0x3c): sprintf(t, "loop"); break;
|
||||
case (0x3d): sprintf(t, "alt1"); break;
|
||||
case (0x3e): sprintf(t, "alt2"); break;
|
||||
case (0x3f): sprintf(t, "alt3"); break;
|
||||
case12(0x40): sprintf(t, "ldb (r%u)", op0 & 15); break;
|
||||
case (0x4c): sprintf(t, "rpix"); break;
|
||||
case (0x4d): sprintf(t, "swap"); break;
|
||||
case (0x4e): sprintf(t, "cmode"); break;
|
||||
case (0x4f): sprintf(t, "not"); break;
|
||||
case16(0x50): sprintf(t, "adc r%u", op0 & 15); break;
|
||||
case16(0x60): sprintf(t, "sbc r%u", op0 & 15); break;
|
||||
case (0x70): sprintf(t, "merge"); break;
|
||||
case15(0x71): sprintf(t, "bic r%u", op0 & 15); break;
|
||||
case16(0x80): sprintf(t, "umult r%u", op0 & 15); break;
|
||||
case (0x90): sprintf(t, "sbk"); break;
|
||||
case4 (0x91): sprintf(t, "link #%u", op0 & 15); break;
|
||||
case (0x95): sprintf(t, "sex"); break;
|
||||
case (0x96): sprintf(t, "div2"); break;
|
||||
case (0x97): sprintf(t, "ror"); break;
|
||||
case6 (0x98): sprintf(t, "ljmp r%u", op0 & 15); break;
|
||||
case (0x9e): sprintf(t, "lob"); break;
|
||||
case (0x9f): sprintf(t, "lmult"); break;
|
||||
case16(0xa0): sprintf(t, "lms r%u,(#$%.4x)", op0 & 15, op1 << 1); break;
|
||||
case16(0xb0): sprintf(t, "from r%u", op0 & 15); break;
|
||||
case (0xc0): sprintf(t, "hib"); break;
|
||||
case15(0xc1): sprintf(t, "xor r%u", op0 & 15); break;
|
||||
case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break;
|
||||
case (0xdf): sprintf(t, "getc"); break;
|
||||
case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break;
|
||||
case (0xef): sprintf(t, "getbh"); break;
|
||||
case16(0xf0): sprintf(t, "lm r%u", op0 & 15); break;
|
||||
}
|
||||
strcat(output, t);
|
||||
}
|
||||
|
||||
void SuperFX::disassemble_alt2(char *output) {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
case (0x01): sprintf(t, "nop"); break;
|
||||
case (0x02): sprintf(t, "cache"); break;
|
||||
case (0x03): sprintf(t, "lsr"); break;
|
||||
case (0x04): sprintf(t, "rol"); break;
|
||||
case (0x05): sprintf(t, "bra %+d", (int8_t)op1); break;
|
||||
case (0x06): sprintf(t, "blt %+d", (int8_t)op1); break;
|
||||
case (0x07): sprintf(t, "bge %+d", (int8_t)op1); break;
|
||||
case (0x08): sprintf(t, "bne %+d", (int8_t)op1); break;
|
||||
case (0x09): sprintf(t, "beq %+d", (int8_t)op1); break;
|
||||
case (0x0a): sprintf(t, "bpl %+d", (int8_t)op1); break;
|
||||
case (0x0b): sprintf(t, "bmi %+d", (int8_t)op1); break;
|
||||
case (0x0c): sprintf(t, "bcc %+d", (int8_t)op1); break;
|
||||
case (0x0d): sprintf(t, "bcs %+d", (int8_t)op1); break;
|
||||
case (0x0e): sprintf(t, "bvc %+d", (int8_t)op1); break;
|
||||
case (0x0f): sprintf(t, "bvs %+d", (int8_t)op1); break;
|
||||
case16(0x10): sprintf(t, "to r%u", op0 & 15); break;
|
||||
case16(0x20): sprintf(t, "with r%u", op0 & 15); break;
|
||||
case12(0x30): sprintf(t, "stw (r%u)", op0 & 15); break;
|
||||
case (0x3c): sprintf(t, "loop"); break;
|
||||
case (0x3d): sprintf(t, "alt1"); break;
|
||||
case (0x3e): sprintf(t, "alt2"); break;
|
||||
case (0x3f): sprintf(t, "alt3"); break;
|
||||
case12(0x40): sprintf(t, "ldw (r%u)", op0 & 15); break;
|
||||
case (0x4c): sprintf(t, "plot"); break;
|
||||
case (0x4d): sprintf(t, "swap"); break;
|
||||
case (0x4e): sprintf(t, "color"); break;
|
||||
case (0x4f): sprintf(t, "not"); break;
|
||||
case16(0x50): sprintf(t, "add #%u", op0 & 15); break;
|
||||
case16(0x60): sprintf(t, "sub #%u", op0 & 15); break;
|
||||
case (0x70): sprintf(t, "merge"); break;
|
||||
case15(0x71): sprintf(t, "and #%u", op0 & 15); break;
|
||||
case16(0x80): sprintf(t, "mult #%u", op0 & 15); break;
|
||||
case (0x90): sprintf(t, "sbk"); break;
|
||||
case4 (0x91): sprintf(t, "link #%u", op0 & 15); break;
|
||||
case (0x95): sprintf(t, "sex"); break;
|
||||
case (0x96): sprintf(t, "asr"); break;
|
||||
case (0x97): sprintf(t, "ror"); break;
|
||||
case6 (0x98): sprintf(t, "jmp r%u", op0 & 15); break;
|
||||
case (0x9e): sprintf(t, "lob"); break;
|
||||
case (0x9f): sprintf(t, "fmult"); break;
|
||||
case16(0xa0): sprintf(t, "sms r%u,(#$%.4x)", op0 & 15, op1 << 1); break;
|
||||
case16(0xb0): sprintf(t, "from r%u", op0 & 15); break;
|
||||
case (0xc0): sprintf(t, "hib"); break;
|
||||
case15(0xc1): sprintf(t, "or #%u", op0 & 15); break;
|
||||
case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break;
|
||||
case (0xdf): sprintf(t, "ramb"); break;
|
||||
case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break;
|
||||
case (0xef): sprintf(t, "getbl"); break;
|
||||
case16(0xf0): sprintf(t, "sm r%u", op0 & 15); break;
|
||||
}
|
||||
strcat(output, t);
|
||||
}
|
||||
|
||||
void SuperFX::disassemble_alt3(char *output) {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
case (0x01): sprintf(t, "nop"); break;
|
||||
case (0x02): sprintf(t, "cache"); break;
|
||||
case (0x03): sprintf(t, "lsr"); break;
|
||||
case (0x04): sprintf(t, "rol"); break;
|
||||
case (0x05): sprintf(t, "bra %+d", (int8_t)op1); break;
|
||||
case (0x06): sprintf(t, "blt %+d", (int8_t)op1); break;
|
||||
case (0x07): sprintf(t, "bge %+d", (int8_t)op1); break;
|
||||
case (0x08): sprintf(t, "bne %+d", (int8_t)op1); break;
|
||||
case (0x09): sprintf(t, "beq %+d", (int8_t)op1); break;
|
||||
case (0x0a): sprintf(t, "bpl %+d", (int8_t)op1); break;
|
||||
case (0x0b): sprintf(t, "bmi %+d", (int8_t)op1); break;
|
||||
case (0x0c): sprintf(t, "bcc %+d", (int8_t)op1); break;
|
||||
case (0x0d): sprintf(t, "bcs %+d", (int8_t)op1); break;
|
||||
case (0x0e): sprintf(t, "bvc %+d", (int8_t)op1); break;
|
||||
case (0x0f): sprintf(t, "bvs %+d", (int8_t)op1); break;
|
||||
case16(0x10): sprintf(t, "to r%u", op0 & 15); break;
|
||||
case16(0x20): sprintf(t, "with r%u", op0 & 15); break;
|
||||
case12(0x30): sprintf(t, "stb (r%u)", op0 & 15); break;
|
||||
case (0x3c): sprintf(t, "loop"); break;
|
||||
case (0x3d): sprintf(t, "alt1"); break;
|
||||
case (0x3e): sprintf(t, "alt2"); break;
|
||||
case (0x3f): sprintf(t, "alt3"); break;
|
||||
case12(0x40): sprintf(t, "ldb (r%u)", op0 & 15); break;
|
||||
case (0x4c): sprintf(t, "rpix"); break;
|
||||
case (0x4d): sprintf(t, "swap"); break;
|
||||
case (0x4e): sprintf(t, "cmode"); break;
|
||||
case (0x4f): sprintf(t, "not"); break;
|
||||
case16(0x50): sprintf(t, "adc #%u", op0 & 15); break;
|
||||
case16(0x60): sprintf(t, "cmp r%u", op0 & 15); break;
|
||||
case (0x70): sprintf(t, "merge"); break;
|
||||
case15(0x71): sprintf(t, "bic #%u", op0 & 15); break;
|
||||
case16(0x80): sprintf(t, "umult #%u", op0 & 15); break;
|
||||
case (0x90): sprintf(t, "sbk"); break;
|
||||
case4 (0x91): sprintf(t, "link #%u", op0 & 15); break;
|
||||
case (0x95): sprintf(t, "sex"); break;
|
||||
case (0x96): sprintf(t, "div2"); break;
|
||||
case (0x97): sprintf(t, "ror"); break;
|
||||
case6 (0x98): sprintf(t, "ljmp r%u", op0 & 15); break;
|
||||
case (0x9e): sprintf(t, "lob"); break;
|
||||
case (0x9f): sprintf(t, "lmult"); break;
|
||||
case16(0xa0): sprintf(t, "lms r%u", op0 & 15); break;
|
||||
case16(0xb0): sprintf(t, "from r%u", op0 & 15); break;
|
||||
case (0xc0): sprintf(t, "hib"); break;
|
||||
case15(0xc1): sprintf(t, "xor #%u", op0 & 15); break;
|
||||
case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break;
|
||||
case (0xdf): sprintf(t, "romb"); break;
|
||||
case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break;
|
||||
case (0xef): sprintf(t, "getbs"); break;
|
||||
case16(0xf0): sprintf(t, "lm r%u", op0 & 15); break;
|
||||
}
|
||||
strcat(output, t);
|
||||
}
|
||||
|
||||
#undef case4
|
||||
#undef case6
|
||||
#undef case12
|
||||
#undef case15
|
||||
#undef case16
|
||||
#undef op0
|
||||
#undef op1
|
||||
#undef op2
|
5
src/chip/superfx/disasm/disasm.hpp
Normal file
5
src/chip/superfx/disasm/disasm.hpp
Normal file
@@ -0,0 +1,5 @@
|
||||
void disassemble_opcode(char *output);
|
||||
void disassemble_alt0(char *output);
|
||||
void disassemble_alt1(char *output);
|
||||
void disassemble_alt2(char *output);
|
||||
void disassemble_alt3(char *output);
|
67
src/chip/superfx/memory/memory.cpp
Normal file
67
src/chip/superfx/memory/memory.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
uint8_t SuperFX::op_read(uint16_t addr) {
|
||||
uint16_t offset = addr - regs.cbr;
|
||||
if(offset < 512) {
|
||||
if(cache.valid[offset >> 4] == false) {
|
||||
unsigned dp = offset & 0xfff0;
|
||||
unsigned sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0);
|
||||
for(unsigned n = 0; n < 16; n++) {
|
||||
add_clocks(memory_access_speed);
|
||||
cache.buffer[dp++] = superfxbus.read(sp++);
|
||||
}
|
||||
cache.valid[offset >> 4] = true;
|
||||
} else {
|
||||
add_clocks(cache_access_speed);
|
||||
}
|
||||
return cache.buffer[offset];
|
||||
}
|
||||
|
||||
if(regs.pbr <= 0x5f) {
|
||||
//$[00-5f]:[0000-ffff] ROM
|
||||
rombuffer_sync();
|
||||
add_clocks(memory_access_speed);
|
||||
return superfxbus.read((regs.pbr << 16) + addr);
|
||||
} else {
|
||||
//$[60-7f]:[0000-ffff] RAM
|
||||
rambuffer_sync();
|
||||
add_clocks(memory_access_speed);
|
||||
return superfxbus.read((regs.pbr << 16) + addr);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SuperFX::peekpipe() {
|
||||
uint8_t result = regs.pipeline;
|
||||
regs.pipeline = op_read(regs.r[15]);
|
||||
r15_modified = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::pipe() {
|
||||
uint8_t result = regs.pipeline;
|
||||
regs.pipeline = op_read(++regs.r[15]);
|
||||
r15_modified = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
void SuperFX::cache_flush() {
|
||||
for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::cache_mmio_read(uint16_t addr) {
|
||||
addr = (addr + regs.cbr) & 511;
|
||||
return cache.buffer[addr];
|
||||
}
|
||||
|
||||
void SuperFX::cache_mmio_write(uint16_t addr, uint8_t data) {
|
||||
addr = (addr + regs.cbr) & 511;
|
||||
cache.buffer[addr] = data;
|
||||
if((addr & 15) == 15) cache.valid[addr >> 4] = true;
|
||||
}
|
||||
|
||||
void SuperFX::memory_reset() {
|
||||
for(unsigned n = 0; n < 512; n++) cache.buffer[n] = 0x00;
|
||||
for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
|
||||
for(unsigned n = 0; n < 2; n++) {
|
||||
pixelcache[n].offset = ~0;
|
||||
pixelcache[n].bitpend = 0x00;
|
||||
}
|
||||
}
|
9
src/chip/superfx/memory/memory.hpp
Normal file
9
src/chip/superfx/memory/memory.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
uint8_t op_read(uint16_t addr);
|
||||
alwaysinline uint8_t peekpipe();
|
||||
alwaysinline uint8_t pipe();
|
||||
|
||||
void cache_flush();
|
||||
uint8_t cache_mmio_read(uint16_t addr);
|
||||
void cache_mmio_write(uint16_t addr, uint8_t data);
|
||||
|
||||
void memory_reset();
|
118
src/chip/superfx/mmio/mmio.cpp
Normal file
118
src/chip/superfx/mmio/mmio.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifdef SUPERFX_CPP
|
||||
|
||||
uint8_t SuperFX::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
return cache_mmio_read(addr - 0x3100);
|
||||
}
|
||||
|
||||
if(addr >= 0x3000 && addr <= 0x301f) {
|
||||
return regs.r[(addr >> 1) & 15] >> ((addr & 1) << 3);
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x3030: {
|
||||
return regs.sfr >> 0;
|
||||
}
|
||||
|
||||
case 0x3031: {
|
||||
uint8_t r = regs.sfr >> 8;
|
||||
regs.sfr.irq = 0;
|
||||
cpu.regs.irq = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
case 0x3034: {
|
||||
return regs.pbr;
|
||||
}
|
||||
|
||||
case 0x3036: {
|
||||
return regs.rombr;
|
||||
}
|
||||
|
||||
case 0x303b: {
|
||||
return regs.vcr;
|
||||
}
|
||||
|
||||
case 0x303c: {
|
||||
return regs.rambr;
|
||||
}
|
||||
|
||||
case 0x303e: {
|
||||
return regs.cbr >> 0;
|
||||
}
|
||||
|
||||
case 0x303f: {
|
||||
return regs.cbr >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void SuperFX::mmio_write(unsigned addr, uint8_t data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
return cache_mmio_write(addr - 0x3100, data);
|
||||
}
|
||||
|
||||
if(addr >= 0x3000 && addr <= 0x301f) {
|
||||
unsigned n = (addr >> 1) & 15;
|
||||
if((addr & 1) == 0) {
|
||||
regs.r[n] = (regs.r[n] & 0xff00) | data;
|
||||
} else {
|
||||
regs.r[n] = (data << 8) | (regs.r[n] & 0xff);
|
||||
}
|
||||
|
||||
if(addr == 0x301f) regs.sfr.g = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x3030: {
|
||||
bool g = regs.sfr.g;
|
||||
regs.sfr = (regs.sfr & 0xff00) | (data << 0);
|
||||
if(g == 1 && regs.sfr.g == 0) {
|
||||
regs.cbr = 0x0000;
|
||||
cache_flush();
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x3031: {
|
||||
regs.sfr = (data << 8) | (regs.sfr & 0x00ff);
|
||||
} break;
|
||||
|
||||
case 0x3033: {
|
||||
regs.bramr = data;
|
||||
} break;
|
||||
|
||||
case 0x3034: {
|
||||
regs.pbr = data;
|
||||
cache_flush();
|
||||
} break;
|
||||
|
||||
case 0x3037: {
|
||||
regs.cfgr = data;
|
||||
if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
} break;
|
||||
|
||||
case 0x3038: {
|
||||
regs.scbr = data;
|
||||
} break;
|
||||
|
||||
case 0x3039: {
|
||||
regs.clsr = data;
|
||||
if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
cache_access_speed = (regs.clsr ? config.superfx.fast_cache_speed : config.superfx.slow_cache_speed );
|
||||
memory_access_speed = (regs.clsr ? config.superfx.fast_memory_speed : config.superfx.slow_memory_speed);
|
||||
} break;
|
||||
|
||||
case 0x303a: {
|
||||
regs.scmr = data;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
2
src/chip/superfx/mmio/mmio.hpp
Normal file
2
src/chip/superfx/mmio/mmio.hpp
Normal file
@@ -0,0 +1,2 @@
|
||||
uint8_t mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8_t data);
|
61
src/chip/superfx/superfx.cpp
Normal file
61
src/chip/superfx/superfx.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include <../base.hpp>
|
||||
|
||||
#define SUPERFX_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "bus/bus.cpp"
|
||||
#include "core/core.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
#include "mmio/mmio.cpp"
|
||||
#include "timing/timing.cpp"
|
||||
#include "disasm/disasm.cpp"
|
||||
|
||||
SuperFX superfx;
|
||||
|
||||
void SuperFX::enter() {
|
||||
while(true) {
|
||||
while(regs.sfr.g == 0) add_clocks(2);
|
||||
exec_opcode();
|
||||
}
|
||||
}
|
||||
|
||||
void SuperFX::init() {
|
||||
initialize_opcode_table();
|
||||
regs.r[14].on_modify = bind(&SuperFX::r14_modify, this);
|
||||
regs.r[15].on_modify = bind(&SuperFX::r15_modify, this);
|
||||
}
|
||||
|
||||
void SuperFX::enable() {
|
||||
for(uint16_t i = 0x3000; i <= 0x32ff; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void SuperFX::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void SuperFX::reset() {
|
||||
superfxbus.init();
|
||||
|
||||
for(unsigned n = 0; n < 16; n++) regs.r[n] = 0x0000;
|
||||
regs.sfr = 0x0000;
|
||||
regs.pbr = 0x00;
|
||||
regs.rombr = 0x00;
|
||||
regs.rambr = 0;
|
||||
regs.cbr = 0x0000;
|
||||
regs.scbr = 0x00;
|
||||
regs.scmr = 0x00;
|
||||
regs.colr = 0x00;
|
||||
regs.por = 0x00;
|
||||
regs.bramr = 0;
|
||||
regs.vcr = 0x04;
|
||||
regs.cfgr = 0x00;
|
||||
regs.clsr = 0;
|
||||
regs.pipeline = 0x01; //nop
|
||||
regs.ramaddr = 0x0000;
|
||||
regs.reset();
|
||||
|
||||
memory_reset();
|
||||
timing_reset();
|
||||
}
|
||||
|
||||
};
|
20
src/chip/superfx/superfx.hpp
Normal file
20
src/chip/superfx/superfx.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "bus/bus.hpp"
|
||||
|
||||
class SuperFX : public MMIO {
|
||||
public:
|
||||
#include "core/core.hpp"
|
||||
#include "memory/memory.hpp"
|
||||
#include "mmio/mmio.hpp"
|
||||
#include "timing/timing.hpp"
|
||||
#include "disasm/disasm.hpp"
|
||||
|
||||
void enter();
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
};
|
||||
|
||||
extern SuperFX superfx;
|
||||
extern SuperFXBus superfxbus;
|
72
src/chip/superfx/timing/timing.cpp
Normal file
72
src/chip/superfx/timing/timing.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
void SuperFX::add_clocks(unsigned clocks) {
|
||||
if(regs.romcl) {
|
||||
regs.romcl -= min(clocks, regs.romcl);
|
||||
if(regs.romcl == 0) {
|
||||
regs.sfr.r = 0;
|
||||
regs.romdr = superfxbus.read((regs.rombr << 16) + regs.r[14]);
|
||||
}
|
||||
}
|
||||
|
||||
if(regs.ramcl) {
|
||||
regs.ramcl -= min(clocks, regs.ramcl);
|
||||
if(regs.ramcl == 0) {
|
||||
superfxbus.write(0x700000 + (regs.rambr << 16) + regs.ramar, regs.ramdr);
|
||||
}
|
||||
}
|
||||
|
||||
scheduler.addclocks_cop(clocks);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
|
||||
void SuperFX::rombuffer_sync() {
|
||||
if(regs.romcl) add_clocks(regs.romcl);
|
||||
}
|
||||
|
||||
void SuperFX::rombuffer_update() {
|
||||
regs.sfr.r = 1;
|
||||
regs.romcl = memory_access_speed;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::rombuffer_read() {
|
||||
rombuffer_sync();
|
||||
return regs.romdr;
|
||||
}
|
||||
|
||||
void SuperFX::rambuffer_sync() {
|
||||
if(regs.ramcl) add_clocks(regs.ramcl);
|
||||
}
|
||||
|
||||
uint8_t SuperFX::rambuffer_read(uint16_t addr) {
|
||||
rambuffer_sync();
|
||||
return superfxbus.read(0x700000 + (regs.rambr << 16) + addr);
|
||||
}
|
||||
|
||||
void SuperFX::rambuffer_write(uint16_t addr, uint8_t data) {
|
||||
rambuffer_sync();
|
||||
regs.ramcl = memory_access_speed;
|
||||
regs.ramar = addr;
|
||||
regs.ramdr = data;
|
||||
}
|
||||
|
||||
void SuperFX::r14_modify(uint16_t data) {
|
||||
regs.r[14].data = data;
|
||||
rombuffer_update();
|
||||
}
|
||||
|
||||
void SuperFX::r15_modify(uint16_t data) {
|
||||
regs.r[15].data = data;
|
||||
r15_modified = true;
|
||||
}
|
||||
|
||||
void SuperFX::timing_reset() {
|
||||
cache_access_speed = config.superfx.slow_cache_speed;
|
||||
memory_access_speed = config.superfx.slow_memory_speed;
|
||||
r15_modified = false;
|
||||
|
||||
regs.romcl = 0;
|
||||
regs.romdr = 0;
|
||||
|
||||
regs.ramcl = 0;
|
||||
regs.ramar = 0;
|
||||
regs.ramdr = 0;
|
||||
}
|
18
src/chip/superfx/timing/timing.hpp
Normal file
18
src/chip/superfx/timing/timing.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
unsigned cache_access_speed;
|
||||
unsigned memory_access_speed;
|
||||
bool r15_modified;
|
||||
|
||||
void add_clocks(unsigned clocks);
|
||||
|
||||
void rombuffer_sync();
|
||||
void rombuffer_update();
|
||||
uint8_t rombuffer_read();
|
||||
|
||||
void rambuffer_sync();
|
||||
uint8_t rambuffer_read(uint16_t addr);
|
||||
void rambuffer_write(uint16_t addr, uint8_t data);
|
||||
|
||||
void r14_modify(uint16_t);
|
||||
void r15_modify(uint16_t);
|
||||
|
||||
void timing_reset();
|
@@ -48,4 +48,3 @@ CPUcore::CPUcore() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -365,5 +365,5 @@ inline void CPUcore::op_tsb_w() {
|
||||
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||
rd.w |= regs.a.w;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -138,4 +138,3 @@ void CPUcore::update_table() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -15,5 +15,5 @@ CPU::CPU() {
|
||||
|
||||
CPU::~CPU() {
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
@@ -270,4 +270,4 @@ void sCPU::dma_reset() {
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
#endif
|
||||
|
@@ -2,29 +2,26 @@
|
||||
|
||||
void sCPU::op_io() {
|
||||
status.clock_count = 6;
|
||||
precycle_edge();
|
||||
add_clocks(6);
|
||||
cycle_edge();
|
||||
add_clocks(6);
|
||||
}
|
||||
|
||||
uint8 sCPU::op_read(uint32 addr) {
|
||||
status.clock_count = speed(addr);
|
||||
precycle_edge();
|
||||
cycle_edge();
|
||||
add_clocks(status.clock_count - 4);
|
||||
scheduler.sync_cpucop();
|
||||
regs.mdr = bus.read(addr);
|
||||
add_clocks(4);
|
||||
cycle_edge();
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void sCPU::op_write(uint32 addr, uint8 data) {
|
||||
status.clock_count = speed(addr);
|
||||
precycle_edge();
|
||||
cycle_edge();
|
||||
add_clocks(status.clock_count);
|
||||
scheduler.sync_cpucop();
|
||||
bus.write(addr, regs.mdr = data);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
unsigned sCPU::speed(unsigned addr) const {
|
||||
@@ -38,4 +35,3 @@ unsigned sCPU::speed(unsigned addr) const {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -534,4 +534,4 @@ void sCPU::mmio_write(unsigned addr, uint8 data) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
#endif
|
||||
|
@@ -96,5 +96,5 @@ sCPU::sCPU() {
|
||||
|
||||
sCPU::~sCPU() {
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
@@ -9,8 +9,6 @@ public:
|
||||
#include "mmio/mmio.hpp"
|
||||
#include "timing/timing.hpp"
|
||||
|
||||
enum DmaState { DmaInactive, DmaRun, DmaCpuSync };
|
||||
|
||||
struct {
|
||||
bool interrupt_pending;
|
||||
uint16 interrupt_vector;
|
||||
@@ -36,12 +34,12 @@ public:
|
||||
bool irq_hold;
|
||||
|
||||
//DMA
|
||||
bool dma_active;
|
||||
unsigned dma_counter;
|
||||
unsigned dma_clocks;
|
||||
bool dma_pending;
|
||||
bool hdma_pending;
|
||||
bool hdma_mode; //0 = init, 1 = run
|
||||
DmaState dma_state;
|
||||
|
||||
//MMIO
|
||||
|
||||
|
@@ -52,14 +52,6 @@ void sCPU::scanline() {
|
||||
}
|
||||
}
|
||||
|
||||
//used for H/DMA bus synchronization
|
||||
void sCPU::precycle_edge() {
|
||||
if(status.dma_state == DmaCpuSync) {
|
||||
add_clocks(status.clock_count - (status.dma_clocks % status.clock_count));
|
||||
status.dma_state = DmaInactive;
|
||||
}
|
||||
}
|
||||
|
||||
//used to test for H/DMA, which can trigger on the edge of every opcode cycle.
|
||||
void sCPU::cycle_edge() {
|
||||
while(cycle_edge_state) {
|
||||
@@ -91,30 +83,34 @@ void sCPU::cycle_edge() {
|
||||
//.. Run one bus CPU cycle
|
||||
//.. CPU sync
|
||||
|
||||
if(status.dma_state == DmaRun) {
|
||||
if(status.dma_active == true) {
|
||||
if(status.hdma_pending) {
|
||||
status.hdma_pending = false;
|
||||
if(hdma_enabled_channels()) {
|
||||
dma_add_clocks(8 - dma_counter()); //DMA sync
|
||||
dma_add_clocks(8 - dma_counter());
|
||||
status.hdma_mode == 0 ? hdma_init() : hdma_run();
|
||||
if(!dma_enabled_channels()) status.dma_state = DmaCpuSync;
|
||||
if(!dma_enabled_channels()) {
|
||||
add_clocks(status.clock_count - (status.dma_clocks % status.clock_count));
|
||||
status.dma_active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(status.dma_pending) {
|
||||
status.dma_pending = false;
|
||||
if(dma_enabled_channels()) {
|
||||
dma_add_clocks(8 - dma_counter()); //DMA sync
|
||||
dma_add_clocks(8 - dma_counter());
|
||||
dma_run();
|
||||
status.dma_state = DmaCpuSync;
|
||||
add_clocks(status.clock_count - (status.dma_clocks % status.clock_count));
|
||||
status.dma_active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(status.dma_state == DmaInactive) {
|
||||
if(status.dma_active == false) {
|
||||
if(status.dma_pending || status.hdma_pending) {
|
||||
status.dma_clocks = 0;
|
||||
status.dma_state = DmaRun;
|
||||
status.dma_active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,12 +155,12 @@ void sCPU::timing_reset() {
|
||||
status.irq_pending = false;
|
||||
status.irq_hold = false;
|
||||
|
||||
status.dma_active = false;
|
||||
status.dma_counter = 0;
|
||||
status.dma_clocks = 0;
|
||||
status.dma_pending = false;
|
||||
status.hdma_pending = false;
|
||||
status.hdma_mode = 0;
|
||||
status.dma_state = DmaInactive;
|
||||
|
||||
cycle_edge_state = 0;
|
||||
}
|
||||
|
@@ -18,9 +18,8 @@
|
||||
void add_clocks(unsigned clocks);
|
||||
void scanline();
|
||||
|
||||
alwaysinline void precycle_edge();
|
||||
alwaysinline void cycle_edge();
|
||||
void last_cycle();
|
||||
alwaysinline void last_cycle();
|
||||
|
||||
void timing_power();
|
||||
void timing_reset();
|
||||
|
@@ -5,15 +5,19 @@
|
||||
|
||||
<h1>bsnes™ Usage Documentation</h1><br>
|
||||
|
||||
bsnes is a Super Nintendo / Super Famicom emulator that strives to provide
|
||||
the most faithful emulation experience possible. It focuses on accuracy and
|
||||
clean code; over speed and features.
|
||||
bsnes is a Super Nintendo / Super Famicom emulator that strives to provide the
|
||||
most faithful hardware emulation possible. It focuses on accuracy and clean
|
||||
code, rather than speed and special features. It is meant as a reference
|
||||
emulator to document how the underlying hardware works. It is thus very useful
|
||||
for development and research. And while it can be used for general purpose
|
||||
gaming, it will require significantly more powerful hardware than a typical
|
||||
emulator.
|
||||
<hr>
|
||||
|
||||
<h2><u>Modes of Operation</u></h2><br>
|
||||
|
||||
bsnes is capable of running both in its default multi-user mode, as well as
|
||||
in single-user mode.<br>
|
||||
bsnes is capable of running both in its default multi-user mode, as well as in
|
||||
single-user mode.<br>
|
||||
<br>
|
||||
|
||||
In multi-user mode, configuration data is stored inside the user's home
|
||||
@@ -39,16 +43,15 @@ configuration data.
|
||||
|
||||
<h2><u>Known Limitations</u></h2><br>
|
||||
|
||||
<b>Cartridge co-processors:</b> certain cartridges contain special co-processor chips to enhance
|
||||
their functionality. Some of these are either partially or completely unsupported. A message box
|
||||
warning will pop up when attempting to load such a cartridge.<br>
|
||||
<b>Satellaview BS-X emulation:</b> this hardware is only partially supported.
|
||||
This is mostly because the satellite network it used (St. GIGA) has been shut
|
||||
down. Access to this network would be required to properly reverse engineer much
|
||||
of the hardware. Working around this would require game-specific hacks, which
|
||||
are contrary to the design goals of this emulator. As a result, most BS-X
|
||||
software will not function correctly.<br>
|
||||
<br>
|
||||
|
||||
<b>Satellaview BS-X emulation:</b> this hardware is only partially supported. As a result,
|
||||
most BS-X software will not function correctly.<br>
|
||||
<br>
|
||||
|
||||
<b>Savestates:</b> due to the design of bsnes, it is not plausible to
|
||||
<b>Savestates:</b> due to the internal design of bsnes, it is not plausible to
|
||||
implement support for savestate and/or rewind functionality.<br>
|
||||
<br>
|
||||
|
||||
@@ -58,6 +61,7 @@ implement support for savestate and/or rewind functionality.<br>
|
||||
<h2><u>Contributors</u></h2>
|
||||
• Andreas Naive<br>
|
||||
• anomie<br>
|
||||
• _Demo_<br>
|
||||
• Derrick Sobodash<br>
|
||||
• DMV27<br>
|
||||
• FirebrandX<br>
|
||||
|
@@ -591,4 +591,3 @@ aDSP::aDSP() {}
|
||||
aDSP::~aDSP() {}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -74,4 +74,4 @@ const int16 aDSP::gaussian_table[512] = {
|
||||
0x517, 0x518, 0x518, 0x518, 0x518, 0x518, 0x519, 0x519
|
||||
};
|
||||
|
||||
#endif //ifdef ADSP_CPP
|
||||
#endif
|
||||
|
@@ -59,4 +59,4 @@ void sDSP::brr_decode(voice_t &v) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef SDSP_CPP
|
||||
#endif
|
||||
|
@@ -49,4 +49,4 @@ inline bool sDSP::counter_poll(unsigned rate) {
|
||||
return (((unsigned)state.counter + counter_offset[rate]) % counter_rate[rate]) == 0;
|
||||
}
|
||||
|
||||
#endif //ifdef SDSP_CPP
|
||||
#endif
|
||||
|
@@ -132,4 +132,4 @@ void sDSP::echo_30() {
|
||||
echo_write(1);
|
||||
}
|
||||
|
||||
#endif //ifdef SDSP_CPP
|
||||
#endif
|
||||
|
@@ -59,4 +59,4 @@ void sDSP::envelope_run(voice_t &v) {
|
||||
if(counter_poll(rate) == true) v.env = env;
|
||||
}
|
||||
|
||||
#endif //ifdef SDSP_CPP
|
||||
#endif
|
||||
|
@@ -51,4 +51,4 @@ int sDSP::gaussian_interpolate(const voice_t &v) {
|
||||
return sclamp<16>(output) & ~1;
|
||||
}
|
||||
|
||||
#endif //ifdef SDSP_CPP
|
||||
#endif
|
||||
|
@@ -32,4 +32,4 @@ void sDSP::misc_30() {
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef SDSP_CPP
|
||||
#endif
|
||||
|
@@ -326,4 +326,3 @@ sDSP::~sDSP() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -171,4 +171,4 @@ void sDSP::voice_9(voice_t &v) {
|
||||
VREG(envx) = (uint8)state.envx_buf;
|
||||
}
|
||||
|
||||
#endif //ifdef SDSP_CPP
|
||||
#endif
|
||||
|
@@ -28,4 +28,3 @@ namespace SNES {
|
||||
#include "chip/chip.hpp"
|
||||
#include "cartridge/cartridge.hpp"
|
||||
};
|
||||
|
||||
|
@@ -1,8 +1,13 @@
|
||||
DirectFilter filter_direct;
|
||||
|
||||
void DirectFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
outwidth = width;
|
||||
outheight = height;
|
||||
}
|
||||
|
||||
void DirectFilter::render(
|
||||
uint32_t *output, unsigned outpitch, unsigned &outwidth, unsigned &outheight,
|
||||
uint16_t *input, unsigned pitch, unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch, uint16_t *input, unsigned pitch,
|
||||
unsigned *line, unsigned width, unsigned height
|
||||
) {
|
||||
pitch >>= 1;
|
||||
outpitch >>= 2;
|
||||
@@ -24,7 +29,4 @@ void DirectFilter::render(
|
||||
input += pitch - width;
|
||||
output += outpitch - width;
|
||||
}
|
||||
|
||||
outwidth = width;
|
||||
outheight = height;
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
class DirectFilter : public Filter {
|
||||
public:
|
||||
void render(uint32_t*, unsigned, unsigned&, unsigned&, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
void size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height);
|
||||
void render(uint32_t*, unsigned, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
};
|
||||
|
||||
extern DirectFilter filter_direct;
|
||||
|
@@ -4,30 +4,26 @@ void FilterInterface::set(FilterInterface::FilterType type) {
|
||||
active_filter = type;
|
||||
}
|
||||
|
||||
void FilterInterface::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
switch(active_filter) { default:
|
||||
case Direct: return filter_direct.size(outwidth, outheight, width, height);
|
||||
case Scanline: return filter_scanline.size(outwidth, outheight, width, height);
|
||||
case Scale2x: return filter_scale2x.size(outwidth, outheight, width, height);
|
||||
case HQ2x: return filter_hq2x.size(outwidth, outheight, width, height);
|
||||
case NTSC: return filter_ntsc.size(outwidth, outheight, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterInterface::render(
|
||||
uint32_t *output, unsigned outpitch, unsigned &outwidth, unsigned &outheight,
|
||||
uint16_t *input, unsigned pitch, unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch, uint16_t *input, unsigned pitch,
|
||||
unsigned *line, unsigned width, unsigned height
|
||||
) {
|
||||
switch(active_filter) { default:
|
||||
case Direct: {
|
||||
filter_direct.render(output, outpitch, outwidth, outheight, input, pitch, line, width, height);
|
||||
} break;
|
||||
|
||||
case Scanline: {
|
||||
filter_scanline.render(output, outpitch, outwidth, outheight, input, pitch, line, width, height);
|
||||
} break;
|
||||
|
||||
case Scale2x: {
|
||||
filter_scale2x.render(output, outpitch, outwidth, outheight, input, pitch, line, width, height);
|
||||
} break;
|
||||
|
||||
case HQ2x: {
|
||||
filter_hq2x.render(output, outpitch, outwidth, outheight, input, pitch, line, width, height);
|
||||
} break;
|
||||
|
||||
case NTSC: {
|
||||
filter_ntsc.render(output, outpitch, outwidth, outheight, input, pitch, line, width, height);
|
||||
} break;
|
||||
case Direct: return filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
case Scanline: return filter_scanline.render(output, outpitch, input, pitch, line, width, height);
|
||||
case Scale2x: return filter_scale2x.render(output, outpitch, input, pitch, line, width, height);
|
||||
case HQ2x: return filter_hq2x.render(output, outpitch, input, pitch, line, width, height);
|
||||
case NTSC: return filter_ntsc.render(output, outpitch, input, pitch, line, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,8 +1,10 @@
|
||||
class Filter {
|
||||
public:
|
||||
virtual void size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) = 0;
|
||||
|
||||
virtual void render(
|
||||
uint32_t *output, unsigned outpitch, unsigned &outwidth, unsigned &outheight,
|
||||
uint16_t *input, unsigned pitch, unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch, uint16_t *input, unsigned pitch,
|
||||
unsigned *line, unsigned width, unsigned height
|
||||
) = 0;
|
||||
};
|
||||
|
||||
@@ -18,9 +20,11 @@ public:
|
||||
|
||||
void set(FilterType type);
|
||||
|
||||
void size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height);
|
||||
|
||||
void render(
|
||||
uint32_t *output, unsigned outpitch, unsigned &outwidth, unsigned &outheight,
|
||||
uint16_t *input, unsigned pitch, unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch, uint16_t *input, unsigned pitch,
|
||||
unsigned *line, unsigned width, unsigned height
|
||||
);
|
||||
|
||||
FilterInterface();
|
||||
|
@@ -56,12 +56,17 @@ static uint16_t blend10(uint32_t c1, uint32_t c2, uint32_t c3) {
|
||||
return c1;
|
||||
}
|
||||
|
||||
void HQ2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
outwidth = width * 2;
|
||||
outheight = height * 2;
|
||||
}
|
||||
|
||||
void HQ2xFilter::render(
|
||||
uint32_t *output, unsigned outpitch, unsigned &outwidth, unsigned &outheight,
|
||||
uint16_t *input, unsigned pitch, unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch, uint16_t *input, unsigned pitch,
|
||||
unsigned *line, unsigned width, unsigned height
|
||||
) {
|
||||
if(width > 256 || height > 240) {
|
||||
filter_direct.render(output, outpitch, outwidth, outheight, input, pitch, line, width, height);
|
||||
filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -125,9 +130,6 @@ void HQ2xFilter::render(
|
||||
|
||||
memset(out0, 0, 2048);
|
||||
memset(out1, 0, 2048);
|
||||
|
||||
outwidth = width * 2;
|
||||
outheight = height * 2;
|
||||
}
|
||||
|
||||
HQ2xFilter::HQ2xFilter() {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
class HQ2xFilter : public Filter {
|
||||
public:
|
||||
void render(uint32_t*, unsigned, unsigned&, unsigned&, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
void size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height);
|
||||
void render(uint32_t*, unsigned, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
|
||||
HQ2xFilter();
|
||||
~HQ2xFilter();
|
||||
|
@@ -11,4 +11,4 @@ namespace libfilter {
|
||||
#include "scale2x.cpp"
|
||||
#include "hq2x.cpp"
|
||||
#include "ntsc.cpp"
|
||||
} //namespace libfilter
|
||||
}
|
||||
|
@@ -17,6 +17,6 @@ namespace libfilter {
|
||||
#include "scale2x.hpp"
|
||||
#include "hq2x.hpp"
|
||||
#include "ntsc.hpp"
|
||||
} //namespace libfilter
|
||||
};
|
||||
|
||||
#endif //ifndef LIBFILTER_H
|
||||
#endif
|
||||
|
@@ -2,37 +2,42 @@
|
||||
|
||||
NTSCFilter filter_ntsc;
|
||||
|
||||
void NTSCFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
outwidth = SNES_NTSC_OUT_WIDTH(256);
|
||||
outheight = height;
|
||||
}
|
||||
|
||||
void NTSCFilter::render(
|
||||
uint32_t *output, unsigned outpitch, unsigned &outwidth, unsigned &outheight,
|
||||
uint16_t *input, unsigned pitch, unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch, uint16_t *input, unsigned pitch,
|
||||
unsigned *line, unsigned width, unsigned height
|
||||
) {
|
||||
if(!ntsc) return;
|
||||
|
||||
int const out_width = outwidth = SNES_NTSC_OUT_WIDTH(256);
|
||||
int const out_height = outheight = height;
|
||||
width = SNES_NTSC_OUT_WIDTH(256);
|
||||
burst ^= burst_toggle;
|
||||
|
||||
//blit multiple scanlines of same width, rather than one at a time
|
||||
int run_start = 0;
|
||||
int run_width = line[0];
|
||||
int l = 0;
|
||||
pitch >>= 1;
|
||||
outpitch >>= 2;
|
||||
|
||||
while(1) {
|
||||
if(run_width != line[l] || l >= out_height) {
|
||||
uint16_t const *in = (uint16_t*)((uint8_t*)input + pitch * run_start);
|
||||
uint16_t *out = (uint16_t*)((uint8_t*)output + outpitch * run_start);
|
||||
int height = l - run_start;
|
||||
int line_burst = (burst + run_start) % 3;
|
||||
if(run_width == 256) {
|
||||
snes_ntsc_blit(ntsc, in, (pitch >> 1), line_burst, out_width, height, out, outpitch);
|
||||
unsigned line_burst = burst;
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
uint16_t *in = input + y * pitch;
|
||||
uint32_t *out = output + y * outpitch;
|
||||
|
||||
//render as many lines in one snes_ntsc_blit as possible:
|
||||
//do this by determining for how many lines the width stays the same
|
||||
unsigned rheight = 1;
|
||||
unsigned rwidth = line[y];
|
||||
while(y + rheight < height && rwidth == line[y + rheight]) rheight++;
|
||||
|
||||
if(rwidth == 256) {
|
||||
snes_ntsc_blit (ntsc, in, pitch, line_burst, rwidth, rheight, out, outpitch << 2);
|
||||
} else {
|
||||
snes_ntsc_blit_hires(ntsc, in, (pitch >> 1), line_burst, out_width, height, out, outpitch);
|
||||
snes_ntsc_blit_hires(ntsc, in, pitch, line_burst, rwidth, rheight, out, outpitch << 2);
|
||||
}
|
||||
if(l >= out_height) break;
|
||||
run_width = line[l];
|
||||
run_start = l;
|
||||
}
|
||||
l++;
|
||||
|
||||
line_burst = (line_burst + rheight) % 3;
|
||||
y += rheight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +59,8 @@ void NTSCFilter::adjust(
|
||||
if(!ntsc) {
|
||||
ntsc = (snes_ntsc_t*)malloc(sizeof *ntsc);
|
||||
if(!ntsc) {
|
||||
return; //to do: report out of memory error
|
||||
fprintf(stderr, "error: snes_ntsc: out of memory\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,8 @@
|
||||
|
||||
class NTSCFilter : public Filter {
|
||||
public:
|
||||
void render(uint32_t*, unsigned, unsigned&, unsigned&, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
void size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height);
|
||||
void render(uint32_t*, unsigned, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
void adjust(float hue, float saturation, float contrast, float brightness, float sharpness, bool merge_fields);
|
||||
|
||||
NTSCFilter();
|
||||
|
@@ -1,11 +1,16 @@
|
||||
Scale2xFilter filter_scale2x;
|
||||
|
||||
void Scale2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
outwidth = width * 2;
|
||||
outheight = height * 2;
|
||||
}
|
||||
|
||||
void Scale2xFilter::render(
|
||||
uint32_t *output, unsigned outpitch, unsigned &outwidth, unsigned &outheight,
|
||||
uint16_t *input, unsigned pitch, unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch, uint16_t *input, unsigned pitch,
|
||||
unsigned *line, unsigned width, unsigned height
|
||||
) {
|
||||
if(width > 256 || height > 240) {
|
||||
filter_direct.render(output, outpitch, outwidth, outheight, input, pitch, line, width, height);
|
||||
filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,7 +46,4 @@ void Scale2xFilter::render(
|
||||
input += pitch - 256;
|
||||
output += outpitch + outpitch - 512;
|
||||
}
|
||||
|
||||
outwidth = width * 2;
|
||||
outheight = height * 2;
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
class Scale2xFilter : public Filter {
|
||||
public:
|
||||
void render(uint32_t*, unsigned, unsigned&, unsigned&, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
void size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height);
|
||||
void render(uint32_t*, unsigned, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
};
|
||||
|
||||
extern Scale2xFilter filter_scale2x;
|
||||
|
@@ -1,11 +1,16 @@
|
||||
ScanlineFilter filter_scanline;
|
||||
|
||||
void ScanlineFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
outwidth = width;
|
||||
outheight = height * 2;
|
||||
}
|
||||
|
||||
void ScanlineFilter::render(
|
||||
uint32_t *output, unsigned outpitch, unsigned &outwidth, unsigned &outheight,
|
||||
uint16_t *input, unsigned pitch, unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch, uint16_t *input, unsigned pitch,
|
||||
unsigned *line, unsigned width, unsigned height
|
||||
) {
|
||||
if(height > 240) {
|
||||
filter_direct.render(output, outpitch, outwidth, outheight, input, pitch, line, width, height);
|
||||
filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,7 +19,7 @@ void ScanlineFilter::render(
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
uint32_t *out0 = output;
|
||||
uint32_t *out1 = output + pitch;
|
||||
uint32_t *out1 = output + outpitch;
|
||||
if(width == 512 && line[y] == 256) {
|
||||
for(unsigned x = 0; x < 256; x++) {
|
||||
uint16_t p = *input++;
|
||||
@@ -34,7 +39,4 @@ void ScanlineFilter::render(
|
||||
input += pitch - width;
|
||||
output += outpitch * 2;
|
||||
}
|
||||
|
||||
outwidth = width;
|
||||
outheight = height * 2;
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
class ScanlineFilter : public Filter {
|
||||
public:
|
||||
void render(uint32_t*, unsigned, unsigned&, unsigned&, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
void size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height);
|
||||
void render(uint32_t*, unsigned, uint16_t*, unsigned, unsigned*, unsigned, unsigned);
|
||||
};
|
||||
|
||||
extern ScanlineFilter filter_scanline;
|
||||
|
54
src/lib/nall/Makefile-qt
Normal file
54
src/lib/nall/Makefile-qt
Normal file
@@ -0,0 +1,54 @@
|
||||
# requires nall/Makefile
|
||||
|
||||
# exports the following symbols:
|
||||
# $(moc) -- meta-object compiler
|
||||
# $(rcc) -- resource compiler
|
||||
# $(qtinc) -- includes for compiling
|
||||
# $(qtlib) -- libraries for linking
|
||||
|
||||
ifeq ($(moc),)
|
||||
moc := moc
|
||||
endif
|
||||
|
||||
ifeq ($(rcc),)
|
||||
rcc := rcc
|
||||
endif
|
||||
|
||||
ifeq ($(platform),x)
|
||||
qtinc := `pkg-config --cflags QtCore QtGui`
|
||||
qtlib := `pkg-config --libs QtCore QtGui`
|
||||
else ifeq ($(platform),osx)
|
||||
qtinc := -I/usr/include/QtCore
|
||||
qtinc += -I/usr/include/QtGui
|
||||
qtinc += -I/Library/Frameworks/QtCore.framework/Versions/4/Headers
|
||||
qtinc += -I/Library/Frameworks/QtGui.framework/Versions/4/Headers
|
||||
|
||||
qtlib := -L/Library/Frameworks
|
||||
qtlib += -framework QtCore
|
||||
qtlib += -framework QtGui
|
||||
qtlib += -framework Carbon
|
||||
qtlib += -framework Cocoa
|
||||
qtlib += -framework AppKit
|
||||
qtlib += -framework ApplicationServices
|
||||
else ifeq ($(platform),win)
|
||||
ifeq ($(qtpath),)
|
||||
# find Qt install directory from PATH environment variable
|
||||
qtpath := $(foreach path,$(subst ;, ,$(PATH)),$(if $(wildcard $(path)/$(moc).exe),$(path)))
|
||||
qtpath := $(strip $(qtpath))
|
||||
qtpath := $(subst \,/,$(qtpath))
|
||||
qtpath := $(patsubst %/bin,%,$(qtpath))
|
||||
endif
|
||||
|
||||
qtinc := -I$(qtpath)/include
|
||||
qtinc += -I$(qtpath)/include/QtCore
|
||||
qtinc += -I$(qtpath)/include/QtGui
|
||||
|
||||
qtlib := -L$(qtpath)/lib
|
||||
qtlib += -L$(qtpath)/plugins/imageformats
|
||||
|
||||
qtlib += -lmingw32 -lqtmain -lQtGui -lcomdlg32 -loleaut32 -limm32 -lwinmm
|
||||
qtlib += -lwinspool -lmsimg32 -lQtCore -lole32 -ladvapi32 -lws2_32 -luuid -lgdi32
|
||||
|
||||
# optional image-file support:
|
||||
# qtlib += -lqjpeg -lqmng
|
||||
endif
|
@@ -1,24 +0,0 @@
|
||||
#ifndef NALL_STRING_CPP
|
||||
#define NALL_STRING_CPP
|
||||
|
||||
#include <math.h>
|
||||
#include <nall/algorithm.hpp>
|
||||
#include <nall/static.hpp>
|
||||
#include <nall/utf8.hpp>
|
||||
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/string/compare.cpp>
|
||||
#include <nall/string/convert.cpp>
|
||||
#include <nall/string/match.cpp>
|
||||
#include <nall/string/math.cpp>
|
||||
#include <nall/string/strl.cpp>
|
||||
#include <nall/string/trim.cpp>
|
||||
#include <nall/string/utility.cpp>
|
||||
|
||||
namespace nall {
|
||||
#include <nall/string/core.cpp>
|
||||
#include <nall/string/replace.cpp>
|
||||
#include <nall/string/split.cpp>
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,175 +1,17 @@
|
||||
#ifndef NALL_STRING_HPP
|
||||
#define NALL_STRING_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
|
||||
//===============
|
||||
//libc extensions
|
||||
//===============
|
||||
|
||||
//compare.cpp
|
||||
char chrlower(char c);
|
||||
char chrupper(char c);
|
||||
|
||||
int stricmp(const char *dest, const char *src);
|
||||
|
||||
int strpos (const char *str, const char *key);
|
||||
int qstrpos(const char *str, const char *key);
|
||||
|
||||
bool strbegin (const char *str, const char *key);
|
||||
bool stribegin(const char *str, const char *key);
|
||||
|
||||
bool strend (const char *str, const char *key);
|
||||
bool striend(const char *str, const char *key);
|
||||
|
||||
//convert.cpp
|
||||
char* strlower(char *str);
|
||||
char* strupper(char *str);
|
||||
|
||||
char* strtr(char *dest, const char *before, const char *after);
|
||||
|
||||
uintmax_t strhex (const char *str);
|
||||
intmax_t strsigned (const char *str);
|
||||
uintmax_t strunsigned(const char *str);
|
||||
uintmax_t strbin (const char *str);
|
||||
double strdouble (const char *str);
|
||||
|
||||
size_t strhex (char *str, uintmax_t value, size_t length = 0);
|
||||
size_t strsigned (char *str, intmax_t value, size_t length = 0);
|
||||
size_t strunsigned(char *str, uintmax_t value, size_t length = 0);
|
||||
size_t strbin (char *str, uintmax_t value, size_t length = 0);
|
||||
size_t strdouble (char *str, double value, size_t length = 0);
|
||||
|
||||
//match.cpp
|
||||
bool match(const char *pattern, const char *str);
|
||||
|
||||
//math.cpp
|
||||
bool strint (const char *str, int &result);
|
||||
bool strmath(const char *str, int &result);
|
||||
|
||||
//strl.cpp
|
||||
size_t strlcpy(char *dest, const char *src, size_t length);
|
||||
size_t strlcat(char *dest, const char *src, size_t length);
|
||||
|
||||
//trim.cpp
|
||||
char* ltrim(char *str, const char *key = " ");
|
||||
char* rtrim(char *str, const char *key = " ");
|
||||
char* trim (char *str, const char *key = " ");
|
||||
|
||||
char* ltrim_once(char *str, const char *key = " ");
|
||||
char* rtrim_once(char *str, const char *key = " ");
|
||||
char* trim_once (char *str, const char *key = " ");
|
||||
|
||||
//================
|
||||
//string + lstring
|
||||
//================
|
||||
|
||||
namespace nall {
|
||||
class string;
|
||||
template<typename T> inline string to_string(T);
|
||||
|
||||
class string {
|
||||
public:
|
||||
void reserve(size_t);
|
||||
unsigned length() const;
|
||||
|
||||
string& assign(const char*);
|
||||
string& append(const char*);
|
||||
template<typename T> string& operator= (T value) { return assign(to_string<T>(value)); }
|
||||
template<typename T> string& operator<<(T value) { return append(to_string<T>(value)); }
|
||||
|
||||
operator const char*() const;
|
||||
char* operator()();
|
||||
char& operator[](int);
|
||||
|
||||
bool operator==(const char*) const;
|
||||
bool operator!=(const char*) const;
|
||||
bool operator< (const char*) const;
|
||||
bool operator<=(const char*) const;
|
||||
bool operator> (const char*) const;
|
||||
bool operator>=(const char*) const;
|
||||
|
||||
string();
|
||||
string(const char*);
|
||||
string(const string&);
|
||||
string& operator=(const string&);
|
||||
~string();
|
||||
|
||||
//core.cpp
|
||||
bool readfile(const char*);
|
||||
|
||||
//replace.cpp
|
||||
string& replace (const char*, const char*);
|
||||
string& qreplace(const char*, const char*);
|
||||
|
||||
protected:
|
||||
char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
class lstring : public vector<string> {
|
||||
public:
|
||||
template<typename T> lstring& operator<<(T value) {
|
||||
operator[](size()).assign(to_string<T>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//core.cpp
|
||||
int find(const char*);
|
||||
|
||||
//split.cpp
|
||||
void split (const char*, const char*, unsigned = 0);
|
||||
void qsplit(const char*, const char*, unsigned = 0);
|
||||
};
|
||||
}
|
||||
|
||||
//=====================
|
||||
//string<>libc wrappers
|
||||
//=====================
|
||||
|
||||
size_t strlcpy(nall::string &dest, const char *src, size_t length);
|
||||
size_t strlcat(nall::string &dest, const char *src, size_t length);
|
||||
|
||||
nall::string& strlower(nall::string &str);
|
||||
nall::string& strupper(nall::string &str);
|
||||
|
||||
nall::string& strtr(nall::string &dest, const char *before, const char *after);
|
||||
|
||||
nall::string& ltrim(nall::string &str, const char *key = " ");
|
||||
nall::string& rtrim(nall::string &str, const char *key = " ");
|
||||
nall::string& trim (nall::string &str, const char *key = " ");
|
||||
|
||||
nall::string& ltrim_once(nall::string &str, const char *key = " ");
|
||||
nall::string& rtrim_once(nall::string &str, const char *key = " ");
|
||||
nall::string& trim_once (nall::string &str, const char *key = " ");
|
||||
|
||||
//==============
|
||||
//misc functions
|
||||
//==============
|
||||
|
||||
nall::string substr(const char *src, size_t start = 0, size_t length = 0);
|
||||
|
||||
nall::string strhex (uintmax_t value);
|
||||
nall::string strsigned (intmax_t value);
|
||||
nall::string strunsigned(uintmax_t value);
|
||||
nall::string strbin (uintmax_t value);
|
||||
nall::string strdouble (double value);
|
||||
|
||||
namespace nall {
|
||||
//this is needed, as C++98 does not support explicit template specialization inside classes;
|
||||
//redundant memory allocation should hopefully be avoided via compiler optimizations.
|
||||
template<> inline string to_string<bool> (bool v) { return v ? "true" : "false"; }
|
||||
template<> inline string to_string<signed int> (signed int v) { return strsigned(v); }
|
||||
template<> inline string to_string<unsigned int> (unsigned int v) { return strunsigned(v); }
|
||||
template<> inline string to_string<double> (double v) { return strdouble(v); }
|
||||
template<> inline string to_string<char*> (char *v) { return v; }
|
||||
template<> inline string to_string<const char*> (const char *v) { return v; }
|
||||
template<> inline string to_string<string> (string v) { return v; }
|
||||
template<> inline string to_string<const string&>(const string &v) { return v; }
|
||||
}
|
||||
#include <nall/string/base.hpp>
|
||||
#include <nall/string/core.hpp>
|
||||
#include <nall/string/cast.hpp>
|
||||
#include <nall/string/compare.hpp>
|
||||
#include <nall/string/convert.hpp>
|
||||
#include <nall/string/match.hpp>
|
||||
#include <nall/string/math.hpp>
|
||||
#include <nall/string/strl.hpp>
|
||||
#include <nall/string/trim.hpp>
|
||||
#include <nall/string/replace.hpp>
|
||||
#include <nall/string/split.hpp>
|
||||
#include <nall/string/utility.hpp>
|
||||
|
||||
#endif
|
||||
|
114
src/lib/nall/string/base.hpp
Normal file
114
src/lib/nall/string/base.hpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#ifndef NALL_STRING_BASE_HPP
|
||||
#define NALL_STRING_BASE_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/utf8.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
|
||||
inline char chrlower(char c);
|
||||
inline char chrupper(char c);
|
||||
inline int stricmp(const char *dest, const char *src);
|
||||
inline int strpos (const char *str, const char *key);
|
||||
inline int qstrpos(const char *str, const char *key);
|
||||
inline bool strbegin (const char *str, const char *key);
|
||||
inline bool stribegin(const char *str, const char *key);
|
||||
inline bool strend (const char *str, const char *key);
|
||||
inline bool striend(const char *str, const char *key);
|
||||
inline char* strlower(char *str);
|
||||
inline char* strupper(char *str);
|
||||
inline char* strtr(char *dest, const char *before, const char *after);
|
||||
inline uintmax_t strhex (const char *str);
|
||||
inline intmax_t strsigned (const char *str);
|
||||
inline uintmax_t strunsigned(const char *str);
|
||||
inline uintmax_t strbin (const char *str);
|
||||
inline double strdouble (const char *str);
|
||||
inline size_t strhex (char *str, uintmax_t value, size_t length = 0);
|
||||
inline size_t strsigned (char *str, intmax_t value, size_t length = 0);
|
||||
inline size_t strunsigned(char *str, uintmax_t value, size_t length = 0);
|
||||
inline size_t strbin (char *str, uintmax_t value, size_t length = 0);
|
||||
inline size_t strdouble (char *str, double value, size_t length = 0);
|
||||
inline bool match(const char *pattern, const char *str);
|
||||
inline bool strint (const char *str, int &result);
|
||||
inline bool strmath(const char *str, int &result);
|
||||
inline size_t strlcpy(char *dest, const char *src, size_t length);
|
||||
inline size_t strlcat(char *dest, const char *src, size_t length);
|
||||
inline char* ltrim(char *str, const char *key = " ");
|
||||
inline char* rtrim(char *str, const char *key = " ");
|
||||
inline char* trim (char *str, const char *key = " ");
|
||||
inline char* ltrim_once(char *str, const char *key = " ");
|
||||
inline char* rtrim_once(char *str, const char *key = " ");
|
||||
inline char* trim_once (char *str, const char *key = " ");
|
||||
|
||||
namespace nall {
|
||||
class string;
|
||||
template<typename T> inline string to_string(T);
|
||||
|
||||
class string {
|
||||
public:
|
||||
inline void reserve(size_t);
|
||||
inline unsigned length() const;
|
||||
|
||||
inline string& assign(const char*);
|
||||
inline string& append(const char*);
|
||||
template<typename T> inline string& operator= (T value);
|
||||
template<typename T> inline string& operator<<(T value);
|
||||
|
||||
inline operator const char*() const;
|
||||
inline char* operator()();
|
||||
inline char& operator[](int);
|
||||
|
||||
inline bool operator==(const char*) const;
|
||||
inline bool operator!=(const char*) const;
|
||||
inline bool operator< (const char*) const;
|
||||
inline bool operator<=(const char*) const;
|
||||
inline bool operator> (const char*) const;
|
||||
inline bool operator>=(const char*) const;
|
||||
|
||||
inline string();
|
||||
inline string(const char*);
|
||||
inline string(const string&);
|
||||
inline string& operator=(const string&);
|
||||
inline ~string();
|
||||
|
||||
inline bool readfile(const char*);
|
||||
inline string& replace (const char*, const char*);
|
||||
inline string& qreplace(const char*, const char*);
|
||||
|
||||
protected:
|
||||
char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
class lstring : public vector<string> {
|
||||
public:
|
||||
template<typename T> inline lstring& operator<<(T value);
|
||||
|
||||
inline int find(const char*);
|
||||
inline void split (const char*, const char*, unsigned = 0);
|
||||
inline void qsplit(const char*, const char*, unsigned = 0);
|
||||
};
|
||||
};
|
||||
|
||||
inline size_t strlcpy(nall::string &dest, const char *src, size_t length);
|
||||
inline size_t strlcat(nall::string &dest, const char *src, size_t length);
|
||||
inline nall::string& strlower(nall::string &str);
|
||||
inline nall::string& strupper(nall::string &str);
|
||||
inline nall::string& strtr(nall::string &dest, const char *before, const char *after);
|
||||
inline nall::string& ltrim(nall::string &str, const char *key = " ");
|
||||
inline nall::string& rtrim(nall::string &str, const char *key = " ");
|
||||
inline nall::string& trim (nall::string &str, const char *key = " ");
|
||||
inline nall::string& ltrim_once(nall::string &str, const char *key = " ");
|
||||
inline nall::string& rtrim_once(nall::string &str, const char *key = " ");
|
||||
inline nall::string& trim_once (nall::string &str, const char *key = " ");
|
||||
|
||||
inline nall::string substr(const char *src, size_t start = 0, size_t length = 0);
|
||||
inline nall::string strhex (uintmax_t value);
|
||||
inline nall::string strsigned (intmax_t value);
|
||||
inline nall::string strunsigned(uintmax_t value);
|
||||
inline nall::string strbin (uintmax_t value);
|
||||
inline nall::string strdouble (double value);
|
||||
|
||||
#endif
|
25
src/lib/nall/string/cast.hpp
Normal file
25
src/lib/nall/string/cast.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef NALL_STRING_CAST_HPP
|
||||
#define NALL_STRING_CAST_HPP
|
||||
|
||||
namespace nall {
|
||||
//this is needed, as C++98 does not support explicit template specialization inside classes;
|
||||
//redundant memory allocation should hopefully be avoided via compiler optimizations.
|
||||
template<> inline string to_string<bool> (bool v) { return v ? "true" : "false"; }
|
||||
template<> inline string to_string<signed int> (signed int v) { return strsigned(v); }
|
||||
template<> inline string to_string<unsigned int> (unsigned int v) { return strunsigned(v); }
|
||||
template<> inline string to_string<double> (double v) { return strdouble(v); }
|
||||
template<> inline string to_string<char*> (char *v) { return v; }
|
||||
template<> inline string to_string<const char*> (const char *v) { return v; }
|
||||
template<> inline string to_string<string> (string v) { return v; }
|
||||
template<> inline string to_string<const string&>(const string &v) { return v; }
|
||||
|
||||
template<typename T> string& string::operator= (T value) { return assign(to_string<T>(value)); }
|
||||
template<typename T> string& string::operator<<(T value) { return append(to_string<T>(value)); }
|
||||
|
||||
template<typename T> lstring& lstring::operator<<(T value) {
|
||||
operator[](size()).assign(to_string<T>(value));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,4 +1,5 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_COMPARE_HPP
|
||||
#define NALL_STRING_COMPARE_HPP
|
||||
|
||||
char chrlower(char c) {
|
||||
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
|
@@ -1,4 +1,5 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_CONVERT_HPP
|
||||
#define NALL_STRING_CONVERT_HPP
|
||||
|
||||
char* strlower(char *str) {
|
||||
if(!str) return 0;
|
@@ -1,4 +1,7 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_CORE_HPP
|
||||
#define NALL_STRING_CORE_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
void string::reserve(size_t size_) {
|
||||
if(size_ > size) {
|
||||
@@ -64,6 +67,7 @@ string::string(const string &value) {
|
||||
|
||||
string& string::operator=(const string &value) {
|
||||
assign(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string::~string() {
|
||||
@@ -100,4 +104,6 @@ int lstring::find(const char *key) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,4 +1,5 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_MATCH_HPP
|
||||
#define NALL_STRING_MATCH_HPP
|
||||
|
||||
bool match(const char *p, const char *s) {
|
||||
const char *p_ = 0, *s_ = 0;
|
@@ -1,4 +1,5 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_MATH_HPP
|
||||
#define NALL_STRING_MATH_HPP
|
||||
|
||||
static int eval_integer(const char *&s) {
|
||||
if(!*s) throw "unrecognized_integer";
|
@@ -1,4 +1,7 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_REPLACE_HPP
|
||||
#define NALL_STRING_REPLACE_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
string& string::replace(const char *key, const char *token) {
|
||||
int i, z, ksl = strlen(key), tsl = strlen(token), ssl = length();
|
||||
@@ -95,4 +98,6 @@ string& string::qreplace(const char *key, const char *token) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,4 +1,7 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_SPLIT_HPP
|
||||
#define NALL_STRING_SPLIT_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
void lstring::split(const char *key, const char *src, unsigned limit) {
|
||||
reset();
|
||||
@@ -48,4 +51,6 @@ void lstring::qsplit(const char *key, const char *src, unsigned limit) {
|
||||
operator[](split_count++) = src + lp;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,4 +1,5 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_STRL_HPP
|
||||
#define NALL_STRING_STRL_HPP
|
||||
|
||||
//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_TRIM_HPP
|
||||
#define NALL_STRING_TRIM_HPP
|
||||
|
||||
char* ltrim(char *str, const char *key) {
|
||||
if(!key || !*key) return str;
|
@@ -1,4 +1,5 @@
|
||||
#ifdef NALL_STRING_CPP
|
||||
#ifndef NALL_STRING_UTILITY_HPP
|
||||
#define NALL_STRING_UTILITY_HPP
|
||||
|
||||
size_t strlcpy(nall::string &dest, const char *src, size_t length) {
|
||||
dest.reserve(length);
|
@@ -8,6 +8,8 @@
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#undef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
@@ -1,22 +1,17 @@
|
||||
class Audio {
|
||||
public:
|
||||
enum Setting {
|
||||
//AudioInterface settings
|
||||
Volume,
|
||||
Resample,
|
||||
ResampleOutputFrequency,
|
||||
ResampleInputFrequency,
|
||||
static const char *Volume;
|
||||
static const char *Resample;
|
||||
static const char *ResampleRatio;
|
||||
|
||||
//Audio settings
|
||||
Handle,
|
||||
Synchronize,
|
||||
Frequency,
|
||||
Latency,
|
||||
};
|
||||
static const char *Handle;
|
||||
static const char *Synchronize;
|
||||
static const char *Frequency;
|
||||
static const char *Latency;
|
||||
|
||||
virtual bool cap(Setting) { return false; }
|
||||
virtual uintptr_t get(Setting) { return false; }
|
||||
virtual bool set(Setting, uintptr_t) { return false; }
|
||||
virtual bool cap(const nall::string& name) { return false; }
|
||||
virtual nall::any get(const nall::string& name) { return false; }
|
||||
virtual bool set(const nall::string& name, const nall::any& value) { return false; }
|
||||
|
||||
virtual void sample(uint16_t left, uint16_t right) {}
|
||||
virtual void clear() {}
|
||||
|
@@ -1,13 +1,14 @@
|
||||
/*
|
||||
audio.alsa (2008-08-12)
|
||||
authors: Nach, RedDwarf
|
||||
*/
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
namespace ruby {
|
||||
|
||||
#include "alsa.hpp"
|
||||
|
||||
class pAudioALSA {
|
||||
public:
|
||||
AudioALSA &self;
|
||||
|
||||
struct {
|
||||
snd_pcm_t *handle;
|
||||
snd_pcm_format_t format;
|
||||
@@ -28,50 +29,41 @@ public:
|
||||
unsigned latency;
|
||||
} settings;
|
||||
|
||||
bool cap(Audio::Setting setting) {
|
||||
if(setting == Audio::Synchronize) return true;
|
||||
if(setting == Audio::Frequency) return true;
|
||||
if(setting == Audio::Latency) return true;
|
||||
bool cap(const string& name) {
|
||||
if(name == Audio::Synchronize) return true;
|
||||
if(name == Audio::Frequency) return true;
|
||||
if(name == Audio::Latency) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uintptr_t get(Audio::Setting setting) {
|
||||
if(setting == Audio::Synchronize) return settings.synchronize;
|
||||
if(setting == Audio::Frequency) return settings.frequency;
|
||||
if(setting == Audio::Latency) return settings.latency;
|
||||
any get(const string& name) {
|
||||
if(name == Audio::Synchronize) return settings.synchronize;
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
if(name == Audio::Latency) return settings.latency;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set(Audio::Setting setting, uintptr_t param) {
|
||||
if(setting == Audio::Synchronize) {
|
||||
if(settings.synchronize != param) {
|
||||
settings.synchronize = param;
|
||||
if(device.handle) {
|
||||
term();
|
||||
init();
|
||||
}
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Audio::Synchronize) {
|
||||
if(settings.synchronize != any_cast<bool>(value)) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
if(device.handle) init();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(setting == Audio::Frequency) {
|
||||
if(settings.frequency != param) {
|
||||
settings.frequency = param;
|
||||
if(device.handle) {
|
||||
term();
|
||||
init();
|
||||
}
|
||||
if(name == Audio::Frequency) {
|
||||
if(settings.frequency != any_cast<unsigned>(value)) {
|
||||
settings.frequency = any_cast<unsigned>(value);
|
||||
if(device.handle) init();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(setting == Audio::Latency) {
|
||||
if(settings.latency != param) {
|
||||
settings.latency = param;
|
||||
if(device.handle) {
|
||||
term();
|
||||
init();
|
||||
}
|
||||
if(name == Audio::Latency) {
|
||||
if(settings.latency != any_cast<unsigned>(value)) {
|
||||
settings.latency = any_cast<unsigned>(value);
|
||||
if(device.handle) init();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -86,12 +78,8 @@ public:
|
||||
if(buffer.length < device.period_size) return;
|
||||
|
||||
if(settings.synchronize == false) {
|
||||
snd_pcm_avail_update(device.handle);
|
||||
snd_pcm_sframes_t delay;
|
||||
snd_pcm_delay(device.handle, &delay);
|
||||
if(delay < 0) {
|
||||
snd_pcm_prepare(device.handle);
|
||||
} else if(delay > device.buffer_size - device.period_size) {
|
||||
snd_pcm_sframes_t avail = snd_pcm_avail_update(device.handle);
|
||||
if(avail < device.period_size) {
|
||||
buffer.length = 0;
|
||||
return;
|
||||
}
|
||||
@@ -120,7 +108,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
}
|
||||
|
||||
bool init() {
|
||||
term();
|
||||
|
||||
if(snd_pcm_open(&device.handle, device.name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
|
||||
term();
|
||||
return false;
|
||||
@@ -128,21 +121,21 @@ public:
|
||||
|
||||
/* //below code will not work with 24khz frequency rate (ALSA library bug)
|
||||
if(snd_pcm_set_params(device.handle, device.format, SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
device.channels, settings.frequency, 1, settings.latency * 100) < 0) {
|
||||
device.channels, settings.frequency, 1, settings.latency * 1000) < 0) {
|
||||
//failed to set device parameters
|
||||
term();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(snd_pcm_get_params(device.handle, &device.buffer_size, &device.period_size) < 0) {
|
||||
device.period_size = settings.latency * 100 * 1e-6 * settings.frequency / 4;
|
||||
device.period_size = settings.latency * 1000 * 1e-6 * settings.frequency / 4;
|
||||
}*/
|
||||
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
unsigned rate = settings.frequency;
|
||||
unsigned buffer_time = settings.latency * 100;
|
||||
unsigned period_time = settings.latency * 100 / 4;
|
||||
unsigned buffer_time = settings.latency * 1000;
|
||||
unsigned period_time = settings.latency * 1000 / 4;
|
||||
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
if(snd_pcm_hw_params_any(device.handle, hwparams) < 0) {
|
||||
@@ -206,7 +199,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
pAudioALSA(AudioALSA &self_) : self(self_) {
|
||||
pAudioALSA() {
|
||||
device.handle = 0;
|
||||
device.format = SND_PCM_FORMAT_S16_LE;
|
||||
device.channels = 2;
|
||||
@@ -225,13 +218,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool AudioALSA::cap(Setting setting) { return p.cap(setting); }
|
||||
uintptr_t AudioALSA::get(Setting setting) { return p.get(setting); }
|
||||
bool AudioALSA::set(Setting setting, uintptr_t param) { return p.set(setting, param); }
|
||||
void AudioALSA::sample(uint16_t left, uint16_t right) { p.sample(left, right); }
|
||||
bool AudioALSA::init() { return p.init(); }
|
||||
void AudioALSA::term() { p.term(); }
|
||||
AudioALSA::AudioALSA() : p(*new pAudioALSA(*this)) {}
|
||||
AudioALSA::~AudioALSA() { delete &p; }
|
||||
DeclareAudio(ALSA)
|
||||
|
||||
} //namespace ruby
|
||||
};
|
||||
|
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
audio.alsa (2008-08-12)
|
||||
authors: Nach, RedDwarf
|
||||
*/
|
||||
|
||||
class pAudioALSA;
|
||||
|
||||
class AudioALSA : public Audio {
|
||||
public:
|
||||
bool cap(Setting);
|
||||
uintptr_t get(Setting);
|
||||
bool set(Setting, uintptr_t);
|
||||
|
||||
void sample(uint16_t left, uint16_t right);
|
||||
bool init();
|
||||
void term();
|
||||
|
||||
AudioALSA();
|
||||
~AudioALSA();
|
||||
|
||||
private:
|
||||
pAudioALSA &p;
|
||||
};
|
@@ -1,13 +1,14 @@
|
||||
/*
|
||||
audio.ao (2008-06-01)
|
||||
authors: Nach, RedDwarf
|
||||
*/
|
||||
|
||||
#include <ao/ao.h>
|
||||
|
||||
namespace ruby {
|
||||
|
||||
#include "ao.hpp"
|
||||
|
||||
class pAudioAO {
|
||||
public:
|
||||
AudioAO &self;
|
||||
|
||||
int driver_id;
|
||||
ao_sample_format driver_format;
|
||||
ao_device *audio_device;
|
||||
@@ -16,25 +17,23 @@ public:
|
||||
unsigned frequency;
|
||||
} settings;
|
||||
|
||||
bool cap(Audio::Setting setting) {
|
||||
if(setting == Audio::Frequency) return true;
|
||||
bool cap(const string& name) {
|
||||
if(name == Audio::Frequency) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uintptr_t get(Audio::Setting setting) {
|
||||
if(setting == Audio::Frequency) return settings.frequency;
|
||||
any get(const string& name) {
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set(Audio::Setting setting, uintptr_t param) {
|
||||
if(setting == Audio::Frequency) {
|
||||
settings.frequency = param;
|
||||
if(audio_device) {
|
||||
term();
|
||||
init();
|
||||
}
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Audio::Frequency) {
|
||||
settings.frequency = any_cast<unsigned>(value);
|
||||
if(audio_device) init();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -43,7 +42,12 @@ public:
|
||||
ao_play(audio_device, (char*)&samp, 4); //This may need to be byte swapped for Big Endian
|
||||
}
|
||||
|
||||
void clear() {
|
||||
}
|
||||
|
||||
bool init() {
|
||||
term();
|
||||
|
||||
driver_id = ao_default_driver_id(); //ao_driver_id((const char*)driver)
|
||||
if(driver_id < 0) return false;
|
||||
|
||||
@@ -72,7 +76,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
pAudioAO(AudioAO &self_) : self(self_) {
|
||||
pAudioAO() {
|
||||
audio_device = 0;
|
||||
ao_initialize();
|
||||
|
||||
@@ -85,13 +89,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool AudioAO::cap(Setting setting) { return p.cap(setting); }
|
||||
uintptr_t AudioAO::get(Setting setting) { return p.get(setting); }
|
||||
bool AudioAO::set(Setting setting, uintptr_t param) { return p.set(setting, param); }
|
||||
void AudioAO::sample(uint16_t l_sample, uint16_t r_sample) { p.sample(l_sample, r_sample); }
|
||||
bool AudioAO::init() { return p.init(); }
|
||||
void AudioAO::term() { p.term(); }
|
||||
AudioAO::AudioAO() : p(*new pAudioAO(*this)) {}
|
||||
AudioAO::~AudioAO() { delete &p; }
|
||||
DeclareAudio(AO)
|
||||
|
||||
} //namespace ruby
|
||||
};
|
||||
|
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
audio.ao (2008-06-01)
|
||||
authors: Nach, RedDwarf
|
||||
*/
|
||||
|
||||
class pAudioAO;
|
||||
|
||||
class AudioAO : public Audio {
|
||||
public:
|
||||
bool cap(Setting);
|
||||
uintptr_t get(Setting);
|
||||
bool set(Setting, uintptr_t);
|
||||
|
||||
void sample(uint16_t left, uint16_t right);
|
||||
bool init();
|
||||
void term();
|
||||
|
||||
AudioAO();
|
||||
~AudioAO();
|
||||
|
||||
private:
|
||||
pAudioAO &p;
|
||||
};
|
@@ -1,14 +1,14 @@
|
||||
#include <windows.h>
|
||||
/*
|
||||
audio.directsound (2007-12-26)
|
||||
author: byuu
|
||||
*/
|
||||
|
||||
#include <dsound.h>
|
||||
|
||||
namespace ruby {
|
||||
|
||||
#include "directsound.hpp"
|
||||
|
||||
class pAudioDS {
|
||||
public:
|
||||
AudioDS &self;
|
||||
|
||||
LPDIRECTSOUND ds;
|
||||
LPDIRECTSOUNDBUFFER dsb_p, dsb_b;
|
||||
DSBUFFERDESC dsbd;
|
||||
@@ -33,42 +33,42 @@ public:
|
||||
unsigned latency;
|
||||
} settings;
|
||||
|
||||
bool cap(Audio::Setting setting) {
|
||||
if(setting == Audio::Handle) return true;
|
||||
if(setting == Audio::Synchronize) return true;
|
||||
if(setting == Audio::Frequency) return true;
|
||||
if(setting == Audio::Latency) return true;
|
||||
bool cap(const string& name) {
|
||||
if(name == Audio::Handle) return true;
|
||||
if(name == Audio::Synchronize) return true;
|
||||
if(name == Audio::Frequency) return true;
|
||||
if(name == Audio::Latency) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uintptr_t get(Audio::Setting setting) {
|
||||
if(setting == Audio::Handle) return (uintptr_t)settings.handle;
|
||||
if(setting == Audio::Synchronize) return settings.synchronize;
|
||||
if(setting == Audio::Frequency) return settings.frequency;
|
||||
if(setting == Audio::Latency) return settings.latency;
|
||||
any get(const string& name) {
|
||||
if(name == Audio::Handle) return (uintptr_t)settings.handle;
|
||||
if(name == Audio::Synchronize) return settings.synchronize;
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
if(name == Audio::Latency) return settings.latency;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set(Audio::Setting setting, uintptr_t param) {
|
||||
if(setting == Audio::Handle) {
|
||||
settings.handle = (HWND)param;
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Audio::Handle) {
|
||||
settings.handle = (HWND)any_cast<uintptr_t>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(setting == Audio::Synchronize) {
|
||||
settings.synchronize = param;
|
||||
if(name == Audio::Synchronize) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
if(ds) clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(setting == Audio::Frequency) {
|
||||
settings.frequency = param;
|
||||
if(name == Audio::Frequency) {
|
||||
settings.frequency = any_cast<unsigned>(value);
|
||||
if(ds) init();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(setting == Audio::Latency) {
|
||||
settings.latency = param;
|
||||
if(name == Audio::Latency) {
|
||||
settings.latency = any_cast<unsigned>(value);
|
||||
if(ds) init();
|
||||
return true;
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
dsb_b->GetCurrentPosition(&pos, 0);
|
||||
unsigned activering = pos / (device.latency * 4);
|
||||
if(activering == device.readring) {
|
||||
if(video.get(Video::Synchronize) == false) Sleep(1);
|
||||
if(settings.synchronize == false) Sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
if(ds) { ds->Release(); ds = 0; }
|
||||
}
|
||||
|
||||
pAudioDS(AudioDS &self_) : self(self_) {
|
||||
pAudioDS() {
|
||||
ds = 0;
|
||||
dsb_p = 0;
|
||||
dsb_b = 0;
|
||||
@@ -207,14 +207,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool AudioDS::cap(Setting setting) { return p.cap(setting); }
|
||||
uintptr_t AudioDS::get(Setting setting) { return p.get(setting); }
|
||||
bool AudioDS::set(Setting setting, uintptr_t param) { return p.set(setting, param); }
|
||||
void AudioDS::sample(uint16_t left, uint16_t right) { p.sample(left, right); }
|
||||
void AudioDS::clear() { p.clear(); }
|
||||
bool AudioDS::init() { return p.init(); }
|
||||
void AudioDS::term() { p.term(); }
|
||||
AudioDS::AudioDS() : p(*new pAudioDS(*this)) {}
|
||||
AudioDS::~AudioDS() { delete &p; }
|
||||
DeclareAudio(DS)
|
||||
|
||||
} //namespace ruby
|
||||
};
|
||||
|
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
audio.directsound (2007-12-26)
|
||||
author: byuu
|
||||
*/
|
||||
|
||||
class pAudioDS;
|
||||
|
||||
class AudioDS : public Audio {
|
||||
public:
|
||||
bool cap(Setting);
|
||||
uintptr_t get(Setting);
|
||||
bool set(Setting, uintptr_t);
|
||||
|
||||
void sample(uint16_t left, uint16_t right);
|
||||
void clear();
|
||||
bool init();
|
||||
void term();
|
||||
|
||||
AudioDS();
|
||||
~AudioDS();
|
||||
|
||||
private:
|
||||
pAudioDS &p;
|
||||
};
|
@@ -1,14 +1,21 @@
|
||||
/*
|
||||
audio.openal (2007-12-26)
|
||||
author: Nach
|
||||
contributors: byuu, wertigon, _willow_
|
||||
*/
|
||||
|
||||
#if defined(PLATFORM_OSX)
|
||||
#include <OpenAL/al.h>
|
||||
#include <OpenAL/alc.h>
|
||||
#else
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#endif
|
||||
|
||||
namespace ruby {
|
||||
|
||||
#include "openal.hpp"
|
||||
|
||||
class pAudioOpenAL {
|
||||
public:
|
||||
AudioOpenAL &self;
|
||||
|
||||
struct {
|
||||
ALCdevice *handle;
|
||||
ALCcontext *context;
|
||||
@@ -30,34 +37,34 @@ public:
|
||||
unsigned latency;
|
||||
} settings;
|
||||
|
||||
bool cap(Audio::Setting setting) {
|
||||
if(setting == Audio::Synchronize) return true;
|
||||
if(setting == Audio::Frequency) return true;
|
||||
if(setting == Audio::Latency) return true;
|
||||
bool cap(const string& name) {
|
||||
if(name == Audio::Synchronize) return true;
|
||||
if(name == Audio::Frequency) return true;
|
||||
if(name == Audio::Latency) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uintptr_t get(Audio::Setting setting) {
|
||||
if(setting == Audio::Synchronize) return settings.synchronize;
|
||||
if(setting == Audio::Frequency) return settings.frequency;
|
||||
if(setting == Audio::Latency) return settings.latency;
|
||||
any get(const string& name) {
|
||||
if(name == Audio::Synchronize) return settings.synchronize;
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
if(name == Audio::Latency) return settings.latency;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set(Audio::Setting setting, uintptr_t param) {
|
||||
if(setting == Audio::Synchronize) {
|
||||
settings.synchronize = param;
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Audio::Synchronize) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(setting == Audio::Frequency) {
|
||||
settings.frequency = param;
|
||||
if(name == Audio::Frequency) {
|
||||
settings.frequency = any_cast<unsigned>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(setting == Audio::Latency) {
|
||||
if(settings.latency != param) {
|
||||
settings.latency = param;
|
||||
if(name == Audio::Latency) {
|
||||
if(settings.latency != any_cast<unsigned>(value)) {
|
||||
settings.latency = any_cast<unsigned>(value);
|
||||
update_latency();
|
||||
}
|
||||
return true;
|
||||
@@ -96,6 +103,9 @@ public:
|
||||
buffer.length = 0;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
}
|
||||
|
||||
void update_latency() {
|
||||
if(buffer.data) delete[] buffer.data;
|
||||
buffer.size = settings.frequency * settings.latency / 1000.0 + 0.5;
|
||||
@@ -174,7 +184,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
pAudioOpenAL(AudioOpenAL &self_) : self(self_) {
|
||||
pAudioOpenAL() {
|
||||
device.source = 0;
|
||||
device.handle = 0;
|
||||
device.context = 0;
|
||||
@@ -195,13 +205,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool AudioOpenAL::cap(Setting setting) { return p.cap(setting); }
|
||||
uintptr_t AudioOpenAL::get(Setting setting) { return p.get(setting); }
|
||||
bool AudioOpenAL::set(Setting setting, uintptr_t param) { return p.set(setting, param); }
|
||||
void AudioOpenAL::sample(uint16_t sl, uint16_t sr) { p.sample(sl, sr); }
|
||||
bool AudioOpenAL::init() { return p.init(); }
|
||||
void AudioOpenAL::term() { p.term(); }
|
||||
AudioOpenAL::AudioOpenAL() : p(*new pAudioOpenAL(*this)) {}
|
||||
AudioOpenAL::~AudioOpenAL() { delete &p; }
|
||||
DeclareAudio(OpenAL)
|
||||
|
||||
} //namespace ruby
|
||||
};
|
||||
|
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
audio.openal (2007-12-26)
|
||||
author: Nach
|
||||
contributors: byuu, wertigon, _willow_
|
||||
*/
|
||||
|
||||
class pAudioOpenAL;
|
||||
|
||||
class AudioOpenAL : public Audio {
|
||||
public:
|
||||
bool cap(Setting);
|
||||
uintptr_t get(Setting);
|
||||
bool set(Setting, uintptr_t);
|
||||
|
||||
void sample(uint16_t sl, uint16_t sr);
|
||||
bool init();
|
||||
void term();
|
||||
|
||||
AudioOpenAL();
|
||||
~AudioOpenAL();
|
||||
|
||||
private:
|
||||
pAudioOpenAL &p;
|
||||
};
|
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
audio.oss (2007-12-26)
|
||||
author: Nach
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
@@ -20,12 +25,8 @@
|
||||
|
||||
namespace ruby {
|
||||
|
||||
#include "oss.hpp"
|
||||
|
||||
class pAudioOSS {
|
||||
public:
|
||||
AudioOSS &self;
|
||||
|
||||
struct {
|
||||
int fd;
|
||||
int format;
|
||||
@@ -37,25 +38,23 @@ public:
|
||||
unsigned frequency;
|
||||
} settings;
|
||||
|
||||
bool cap(Audio::Setting setting) {
|
||||
if(setting == Audio::Frequency) return true;
|
||||
bool cap(const string& name) {
|
||||
if(name == Audio::Frequency) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uintptr_t get(Audio::Setting setting) {
|
||||
if(setting == Audio::Frequency) return settings.frequency;
|
||||
any get(const string& name) {
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set(Audio::Setting setting, uintptr_t param) {
|
||||
if(setting == Audio::Frequency) {
|
||||
settings.frequency = param;
|
||||
if(device.fd > 0) {
|
||||
term();
|
||||
init();
|
||||
}
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Audio::Frequency) {
|
||||
settings.frequency = any_cast<unsigned>(value);
|
||||
if(device.fd > 0) init();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -64,7 +63,12 @@ public:
|
||||
unsigned unused = write(device.fd, &sample, 4);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
}
|
||||
|
||||
bool init() {
|
||||
term();
|
||||
|
||||
device.fd = open(device.name, O_WRONLY, O_NONBLOCK);
|
||||
if(device.fd < 0) return false;
|
||||
|
||||
@@ -90,7 +94,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
pAudioOSS(AudioOSS &self_) : self(self_) {
|
||||
pAudioOSS() {
|
||||
device.fd = -1;
|
||||
device.format = AFMT_S16_LE;
|
||||
device.channels = 2;
|
||||
@@ -104,13 +108,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool AudioOSS::cap(Setting setting) { return p.cap(setting); }
|
||||
uintptr_t AudioOSS::get(Setting setting) { return p.get(setting); }
|
||||
bool AudioOSS::set(Setting setting, uintptr_t param) { return p.set(setting, param); }
|
||||
void AudioOSS::sample(uint16_t sl, uint16_t sr) { p.sample(sl, sr); }
|
||||
bool AudioOSS::init() { return p.init(); }
|
||||
void AudioOSS::term() { p.term(); }
|
||||
AudioOSS::AudioOSS() : p(*new pAudioOSS(*this)) {}
|
||||
AudioOSS::~AudioOSS() { delete &p; }
|
||||
DeclareAudio(OSS)
|
||||
|
||||
} //namespace ruby
|
||||
};
|
||||
|
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
audio.oss (2007-12-26)
|
||||
author: Nach
|
||||
*/
|
||||
|
||||
class pAudioOSS;
|
||||
|
||||
class AudioOSS : public Audio {
|
||||
public:
|
||||
bool cap(Setting);
|
||||
uintptr_t get(Setting);
|
||||
bool set(Setting, uintptr_t);
|
||||
|
||||
void sample(uint16_t sl, uint16_t sr);
|
||||
bool init();
|
||||
void term();
|
||||
|
||||
AudioOSS();
|
||||
~AudioOSS();
|
||||
|
||||
private:
|
||||
pAudioOSS &p;
|
||||
};
|
@@ -1,10 +1,13 @@
|
||||
/*
|
||||
audio.pulseaudio (2008-10-31)
|
||||
author: byuu
|
||||
*/
|
||||
|
||||
#include <pulse/simple.h>
|
||||
#include <pulse/error.h>
|
||||
|
||||
namespace ruby {
|
||||
|
||||
#include "pulseaudio.hpp"
|
||||
|
||||
class pAudioPulseAudio {
|
||||
public:
|
||||
struct {
|
||||
@@ -21,25 +24,20 @@ public:
|
||||
unsigned frequency;
|
||||
} settings;
|
||||
|
||||
AudioPulseAudio &self;
|
||||
|
||||
bool cap(Audio::Setting setting) {
|
||||
if(setting == Audio::Frequency) return true;
|
||||
bool cap(const string& name) {
|
||||
if(name == Audio::Frequency) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uintptr_t get(Audio::Setting setting) {
|
||||
if(setting == Audio::Frequency) return settings.frequency;
|
||||
any get(const string& name) {
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set(Audio::Setting setting, uintptr_t param) {
|
||||
if(setting == Audio::Frequency) {
|
||||
settings.frequency = param;
|
||||
if(device.handle) {
|
||||
term();
|
||||
init();
|
||||
}
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Audio::Frequency) {
|
||||
settings.frequency = any_cast<unsigned>(value);
|
||||
if(device.handle) init();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -57,7 +55,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
}
|
||||
|
||||
bool init() {
|
||||
term();
|
||||
|
||||
device.spec.format = PA_SAMPLE_S16LE;
|
||||
device.spec.channels = 2;
|
||||
device.spec.rate = settings.frequency;
|
||||
@@ -98,7 +101,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
pAudioPulseAudio(AudioPulseAudio &self_) : self(self_) {
|
||||
pAudioPulseAudio() {
|
||||
device.handle = 0;
|
||||
buffer.data = 0;
|
||||
settings.frequency = 22050;
|
||||
@@ -109,13 +112,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool AudioPulseAudio::cap(Setting setting) { return p.cap(setting); }
|
||||
uintptr_t AudioPulseAudio::get(Setting setting) { return p.get(setting); }
|
||||
bool AudioPulseAudio::set(Setting setting, uintptr_t param) { return p.set(setting, param); }
|
||||
void AudioPulseAudio::sample(uint16_t left, uint16_t right) { return p.sample(left, right); }
|
||||
bool AudioPulseAudio::init() { return p.init(); }
|
||||
void AudioPulseAudio::term() { p.term(); }
|
||||
AudioPulseAudio::AudioPulseAudio() : p(*new pAudioPulseAudio(*this)) {}
|
||||
AudioPulseAudio::~AudioPulseAudio() { delete &p; }
|
||||
DeclareAudio(PulseAudio)
|
||||
|
||||
} //namespace ruby
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user