Update to v089r04 release.

byuu says:

Changelog: (SPC7110)
- emulated $480b.d0 + $4807 deinterleave mode
- cleaned up decompression core (I'd still like to wipe out those static
  variables, those are bad for save states.)
- improved emulation of data port ($481a only increments, never reads)
- improved emulation of RTC (block appropriate bits in the hour register
  based on 12/24h mode select; $4840 modes != 1 all disable the chip;
  added MDR; etc.)
This commit is contained in:
Tim Allen 2012-05-19 16:28:54 +10:00
parent 6ac7b733bd
commit 0611fefefa
8 changed files with 220 additions and 253 deletions

View File

@ -3,7 +3,7 @@
namespace Emulator {
static const char Name[] = "bsnes";
static const char Version[] = "089.03";
static const char Version[] = "089.04";
static const char Author[] = "byuu";
static const char License[] = "GPLv3";
}

View File

@ -18,7 +18,7 @@ unsigned SPC7110::data_increment() { return r4816 | r4817 << 8; }
void SPC7110::set_data_offset(unsigned addr) { r4811 = addr; r4812 = addr >> 8; r4813 = addr >> 16; }
void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8; }
void SPC7110::data_port_read_a() {
void SPC7110::data_port_read() {
unsigned offset = data_offset();
unsigned adjust = data_adjust();
if(r4818 & 8) adjust = (int16)adjust;
@ -26,18 +26,6 @@ void SPC7110::data_port_read_a() {
r4810 = datarom_read(offset);
}
void SPC7110::data_port_read_b() {
unsigned offset = data_offset();
unsigned adjust = data_adjust();
if(r4818 & 8) adjust = (int16)adjust;
r481a = datarom_read(offset + adjust);
}
void SPC7110::data_port_read() {
data_port_read_a();
data_port_read_b();
}
void SPC7110::data_port_increment_a() {
unsigned adjust = data_adjust();
if(r4818 & 8) adjust = (int16)adjust;
@ -61,7 +49,7 @@ void SPC7110::data_port_increment_b() {
if((r4818 & 16) != 0) set_data_adjust(adjust + adjust);
}
void SPC7110::data_port_increment() {
void SPC7110::data_port_increment_c() {
if((r4818 & 2) == 0) return;
if(r4818 & 16) return;

View File

@ -1,72 +1,72 @@
#ifdef SPC7110_CPP
void SPC7110::dcu_load_address() {
unsigned table = r4801 | r4802 << 8 | r4803 << 16;
unsigned index = r4804 << 2;
uint8 SPC7110::Decomp::read() {
if(decomp_buffer_length == 0) {
//decompress at least (decomp_buffer_size / 2) bytes to the buffer
switch(decomp_mode) {
case 0: mode0(false); break;
case 1: mode1(false); break;
case 2: mode2(false); break;
default: return 0x00;
unsigned addr = table + index;
dcu_mode = datarom_read(addr + 0);
dcu_addr = datarom_read(addr + 1) << 16;
dcu_addr |= datarom_read(addr + 2) << 8;
dcu_addr |= datarom_read(addr + 3) << 0;
}
void SPC7110::dcu_begin_transfer() {
switch(dcu_mode) {
case 0: decompress_1bpp(true); break;
case 1: decompress_2bpp(true); break;
case 2: decompress_4bpp(true); break;
case 3: return;
}
r480c |= 0x80;
dcu_sp = 0;
//reset context states
for(auto &ctx : context) {
ctx.index = 0;
ctx.invert = 0;
}
unsigned seek = (r4805 | r4806 << 8) << dcu_mode;
while(seek--) dcu_read();
}
uint8 SPC7110::dcu_read() {
unsigned tilesize = 8 << dcu_mode;
if(dcu_sp == 0) {
unsigned tiles = r480b & 1 ? r4807 : 1;
for(unsigned tile = 0; tile < tiles; tile++) {
dcu_dp = tile * tilesize;
switch(dcu_mode) {
case 0: decompress_1bpp(); deinterleave_1bpp(tiles); break;
case 1: decompress_2bpp(); deinterleave_2bpp(tiles); break;
case 2: decompress_4bpp(); deinterleave_4bpp(tiles); break;
case 3: return 0x00;
}
}
}
uint8 data = decomp_buffer[decomp_buffer_rdoffset++];
decomp_buffer_rdoffset &= decomp_buffer_size - 1;
decomp_buffer_length--;
uint8 data = dcu_output[dcu_sp++];
dcu_sp &= tilesize - 1;
return data;
}
void SPC7110::Decomp::write(uint8 data) {
decomp_buffer[decomp_buffer_wroffset++] = data;
decomp_buffer_wroffset &= decomp_buffer_size - 1;
decomp_buffer_length++;
}
uint8 SPC7110::Decomp::dataread() {
return spc7110.datarom_read(decomp_offset++);
}
void SPC7110::Decomp::init(unsigned mode, unsigned offset, unsigned index) {
decomp_mode = mode;
decomp_offset = offset;
decomp_buffer_rdoffset = 0;
decomp_buffer_wroffset = 0;
decomp_buffer_length = 0;
//reset context states
for(unsigned i = 0; i < 32; i++) {
context[i].index = 0;
context[i].invert = 0;
}
switch(decomp_mode) {
case 0: mode0(true); break;
case 1: mode1(true); break;
case 2: mode2(true); break;
}
//decompress up to requested output data index
while(index--) read();
}
//
void SPC7110::Decomp::mode0(bool init) {
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 = dataread();
in = dataread();
val = datarom_read(dcu_addr++);
in = datarom_read(dcu_addr++);
in_count = 8;
return;
}
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
for(unsigned row = 0; row < 8; row++) {
for(unsigned bit = 0; bit < 8; bit++) {
//get context
uint8 mask = (1 << (bit & 3)) - 1;
@ -100,7 +100,7 @@ void SPC7110::Decomp::mode0(bool init) {
in <<= 1;
if(--in_count == 0) {
in = dataread();
in = datarom_read(dcu_addr++);
in_count = 8;
}
}
@ -116,11 +116,11 @@ void SPC7110::Decomp::mode0(bool init) {
}
//save byte
write(out);
dcu_tiledata[dcu_dp + row] = out;
}
}
void SPC7110::Decomp::mode1(bool init) {
void SPC7110::decompress_2bpp(bool init) {
static int pixelorder[4], realorder[4];
static uint8 in, val, span;
static int out, inverts, lps, in_count;
@ -129,13 +129,13 @@ void SPC7110::Decomp::mode1(bool init) {
for(unsigned i = 0; i < 4; i++) pixelorder[i] = i;
out = inverts = lps = 0;
span = 0xff;
val = dataread();
in = dataread();
val = datarom_read(dcu_addr++);
in = datarom_read(dcu_addr++);
in_count = 8;
return;
}
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
for(unsigned row = 0; row < 8; row++) {
for(unsigned pixel = 0; pixel < 8; pixel++) {
//get first symbol context
unsigned a = ((out >> (1 * 2)) & 3);
@ -193,7 +193,7 @@ void SPC7110::Decomp::mode1(bool init) {
in <<= 1;
if(--in_count == 0) {
in = dataread();
in = datarom_read(dcu_addr++);
in_count = 8;
}
}
@ -218,29 +218,27 @@ void SPC7110::Decomp::mode1(bool init) {
//turn pixel data into bitplanes
unsigned data = deinterleave_2x8(out);
write(data >> 8);
write(data >> 0);
dcu_tiledata[dcu_dp + row * 2 + 0] = data >> 8;
dcu_tiledata[dcu_dp + row * 2 + 1] = data >> 0;
}
}
void SPC7110::Decomp::mode2(bool init) {
void SPC7110::decompress_4bpp(bool init) {
static int pixelorder[16], realorder[16];
static uint8 bitplanebuffer[16], buffer_index;
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;
buffer_index = 0;
out0 = out1 = inverts = lps = 0;
span = 0xff;
val = dataread();
in = dataread();
val = datarom_read(dcu_addr++);
in = datarom_read(dcu_addr++);
in_count = 8;
return;
}
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
for(unsigned row = 0; row < 8; row++) {
for(unsigned pixel = 0; pixel < 8; pixel++) {
//get first symbol context
unsigned a = ((out0 >> (0 * 4)) & 15);
@ -299,7 +297,7 @@ void SPC7110::Decomp::mode2(bool init) {
in <<= 1;
if(--in_count == 0) {
in = dataread();
in = datarom_read(dcu_addr++);
in_count = 8;
}
}
@ -315,7 +313,7 @@ void SPC7110::Decomp::mode2(bool init) {
else if(shift) context[con].index = next_mps(con);
//get next context
con = mode2_context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0);
con = context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0);
}
//get pixel
@ -326,21 +324,75 @@ void SPC7110::Decomp::mode2(bool init) {
//convert pixel data into bitplanes
unsigned data = deinterleave_4x8(out0);
write(data >> 24);
write(data >> 16);
bitplanebuffer[buffer_index++] = data >> 8;
bitplanebuffer[buffer_index++] = data >> 0;
if(buffer_index == 16) {
for(unsigned i = 0; i < 16; i++) write(bitplanebuffer[i]);
buffer_index = 0;
}
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;
}
}
//
const uint8 SPC7110::Decomp::evolution_table[53][4] = {
void SPC7110::deinterleave_1bpp(unsigned length) {
uint8 *target = dcu_output, *source = dcu_tiledata;
for(unsigned row = 0, sp = 0; row < 8; row++) {
target[row] = source[sp];
sp += length;
}
}
void SPC7110::deinterleave_2bpp(unsigned length) {
uint8 *target = dcu_output, *source = dcu_tiledata;
for(unsigned row = 0, sp = 0; row < 8; row++) {
target[row * 2 + 0] = source[sp + 0];
target[row * 2 + 1] = source[sp + 1];
sp += 2 * length;
}
}
void SPC7110::deinterleave_4bpp(unsigned length) {
uint8 *target = dcu_output, *source = dcu_tiledata;
for(unsigned row = 0, sp = 0; row < 8; row++) {
target[row * 2 + 0] = source[sp + 0];
target[row * 2 + 1] = source[sp + 1];
target[row * 2 + 16] = source[sp + 16];
target[row * 2 + 17] = source[sp + 17];
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},
@ -402,7 +454,7 @@ const uint8 SPC7110::Decomp::evolution_table[53][4] = {
{0x37, 51, 43, 0},
};
const uint8 SPC7110::Decomp::mode2_context_table[32][2] = {
const uint8 SPC7110::context_table[32][2] = {
//{next 0, next 1},
{ 1, 2},
@ -442,55 +494,3 @@ const uint8 SPC7110::Decomp::mode2_context_table[32][2] = {
{31, 31},
};
uint8 SPC7110::Decomp::probability (unsigned n) { return evolution_table[context[n].index][0]; }
uint8 SPC7110::Decomp::next_lps (unsigned n) { return evolution_table[context[n].index][1]; }
uint8 SPC7110::Decomp::next_mps (unsigned n) { return evolution_table[context[n].index][2]; }
bool SPC7110::Decomp::toggle_invert(unsigned n) { return evolution_table[context[n].index][3]; }
unsigned SPC7110::Decomp::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::Decomp::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;
}
//
void SPC7110::Decomp::reset() {
//mode 3 is invalid; this is treated as a special case to always return 0x00
//set to mode 3 so that reading decomp port before starting first decomp will return 0x00
decomp_mode = 3;
decomp_buffer_rdoffset = 0;
decomp_buffer_wroffset = 0;
decomp_buffer_length = 0;
}
SPC7110::Decomp::Decomp() {
decomp_buffer = new uint8_t[decomp_buffer_size];
reset();
}
SPC7110::Decomp::~Decomp() {
delete[] decomp_buffer;
}
#endif

View File

@ -1,43 +0,0 @@
struct Decomp {
uint8 read();
void init(unsigned mode, unsigned offset, unsigned index);
void reset();
void serialize(serializer&);
Decomp();
~Decomp();
private:
unsigned decomp_mode;
unsigned decomp_offset;
//read() will spool chunks half the size of decomp_buffer_size
enum { decomp_buffer_size = 64 }; //must be >= 64, and must be a power of two
uint8 *decomp_buffer;
unsigned decomp_buffer_rdoffset;
unsigned decomp_buffer_wroffset;
unsigned decomp_buffer_length;
void write(uint8 data);
uint8 dataread();
void mode0(bool init);
void mode1(bool init);
void mode2(bool init);
static const uint8 evolution_table[53][4];
static const uint8 mode2_context_table[32][2];
struct ContextState {
uint8 index;
uint8 invert;
} context[32];
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);
};

View File

@ -78,7 +78,10 @@ void SPC7110::rtc_write(uint4 addr, uint4 data) {
case 0x2: rtcram[0x2] = data; break;
case 0x3: rtcram[0x3] = data; break;
case 0x4: rtcram[0x4] = data; break;
case 0x5: rtcram[0x5] = data; break;
case 0x5:
if((rtcram[0xf] & 4) == 0) rtcram[0x5] = data & ~2; //12-hour mode cannot set D5
if((rtcram[0xf] & 4) != 0) rtcram[0x5] = data & ~4; //24-hour mode cannot set AM/PM
break;
case 0x6: rtcram[0x6] = data; break;
case 0x7: rtcram[0x7] = data; break;
case 0x8: rtcram[0x8] = data; break;

View File

@ -1,20 +1,5 @@
#ifdef SPC7110_CPP
void SPC7110::Decomp::serialize(serializer &s) {
s.integer(decomp_mode);
s.integer(decomp_offset);
s.array(decomp_buffer, decomp_buffer_size);
s.integer(decomp_buffer_rdoffset);
s.integer(decomp_buffer_wroffset);
s.integer(decomp_buffer_length);
for(unsigned n = 0; n < 32; n++) {
s.integer(context[n].index);
s.integer(context[n].invert);
}
}
void SPC7110::serialize(serializer &s) {
for(auto &byte : rtcram) s.integer(byte);
@ -25,13 +10,22 @@ void SPC7110::serialize(serializer &s) {
s.integer(r4805);
s.integer(r4806);
s.integer(r4807);
s.integer(r4808);
s.integer(r4809);
s.integer(r480a);
s.integer(r480b);
s.integer(r480c);
decomp.serialize(s);
s.integer(dcu_mode);
s.integer(dcu_addr);
s.integer(dcu_sp);
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(r4811);
@ -82,6 +76,7 @@ void SPC7110::serialize(serializer &s) {
s.integer(rtc_mode);
s.integer(rtc_addr);
s.integer(rtc_wait);
s.integer(rtc_mdr);
}
#endif

View File

@ -3,7 +3,7 @@
#define SPC7110_CPP
namespace SuperFamicom {
#include "decomp.cpp"
#include "dcu.cpp"
#include "data.cpp"
#include "alu.cpp"
#include "rtc.cpp"
@ -20,7 +20,7 @@ void SPC7110::enter() {
if(mul_wait) { if(--mul_wait == 0) alu_multiply(); }
if(div_wait) { if(--div_wait == 0) alu_divide(); }
if(rtc_wait) { if(--rtc_wait == 0) r4842 &= 0x7f; }
if(rtc_wait) { if(--rtc_wait == 0) r4842 |= 0x80; }
rtc_clocks++;
if((rtc_clocks & 0x7fff) == 0) rtc_duty(); //1/128th second
@ -65,13 +65,15 @@ void SPC7110::reset() {
r4805 = 0x00;
r4806 = 0x00;
r4807 = 0x00;
r4808 = 0x00;
r4809 = 0x00;
r480a = 0x00;
r480b = 0x00;
r480c = 0x00;
decomp.reset();
dcu_mode = 0;
dcu_addr = 0;
dcu_sp = 0;
dcu_dp = 0;
r4810 = 0x00;
r4811 = 0x00;
@ -122,6 +124,7 @@ void SPC7110::reset() {
rtc_mode = 0;
rtc_addr = 0;
rtc_wait = 0;
rtc_mdr = 0;
}
uint8 SPC7110::mmio_read(unsigned addr) {
@ -137,9 +140,9 @@ uint8 SPC7110::mmio_read(unsigned addr) {
case 0x4800: {
uint16 counter = r4809 | r480a << 8;
counter--;
r4809 = counter;
r4809 = counter >> 0;
r480a = counter >> 8;
return decomp.read();
return dcu_read();
}
case 0x4801: return r4801;
case 0x4802: return r4802;
@ -165,7 +168,7 @@ uint8 SPC7110::mmio_read(unsigned addr) {
case 0x4810: {
uint8 data = r4810;
data_port_increment_a();
data_port_read_a();
data_port_read();
return data;
}
case 0x4811: return r4811;
@ -177,10 +180,8 @@ uint8 SPC7110::mmio_read(unsigned addr) {
case 0x4817: return r4817;
case 0x4818: return r4818;
case 0x481a: {
uint8 data = r481a;
data_port_increment_b();
data_port_read_b();
return data;
return 0x00;
}
//=========
@ -220,8 +221,11 @@ uint8 SPC7110::mmio_read(unsigned addr) {
case 0x4840: return r4840;
case 0x4841: {
if((r4840 & 1) == 0) return 0x00; //RTC disabled?
if(rtc_mode != 2) return 0x00;
if(r4840 != 1) return 0x00; //RTC disabled?
if(r4842 == 0) return 0x00; //RTC busy?
if(rtc_mode != 2) return 0x00; //waiting for command or address?
if(r4841 == 0x03) return rtc_mdr; //in write mode?
if(r4841 != 0x0c) return 0x00; //not in read mode?
r4842 |= 0x80;
rtc_wait = rtc_delay;
return rtc_read(rtc_addr++);
@ -246,22 +250,9 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
case 0x4801: r4801 = data; break;
case 0x4802: r4802 = data; break;
case 0x4803: r4803 = data & 0x7f; break;
case 0x4804: r4804 = data; break;
case 0x4804: r4804 = data; dcu_load_address(); break;
case 0x4805: r4805 = data; break;
case 0x4806: r4806 = data; {
unsigned table = r4801 | r4802 << 8 | r4803 << 16;
unsigned index = r4804 << 2;
unsigned addr = table + index;
unsigned length = r4809 | r480a << 8;
unsigned mode = datarom_read(addr + 0);
unsigned offset = datarom_read(addr + 1) << 16
| datarom_read(addr + 2) << 8
| datarom_read(addr + 3) << 0;
decomp.init(mode, offset, (r4805 | r4806 << 8) << mode);
r480c = 0x80;
} break;
case 0x4806: r4806 = data; dcu_begin_transfer(); break;
case 0x4807: r4807 = data; break;
case 0x4808: break;
case 0x4809: r4809 = data; break;
@ -279,7 +270,7 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
case 0x4815: {
if((addr & 1) == 0) r4814 = data, r4814_latch = true;
if((addr & 1) == 1) r4815 = data, r4815_latch = true;
if(r4814_latch && r4815_latch) data_port_increment();
if(r4814_latch && r4815_latch) data_port_increment_c();
} break;
case 0x4816: r4816 = data; break;
case 0x4817: r4817 = data; break;
@ -317,32 +308,33 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
//====================
case 0x4840: r4840 = data & 0x03; {
if((r4840 & 1) == 0) rtc_reset();
if(r4840 != 1) rtc_reset();
r4842 |= 0x80;
rtc_wait = rtc_delay;
} break;
case 0x4841: {
if((r4840 & 1) == 0) break; //RTC disabled?
if(r4840 != 1) break; //RTC disabled?
if(r4842 == 0) break; //RTC busy?
r4842 |= 0x80;
rtc_wait = rtc_delay;
rtc_mdr = data;
if(rtc_mode == 0) {
r4841 = data & 0xf;
rtc_mode = 1;
rtc_addr = 0;
r4841 = rtc_mdr;
break;
}
if(rtc_mode == 1) {
rtc_mode = r4841 == 0x0c ? 2 : r4841 == 0x3 ? 3 : 0;
rtc_addr = data & 0xf;
rtc_mode = 2;
rtc_addr = rtc_mdr;
break;
}
if(rtc_mode == 3) {
rtc_write(rtc_addr++, data);
if(r4841 == 0x03) {
rtc_write(rtc_addr++, rtc_mdr);
break;
}
}

View File

@ -6,7 +6,7 @@ struct SPC7110 : Coprocessor {
enum : unsigned {
mul_delay = 6,
div_delay = 8,
rtc_delay = 24,
rtc_delay = 20,
};
static void Enter();
@ -32,6 +32,27 @@ struct SPC7110 : Coprocessor {
void serialize(serializer&);
SPC7110();
//dcu.cpp
void dcu_load_address();
void dcu_begin_transfer();
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_2bpp(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
uint8 datarom_read(unsigned addr);
@ -42,13 +63,11 @@ struct SPC7110 : Coprocessor {
void set_data_offset(unsigned addr);
void set_data_adjust(unsigned addr);
void data_port_read_a();
void data_port_read_b();
void data_port_read();
void data_port_increment_a();
void data_port_increment_b();
void data_port_increment();
void data_port_increment_c();
//alu.cpp
void alu_multiply();
@ -82,15 +101,27 @@ private:
uint8 r4804; //compression table index
uint8 r4805; //decompression buffer index low
uint8 r4806; //decompression buffer index high
uint8 r4807; //??? (used when $480b.d0 = 1)
uint8 r4808; //???
uint8 r4807; //deinterleave length
uint8 r4809; //compression length low
uint8 r480a; //compression length high
uint8 r480b; //decompression control register
uint8 r480b; //deinterleave enable
uint8 r480c; //decompression status
#include "decomp.hpp"
Decomp decomp;
uint2 dcu_mode;
uint23 dcu_addr;
unsigned dcu_sp;
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
@ -146,13 +177,14 @@ private:
//====================
uint8 r4840; //RTC enable
uint8 r4841; //RTC data port
uint8 r4842; //RTC status
uint8 r4842; //RTC status (d7 = ready)
uint22 rtc_clocks;
unsigned rtc_seconds;
uint2 rtc_mode; //0 = idle, 1 = seek, 2 = read, 3 = write
unsigned rtc_mode; //0 = command, 1 = index, 2 = read or write
uint4 rtc_addr;
unsigned rtc_wait;
uint4 rtc_mdr;
};
extern SPC7110 spc7110;