mirror of https://github.com/bsnes-emu/bsnes.git
Update to v089r10 release.
byuu says: Changelog: - Cydrak merged all three SPC7110 decompression routines into one, cuts the size in half - fixed masking of $4803.d7 and $4813.d7 - data port out of bounds accesses emulated correctly for app SPC7110 boards - all(?) data port $4810 reload cases now supported - basic timing for $4805-6 seeking; reworked delay timing to work better as well - fixed $480c.d7 flag (1 = ready, not busy) - AbsoluteInput returns -32768 if presentation window lacks focus and you don't always allow input
This commit is contained in:
parent
3302398907
commit
4545e7c62d
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "089.09";
|
static const char Version[] = "089.10";
|
||||||
static const char Author[] = "byuu";
|
static const char Author[] = "byuu";
|
||||||
static const char License[] = "GPLv3";
|
static const char License[] = "GPLv3";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifdef SPC7110_CPP
|
#ifdef SPC7110_CPP
|
||||||
|
|
||||||
void SPC7110::alu_multiply() {
|
void SPC7110::alu_multiply() {
|
||||||
|
add_clocks(30);
|
||||||
|
|
||||||
if(r482e & 1) {
|
if(r482e & 1) {
|
||||||
//signed 16-bit x 16-bit multiplication
|
//signed 16-bit x 16-bit multiplication
|
||||||
int16 r0 = (int16)(r4824 | r4825 << 8);
|
int16 r0 = (int16)(r4824 | r4825 << 8);
|
||||||
|
@ -27,6 +29,8 @@ void SPC7110::alu_multiply() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110::alu_divide() {
|
void SPC7110::alu_divide() {
|
||||||
|
add_clocks(40);
|
||||||
|
|
||||||
if(r482e & 1) {
|
if(r482e & 1) {
|
||||||
//signed 32-bit x 16-bit division
|
//signed 32-bit x 16-bit division
|
||||||
int32 dividend = (int32)(r4820 | r4821 << 8 | r4822 << 16 | r4823 << 24);
|
int32 dividend = (int32)(r4820 | r4821 << 8 | r4822 << 16 | r4823 << 24);
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
#ifdef SPC7110_CPP
|
#ifdef SPC7110_CPP
|
||||||
|
|
||||||
uint8 SPC7110::datarom_read(unsigned addr) {
|
uint8 SPC7110::datarom_read(unsigned addr) {
|
||||||
unsigned mask = (1 << (r4834 & 3)) - 1; //8mbit, 16mbit, 32mbit, 64mbit
|
unsigned size = 1 << (r4834 & 3); //size in MB
|
||||||
unsigned range = 0x100000 * (1 + mask);
|
unsigned mask = 0x100000 * size - 1;
|
||||||
unsigned offset = addr & 0x7fffff;
|
unsigned offset = addr & mask;
|
||||||
|
if((r4834 & 3) != 3 && (addr & 0x400000)) return 0x00;
|
||||||
//mirroring behavior is non-sensical. assuming a 32mbit data ROM:
|
|
||||||
//banks 4-7 with mask 0-2 returns 0x00; banks 4-7 with mask 3 mirrors banks 0-3
|
|
||||||
if(range <= drom_size && offset >= drom_size) return 0x00;
|
|
||||||
|
|
||||||
return cartridge.rom.read(drom_base + Bus::mirror(offset, drom_size));
|
return cartridge.rom.read(drom_base + Bus::mirror(offset, drom_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +29,7 @@ void SPC7110::data_port_increment_4810() {
|
||||||
if(r4818 & 8) adjust = (int16)adjust;
|
if(r4818 & 8) adjust = (int16)adjust;
|
||||||
if((r4818 & 16) == 0) set_data_offset(offset + stride);
|
if((r4818 & 16) == 0) set_data_offset(offset + stride);
|
||||||
if((r4818 & 16) != 0) set_data_adjust(adjust + stride);
|
if((r4818 & 16) != 0) set_data_adjust(adjust + stride);
|
||||||
|
data_port_read();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110::data_port_increment_4814() {
|
void SPC7110::data_port_increment_4814() {
|
||||||
|
@ -41,6 +38,7 @@ void SPC7110::data_port_increment_4814() {
|
||||||
unsigned adjust = data_adjust();
|
unsigned adjust = data_adjust();
|
||||||
if(r4818 & 8) adjust = (int16)adjust;
|
if(r4818 & 8) adjust = (int16)adjust;
|
||||||
set_data_offset(offset + adjust);
|
set_data_offset(offset + adjust);
|
||||||
|
data_port_read();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110::data_port_increment_4815() {
|
void SPC7110::data_port_increment_4815() {
|
||||||
|
@ -49,6 +47,7 @@ void SPC7110::data_port_increment_4815() {
|
||||||
unsigned adjust = data_adjust();
|
unsigned adjust = data_adjust();
|
||||||
if(r4818 & 8) adjust = (int16)adjust;
|
if(r4818 & 8) adjust = (int16)adjust;
|
||||||
set_data_offset(offset + adjust);
|
set_data_offset(offset + adjust);
|
||||||
|
data_port_read();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110::data_port_increment_481a() {
|
void SPC7110::data_port_increment_481a() {
|
||||||
|
@ -57,6 +56,7 @@ void SPC7110::data_port_increment_481a() {
|
||||||
unsigned adjust = data_adjust();
|
unsigned adjust = data_adjust();
|
||||||
if(r4818 & 8) adjust = (int16)adjust;
|
if(r4818 & 8) adjust = (int16)adjust;
|
||||||
set_data_offset(offset + adjust);
|
set_data_offset(offset + adjust);
|
||||||
|
data_port_read();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "decompressor.cpp"
|
||||||
|
|
||||||
void SPC7110::dcu_load_address() {
|
void SPC7110::dcu_load_address() {
|
||||||
unsigned table = r4801 | r4802 << 8 | r4803 << 16;
|
unsigned table = r4801 | r4802 << 8 | r4803 << 16;
|
||||||
unsigned index = r4804 << 2;
|
unsigned index = r4804 << 2;
|
||||||
|
@ -10,29 +12,26 @@ void SPC7110::dcu_load_address() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110::dcu_begin_transfer() {
|
void SPC7110::dcu_begin_transfer() {
|
||||||
switch(dcu_mode) {
|
if(dcu_mode == 3) return; //invalid mode
|
||||||
case 0: decompress_1bpp(true); break;
|
|
||||||
case 1: decompress_2bpp(true); break;
|
|
||||||
case 2: decompress_4bpp(true); break;
|
|
||||||
case 3: return;
|
|
||||||
}
|
|
||||||
|
|
||||||
r480c |= 0x80;
|
add_clocks(20);
|
||||||
dcu_sp = 0;
|
decompressor->initialize(dcu_mode, dcu_addr);
|
||||||
|
|
||||||
//reset context states
|
|
||||||
for(auto &ctx : context) {
|
|
||||||
ctx.index = 0;
|
|
||||||
ctx.invert = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(r480b & 2) {
|
if(r480b & 2) {
|
||||||
unsigned seek = (r4805 | r4806 << 8) << dcu_mode;
|
unsigned seek = (r4805 | r4806 << 8) << dcu_mode;
|
||||||
while(seek--) dcu_read();
|
add_clocks(seek);
|
||||||
|
while(seek--) decompressor->output();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r480c |= 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SPC7110::dcu_read() {
|
uint8 SPC7110::dcu_read() {
|
||||||
|
if((r480c & 0x80) == 0) return 0x00;
|
||||||
|
return decompressor->output();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
unsigned tilesize = 8 << dcu_mode;
|
unsigned tilesize = 8 << dcu_mode;
|
||||||
|
|
||||||
if(dcu_sp == 0) {
|
if(dcu_sp == 0) {
|
||||||
|
@ -51,290 +50,9 @@ uint8 SPC7110::dcu_read() {
|
||||||
uint8 data = dcu_output[dcu_sp++];
|
uint8 data = dcu_output[dcu_sp++];
|
||||||
dcu_sp &= tilesize - 1;
|
dcu_sp &= tilesize - 1;
|
||||||
return data;
|
return data;
|
||||||
}
|
*/
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
void SPC7110::decompress_1bpp(bool init) {
|
|
||||||
static uint8 val, in, span;
|
|
||||||
static int out, inverts, lps, in_count;
|
|
||||||
|
|
||||||
if(init == true) {
|
|
||||||
out = inverts = lps = 0;
|
|
||||||
span = 0xff;
|
|
||||||
val = datarom_read(dcu_addr++);
|
|
||||||
in = datarom_read(dcu_addr++);
|
|
||||||
in_count = 8;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unsigned row = 0; row < 8; row++) {
|
|
||||||
for(unsigned bit = 0; bit < 8; bit++) {
|
|
||||||
//get context
|
|
||||||
uint8 mask = (1 << (bit & 3)) - 1;
|
|
||||||
uint8 con = mask + ((inverts & mask) ^ (lps & mask));
|
|
||||||
if(bit > 3) con += 15;
|
|
||||||
|
|
||||||
//get prob and mps
|
|
||||||
unsigned prob = probability(con);
|
|
||||||
unsigned mps = (((out >> 15) & 1) ^ context[con].invert);
|
|
||||||
|
|
||||||
//get bit
|
|
||||||
unsigned flag_lps;
|
|
||||||
if(val <= span - prob) { //mps
|
|
||||||
span = span - prob;
|
|
||||||
out = (out << 1) + mps;
|
|
||||||
flag_lps = 0;
|
|
||||||
} else { //lps
|
|
||||||
val = val - (span - (prob - 1));
|
|
||||||
span = prob - 1;
|
|
||||||
out = (out << 1) + 1 - mps;
|
|
||||||
flag_lps = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//renormalize
|
|
||||||
unsigned shift = 0;
|
|
||||||
while(span < 0x7f) {
|
|
||||||
shift++;
|
|
||||||
|
|
||||||
span = (span << 1) + 1;
|
|
||||||
val = (val << 1) + (in >> 7);
|
|
||||||
|
|
||||||
in <<= 1;
|
|
||||||
if(--in_count == 0) {
|
|
||||||
in = datarom_read(dcu_addr++);
|
|
||||||
in_count = 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//update processing info
|
|
||||||
lps = (lps << 1) + flag_lps;
|
|
||||||
inverts = (inverts << 1) + context[con].invert;
|
|
||||||
|
|
||||||
//update context state
|
|
||||||
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
|
||||||
if(flag_lps) context[con].index = next_lps(con);
|
|
||||||
else if(shift) context[con].index = next_mps(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
//save byte
|
|
||||||
dcu_tiledata[dcu_dp + row] = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPC7110::decompress_2bpp(bool init) {
|
|
||||||
static int pixelorder[4], realorder[4];
|
|
||||||
static uint8 in, val, span;
|
|
||||||
static int out, inverts, lps, in_count;
|
|
||||||
|
|
||||||
if(init == true) {
|
|
||||||
for(unsigned i = 0; i < 4; i++) pixelorder[i] = i;
|
|
||||||
out = inverts = lps = 0;
|
|
||||||
span = 0xff;
|
|
||||||
val = datarom_read(dcu_addr++);
|
|
||||||
in = datarom_read(dcu_addr++);
|
|
||||||
in_count = 8;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unsigned row = 0; row < 8; row++) {
|
|
||||||
for(unsigned pixel = 0; pixel < 8; pixel++) {
|
|
||||||
//get first symbol context
|
|
||||||
unsigned a = ((out >> (1 * 2)) & 3);
|
|
||||||
unsigned b = ((out >> (7 * 2)) & 3);
|
|
||||||
unsigned c = ((out >> (8 * 2)) & 3);
|
|
||||||
unsigned con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
|
||||||
|
|
||||||
//update pixel order
|
|
||||||
unsigned m, n;
|
|
||||||
for(m = 0; m < 4; m++) if(pixelorder[m] == a) break;
|
|
||||||
for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1];
|
|
||||||
pixelorder[0] = a;
|
|
||||||
|
|
||||||
//calculate the real pixel order
|
|
||||||
for(m = 0; m < 4; m++) realorder[m] = pixelorder[m];
|
|
||||||
|
|
||||||
//rotate reference pixel c value to top
|
|
||||||
for(m = 0; m < 4; m++) if(realorder[m] == c) break;
|
|
||||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
|
||||||
realorder[0] = c;
|
|
||||||
|
|
||||||
//rotate reference pixel b value to top
|
|
||||||
for(m = 0; m < 4; m++) if(realorder[m] == b) break;
|
|
||||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
|
||||||
realorder[0] = b;
|
|
||||||
|
|
||||||
//rotate reference pixel a value to top
|
|
||||||
for(m = 0; m < 4; m++) if(realorder[m] == a) break;
|
|
||||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
|
||||||
realorder[0] = a;
|
|
||||||
|
|
||||||
//get 2 symbols
|
|
||||||
for(unsigned bit = 0; bit < 2; bit++) {
|
|
||||||
//get prob
|
|
||||||
unsigned prob = probability(con);
|
|
||||||
|
|
||||||
//get symbol
|
|
||||||
unsigned flag_lps;
|
|
||||||
if(val <= span - prob) { //mps
|
|
||||||
span = span - prob;
|
|
||||||
flag_lps = 0;
|
|
||||||
} else { //lps
|
|
||||||
val = val - (span - (prob - 1));
|
|
||||||
span = prob - 1;
|
|
||||||
flag_lps = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//renormalize
|
|
||||||
unsigned shift = 0;
|
|
||||||
while(span < 0x7f) {
|
|
||||||
shift++;
|
|
||||||
|
|
||||||
span = (span << 1) + 1;
|
|
||||||
val = (val << 1) + (in >> 7);
|
|
||||||
|
|
||||||
in <<= 1;
|
|
||||||
if(--in_count == 0) {
|
|
||||||
in = datarom_read(dcu_addr++);
|
|
||||||
in_count = 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//update processing info
|
|
||||||
lps = (lps << 1) + flag_lps;
|
|
||||||
inverts = (inverts << 1) + context[con].invert;
|
|
||||||
|
|
||||||
//update context state
|
|
||||||
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
|
||||||
if(flag_lps) context[con].index = next_lps(con);
|
|
||||||
else if(shift) context[con].index = next_mps(con);
|
|
||||||
|
|
||||||
//get next context
|
|
||||||
con = 5 + (con << 1) + ((lps ^ inverts) & 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//get pixel
|
|
||||||
b = realorder[(lps ^ inverts) & 3];
|
|
||||||
out = (out << 2) + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
//turn pixel data into bitplanes
|
|
||||||
unsigned data = deinterleave_2x8(out);
|
|
||||||
dcu_tiledata[dcu_dp + row * 2 + 0] = data >> 8;
|
|
||||||
dcu_tiledata[dcu_dp + row * 2 + 1] = data >> 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPC7110::decompress_4bpp(bool init) {
|
|
||||||
static int pixelorder[16], realorder[16];
|
|
||||||
static uint8 in, val, span;
|
|
||||||
static int out0, out1, inverts, lps, in_count;
|
|
||||||
|
|
||||||
if(init == true) {
|
|
||||||
for(unsigned i = 0; i < 16; i++) pixelorder[i] = i;
|
|
||||||
out0 = out1 = inverts = lps = 0;
|
|
||||||
span = 0xff;
|
|
||||||
val = datarom_read(dcu_addr++);
|
|
||||||
in = datarom_read(dcu_addr++);
|
|
||||||
in_count = 8;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unsigned row = 0; row < 8; row++) {
|
|
||||||
for(unsigned pixel = 0; pixel < 8; pixel++) {
|
|
||||||
//get first symbol context
|
|
||||||
unsigned a = ((out0 >> (0 * 4)) & 15);
|
|
||||||
unsigned b = ((out0 >> (7 * 4)) & 15);
|
|
||||||
unsigned c = ((out1 >> (0 * 4)) & 15);
|
|
||||||
unsigned con = 0;
|
|
||||||
unsigned refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
|
||||||
|
|
||||||
//update pixel order
|
|
||||||
unsigned m, n;
|
|
||||||
for(m = 0; m < 16; m++) if(pixelorder[m] == a) break;
|
|
||||||
for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1];
|
|
||||||
pixelorder[0] = a;
|
|
||||||
|
|
||||||
//calculate the real pixel order
|
|
||||||
for(m = 0; m < 16; m++) realorder[m] = pixelorder[m];
|
|
||||||
|
|
||||||
//rotate reference pixel c value to top
|
|
||||||
for(m = 0; m < 16; m++) if(realorder[m] == c) break;
|
|
||||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
|
||||||
realorder[0] = c;
|
|
||||||
|
|
||||||
//rotate reference pixel b value to top
|
|
||||||
for(m = 0; m < 16; m++) if(realorder[m] == b) break;
|
|
||||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
|
||||||
realorder[0] = b;
|
|
||||||
|
|
||||||
//rotate reference pixel a value to top
|
|
||||||
for(m = 0; m < 16; m++) if(realorder[m] == a) break;
|
|
||||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
|
||||||
realorder[0] = a;
|
|
||||||
|
|
||||||
//get 4 symbols
|
|
||||||
for(unsigned bit = 0; bit < 4; bit++) {
|
|
||||||
//get prob
|
|
||||||
unsigned prob = probability(con);
|
|
||||||
|
|
||||||
//get symbol
|
|
||||||
unsigned flag_lps;
|
|
||||||
if(val <= span - prob) { //mps
|
|
||||||
span = span - prob;
|
|
||||||
flag_lps = 0;
|
|
||||||
} else { //lps
|
|
||||||
val = val - (span - (prob - 1));
|
|
||||||
span = prob - 1;
|
|
||||||
flag_lps = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//renormalize
|
|
||||||
unsigned shift = 0;
|
|
||||||
while(span < 0x7f) {
|
|
||||||
shift++;
|
|
||||||
|
|
||||||
span = (span << 1) + 1;
|
|
||||||
val = (val << 1) + (in >> 7);
|
|
||||||
|
|
||||||
in <<= 1;
|
|
||||||
if(--in_count == 0) {
|
|
||||||
in = datarom_read(dcu_addr++);
|
|
||||||
in_count = 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//update processing info
|
|
||||||
lps = (lps << 1) + flag_lps;
|
|
||||||
unsigned invertbit = context[con].invert;
|
|
||||||
inverts = (inverts << 1) + invertbit;
|
|
||||||
|
|
||||||
//update context state
|
|
||||||
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
|
||||||
if(flag_lps) context[con].index = next_lps(con);
|
|
||||||
else if(shift) context[con].index = next_mps(con);
|
|
||||||
|
|
||||||
//get next context
|
|
||||||
con = context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//get pixel
|
|
||||||
b = realorder[(lps ^ inverts) & 0x0f];
|
|
||||||
out1 = (out1 << 4) + ((out0 >> 28) & 0x0f);
|
|
||||||
out0 = (out0 << 4) + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
//convert pixel data into bitplanes
|
|
||||||
unsigned data = deinterleave_4x8(out0);
|
|
||||||
dcu_tiledata[dcu_dp + row * 2 + 0] = data >> 24;
|
|
||||||
dcu_tiledata[dcu_dp + row * 2 + 1] = data >> 16;
|
|
||||||
dcu_tiledata[dcu_dp + row * 2 + 16] = data >> 8;
|
|
||||||
dcu_tiledata[dcu_dp + row * 2 + 17] = data >> 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
|
/*
|
||||||
void SPC7110::deinterleave_1bpp(unsigned length) {
|
void SPC7110::deinterleave_1bpp(unsigned length) {
|
||||||
uint8 *target = dcu_output, *source = dcu_tiledata;
|
uint8 *target = dcu_output, *source = dcu_tiledata;
|
||||||
for(unsigned row = 0, sp = 0; row < 8; row++) {
|
for(unsigned row = 0, sp = 0; row < 8; row++) {
|
||||||
|
@ -362,137 +80,4 @@ void SPC7110::deinterleave_4bpp(unsigned length) {
|
||||||
sp = sp + 2 * length + 16 * ((sp + 2 * length) / 16 - sp / 16);
|
sp = sp + 2 * length + 16 * ((sp + 2 * length) / 16 - sp / 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//
|
|
||||||
|
|
||||||
uint8 SPC7110::probability (unsigned n) { return evolution_table[context[n].index][0]; }
|
|
||||||
uint8 SPC7110::next_lps (unsigned n) { return evolution_table[context[n].index][1]; }
|
|
||||||
uint8 SPC7110::next_mps (unsigned n) { return evolution_table[context[n].index][2]; }
|
|
||||||
bool SPC7110::toggle_invert(unsigned n) { return evolution_table[context[n].index][3]; }
|
|
||||||
|
|
||||||
unsigned SPC7110::deinterleave_2x8(unsigned data) {
|
|
||||||
//reverse morton lookup: de-interleave two 8-bit values
|
|
||||||
//15, 13, 11, 9, 7, 5, 3, 1 -> 15- 8
|
|
||||||
//14, 12, 10, 8, 6, 4, 2, 0 -> 7- 0
|
|
||||||
unsigned result = 0;
|
|
||||||
for(unsigned mask = 1u << 15; mask; mask >>= 2) result = (result << 1) | (bool)(data & mask);
|
|
||||||
for(unsigned mask = 1u << 14; mask; mask >>= 2) result = (result << 1) | (bool)(data & mask);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned SPC7110::deinterleave_4x8(unsigned data) {
|
|
||||||
//reverse morton lookup: de-interleave four 8-bit values
|
|
||||||
//31, 27, 23, 19, 15, 11, 7, 3 -> 31-24
|
|
||||||
//30, 26, 22, 18, 14, 10, 6, 2 -> 23-16
|
|
||||||
//29, 25, 21, 17, 13, 9, 5, 1 -> 15- 8
|
|
||||||
//28, 24, 20, 16, 12, 8, 4, 0 -> 7- 0
|
|
||||||
unsigned result = 0;
|
|
||||||
for(unsigned mask = 1u << 31; mask; mask >>= 4) result = (result << 1) | (bool)(data & mask);
|
|
||||||
for(unsigned mask = 1u << 30; mask; mask >>= 4) result = (result << 1) | (bool)(data & mask);
|
|
||||||
for(unsigned mask = 1u << 29; mask; mask >>= 4) result = (result << 1) | (bool)(data & mask);
|
|
||||||
for(unsigned mask = 1u << 28; mask; mask >>= 4) result = (result << 1) | (bool)(data & mask);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8 SPC7110::evolution_table[53][4] = {
|
|
||||||
//{prob, nextlps, nextmps, toggle invert},
|
|
||||||
|
|
||||||
{0x5a, 1, 1, 1},
|
|
||||||
{0x25, 6, 2, 0},
|
|
||||||
{0x11, 8, 3, 0},
|
|
||||||
{0x08, 10, 4, 0},
|
|
||||||
{0x03, 12, 5, 0},
|
|
||||||
{0x01, 15, 5, 0},
|
|
||||||
|
|
||||||
{0x5a, 7, 7, 1},
|
|
||||||
{0x3f, 19, 8, 0},
|
|
||||||
{0x2c, 21, 9, 0},
|
|
||||||
{0x20, 22, 10, 0},
|
|
||||||
{0x17, 23, 11, 0},
|
|
||||||
{0x11, 25, 12, 0},
|
|
||||||
{0x0c, 26, 13, 0},
|
|
||||||
{0x09, 28, 14, 0},
|
|
||||||
{0x07, 29, 15, 0},
|
|
||||||
{0x05, 31, 16, 0},
|
|
||||||
{0x04, 32, 17, 0},
|
|
||||||
{0x03, 34, 18, 0},
|
|
||||||
{0x02, 35, 5, 0},
|
|
||||||
|
|
||||||
{0x5a, 20, 20, 1},
|
|
||||||
{0x48, 39, 21, 0},
|
|
||||||
{0x3a, 40, 22, 0},
|
|
||||||
{0x2e, 42, 23, 0},
|
|
||||||
{0x26, 44, 24, 0},
|
|
||||||
{0x1f, 45, 25, 0},
|
|
||||||
{0x19, 46, 26, 0},
|
|
||||||
{0x15, 25, 27, 0},
|
|
||||||
{0x11, 26, 28, 0},
|
|
||||||
{0x0e, 26, 29, 0},
|
|
||||||
{0x0b, 27, 30, 0},
|
|
||||||
{0x09, 28, 31, 0},
|
|
||||||
{0x08, 29, 32, 0},
|
|
||||||
{0x07, 30, 33, 0},
|
|
||||||
{0x05, 31, 34, 0},
|
|
||||||
{0x04, 33, 35, 0},
|
|
||||||
{0x04, 33, 36, 0},
|
|
||||||
{0x03, 34, 37, 0},
|
|
||||||
{0x02, 35, 38, 0},
|
|
||||||
{0x02, 36, 5, 0},
|
|
||||||
|
|
||||||
{0x58, 39, 40, 1},
|
|
||||||
{0x4d, 47, 41, 0},
|
|
||||||
{0x43, 48, 42, 0},
|
|
||||||
{0x3b, 49, 43, 0},
|
|
||||||
{0x34, 50, 44, 0},
|
|
||||||
{0x2e, 51, 45, 0},
|
|
||||||
{0x29, 44, 46, 0},
|
|
||||||
{0x25, 45, 24, 0},
|
|
||||||
|
|
||||||
{0x56, 47, 48, 1},
|
|
||||||
{0x4f, 47, 49, 0},
|
|
||||||
{0x47, 48, 50, 0},
|
|
||||||
{0x41, 49, 51, 0},
|
|
||||||
{0x3c, 50, 52, 0},
|
|
||||||
{0x37, 51, 43, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint8 SPC7110::context_table[32][2] = {
|
|
||||||
//{next 0, next 1},
|
|
||||||
|
|
||||||
{ 1, 2},
|
|
||||||
|
|
||||||
{ 3, 8},
|
|
||||||
{13, 14},
|
|
||||||
|
|
||||||
{15, 16},
|
|
||||||
{17, 18},
|
|
||||||
{19, 20},
|
|
||||||
{21, 22},
|
|
||||||
{23, 24},
|
|
||||||
{25, 26},
|
|
||||||
{25, 26},
|
|
||||||
{25, 26},
|
|
||||||
{25, 26},
|
|
||||||
{25, 26},
|
|
||||||
{27, 28},
|
|
||||||
{29, 30},
|
|
||||||
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
{31, 31},
|
|
||||||
|
|
||||||
{31, 31},
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
//SPC7110 decompressor
|
||||||
|
//original implementation: neviksti
|
||||||
|
//optimized implementation: cydrak
|
||||||
|
|
||||||
|
struct Decompressor {
|
||||||
|
SPC7110 &spc7110;
|
||||||
|
|
||||||
|
Decompressor(SPC7110 &spc7110) : spc7110(spc7110) {}
|
||||||
|
|
||||||
|
uint8 input() {
|
||||||
|
return spc7110.datarom_read(offset++);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 output() {
|
||||||
|
if(cursor == 0) decompress();
|
||||||
|
uint8 data = tile[cursor++];
|
||||||
|
cursor &= 8 * bpp - 1;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 deinterleave(uint64 data, unsigned bits) {
|
||||||
|
data = data & (1ull << bits) - 1;
|
||||||
|
data = 0x5555555555555555ull & (data << bits | data >> 1);
|
||||||
|
data = 0x3333333333333333ull & (data | data >> 1);
|
||||||
|
data = 0x0f0f0f0f0f0f0f0full & (data | data >> 2);
|
||||||
|
data = 0x00ff00ff00ff00ffull & (data | data >> 4);
|
||||||
|
data = 0x0000ffff0000ffffull & (data | data >> 8);
|
||||||
|
return data | data >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 moveToFront(uint64 list, unsigned nibble) {
|
||||||
|
for(uint64 n = 0, mask = ~15; n < 64; n += 4, mask <<= 4) {
|
||||||
|
if((list >> n & 15) != nibble) continue;
|
||||||
|
return list = (list & mask) + (list << 4 & ~mask) + nibble;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(unsigned mode, unsigned origin) {
|
||||||
|
for(auto &root : context) for(auto &node : root) node = {0, 0};
|
||||||
|
base = 0;
|
||||||
|
range = Max + 1;
|
||||||
|
bpp = 1 << mode;
|
||||||
|
offset = origin;
|
||||||
|
cursor = 0;
|
||||||
|
bits = 8;
|
||||||
|
read = input();
|
||||||
|
read = read << 8 | input();
|
||||||
|
write = 0;
|
||||||
|
pixels = 0;
|
||||||
|
colormap = 0xfedcba9876543210ull;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decompress() {
|
||||||
|
for(unsigned row = 0; row < 8; row++) {
|
||||||
|
for(unsigned pixel = 0; pixel < 8; pixel++) {
|
||||||
|
uint64 map = colormap;
|
||||||
|
unsigned diff = 0;
|
||||||
|
|
||||||
|
if(bpp > 1) {
|
||||||
|
unsigned pa = (bpp == 2 ? pixels >> 2 & 3 : pixels >> 0 & 15);
|
||||||
|
unsigned pb = (bpp == 2 ? pixels >> 14 & 3 : pixels >> 28 & 15);
|
||||||
|
unsigned pc = (bpp == 2 ? pixels >> 16 & 3 : pixels >> 32 & 15);
|
||||||
|
|
||||||
|
if(pa != pb || pb != pc) {
|
||||||
|
unsigned match = pa ^ pb ^ pc;
|
||||||
|
diff = 4;
|
||||||
|
if((match ^ pc) == 0) diff = 3;
|
||||||
|
if((match ^ pb) == 0) diff = 2;
|
||||||
|
if((match ^ pa) == 0) diff = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
colormap = moveToFront(colormap, pa);
|
||||||
|
|
||||||
|
map = moveToFront(map, pc);
|
||||||
|
map = moveToFront(map, pb);
|
||||||
|
map = moveToFront(map, pa);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(unsigned plane = 0; plane < bpp; plane++) {
|
||||||
|
unsigned bit = bpp > 1 ? 1 << plane : 1 << (pixel & 3);
|
||||||
|
unsigned history = bit - 1 & write;
|
||||||
|
unsigned set = 0;
|
||||||
|
|
||||||
|
if(bpp == 1) set = pixel >= 4;
|
||||||
|
if(bpp == 2) set = diff;
|
||||||
|
if(plane >= 2 && history <= 1) set = diff;
|
||||||
|
|
||||||
|
auto &ctx = context[set][bit + history - 1];
|
||||||
|
auto &model = evolution[ctx.prediction];
|
||||||
|
uint8 lps_offset = range - model.probability;
|
||||||
|
bool symbol = read >= (lps_offset << 8);
|
||||||
|
|
||||||
|
write = write << 1 | (symbol ^ ctx.swap);
|
||||||
|
|
||||||
|
if(symbol == MPS) {
|
||||||
|
range = lps_offset;
|
||||||
|
} else {
|
||||||
|
range -= lps_offset;
|
||||||
|
read -= lps_offset << 8;
|
||||||
|
base += lps_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(range <= Max / 2) {
|
||||||
|
ctx.prediction = model.next[symbol];
|
||||||
|
|
||||||
|
range <<= 1;
|
||||||
|
read <<= 1;
|
||||||
|
base <<= 1;
|
||||||
|
|
||||||
|
if(--bits == 0) {
|
||||||
|
bits = 8;
|
||||||
|
read += input();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(symbol == LPS && model.probability > Half) ctx.swap ^= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned index = write & (1 << bpp) - 1;
|
||||||
|
if(bpp == 1) index ^= pixels >> 15 & 1;
|
||||||
|
|
||||||
|
pixels = pixels << bpp | (map >> 4 * index & 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bpp == 1) {
|
||||||
|
tile[row] = pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bpp == 2) {
|
||||||
|
uint32 slice = deinterleave(pixels, 16);
|
||||||
|
tile[row * 2 + 0] = slice >> 0;
|
||||||
|
tile[row * 2 + 1] = slice >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bpp == 4) {
|
||||||
|
uint32 slice = deinterleave(deinterleave(pixels, 32), 32);
|
||||||
|
tile[row * 2 + 0x00] = slice >> 0;
|
||||||
|
tile[row * 2 + 0x01] = slice >> 8;
|
||||||
|
tile[row * 2 + 0x10] = slice >> 16;
|
||||||
|
tile[row * 2 + 0x11] = slice >> 24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void serialize(serializer &s) {
|
||||||
|
for(auto &root : context) {
|
||||||
|
for(auto &node : root) {
|
||||||
|
s.integer(node.prediction);
|
||||||
|
s.integer(node.swap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.integer(base);
|
||||||
|
s.integer(range);
|
||||||
|
s.integer(bpp);
|
||||||
|
s.integer(offset);
|
||||||
|
s.integer(cursor);
|
||||||
|
s.integer(bits);
|
||||||
|
s.integer(read);
|
||||||
|
s.integer(write);
|
||||||
|
s.integer(pixels);
|
||||||
|
s.integer(colormap);
|
||||||
|
s.array(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum : unsigned { MPS = 0, LPS = 1 };
|
||||||
|
enum : unsigned { One = 0xaa, Half = 0x55, Max = 0xff };
|
||||||
|
|
||||||
|
struct ModelState {
|
||||||
|
uint8 probability;
|
||||||
|
uint8 next[2];
|
||||||
|
};
|
||||||
|
static ModelState evolution[53];
|
||||||
|
|
||||||
|
struct Context {
|
||||||
|
uint8 prediction;
|
||||||
|
uint8 swap;
|
||||||
|
} context[5][15];
|
||||||
|
|
||||||
|
uint8 base;
|
||||||
|
uint16 range;
|
||||||
|
unsigned bpp;
|
||||||
|
unsigned offset;
|
||||||
|
unsigned cursor;
|
||||||
|
unsigned bits;
|
||||||
|
uint16 read;
|
||||||
|
uint8 write;
|
||||||
|
uint64 pixels;
|
||||||
|
uint64 colormap;
|
||||||
|
uint8 tile[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
Decompressor::ModelState Decompressor::evolution[53] = {
|
||||||
|
{0x5a, { 1, 1}}, {0x25, { 2, 6}}, {0x11, { 3, 8}},
|
||||||
|
{0x08, { 4,10}}, {0x03, { 5,12}}, {0x01, { 5,15}},
|
||||||
|
|
||||||
|
{0x5a, { 7, 7}}, {0x3f, { 8,19}}, {0x2c, { 9,21}},
|
||||||
|
{0x20, {10,22}}, {0x17, {11,23}}, {0x11, {12,25}},
|
||||||
|
{0x0c, {13,26}}, {0x09, {14,28}}, {0x07, {15,29}},
|
||||||
|
{0x05, {16,31}}, {0x04, {17,32}}, {0x03, {18,34}},
|
||||||
|
{0x02, { 5,35}},
|
||||||
|
|
||||||
|
{0x5a, {20,20}}, {0x48, {21,39}}, {0x3a, {22,40}},
|
||||||
|
{0x2e, {23,42}}, {0x26, {24,44}}, {0x1f, {25,45}},
|
||||||
|
{0x19, {26,46}}, {0x15, {27,25}}, {0x11, {28,26}},
|
||||||
|
{0x0e, {29,26}}, {0x0b, {30,27}}, {0x09, {31,28}},
|
||||||
|
{0x08, {32,29}}, {0x07, {33,30}}, {0x05, {34,31}},
|
||||||
|
{0x04, {35,33}}, {0x04, {36,33}}, {0x03, {37,34}},
|
||||||
|
{0x02, {38,35}}, {0x02, { 5,36}},
|
||||||
|
|
||||||
|
{0x58, {40,39}}, {0x4d, {41,47}}, {0x43, {42,48}},
|
||||||
|
{0x3b, {43,49}}, {0x34, {44,50}}, {0x2e, {45,51}},
|
||||||
|
{0x29, {46,44}}, {0x25, {24,45}},
|
||||||
|
|
||||||
|
{0x56, {48,47}}, {0x4f, {49,47}}, {0x47, {50,48}},
|
||||||
|
{0x41, {51,49}}, {0x3c, {52,50}}, {0x37, {43,51}},
|
||||||
|
};
|
|
@ -13,17 +13,10 @@ void SPC7110::serialize(serializer &s) {
|
||||||
s.integer(r480b);
|
s.integer(r480b);
|
||||||
s.integer(r480c);
|
s.integer(r480c);
|
||||||
|
|
||||||
|
s.integer(dcu_pending);
|
||||||
s.integer(dcu_mode);
|
s.integer(dcu_mode);
|
||||||
s.integer(dcu_addr);
|
s.integer(dcu_addr);
|
||||||
s.integer(dcu_sp);
|
decompressor->serialize(s);
|
||||||
s.integer(dcu_dp);
|
|
||||||
|
|
||||||
s.array(dcu_output);
|
|
||||||
|
|
||||||
for(auto &ctx : context) {
|
|
||||||
s.integer(ctx.index);
|
|
||||||
s.integer(ctx.invert);
|
|
||||||
}
|
|
||||||
|
|
||||||
s.integer(r4810);
|
s.integer(r4810);
|
||||||
s.integer(r4811);
|
s.integer(r4811);
|
||||||
|
@ -53,8 +46,8 @@ void SPC7110::serialize(serializer &s) {
|
||||||
s.integer(r482e);
|
s.integer(r482e);
|
||||||
s.integer(r482f);
|
s.integer(r482f);
|
||||||
|
|
||||||
s.integer(mul_wait);
|
s.integer(mul_pending);
|
||||||
s.integer(div_wait);
|
s.integer(div_pending);
|
||||||
|
|
||||||
s.integer(r4830);
|
s.integer(r4830);
|
||||||
s.integer(r4831);
|
s.integer(r4831);
|
||||||
|
|
|
@ -9,6 +9,14 @@ namespace SuperFamicom {
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
SPC7110 spc7110;
|
SPC7110 spc7110;
|
||||||
|
|
||||||
|
SPC7110::SPC7110() {
|
||||||
|
decompressor = new Decompressor(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPC7110::~SPC7110() {
|
||||||
|
delete decompressor;
|
||||||
|
}
|
||||||
|
|
||||||
void SPC7110::Enter() { spc7110.enter(); }
|
void SPC7110::Enter() { spc7110.enter(); }
|
||||||
|
|
||||||
void SPC7110::enter() {
|
void SPC7110::enter() {
|
||||||
|
@ -17,14 +25,19 @@ void SPC7110::enter() {
|
||||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mul_wait) { if(--mul_wait == 0) alu_multiply(); }
|
if(dcu_pending) { dcu_pending = 0; dcu_begin_transfer(); }
|
||||||
if(div_wait) { if(--div_wait == 0) alu_divide(); }
|
if(mul_pending) { mul_pending = 0; alu_multiply(); }
|
||||||
|
if(div_pending) { div_pending = 0; alu_divide(); }
|
||||||
|
|
||||||
step(1);
|
add_clocks(1);
|
||||||
synchronize_cpu();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SPC7110::add_clocks(unsigned clocks) {
|
||||||
|
step(clocks);
|
||||||
|
synchronize_cpu();
|
||||||
|
}
|
||||||
|
|
||||||
void SPC7110::init() {
|
void SPC7110::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +51,7 @@ void SPC7110::power() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPC7110::reset() {
|
void SPC7110::reset() {
|
||||||
create(SPC7110::Enter, 32768 * 128);
|
create(SPC7110::Enter, 21477272);
|
||||||
|
|
||||||
r4801 = 0x00;
|
r4801 = 0x00;
|
||||||
r4802 = 0x00;
|
r4802 = 0x00;
|
||||||
|
@ -52,10 +65,9 @@ void SPC7110::reset() {
|
||||||
r480b = 0x00;
|
r480b = 0x00;
|
||||||
r480c = 0x00;
|
r480c = 0x00;
|
||||||
|
|
||||||
|
dcu_pending = 0;
|
||||||
dcu_mode = 0;
|
dcu_mode = 0;
|
||||||
dcu_addr = 0;
|
dcu_addr = 0;
|
||||||
dcu_sp = 0;
|
|
||||||
dcu_dp = 0;
|
|
||||||
|
|
||||||
r4810 = 0x00;
|
r4810 = 0x00;
|
||||||
r4811 = 0x00;
|
r4811 = 0x00;
|
||||||
|
@ -85,8 +97,8 @@ void SPC7110::reset() {
|
||||||
r482e = 0x00;
|
r482e = 0x00;
|
||||||
r482f = 0x00;
|
r482f = 0x00;
|
||||||
|
|
||||||
mul_wait = 0;
|
mul_pending = 0;
|
||||||
div_wait = 0;
|
div_pending = 0;
|
||||||
|
|
||||||
r4830 = 0x00;
|
r4830 = 0x00;
|
||||||
r4831 = 0x00;
|
r4831 = 0x00;
|
||||||
|
@ -123,11 +135,7 @@ uint8 SPC7110::mmio_read(unsigned addr) {
|
||||||
case 0x4809: return r4809;
|
case 0x4809: return r4809;
|
||||||
case 0x480a: return r480a;
|
case 0x480a: return r480a;
|
||||||
case 0x480b: return r480b;
|
case 0x480b: return r480b;
|
||||||
case 0x480c: {
|
case 0x480c: return r480c;
|
||||||
uint8 status = r480c;
|
|
||||||
r480c &= 0x7f;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============
|
//==============
|
||||||
//data port unit
|
//data port unit
|
||||||
|
@ -136,7 +144,6 @@ uint8 SPC7110::mmio_read(unsigned addr) {
|
||||||
case 0x4810: {
|
case 0x4810: {
|
||||||
uint8 data = r4810;
|
uint8 data = r4810;
|
||||||
data_port_increment_4810();
|
data_port_increment_4810();
|
||||||
data_port_read();
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
case 0x4811: return r4811;
|
case 0x4811: return r4811;
|
||||||
|
@ -200,10 +207,10 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||||
|
|
||||||
case 0x4801: r4801 = data; break;
|
case 0x4801: r4801 = data; break;
|
||||||
case 0x4802: r4802 = data; break;
|
case 0x4802: r4802 = data; break;
|
||||||
case 0x4803: r4803 = data & 0x7f; break;
|
case 0x4803: r4803 = data; break;
|
||||||
case 0x4804: r4804 = data; dcu_load_address(); break;
|
case 0x4804: r4804 = data; dcu_load_address(); break;
|
||||||
case 0x4805: r4805 = data; break;
|
case 0x4805: r4805 = data; break;
|
||||||
case 0x4806: r4806 = data; dcu_begin_transfer(); break;
|
case 0x4806: r4806 = data; r480c &= 0x7f; dcu_pending = 1; break;
|
||||||
case 0x4807: r4807 = data; break;
|
case 0x4807: r4807 = data; break;
|
||||||
case 0x4808: break;
|
case 0x4808: break;
|
||||||
case 0x4809: r4809 = data; break;
|
case 0x4809: r4809 = data; break;
|
||||||
|
@ -216,9 +223,9 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||||
|
|
||||||
case 0x4811: r4811 = data; break;
|
case 0x4811: r4811 = data; break;
|
||||||
case 0x4812: r4812 = data; break;
|
case 0x4812: r4812 = data; break;
|
||||||
case 0x4813: r4813 = data & 0x7f; data_port_read(); break;
|
case 0x4813: r4813 = data; data_port_read(); break;
|
||||||
case 0x4814: r4814 = data; data_port_increment_4814(); break;
|
case 0x4814: r4814 = data; data_port_increment_4814(); break;
|
||||||
case 0x4815: r4815 = data; data_port_increment_4815(); break;
|
case 0x4815: r4815 = data; if(r4818 & 2) data_port_read(); data_port_increment_4815(); break;
|
||||||
case 0x4816: r4816 = data; break;
|
case 0x4816: r4816 = data; break;
|
||||||
case 0x4817: r4817 = data; break;
|
case 0x4817: r4817 = data; break;
|
||||||
case 0x4818: r4818 = data & 0x7f; data_port_read(); break;
|
case 0x4818: r4818 = data & 0x7f; data_port_read(); break;
|
||||||
|
@ -232,9 +239,9 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||||
case 0x4822: r4822 = data; break;
|
case 0x4822: r4822 = data; break;
|
||||||
case 0x4823: r4823 = data; break;
|
case 0x4823: r4823 = data; break;
|
||||||
case 0x4824: r4824 = data; break;
|
case 0x4824: r4824 = data; break;
|
||||||
case 0x4825: r4825 = data; r482f |= 0x81; mul_wait = mul_delay; break;
|
case 0x4825: r4825 = data; r482f |= 0x81; mul_pending = 1; break;
|
||||||
case 0x4826: r4826 = data; break;
|
case 0x4826: r4826 = data; break;
|
||||||
case 0x4827: r4827 = data; r482f |= 0x80; div_wait = div_delay; break;
|
case 0x4827: r4827 = data; r482f |= 0x80; div_pending = 1; break;
|
||||||
case 0x482e: r482e = data & 0x01; break;
|
case 0x482e: r482e = data & 0x01; break;
|
||||||
|
|
||||||
//===================
|
//===================
|
||||||
|
@ -250,9 +257,6 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SPC7110::SPC7110() {
|
|
||||||
}
|
|
||||||
|
|
||||||
//============
|
//============
|
||||||
//SPC7110::DCU
|
//SPC7110::DCU
|
||||||
//============
|
//============
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
|
struct Decompressor;
|
||||||
|
|
||||||
struct SPC7110 : Coprocessor {
|
struct SPC7110 : Coprocessor {
|
||||||
unsigned prom_base, prom_size; //program ROM
|
unsigned prom_base, prom_size; //program ROM
|
||||||
unsigned drom_base, drom_size; //data ROM
|
unsigned drom_base, drom_size; //data ROM
|
||||||
|
|
||||||
uint4 rtcram[16];
|
|
||||||
|
|
||||||
enum : unsigned {
|
|
||||||
mul_delay = 6,
|
|
||||||
div_delay = 8,
|
|
||||||
rtc_delay = 20,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void Enter();
|
static void Enter();
|
||||||
void enter();
|
void enter();
|
||||||
void init();
|
void init();
|
||||||
|
@ -18,6 +12,8 @@ struct SPC7110 : Coprocessor {
|
||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
void add_clocks(unsigned clocks);
|
||||||
|
|
||||||
uint8 mmio_read(unsigned addr);
|
uint8 mmio_read(unsigned addr);
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
|
@ -32,28 +28,17 @@ struct SPC7110 : Coprocessor {
|
||||||
|
|
||||||
void serialize(serializer&);
|
void serialize(serializer&);
|
||||||
SPC7110();
|
SPC7110();
|
||||||
|
~SPC7110();
|
||||||
|
|
||||||
//dcu.cpp
|
//dcu.cpp
|
||||||
void dcu_load_address();
|
void dcu_load_address();
|
||||||
void dcu_begin_transfer();
|
void dcu_begin_transfer();
|
||||||
uint8 dcu_read();
|
uint8 dcu_read();
|
||||||
|
|
||||||
void decompress_1bpp(bool init = false);
|
|
||||||
void decompress_2bpp(bool init = false);
|
|
||||||
void decompress_4bpp(bool init = false);
|
|
||||||
|
|
||||||
void deinterleave_1bpp(unsigned length);
|
void deinterleave_1bpp(unsigned length);
|
||||||
void deinterleave_2bpp(unsigned length);
|
void deinterleave_2bpp(unsigned length);
|
||||||
void deinterleave_4bpp(unsigned length);
|
void deinterleave_4bpp(unsigned length);
|
||||||
|
|
||||||
uint8 probability(unsigned n);
|
|
||||||
uint8 next_lps(unsigned n);
|
|
||||||
uint8 next_mps(unsigned n);
|
|
||||||
bool toggle_invert(unsigned n);
|
|
||||||
|
|
||||||
unsigned deinterleave_2x8(unsigned data);
|
|
||||||
unsigned deinterleave_4x8(unsigned data);
|
|
||||||
|
|
||||||
//data.cpp
|
//data.cpp
|
||||||
uint8 datarom_read(unsigned addr);
|
uint8 datarom_read(unsigned addr);
|
||||||
|
|
||||||
|
@ -81,7 +66,7 @@ private:
|
||||||
//==================
|
//==================
|
||||||
uint8 r4801; //compression table B0
|
uint8 r4801; //compression table B0
|
||||||
uint8 r4802; //compression table B1
|
uint8 r4802; //compression table B1
|
||||||
uint8 r4803; //compression table B2
|
uint7 r4803; //compression table B2
|
||||||
uint8 r4804; //compression table index
|
uint8 r4804; //compression table index
|
||||||
uint8 r4805; //decompression buffer index B0
|
uint8 r4805; //decompression buffer index B0
|
||||||
uint8 r4806; //decompression buffer index B1
|
uint8 r4806; //decompression buffer index B1
|
||||||
|
@ -91,21 +76,10 @@ private:
|
||||||
uint8 r480b; //decompression settings
|
uint8 r480b; //decompression settings
|
||||||
uint8 r480c; //decompression status
|
uint8 r480c; //decompression status
|
||||||
|
|
||||||
|
bool dcu_pending;
|
||||||
uint2 dcu_mode;
|
uint2 dcu_mode;
|
||||||
uint23 dcu_addr;
|
uint23 dcu_addr;
|
||||||
unsigned dcu_sp;
|
Decompressor *decompressor;
|
||||||
unsigned dcu_dp;
|
|
||||||
|
|
||||||
uint8 dcu_output[32];
|
|
||||||
uint8 dcu_tiledata[256 * 32];
|
|
||||||
|
|
||||||
struct ContextState {
|
|
||||||
uint8 index;
|
|
||||||
uint8 invert;
|
|
||||||
} context[32];
|
|
||||||
|
|
||||||
static const uint8 evolution_table[53][4];
|
|
||||||
static const uint8 context_table[32][2];
|
|
||||||
|
|
||||||
//==============
|
//==============
|
||||||
//data port unit
|
//data port unit
|
||||||
|
@ -113,7 +87,7 @@ private:
|
||||||
uint8 r4810; //data port read + seek
|
uint8 r4810; //data port read + seek
|
||||||
uint8 r4811; //data offset B0
|
uint8 r4811; //data offset B0
|
||||||
uint8 r4812; //data offset B1
|
uint8 r4812; //data offset B1
|
||||||
uint8 r4813; //data offset B2
|
uint7 r4813; //data offset B2
|
||||||
uint8 r4814; //data adjust B0
|
uint8 r4814; //data adjust B0
|
||||||
uint8 r4815; //data adjust B1
|
uint8 r4815; //data adjust B1
|
||||||
uint8 r4816; //data stride B0
|
uint8 r4816; //data stride B0
|
||||||
|
@ -141,8 +115,8 @@ private:
|
||||||
uint8 r482e; //math settings
|
uint8 r482e; //math settings
|
||||||
uint8 r482f; //math status
|
uint8 r482f; //math status
|
||||||
|
|
||||||
unsigned mul_wait;
|
bool mul_pending;
|
||||||
unsigned div_wait;
|
bool div_pending;
|
||||||
|
|
||||||
//===================
|
//===================
|
||||||
//memory control unit
|
//memory control unit
|
||||||
|
|
|
@ -9,6 +9,10 @@ Emulator::Interface& system() {
|
||||||
return *application->active;
|
return *application->active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Application::focused() {
|
||||||
|
return config->input.focusAllow || presentation->focused();
|
||||||
|
}
|
||||||
|
|
||||||
string Application::path(const string &filename) {
|
string Application::path(const string &filename) {
|
||||||
string path = {basepath, filename};
|
string path = {basepath, filename};
|
||||||
if(file::exists(path)) return path;
|
if(file::exists(path)) return path;
|
||||||
|
|
|
@ -45,6 +45,7 @@ struct Application {
|
||||||
string titleFont;
|
string titleFont;
|
||||||
string monospaceFont;
|
string monospaceFont;
|
||||||
|
|
||||||
|
bool focused();
|
||||||
string path(const string &filename);
|
string path(const string &filename);
|
||||||
void commandLineLoad(string pathname);
|
void commandLineLoad(string pathname);
|
||||||
void run();
|
void run();
|
||||||
|
|
|
@ -78,6 +78,7 @@ bool DigitalInput::bind(unsigned scancode, int16_t value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t DigitalInput::poll() {
|
int16_t DigitalInput::poll() {
|
||||||
|
if(application->focused() == false) return 0;
|
||||||
bool result = logic;
|
bool result = logic;
|
||||||
|
|
||||||
for(auto &item : inputList) {
|
for(auto &item : inputList) {
|
||||||
|
@ -121,6 +122,7 @@ bool RelativeInput::bind(unsigned scancode, int16_t value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t RelativeInput::poll() {
|
int16_t RelativeInput::poll() {
|
||||||
|
if(application->focused() == false) return 0;
|
||||||
int16_t result = 0;
|
int16_t result = 0;
|
||||||
|
|
||||||
for(auto &item : inputList) {
|
for(auto &item : inputList) {
|
||||||
|
@ -160,6 +162,7 @@ bool AbsoluteInput::bind(unsigned scancode, int16_t value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t AbsoluteInput::poll() {
|
int16_t AbsoluteInput::poll() {
|
||||||
|
if(application->focused() == false) return -32768;
|
||||||
int16_t result = -32768; //offscreen value
|
int16_t result = -32768; //offscreen value
|
||||||
|
|
||||||
using nall::Mouse;
|
using nall::Mouse;
|
||||||
|
|
|
@ -103,7 +103,6 @@ void Interface::audioSample(int16_t lsample, int16_t rsample) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t Interface::inputPoll(unsigned port, unsigned device, unsigned input) {
|
int16_t Interface::inputPoll(unsigned port, unsigned device, unsigned input) {
|
||||||
if(config->input.focusAllow == false && presentation->focused() == false) return 0;
|
|
||||||
unsigned guid = system().port[port].device[device].input[input].guid;
|
unsigned guid = system().port[port].device[device].input[input].guid;
|
||||||
return inputManager->inputMap[guid]->poll();
|
return inputManager->inputMap[guid]->poll();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue