mirror of
https://github.com/libretro/snes9x2005.git
synced 2024-11-23 08:19:48 +00:00
Copied SPC7110 emulation from snes9x_3ds.
This commit is contained in:
parent
e18e3e55bb
commit
fdaf2925f1
@ -40,6 +40,7 @@ SOURCES_C := \
|
||||
$(CORE_DIR)/soundux.c \
|
||||
$(CORE_DIR)/spc700.c \
|
||||
$(CORE_DIR)/spc7110.c \
|
||||
$(CORE_DIR)/spc7110dec.c \
|
||||
$(CORE_DIR)/srtc.c \
|
||||
$(CORE_DIR)/tile.c \
|
||||
$(CORE_DIR)/apu_blargg.c \
|
||||
|
61
libretro.c
61
libretro.c
@ -340,7 +340,7 @@ void retro_init(void)
|
||||
void retro_deinit(void)
|
||||
{
|
||||
if (Settings.SPC7110)
|
||||
(*CleanUp7110)();
|
||||
Del7110Gfx();
|
||||
|
||||
S9xDeinitGFX();
|
||||
S9xDeinitDisplay();
|
||||
@ -499,50 +499,6 @@ void JustifierButtons(uint32_t* justifiers)
|
||||
{
|
||||
}
|
||||
|
||||
char* osd_GetPackDir()
|
||||
{
|
||||
static char filename[_MAX_PATH];
|
||||
memset(filename, 0, _MAX_PATH);
|
||||
|
||||
char dir [_MAX_DIR + 1];
|
||||
char drive [_MAX_DRIVE + 1];
|
||||
char name [_MAX_FNAME + 1];
|
||||
char ext [_MAX_EXT + 1];
|
||||
_splitpath(Memory.ROMFilename, drive, dir, name, ext);
|
||||
_makepath(filename, drive, dir, NULL, NULL);
|
||||
|
||||
if (!strncmp((char*)&Memory.ROM [0xffc0], "SUPER POWER LEAG 4 ", 21))
|
||||
{
|
||||
if (getenv("SPL4PACK"))
|
||||
return getenv("SPL4PACK");
|
||||
else
|
||||
strcat(filename, "/SPL4-SP7");
|
||||
}
|
||||
else if (!strncmp((char*)&Memory.ROM [0xffc0], "MOMOTETSU HAPPY ", 21))
|
||||
{
|
||||
if (getenv("MDHPACK"))
|
||||
return getenv("MDHPACK");
|
||||
else
|
||||
strcat(filename, "/SMHT-SP7");
|
||||
}
|
||||
else if (!strncmp((char*)&Memory.ROM [0xffc0], "HU TENGAI MAKYO ZERO ", 21))
|
||||
{
|
||||
if (getenv("FEOEZPACK"))
|
||||
return getenv("FEOEZPACK");
|
||||
else
|
||||
strcat(filename, "/FEOEZSP7");
|
||||
}
|
||||
else if (!strncmp((char*)&Memory.ROM [0xffc0], "JUMP TENGAIMAKYO ZERO", 21))
|
||||
{
|
||||
if (getenv("SJNSPACK"))
|
||||
return getenv("SJNSPACK");
|
||||
else
|
||||
strcat(filename, "/SJUMPSP7");
|
||||
}
|
||||
else strcat(filename, "/MISC-SP7");
|
||||
return filename;
|
||||
}
|
||||
|
||||
unsigned retro_get_region()
|
||||
{
|
||||
return Settings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC;
|
||||
@ -577,11 +533,9 @@ void retro_get_system_av_info(struct retro_system_av_info* info)
|
||||
info->geometry.aspect_ratio = 4.0 / 3.0;
|
||||
|
||||
if (!Settings.PAL)
|
||||
info->timing.fps = (SNES_CLOCK_SPEED * 6.0 / (SNES_CYCLES_PER_SCANLINE *
|
||||
SNES_MAX_NTSC_VCOUNTER));
|
||||
info->timing.fps = (SNES_CLOCK_SPEED * 6.0 / (SNES_CYCLES_PER_SCANLINE * SNES_MAX_NTSC_VCOUNTER));
|
||||
else
|
||||
info->timing.fps = (SNES_CLOCK_SPEED * 6.0 / (SNES_CYCLES_PER_SCANLINE *
|
||||
SNES_MAX_PAL_VCOUNTER));
|
||||
info->timing.fps = (SNES_CLOCK_SPEED * 6.0 / (SNES_CYCLES_PER_SCANLINE * SNES_MAX_PAL_VCOUNTER));
|
||||
|
||||
info->timing.sample_rate = samplerate;
|
||||
}
|
||||
@ -597,18 +551,16 @@ size_t retro_serialize_size(void)
|
||||
return sizeof(CPU) + sizeof(ICPU) + sizeof(PPU) + sizeof(DMA) +
|
||||
0x10000 + 0x20000 + 0x20000 + 0x8000 +
|
||||
#ifndef USE_BLARGG_APU
|
||||
sizeof(APU) + sizeof(IAPU) + 0x10000
|
||||
sizeof(APU) + sizeof(IAPU) + 0x10000 +
|
||||
#else
|
||||
SPC_SAVE_STATE_BLOCK_SIZE
|
||||
SPC_SAVE_STATE_BLOCK_SIZE +
|
||||
#endif
|
||||
+ sizeof(SA1) +
|
||||
sizeof(s7r) + sizeof(rtc_f9);
|
||||
sizeof(SA1) + sizeof(s7r) + sizeof(rtc_f9);
|
||||
}
|
||||
|
||||
bool retro_serialize(void* data, size_t size)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
S9xUpdateRTC();
|
||||
S9xSRTCPreSaveState();
|
||||
uint8_t* buffer = data;
|
||||
@ -721,7 +673,6 @@ bool retro_unserialize(const void* data, size_t size)
|
||||
S9xUnpackStatus();
|
||||
S9xFixCycles();
|
||||
S9xReschedule();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
120
source/dma.c
120
source/dma.c
@ -7,8 +7,9 @@
|
||||
#include "dma.h"
|
||||
#include "apu.h"
|
||||
#include "sa1.h"
|
||||
#include "spc7110.h"
|
||||
#include "sdd1emu.h"
|
||||
#include "spc7110.h"
|
||||
#include "spc7110dec.h"
|
||||
|
||||
static uint8_t sdd1_decode_buffer[0x10000];
|
||||
|
||||
@ -17,7 +18,7 @@ extern uint8_t* HDMAMemPointers [8];
|
||||
extern uint8_t* HDMABasePointers [8];
|
||||
|
||||
/**********************************************************************************************/
|
||||
/* S9xDoDMA() */
|
||||
/* S9xDoDMA() */
|
||||
/* This function preforms the general dma transfer */
|
||||
/**********************************************************************************************/
|
||||
void S9xDoDMA(uint8_t Channel)
|
||||
@ -36,7 +37,6 @@ void S9xDoDMA(uint8_t Channel)
|
||||
|
||||
CPU.InDMA = true;
|
||||
d = &DMA[Channel];
|
||||
|
||||
count = d->TransferBytes;
|
||||
|
||||
// Prepare for custom chip DMA
|
||||
@ -66,7 +66,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
{
|
||||
if (d->AAddressFixed && Memory.FillRAM [0x4801] > 0)
|
||||
{
|
||||
uint8_t *in_ptr;
|
||||
uint8_t* in_ptr;
|
||||
|
||||
// XXX: Should probably verify that we're DMAing from ROM?
|
||||
// And somewhere we should make sure we're not running across a mapping boundary too.
|
||||
@ -85,43 +85,23 @@ void S9xDoDMA(uint8_t Channel)
|
||||
}
|
||||
if (Settings.SPC7110 && (d->AAddress == 0x4800 || d->ABank == 0x50))
|
||||
{
|
||||
uint32_t i;
|
||||
int32_t icount;
|
||||
i = (s7r.reg4805 | (s7r.reg4806 << 8));
|
||||
i *= s7r.AlignBy;
|
||||
i += s7r.bank50Internal;
|
||||
i %= DECOMP_BUFFER_SIZE;
|
||||
if ((i + d->TransferBytes) < DECOMP_BUFFER_SIZE)
|
||||
spc7110_dma = &s7r.bank50[i];
|
||||
else
|
||||
{
|
||||
uint32_t j;
|
||||
|
||||
spc7110_dma = (uint8_t*)malloc(d->TransferBytes);
|
||||
j = DECOMP_BUFFER_SIZE - i;
|
||||
memcpy(spc7110_dma, &s7r.bank50[i], j);
|
||||
memcpy(&spc7110_dma[j], s7r.bank50, d->TransferBytes - j);
|
||||
s7_wrap = true;
|
||||
}
|
||||
|
||||
icount = s7r.reg4809 | (s7r.reg480A << 8);
|
||||
icount -= d->TransferBytes;
|
||||
int32_t c;
|
||||
spc7110_dma = &s7r.bank50[0];
|
||||
for(c = 0; c < count; c++)
|
||||
s7r.bank50[c] = spc7110dec_read();
|
||||
int32_t icount = (s7r.reg4809 | (s7r.reg480A << 8)) - count;
|
||||
s7r.reg4809 = 0x00ff & icount;
|
||||
s7r.reg480A = (0xff00 & icount) >> 8;
|
||||
|
||||
s7r.bank50Internal += d->TransferBytes;
|
||||
s7r.bank50Internal %= DECOMP_BUFFER_SIZE;
|
||||
inc = 1;
|
||||
d->AAddress -= count;
|
||||
}
|
||||
if (d->BAddress == 0x18 && SA1.in_char_dma && (d->ABank & 0xf0) == 0x40)
|
||||
{
|
||||
int32_t i;
|
||||
// Perform packed bitmap to PPU character format conversion on the
|
||||
// data before transmitting it to V-RAM via-DMA.
|
||||
int32_t i;
|
||||
int32_t num_chars = 1 << ((Memory.FillRAM [0x2231] >> 2) & 7);
|
||||
int32_t depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 :
|
||||
(Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2;
|
||||
int32_t depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2;
|
||||
|
||||
int32_t bytes_per_char = 8 * depth;
|
||||
int32_t bytes_per_line = depth * num_chars;
|
||||
@ -138,13 +118,11 @@ void S9xDoDMA(uint8_t Channel)
|
||||
switch (depth)
|
||||
{
|
||||
case 2:
|
||||
for (i = 0; i < count; i += inc, base += char_line_bytes,
|
||||
inc = char_line_bytes, char_count = num_chars)
|
||||
for (i = 0 ; i < count ; i += inc, base += char_line_bytes, inc = char_line_bytes, char_count = num_chars)
|
||||
{
|
||||
uint32_t j;
|
||||
uint8_t* line = base + (num_chars - char_count) * 2;
|
||||
for (j = 0; j < char_count && p - buffer < count;
|
||||
j++, line += 2)
|
||||
for (j = 0 ; j < char_count && p - buffer < count ; j++, line += 2)
|
||||
{
|
||||
int32_t b, l;
|
||||
uint8_t* q = line;
|
||||
@ -168,13 +146,11 @@ void S9xDoDMA(uint8_t Channel)
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (i = 0; i < count; i += inc, base += char_line_bytes,
|
||||
inc = char_line_bytes, char_count = num_chars)
|
||||
for (i = 0 ; i < count ; i += inc, base += char_line_bytes, inc = char_line_bytes, char_count = num_chars)
|
||||
{
|
||||
uint32_t j;
|
||||
uint8_t* line = base + (num_chars - char_count) * 4;
|
||||
for (j = 0; j < char_count && p - buffer < count;
|
||||
j++, line += 4)
|
||||
for (j = 0 ; j < char_count && p - buffer < count ; j++, line += 4)
|
||||
{
|
||||
uint8_t* q = line;
|
||||
int32_t b, l;
|
||||
@ -199,13 +175,11 @@ void S9xDoDMA(uint8_t Channel)
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
for (i = 0; i < count; i += inc, base += char_line_bytes,
|
||||
inc = char_line_bytes, char_count = num_chars)
|
||||
for(i = 0 ; i < count ; i += inc, base += char_line_bytes, inc = char_line_bytes, char_count = num_chars)
|
||||
{
|
||||
uint8_t* line = base + (num_chars - char_count) * 8;
|
||||
uint32_t j;
|
||||
for (j = 0; j < char_count && p - buffer < count;
|
||||
j++, line += 8)
|
||||
for(j = 0 ; j < char_count && p - buffer < count ; j++, line += 8)
|
||||
{
|
||||
uint8_t* q = line;
|
||||
int32_t b, l;
|
||||
@ -242,7 +216,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
* XXX: GetBasePointer whenever we cross a boundry, and when
|
||||
* XXX: GetBasePointer returns (0) to take the 'slow path' and use
|
||||
* XXX: S9xGetByte instead of *base. GetBasePointer() would want to
|
||||
* XXX: return (0) for MAP_PPU and whatever else is a register range
|
||||
* XXX: return 0 for MAP_PPU and whatever else is a register range
|
||||
* XXX: rather than a RAM/ROM block, and we'd want to detect MAP_PPU
|
||||
* XXX: (or specifically, Address Bus B addresses $2100-$21FF in
|
||||
* XXX: banks $00-$3F) specially and treat it as MAP_NONE (since
|
||||
@ -289,8 +263,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
Work = *(base + p);
|
||||
REGISTER_2104(Work);
|
||||
p += inc;
|
||||
}
|
||||
while (--count > 0);
|
||||
} while (--count > 0);
|
||||
break;
|
||||
case 0x18:
|
||||
IPPU.FirstVRAMRead = true;
|
||||
@ -301,8 +274,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
Work = *(base + p);
|
||||
REGISTER_2118_linear(Work);
|
||||
p += inc;
|
||||
}
|
||||
while (--count > 0);
|
||||
} while (--count > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -311,8 +283,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
Work = *(base + p);
|
||||
REGISTER_2118_tile(Work);
|
||||
p += inc;
|
||||
}
|
||||
while (--count > 0);
|
||||
} while (--count > 0);
|
||||
}
|
||||
break;
|
||||
case 0x19:
|
||||
@ -324,8 +295,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
Work = *(base + p);
|
||||
REGISTER_2119_linear(Work);
|
||||
p += inc;
|
||||
}
|
||||
while (--count > 0);
|
||||
} while (--count > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -334,8 +304,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
Work = *(base + p);
|
||||
REGISTER_2119_tile(Work);
|
||||
p += inc;
|
||||
}
|
||||
while (--count > 0);
|
||||
} while (--count > 0);
|
||||
}
|
||||
break;
|
||||
case 0x22:
|
||||
@ -344,8 +313,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
Work = *(base + p);
|
||||
REGISTER_2122(Work);
|
||||
p += inc;
|
||||
}
|
||||
while (--count > 0);
|
||||
} while (--count > 0);
|
||||
break;
|
||||
case 0x80:
|
||||
do
|
||||
@ -353,8 +321,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
Work = *(base + p);
|
||||
REGISTER_2180(Work);
|
||||
p += inc;
|
||||
}
|
||||
while (--count > 0);
|
||||
} while (--count > 0);
|
||||
break;
|
||||
default:
|
||||
do
|
||||
@ -362,8 +329,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
Work = *(base + p);
|
||||
S9xSetPPU(Work, 0x2100 + d->BAddress);
|
||||
p += inc;
|
||||
}
|
||||
while (--count > 0);
|
||||
} while (--count > 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -459,8 +425,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
S9xSetPPU(Work, 0x2101 + d->BAddress);
|
||||
p += inc;
|
||||
count -= 4;
|
||||
}
|
||||
while (count > 0);
|
||||
} while (count > 0);
|
||||
}
|
||||
else if (d->TransferMode == 4)
|
||||
{
|
||||
@ -488,8 +453,7 @@ void S9xDoDMA(uint8_t Channel)
|
||||
S9xSetPPU(Work, 0x2103 + d->BAddress);
|
||||
p += inc;
|
||||
count -= 4;
|
||||
}
|
||||
while (count > 0);
|
||||
} while (count > 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -549,7 +513,6 @@ void S9xDoDMA(uint8_t Channel)
|
||||
d->AAddress += inc;
|
||||
count--;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
Work = S9xGetPPU(0x2100 + d->BAddress);
|
||||
S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
|
||||
@ -574,13 +537,11 @@ void S9xDoDMA(uint8_t Channel)
|
||||
d->AAddress += inc;
|
||||
count--;
|
||||
break;
|
||||
|
||||
default:
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (count);
|
||||
} while (count);
|
||||
}
|
||||
#ifndef USE_BLARGG_APU
|
||||
IAPU.APUExecuting = Settings.APUEnabled;
|
||||
@ -593,20 +554,15 @@ void S9xDoDMA(uint8_t Channel)
|
||||
while (CPU.Cycles > CPU.NextEvent)
|
||||
S9xDoHBlankProcessing_NoSFX();
|
||||
|
||||
if (Settings.SPC7110 && spc7110_dma)
|
||||
{
|
||||
if (spc7110_dma && s7_wrap)
|
||||
free(spc7110_dma);
|
||||
}
|
||||
if (Settings.SPC7110 && spc7110_dma && s7_wrap)
|
||||
free(spc7110_dma);
|
||||
|
||||
update_address:
|
||||
// Super Punch-Out requires that the A-BUS address be updated after the
|
||||
// DMA transfer.
|
||||
// Super Punch-Out requires that the A-BUS address be updated after the DMA transfer.
|
||||
Memory.FillRAM[0x4302 + (Channel << 4)] = (uint8_t) d->AAddress;
|
||||
Memory.FillRAM[0x4303 + (Channel << 4)] = d->AAddress >> 8;
|
||||
|
||||
// Secret of the Mana requires that the DMA bytes transfer count be set to
|
||||
// zero when DMA has completed.
|
||||
// Secret of the Mana requires that the DMA bytes transfer count be set to zero when DMA has completed.
|
||||
Memory.FillRAM [0x4305 + (Channel << 4)] = 0;
|
||||
Memory.FillRAM [0x4306 + (Channel << 4)] = 0;
|
||||
|
||||
@ -619,13 +575,8 @@ update_address:
|
||||
void S9xStartHDMA()
|
||||
{
|
||||
uint8_t i;
|
||||
IPPU.HDMA = Memory.FillRAM [0x420c];
|
||||
|
||||
if (Settings.DisableHDMA)
|
||||
IPPU.HDMA = 0;
|
||||
else
|
||||
IPPU.HDMA = Memory.FillRAM [0x420c];
|
||||
|
||||
//per anomie timing post
|
||||
if (IPPU.HDMA != 0)
|
||||
CPU.Cycles += ONE_CYCLE * 3;
|
||||
|
||||
@ -718,8 +669,7 @@ uint8_t S9xDoHDMA(uint8_t byte)
|
||||
p->IndirectAddress = p->Address;
|
||||
}
|
||||
|
||||
if (!(HDMABasePointers [d] = HDMAMemPointers [d] =
|
||||
S9xGetMemPointer((p->IndirectBank << 16) + p->IndirectAddress)))
|
||||
if (!(HDMABasePointers [d] = HDMAMemPointers [d] = S9xGetMemPointer((p->IndirectBank << 16) + p->IndirectAddress)))
|
||||
{
|
||||
/* XXX: Instead of this, goto a slow path that first
|
||||
* XXX: verifies src!=Address Bus B, then uses
|
||||
|
@ -7,5 +7,4 @@ void S9xResetDMA(void);
|
||||
uint8_t S9xDoHDMA(uint8_t);
|
||||
void S9xStartHDMA(void);
|
||||
void S9xDoDMA(uint8_t);
|
||||
|
||||
#endif
|
||||
|
@ -21,10 +21,7 @@ void S9xResetDSP1()
|
||||
|
||||
uint8_t S9xGetDSP(uint16_t address)
|
||||
{
|
||||
uint8_t t;
|
||||
|
||||
t = (*GetDSP)(address);
|
||||
return (t);
|
||||
return (*GetDSP)(address);
|
||||
}
|
||||
|
||||
void S9xSetDSP(uint8_t byte, uint16_t address)
|
||||
@ -48,8 +45,7 @@ void DSP1SetByte(uint8_t byte, uint16_t address)
|
||||
DSP1.in_index = 0;
|
||||
DSP1.waiting4command = false;
|
||||
DSP1.first_parameter = true;
|
||||
// Mario Kart uses 0x00, 0x02, 0x06, 0x0c, 0x28, 0x0a
|
||||
switch (byte)
|
||||
switch (byte) // Mario Kart uses 0x00, 0x02, 0x06, 0x0c, 0x28, 0x0a
|
||||
{
|
||||
case 0x07:
|
||||
case 0x0a:
|
||||
@ -628,8 +624,7 @@ void DSP2SetByte(uint8_t byte, uint16_t address)
|
||||
uint32_t temp;
|
||||
#endif
|
||||
|
||||
if ((address & 0xf000) == 0x6000 ||
|
||||
(address >= 0x8000 && address < 0xc000))
|
||||
if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000))
|
||||
{
|
||||
if (DSP1.waiting4command)
|
||||
{
|
||||
|
@ -199,9 +199,6 @@ inline void S9xSetByte(uint8_t Byte, uint32_t Address)
|
||||
case MAP_C4:
|
||||
S9xSetC4(Byte, Address & 0xffff);
|
||||
return;
|
||||
case MAP_SPC7110_DRAM:
|
||||
s7r.bank50[(Address & 0xffff)] = (uint8_t) Byte;
|
||||
break;
|
||||
case MAP_OBC_RAM:
|
||||
SetOBC1(Byte, Address & 0xFFFF);
|
||||
return;
|
||||
@ -297,10 +294,6 @@ inline void S9xSetWord(uint16_t Word, uint32_t Address)
|
||||
#endif
|
||||
CPU.SRAMModified = true;
|
||||
return;
|
||||
case MAP_SPC7110_DRAM:
|
||||
s7r.bank50[(Address & 0xffff)] = (uint8_t) Word;
|
||||
s7r.bank50[((Address + 1) & 0xffff)] = (uint8_t) Word;
|
||||
break;
|
||||
case MAP_SA1RAM:
|
||||
*(Memory.SRAM + (Address & 0xffff)) = (uint8_t) Word;
|
||||
*(Memory.SRAM + ((Address + 1) & 0xffff)) = (uint8_t)(Word >> 8);
|
||||
|
@ -578,8 +578,7 @@ bool LoadROM(
|
||||
uint8_t* RomHeader = Memory.ROM;
|
||||
Memory.ExtendedFormat = NOPE;
|
||||
|
||||
if (CleanUp7110 != NULL)
|
||||
(*CleanUp7110)();
|
||||
Del7110Gfx();
|
||||
|
||||
memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
|
||||
SNESGameFixes.SRAMInitialValue = 0x60;
|
||||
|
1328
source/spc7110.c
1328
source/spc7110.c
File diff suppressed because it is too large
Load Diff
@ -6,15 +6,7 @@
|
||||
|
||||
#define DECOMP_BUFFER_SIZE 0x10000
|
||||
|
||||
extern void (*LoadUp7110)(char*);
|
||||
extern void (*CleanUp7110)(void);
|
||||
extern void (*Copy7110)(void);
|
||||
|
||||
extern uint16_t cacheMegs;
|
||||
|
||||
void Del7110Gfx(void);
|
||||
void Close7110Gfx(void);
|
||||
void Drop7110Gfx(void);
|
||||
uint8_t S9xGetSPC7110(uint16_t Address);
|
||||
uint8_t S9xGetSPC7110Byte(uint32_t Address);
|
||||
uint8_t* Get7110BasePtr(uint32_t);
|
||||
@ -26,12 +18,6 @@ void S9xUpdateRTC(void);
|
||||
void Do7110Logging(void);
|
||||
int32_t S9xRTCDaysInMonth(int32_t month, int32_t year);
|
||||
|
||||
//These are platform-dependant functions, but should work on
|
||||
//most systems that use GNU compilers, and on Win32.
|
||||
void SPC7110Load(char*);
|
||||
void SPC7110Open(char*);
|
||||
void SPC7110Grab(char*);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t reg[16];
|
||||
@ -99,9 +85,4 @@ typedef struct
|
||||
|
||||
extern SPC7110Regs s7r;
|
||||
extern S7RTC rtc_f9;
|
||||
|
||||
// These are defined in spc7110.cpp
|
||||
bool S9xSaveSPC7110RTC(S7RTC* rtc_f9);
|
||||
bool S9xLoadSPC7110RTC(S7RTC* rtc_f9);
|
||||
|
||||
#endif
|
||||
|
619
source/spc7110dec.c
Normal file
619
source/spc7110dec.c
Normal file
@ -0,0 +1,619 @@
|
||||
#include "../copyright"
|
||||
|
||||
#include "memmap.h"
|
||||
#include "spc7110dec.h"
|
||||
|
||||
#define SPC7110_DECOMP_BUFFER_SIZE 64 /* must be >= 64, and must be a power of two */
|
||||
|
||||
static const uint8_t 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},
|
||||
};
|
||||
|
||||
static const uint8_t mode2_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},
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t mode;
|
||||
uint32_t offset;
|
||||
uint32_t original_mode;
|
||||
uint32_t original_offset;
|
||||
uint32_t original_index;
|
||||
uint32_t read_counter;
|
||||
uint8_t *buffer;
|
||||
uint32_t buffer_rdoffset;
|
||||
uint32_t buffer_wroffset;
|
||||
uint32_t buffer_length;
|
||||
|
||||
struct ContextState
|
||||
{
|
||||
uint8_t index;
|
||||
uint8_t invert;
|
||||
} context[32];
|
||||
|
||||
uint32_t morton16[2][256];
|
||||
uint32_t morton32[4][256];
|
||||
} SPC7110Decomp;
|
||||
|
||||
SPC7110Decomp decomp;
|
||||
|
||||
uint8_t spc7110dec_read()
|
||||
{
|
||||
decomp.read_counter++;
|
||||
|
||||
if(decomp.buffer_length == 0)
|
||||
{
|
||||
switch(decomp.mode)
|
||||
{
|
||||
case 0:
|
||||
spc7110dec_mode0(false);
|
||||
break;
|
||||
case 1:
|
||||
spc7110dec_mode1(false);
|
||||
break;
|
||||
case 2:
|
||||
spc7110dec_mode2(false);
|
||||
break;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t data = decomp.buffer[decomp.buffer_rdoffset++];
|
||||
|
||||
decomp.buffer_rdoffset &= SPC7110_DECOMP_BUFFER_SIZE - 1;
|
||||
decomp.buffer_length--;
|
||||
return data;
|
||||
}
|
||||
|
||||
void spc7110dec_write(uint8_t data)
|
||||
{
|
||||
decomp.buffer[decomp.buffer_wroffset++] = data;
|
||||
decomp.buffer_wroffset &= SPC7110_DECOMP_BUFFER_SIZE - 1;
|
||||
decomp.buffer_length++;
|
||||
}
|
||||
|
||||
uint8_t spc7110dec_dataread()
|
||||
{
|
||||
uint32_t size = Memory.CalculatedSize - 0x100000;
|
||||
|
||||
while(decomp.offset >= size)
|
||||
decomp.offset -= size;
|
||||
return Memory.ROM[0x100000 + decomp.offset++];
|
||||
}
|
||||
|
||||
void spc7110dec_clear(uint32_t mode, uint32_t offset, uint32_t index)
|
||||
{
|
||||
decomp.original_mode = mode;
|
||||
decomp.original_offset = offset;
|
||||
decomp.original_index = index;
|
||||
decomp.mode = mode;
|
||||
decomp.offset = offset;
|
||||
decomp.buffer_rdoffset = 0;
|
||||
decomp.buffer_wroffset = 0;
|
||||
decomp.buffer_length = 0;
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < 32; i++) // reset decomp.context states
|
||||
{
|
||||
decomp.context[i].index = 0;
|
||||
decomp.context[i].invert = 0;
|
||||
}
|
||||
|
||||
switch(decomp.mode)
|
||||
{
|
||||
case 0:
|
||||
spc7110dec_mode0(true);
|
||||
break;
|
||||
case 1:
|
||||
spc7110dec_mode1(true);
|
||||
break;
|
||||
case 2:
|
||||
spc7110dec_mode2(true);
|
||||
break;
|
||||
}
|
||||
|
||||
while(index--) // decompress up to requested output data index
|
||||
spc7110dec_read();
|
||||
|
||||
decomp.read_counter = 0;
|
||||
}
|
||||
|
||||
void spc7110dec_mode0(bool init)
|
||||
{
|
||||
static uint8_t val, in, span;
|
||||
static int32_t out, inverts, lps, in_count;
|
||||
|
||||
if(init)
|
||||
{
|
||||
out = inverts = lps = 0;
|
||||
span = 0xff;
|
||||
val = spc7110dec_dataread();
|
||||
in = spc7110dec_dataread();
|
||||
in_count = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
while(decomp.buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1))
|
||||
{
|
||||
uint32_t bit;
|
||||
|
||||
for(bit = 0; bit < 8; bit++)
|
||||
{
|
||||
/* Get decomp.context */
|
||||
uint8_t mask = (1 << (bit & 3)) - 1;
|
||||
uint8_t con = mask + ((inverts & mask) ^ (lps & mask));
|
||||
|
||||
if(bit > 3)
|
||||
con += 15;
|
||||
|
||||
/* Get prob and mps */
|
||||
uint32_t prob = spc7110dec_probability(con);
|
||||
uint32_t mps = (((out >> 15) & 1) ^ decomp.context[con].invert);
|
||||
|
||||
/* Get bit */
|
||||
uint32_t 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 */
|
||||
uint32_t shift = 0;
|
||||
|
||||
while(span < 0x7f)
|
||||
{
|
||||
shift++;
|
||||
span = (span << 1) + 1;
|
||||
val = (val << 1) + (in >> 7);
|
||||
in <<= 1;
|
||||
|
||||
if(--in_count == 0)
|
||||
{
|
||||
in = spc7110dec_dataread();
|
||||
in_count = 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update processing info */
|
||||
lps = (lps << 1) + flag_lps;
|
||||
inverts = (inverts << 1) + decomp.context[con].invert;
|
||||
|
||||
/* Update context state */
|
||||
if(flag_lps & spc7110dec_toggle_invert(con))
|
||||
decomp.context[con].invert ^= 1;
|
||||
|
||||
if(flag_lps)
|
||||
decomp.context[con].index = spc7110dec_next_lps(con);
|
||||
else if(shift)
|
||||
decomp.context[con].index = spc7110dec_next_mps(con);
|
||||
}
|
||||
|
||||
/* Save byte */
|
||||
spc7110dec_write(out);
|
||||
}
|
||||
}
|
||||
|
||||
void spc7110dec_mode1(bool init)
|
||||
{
|
||||
static uint32_t pixelorder[4], realorder[4];
|
||||
static uint8_t in, val, span;
|
||||
static int32_t out, inverts, lps, in_count;
|
||||
|
||||
if(init)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
pixelorder[i] = i;
|
||||
out = inverts = lps = 0;
|
||||
span = 0xff;
|
||||
val = spc7110dec_dataread();
|
||||
in = spc7110dec_dataread();
|
||||
in_count = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
while(decomp.buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1))
|
||||
{
|
||||
uint32_t pixel;
|
||||
|
||||
for(pixel = 0; pixel < 8; pixel++)
|
||||
{
|
||||
/* Get first symbol decomp.context */
|
||||
uint32_t a = ((out >> (1 * 2)) & 3);
|
||||
uint32_t b = ((out >> (7 * 2)) & 3);
|
||||
uint32_t c = ((out >> (8 * 2)) & 3);
|
||||
uint32_t con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
||||
|
||||
/* Update pixel order */
|
||||
uint32_t 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 */
|
||||
uint32_t bit;
|
||||
|
||||
for(bit = 0; bit < 2; bit++)
|
||||
{
|
||||
/* Get prob */
|
||||
uint32_t prob = spc7110dec_probability(con);
|
||||
|
||||
/* Get symbol */
|
||||
uint32_t 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 */
|
||||
uint32_t shift = 0;
|
||||
|
||||
while(span < 0x7f)
|
||||
{
|
||||
shift++;
|
||||
span = (span << 1) + 1;
|
||||
val = (val << 1) + (in >> 7);
|
||||
in <<= 1;
|
||||
if(--in_count == 0)
|
||||
{
|
||||
in = spc7110dec_dataread();
|
||||
in_count = 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update processing info */
|
||||
lps = (lps << 1) + flag_lps;
|
||||
inverts = (inverts << 1) + decomp.context[con].invert;
|
||||
|
||||
/* Update context state */
|
||||
if(flag_lps & spc7110dec_toggle_invert(con))
|
||||
decomp.context[con].invert ^= 1;
|
||||
|
||||
if(flag_lps)
|
||||
decomp.context[con].index = spc7110dec_next_lps(con);
|
||||
else if(shift)
|
||||
decomp.context[con].index = spc7110dec_next_mps(con);
|
||||
|
||||
/* Get next decomp.context */
|
||||
con = 5 + (con << 1) + ((lps ^ inverts) & 1);
|
||||
}
|
||||
|
||||
/* Get pixel */
|
||||
b = realorder[(lps ^ inverts) & 3];
|
||||
out = (out << 2) + b;
|
||||
}
|
||||
|
||||
/* Turn pixel data into bitplanes */
|
||||
uint32_t data = spc7110dec_morton_2x8(out);
|
||||
|
||||
spc7110dec_write(data >> 8);
|
||||
spc7110dec_write(data >> 0);
|
||||
}
|
||||
}
|
||||
|
||||
void spc7110dec_mode2(bool init)
|
||||
{
|
||||
static uint32_t pixelorder[16], realorder[16];
|
||||
static uint8_t bitplanebuffer[16], buffer_index;
|
||||
static uint8_t in, val, span;
|
||||
static int32_t out0, out1, inverts, lps, in_count;
|
||||
|
||||
if(init)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
pixelorder[i] = i;
|
||||
buffer_index = 0;
|
||||
out0 = out1 = inverts = lps = 0;
|
||||
span = 0xff;
|
||||
val = spc7110dec_dataread();
|
||||
in = spc7110dec_dataread();
|
||||
in_count = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
while(decomp.buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1))
|
||||
{
|
||||
uint32_t pixel;
|
||||
|
||||
for(pixel = 0; pixel < 8; pixel++)
|
||||
{
|
||||
/* Get first symbol context */
|
||||
uint32_t a = ((out0 >> (0 * 4)) & 15);
|
||||
uint32_t b = ((out0 >> (7 * 4)) & 15);
|
||||
uint32_t c = ((out1 >> (0 * 4)) & 15);
|
||||
uint32_t con = 0;
|
||||
uint32_t refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
||||
|
||||
/* Update pixel order */
|
||||
uint32_t 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 */
|
||||
uint32_t bit;
|
||||
|
||||
for(bit = 0; bit < 4; bit++)
|
||||
{
|
||||
/* Get prob */
|
||||
uint32_t prob = spc7110dec_probability(con);
|
||||
|
||||
/* Get symbol */
|
||||
uint32_t 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 */
|
||||
uint32_t shift = 0;
|
||||
|
||||
while(span < 0x7f)
|
||||
{
|
||||
shift++;
|
||||
span = (span << 1) + 1;
|
||||
val = (val << 1) + (in >> 7);
|
||||
in <<= 1;
|
||||
if(--in_count == 0)
|
||||
{
|
||||
in = spc7110dec_dataread();
|
||||
in_count = 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update processing info */
|
||||
lps = (lps << 1) + flag_lps;
|
||||
uint32_t invertbit = decomp.context[con].invert;
|
||||
|
||||
inverts = (inverts << 1) + invertbit;
|
||||
|
||||
/* Update decomp.context state */
|
||||
if(flag_lps & spc7110dec_toggle_invert(con))
|
||||
decomp.context[con].invert ^= 1;
|
||||
|
||||
if(flag_lps)
|
||||
decomp.context[con].index = spc7110dec_next_lps(con);
|
||||
else if(shift)
|
||||
decomp.context[con].index = spc7110dec_next_mps(con);
|
||||
|
||||
/* Get next decomp.context */
|
||||
con = mode2_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 */
|
||||
uint32_t data = spc7110dec_morton_4x8(out0);
|
||||
|
||||
spc7110dec_write(data >> 24);
|
||||
spc7110dec_write(data >> 16);
|
||||
bitplanebuffer[buffer_index++] = data >> 8;
|
||||
bitplanebuffer[buffer_index++] = data >> 0;
|
||||
|
||||
if(buffer_index == 16)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
spc7110dec_write(bitplanebuffer[i]);
|
||||
buffer_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t spc7110dec_probability(uint32_t n)
|
||||
{
|
||||
return evolution_table[decomp.context[n].index][0];
|
||||
}
|
||||
|
||||
uint8_t spc7110dec_next_lps(uint32_t n)
|
||||
{
|
||||
return evolution_table[decomp.context[n].index][1];
|
||||
}
|
||||
|
||||
uint8_t spc7110dec_next_mps(uint32_t n)
|
||||
{
|
||||
return evolution_table[decomp.context[n].index][2];
|
||||
}
|
||||
|
||||
bool spc7110dec_toggle_invert(uint32_t n)
|
||||
{
|
||||
return evolution_table[decomp.context[n].index][3];
|
||||
}
|
||||
|
||||
uint32_t spc7110dec_morton_2x8(uint32_t 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 */
|
||||
return decomp.morton16[0][(data >> 0) & 255] + decomp.morton16[1][(data >> 8) & 255];
|
||||
}
|
||||
|
||||
uint32_t spc7110dec_morton_4x8(uint32_t 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 */
|
||||
return decomp.morton32[0][(data >> 0) & 255] + decomp.morton32[1][(data >> 8) & 255] + decomp.morton32[2][(data >> 16) & 255] + decomp.morton32[3][(data >> 24) & 255];
|
||||
}
|
||||
|
||||
void spc7110dec_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;
|
||||
}
|
||||
|
||||
void spc7110dec_init()
|
||||
{
|
||||
decomp.buffer = malloc(SPC7110_DECOMP_BUFFER_SIZE);
|
||||
spc7110dec_reset();
|
||||
|
||||
/* Initialize reverse morton lookup tables */
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < 256; i++)
|
||||
{
|
||||
#define map(x, y) (((i >> x) & 1) << y)
|
||||
/* 2x8-bit */
|
||||
decomp.morton16[1][i] = map(7, 15) + map(6, 7) + map(5, 14) + map(4, 6) + map(3, 13) + map(2, 5) + map(1, 12) + map(0, 4);
|
||||
decomp.morton16[0][i] = map(7, 11) + map(6, 3) + map(5, 10) + map(4, 2) + map(3, 9) + map(2, 1) + map(1, 8) + map(0, 0);
|
||||
/* 4x8-bit */
|
||||
decomp.morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4, 7) + map(3, 30) + map(2, 22) + map(1, 14) + map(0, 6);
|
||||
decomp.morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4, 5) + map(3, 28) + map(2, 20) + map(1, 12) + map(0, 4);
|
||||
decomp.morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4, 3) + map(3, 26) + map(2, 18) + map(1, 10) + map(0, 2);
|
||||
decomp.morton32[0][i] = map(7, 25) + map(6, 17) + map(5, 9) + map(4, 1) + map(3, 24) + map(2, 16) + map(1, 8) + map(0, 0);
|
||||
#undef map
|
||||
}
|
||||
}
|
||||
|
||||
void spc7110dec_deinit()
|
||||
{
|
||||
free(decomp.buffer);
|
||||
}
|
28
source/spc7110dec.h
Normal file
28
source/spc7110dec.h
Normal file
@ -0,0 +1,28 @@
|
||||
#include "../copyright"
|
||||
|
||||
#ifndef _SPC7110DEC_H_
|
||||
#define _SPC7110DEC_H_
|
||||
#include "port.h"
|
||||
|
||||
uint8_t spc7110dec_read(void);
|
||||
void spc7110dec_clear(uint32_t mode, uint32_t offset, uint32_t index);
|
||||
void spc7110dec_reset(void);
|
||||
|
||||
void spc7110dec_init(void);
|
||||
void spc7110dec_deinit(void);
|
||||
|
||||
void spc7110dec_write(uint8_t data);
|
||||
uint8_t spc7110dec_dataread(void);
|
||||
|
||||
void spc7110dec_mode0(bool init);
|
||||
void spc7110dec_mode1(bool init);
|
||||
void spc7110dec_mode2(bool init);
|
||||
|
||||
uint8_t spc7110dec_probability(uint32_t n);
|
||||
uint8_t spc7110dec_next_lps(uint32_t n);
|
||||
uint8_t spc7110dec_next_mps(uint32_t n);
|
||||
bool spc7110dec_toggle_invert(uint32_t n);
|
||||
|
||||
uint32_t spc7110dec_morton_2x8(uint32_t data);
|
||||
uint32_t spc7110dec_morton_4x8(uint32_t data);
|
||||
#endif
|
133
source/srtc.c
133
source/srtc.c
@ -34,12 +34,10 @@ Index Description Range (nibble)
|
||||
|
||||
SRTC_DATA rtc;
|
||||
|
||||
|
||||
static int32_t month_keys[12] = { 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6 };
|
||||
|
||||
|
||||
/*********************************************************************************************
|
||||
*
|
||||
* Note, if you are doing a save state for this game:
|
||||
*
|
||||
* On save:
|
||||
@ -50,8 +48,6 @@ static int32_t month_keys[12] = { 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6 };
|
||||
*
|
||||
* restore the rtc data structure
|
||||
* rtc.system_timestamp = time (NULL);
|
||||
*
|
||||
*
|
||||
*********************************************************************************************/
|
||||
|
||||
|
||||
@ -68,9 +64,7 @@ void S9xHardResetSRTC(void)
|
||||
rtc.mode = MODE_READ;
|
||||
rtc.count_enable = false;
|
||||
rtc.needs_init = true;
|
||||
|
||||
// Get system timestamp
|
||||
rtc.system_timestamp = time(NULL);
|
||||
rtc.system_timestamp = time(NULL); // Get system timestamp
|
||||
}
|
||||
|
||||
/**********************************************************************************************/
|
||||
@ -83,10 +77,9 @@ uint32_t S9xSRTCComputeDayOfWeek(void)
|
||||
uint32_t month = rtc.data[8];
|
||||
uint32_t day = rtc.data[7] * 10 + rtc.data[6];
|
||||
uint32_t day_of_week;
|
||||
|
||||
year += (rtc.data[11] - 9) * 100;
|
||||
|
||||
// Range check the month for valid array indicies
|
||||
// Range check the month for valid array indices
|
||||
if (month > 12)
|
||||
month = 1;
|
||||
|
||||
@ -102,48 +95,37 @@ uint32_t S9xSRTCComputeDayOfWeek(void)
|
||||
|
||||
|
||||
/**********************************************************************************************/
|
||||
/* S9xSRTCDaysInMonth(void) */
|
||||
/* S9xSRTCDaysInMonth() */
|
||||
/* Return the number of days in a specific month for a certain year */
|
||||
/**********************************************************************************************/
|
||||
int32_t S9xSRTCDaysInMmonth(int32_t month, int32_t year)
|
||||
{
|
||||
int32_t mdays;
|
||||
|
||||
switch (month)
|
||||
switch(month)
|
||||
{
|
||||
case 2:
|
||||
if ((year % 4 == 0)) // DKJM2 only uses 199x - 22xx
|
||||
mdays = 29;
|
||||
else
|
||||
mdays = 28;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11:
|
||||
mdays = 30;
|
||||
break;
|
||||
|
||||
default: // months 1,3,5,7,8,10,12
|
||||
mdays = 31;
|
||||
break;
|
||||
case 2:
|
||||
if((year % 4 == 0)) /* DKJM2 only uses 199x - 22xx */
|
||||
return 29;
|
||||
return 28;
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11:
|
||||
return 30;
|
||||
default:
|
||||
return 31;
|
||||
}
|
||||
|
||||
return mdays;
|
||||
}
|
||||
|
||||
|
||||
#define DAYTICKS (60*60*24)
|
||||
#define HOURTICKS (60*60)
|
||||
#define MINUTETICKS 60
|
||||
#define MINUTETICKS 60
|
||||
#define HOURTICKS (60 * MINUTETICKS)
|
||||
#define DAYTICKS (24 * HOURTICKS)
|
||||
|
||||
|
||||
/**********************************************************************************************/
|
||||
/* S9xUpdateSrtcTime(void) */
|
||||
/* S9xUpdateSrtcTime() */
|
||||
/* Advance the S-RTC time if counting is enabled */
|
||||
/**********************************************************************************************/
|
||||
void S9xUpdateSrtcTime(void)
|
||||
void S9xUpdateSrtcTime(void)
|
||||
{
|
||||
time_t cur_systime;
|
||||
int32_t time_diff;
|
||||
@ -160,12 +142,6 @@ void S9xUpdateSrtcTime(void)
|
||||
if (rtc.count_enable && !rtc.needs_init)
|
||||
{
|
||||
cur_systime = time(NULL);
|
||||
|
||||
// This method assumes one time_t clock tick is one second
|
||||
// which should work on PCs and GNU systems.
|
||||
// If your tick interval is different adjust the
|
||||
// DAYTICK, HOURTICK, and MINUTETICK defines
|
||||
|
||||
time_diff = (int32_t)(cur_systime - rtc.system_timestamp);
|
||||
rtc.system_timestamp = cur_systime;
|
||||
|
||||
@ -178,7 +154,6 @@ void S9xUpdateSrtcTime(void)
|
||||
int32_t month;
|
||||
int32_t year;
|
||||
int32_t temp_days;
|
||||
|
||||
int32_t year_hundreds;
|
||||
int32_t year_tens;
|
||||
int32_t year_ones;
|
||||
@ -238,7 +213,6 @@ void S9xUpdateSrtcTime(void)
|
||||
{
|
||||
year = rtc.data[10] * 10 + rtc.data[9];
|
||||
year += (1000 + rtc.data[11] * 100);
|
||||
|
||||
month = rtc.data[8];
|
||||
days += (rtc.data[7] * 10 + rtc.data[6]);
|
||||
while (days > (temp_days = S9xSRTCDaysInMmonth(month, year)))
|
||||
@ -256,7 +230,6 @@ void S9xUpdateSrtcTime(void)
|
||||
year_ones = year_tens % 10;
|
||||
year_tens /= 10;
|
||||
year_hundreds = (year - 1000) / 100;
|
||||
|
||||
rtc.data[6] = days % 10;
|
||||
rtc.data[7] = days / 10;
|
||||
rtc.data[8] = month;
|
||||
@ -272,7 +245,6 @@ void S9xUpdateSrtcTime(void)
|
||||
rtc.data[3] = minutes / 10;
|
||||
rtc.data[4] = hours % 10;
|
||||
rtc.data[5] = hours / 10;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -287,25 +259,18 @@ void S9xSetSRTC(uint8_t data, uint16_t Address)
|
||||
{
|
||||
data &= 0x0F; // Data is only 4-bits, mask out unused bits.
|
||||
|
||||
if (data >= 0xD)
|
||||
if (data >= 0xD) // It's an RTC command
|
||||
{
|
||||
// It's an RTC command
|
||||
|
||||
switch (data)
|
||||
{
|
||||
case 0xD:
|
||||
rtc.mode = MODE_READ;
|
||||
rtc.index = -1;
|
||||
break;
|
||||
|
||||
case 0xE:
|
||||
rtc.mode = MODE_COMMAND;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Ignore the write if it's an 0xF ???
|
||||
// Probably should switch back to read mode -- but this
|
||||
// sequence never occurs in DKJM2
|
||||
break;
|
||||
}
|
||||
|
||||
@ -318,14 +283,10 @@ void S9xSetSRTC(uint8_t data, uint16_t Address)
|
||||
{
|
||||
rtc.data[rtc.index++] = data;
|
||||
|
||||
if (rtc.index == MAX_RTC_INDEX)
|
||||
if (rtc.index == MAX_RTC_INDEX) // We have all the data for the RTC load
|
||||
{
|
||||
// We have all the data for the RTC load
|
||||
|
||||
rtc.system_timestamp = time(NULL); // Get local system time
|
||||
|
||||
// Get the day of the week
|
||||
rtc.data[rtc.index++] = S9xSRTCComputeDayOfWeek();
|
||||
rtc.system_timestamp = time(NULL); // Get local system time
|
||||
rtc.data[rtc.index++] = S9xSRTCComputeDayOfWeek(); // Get the day of the week
|
||||
|
||||
// Start RTC counting again
|
||||
rtc.count_enable = true;
|
||||
@ -334,55 +295,32 @@ void S9xSetSRTC(uint8_t data, uint16_t Address)
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempting to write too much data
|
||||
// error(); // ignore??
|
||||
}
|
||||
}
|
||||
else if (rtc.mode == MODE_COMMAND)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case COMMAND_CLEAR_RTC:
|
||||
// Disable RTC counter
|
||||
rtc.count_enable = false;
|
||||
|
||||
rtc.count_enable = false; // Disable RTC counter
|
||||
memset(rtc.data, 0, MAX_RTC_INDEX + 1);
|
||||
rtc.index = -1;
|
||||
rtc.mode = MODE_COMMAND_DONE;
|
||||
break;
|
||||
case COMMAND_LOAD_RTC:
|
||||
// Disable RTC counter
|
||||
rtc.count_enable = false;
|
||||
|
||||
rtc.count_enable = false; // Disable RTC counter
|
||||
rtc.index = 0; // Setup for writing
|
||||
rtc.mode = MODE_LOAD_RTC;
|
||||
break;
|
||||
default:
|
||||
rtc.mode = MODE_COMMAND_DONE;
|
||||
// unrecognized command - need to implement.
|
||||
rtc.mode = MODE_COMMAND_DONE; // unrecognized command - need to implement.
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rtc.mode == MODE_READ)
|
||||
{
|
||||
// Attempting to write while in read mode. Ignore.
|
||||
}
|
||||
|
||||
if (rtc.mode == MODE_COMMAND_DONE)
|
||||
{
|
||||
// Maybe this isn't an error. Maybe we should kick off
|
||||
// a new E command. But is this valid?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************************************/
|
||||
/* S9xGetSRTC(void) */
|
||||
/* S9xGetSRTC() */
|
||||
/* This function retrieves data from the S-RTC */
|
||||
/**********************************************************************************************/
|
||||
uint8_t S9xGetSRTC(uint16_t Address)
|
||||
@ -391,20 +329,17 @@ uint8_t S9xGetSRTC(uint16_t Address)
|
||||
{
|
||||
if (rtc.index < 0)
|
||||
{
|
||||
S9xUpdateSrtcTime(); // Only update it if the game reads it
|
||||
S9xUpdateSrtcTime(); // Only update it if the game reads it
|
||||
rtc.index++;
|
||||
return (0x0f); // Send start marker.
|
||||
return 0x0f; // Send start marker.
|
||||
}
|
||||
else if (rtc.index > MAX_RTC_INDEX)
|
||||
{
|
||||
rtc.index = -1; // Setup for next set of reads
|
||||
return (0x0f); // Data done marker.
|
||||
rtc.index = -1; // Setup for next set of reads
|
||||
return 0x0f; // Data done marker.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Feed out the data
|
||||
return rtc.data[rtc.index++];
|
||||
}
|
||||
return rtc.data[rtc.index++]; // Feed out the data
|
||||
}
|
||||
else
|
||||
return 0x0;
|
||||
@ -415,8 +350,8 @@ void S9xSRTCPreSaveState()
|
||||
if (Settings.SRTC)
|
||||
{
|
||||
S9xUpdateSrtcTime();
|
||||
|
||||
int32_t s = Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0;
|
||||
|
||||
if (s > 0x20000)
|
||||
s = 0x20000;
|
||||
|
||||
|
@ -36,11 +36,11 @@ Index Description Range (nibble)
|
||||
typedef struct
|
||||
{
|
||||
bool needs_init;
|
||||
bool count_enable; // Does RTC mark time or is it frozen
|
||||
bool count_enable; // Does RTC mark time or is it frozen
|
||||
uint8_t data [MAX_RTC_INDEX + 1];
|
||||
int8_t index;
|
||||
uint8_t mode;
|
||||
time_t system_timestamp; // Of latest RTC load time
|
||||
time_t system_timestamp; // Of latest RTC load time
|
||||
} SRTC_DATA;
|
||||
|
||||
extern SRTC_DATA rtc;
|
||||
@ -52,7 +52,4 @@ void S9xSRTCPreSaveState(void);
|
||||
void S9xSRTCPostLoadState(void);
|
||||
void S9xResetSRTC(void);
|
||||
void S9xHardResetSRTC(void);
|
||||
|
||||
#define SRTC_SRAM_PAD (4 + 8 + 1 + MAX_RTC_INDEX)
|
||||
|
||||
#endif // _srtc_h
|
||||
|
Loading…
Reference in New Issue
Block a user