From fdaf2925f1353b07cd957ae47b0e6793648559be Mon Sep 17 00:00:00 2001 From: João Silva Date: Sun, 13 Aug 2017 06:02:24 +0100 Subject: Copied SPC7110 emulation from snes9x_3ds. --- source/dma.c | 120 ++--- source/dma.h | 1 - source/dsp1.c | 11 +- source/getset.h | 7 - source/memmap.c | 3 +- source/spc7110.c | 1328 ++++++--------------------------------------------- source/spc7110.h | 19 - source/spc7110dec.c | 619 ++++++++++++++++++++++++ source/spc7110dec.h | 28 ++ source/srtc.c | 133 ++---- source/srtc.h | 7 +- 11 files changed, 860 insertions(+), 1416 deletions(-) create mode 100644 source/spc7110dec.c create mode 100644 source/spc7110dec.h (limited to 'source') diff --git a/source/dma.c b/source/dma.c index eefe135..63aab98 100644 --- a/source/dma.c +++ b/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 diff --git a/source/dma.h b/source/dma.h index c2ab8d2..f9ad36f 100644 --- a/source/dma.h +++ b/source/dma.h @@ -7,5 +7,4 @@ void S9xResetDMA(void); uint8_t S9xDoHDMA(uint8_t); void S9xStartHDMA(void); void S9xDoDMA(uint8_t); - #endif diff --git a/source/dsp1.c b/source/dsp1.c index 98c0077..6a7a6b6 100644 --- a/source/dsp1.c +++ b/source/dsp1.c @@ -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) { diff --git a/source/getset.h b/source/getset.h index ebf996f..ab2186d 100644 --- a/source/getset.h +++ b/source/getset.h @@ -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); diff --git a/source/memmap.c b/source/memmap.c index 5efeacb..9011f90 100644 --- a/source/memmap.c +++ b/source/memmap.c @@ -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; diff --git a/source/spc7110.c b/source/spc7110.c index bdeb7be..f2dc0e7 100644 --- a/source/spc7110.c +++ b/source/spc7110.c @@ -1,87 +1,19 @@ #include "../copyright" #include "spc7110.h" +#include "spc7110dec.h" #include "memmap.h" #include -#include - -//Windows includes -#ifdef __WIN32__ -#ifndef _XBOX // chdir and getcwd not supported on Xbox hardware -#include -#define chdir _chdir -#define getcwd _getcwd -#endif - -#ifndef PATH_MAX -#ifdef MAX_PATH -#define PATH_MAX MAX_PATH -#else -#define PATH_MAX 1024 -#endif -#endif - -#else // Unix -#include "display.h" -#include -#include -#endif const char* S9xGetFilename(const char*); -char* osd_GetPackDir(void); -//really not needed, but usually MS adds the _ to POSIX functions, -//while *nix doesn't, so this was to "un-M$" the function. -#define splitpath _splitpath - -//not much headroom, but FEOEZ has 41 tables, I think, and SPL4 has 38. -#define MAX_TABLES 48 - -//default to using 5 megs of RAM for method 3 caching. -uint16_t cacheMegs = 5; - -//using function pointers to initialize cache management -void (*CleanUp7110)(void) = NULL; -void (*LoadUp7110)(char*) = &SPC7110Load; -void (*Copy7110)(void) = NULL; - -//size and offset of the pack data -//offset and size of reads from pack -typedef struct -{ - uint32_t offset; - uint32_t size; - uint16_t used_offset; - uint16_t used_len; -} Data7110; - -//this maps an index.bin table to the decompression pack -typedef struct -{ - int32_t table; - bool is_file; - Data7110 location[256]; -} Index7110; - -//this contains all the data for the decompression pack. -typedef struct -{ - uint8_t* binfiles[MAX_TABLES]; - Index7110 tableEnts[MAX_TABLES]; - int32_t last_table; - int32_t idx; - uint8_t last_idx; - uint16_t last_offset; -} Pack7110; -char pfold[9]; // Hack variable for log naming (each game makes a different log) -Pack7110* decompack = NULL; // Decompression pack uses a fair chunk of RAM, so dynalloc it. SPC7110Regs s7r; // SPC7110 registers, about 33KB S7RTC rtc_f9; // FEOEZ (and Shounen Jump no SHou) RTC -void S9xUpdateRTC(void); // S-RTC function hacked to work with the RTC +void S9xUpdateRTC(void); // S-RTC function hacked to work with the RTC -//Emulate power on state -void S9xSpc7110Init(void) +void S9xSpc7110Init(void) // Emulate power on state { + spc7110dec_init(); s7r.DataRomOffset = 0x00100000; //handy constant! s7r.DataRomSize = Memory.CalculatedSize - s7r.DataRomOffset; s7r.reg4800 = 0; @@ -132,308 +64,10 @@ void S9xSpc7110Init(void) s7r.written = 0; s7r.offset_add = 0; s7r.AlignBy = 1; - - (*LoadUp7110)(osd_GetPackDir()); - s7r.bank50Internal = 0; memset(s7r.bank50, 0x00, DECOMP_BUFFER_SIZE); } -//full cache decompression routine (memcpy) Method 1 -void MovePackData(void) -{ - //log the last entry - Data7110* log = &(decompack->tableEnts[decompack->idx].location[decompack->last_idx]); - if ((log->used_len + log->used_offset) < (decompack->last_offset + - (uint16_t)s7r.bank50Internal)) - { - log->used_len = s7r.bank50Internal; - log->used_offset = decompack->last_offset; - } - - //set up for next logging - decompack->last_offset = (s7r.reg4805) | (s7r.reg4806 << 8); - - decompack->last_idx = s7r.reg4804; - - //start decompression - int32_t table = (s7r.reg4803 << 16) | (s7r.reg4802 << 8) | s7r.reg4801; - - //the table is a offset multiplier byte and a big-endian pointer - int32_t j = 4 * s7r.reg4804; - j += s7r.DataRomOffset; - j += table; - - //set proper offsetting. - if (s7r.reg480B == 0) - s7r.AlignBy = 0; - else - { - switch (Memory.ROM[j]) - { - case 0x03: - s7r.AlignBy = 8; - break; - case 0x01: - s7r.AlignBy = 2; - break; - case 0x02: - s7r.AlignBy = 4; - break; - case 0x00: - default: - s7r.AlignBy = 1; - break; - } - } - //note that we are still setting up for the next log. - decompack->last_offset *= s7r.AlignBy; - decompack->last_offset %= DECOMP_BUFFER_SIZE; - - //find the table - if (table != decompack->last_table) - { - int32_t i = 0; - while (i < MAX_TABLES && decompack->tableEnts[i].table != table) - i++; - if (i == MAX_TABLES) - { -#ifdef _XBOX - FILE* fp = fopen("T:\\sp7err.out", "a"); -#else - FILE* fp = fopen("sp7err.out", "a"); -#endif - - fclose(fp); - return; - } - decompack->idx = i; - decompack->last_table = table; - } - - //copy data - if (decompack->binfiles[decompack->idx]) - { - memcpy(s7r.bank50, - &(decompack->binfiles[decompack->idx][decompack->tableEnts[decompack->idx].location[s7r.reg4804].offset]), - decompack->tableEnts[decompack->idx].location[s7r.reg4804].size); - } -} - -// This is similar to the last function, but it keeps the last 5 accessed files open, -// and reads the data directly. Method 2 -void ReadPackData(void) -{ - static int32_t table_age_2; - static int32_t table_age_3; - static int32_t table_age_4; - static int32_t table_age_5; - - int32_t table = (s7r.reg4803 << 16) | (s7r.reg4802 << 8) | s7r.reg4801; - - if (table == 0) - { - table_age_2 = table_age_3 = table_age_4 = table_age_5 = MAX_TABLES; - return; - } - - if (table_age_2 == 0 && table_age_3 == 0 && table_age_4 == 0 && table_age_5 == 0) - table_age_2 = table_age_3 = table_age_4 = table_age_5 = MAX_TABLES; - Data7110* log = &(decompack->tableEnts[decompack->idx].location[decompack->last_idx]); - if ((log->used_len + log->used_offset) < (decompack->last_offset + - (uint16_t)s7r.bank50Internal)) - { - log->used_len = s7r.bank50Internal; - log->used_offset = decompack->last_offset; - } - - decompack->last_offset = (s7r.reg4805) | (s7r.reg4806 << 8); - - decompack->last_idx = s7r.reg4804; - - int32_t j = 4 * s7r.reg4804; - j += s7r.DataRomOffset; - j += table; - - if (s7r.reg480B == 0) - s7r.AlignBy = 0; - else - { - switch (Memory.ROM[j]) - { - case 0x03: - s7r.AlignBy = 8; - break; - case 0x01: - s7r.AlignBy = 2; - break; - case 0x02: - s7r.AlignBy = 4; - break; - case 0x00: - default: - s7r.AlignBy = 1; - break; - } - } - decompack->last_offset *= s7r.AlignBy; - decompack->last_offset %= DECOMP_BUFFER_SIZE; - if (table != decompack->last_table) - { - int32_t i = 0; - while (i < MAX_TABLES && decompack->tableEnts[i].table != table) - i++; - if (i == MAX_TABLES) - { - FILE* fp = fopen("sp7err.out", "a"); - fclose(fp); - return; - } - if (i != table_age_2 && i != table_age_3 && i != table_age_4 && i != table_age_5) - { - if (table_age_5 != MAX_TABLES && decompack->binfiles[table_age_5]) - { - fclose((FILE*)(decompack->binfiles[table_age_5])); - (decompack->binfiles[table_age_5]) = NULL; - } - table_age_5 = table_age_4; - table_age_4 = table_age_3; - table_age_3 = table_age_2; - table_age_2 = decompack->idx; - char name[PATH_MAX]; - //open file - char drive [_MAX_DRIVE + 1]; - char dir [_MAX_DIR + 1]; - char fname [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - - splitpath(Memory.ROMFilename, drive, dir, fname, ext); - strcpy(name, drive); - strcat(name, dir); - - strcat(name, pfold); - char bfname[11]; - sprintf(bfname, "%06X.bin", table); - strcat(name, "/"); - strcat(name, bfname); - decompack->binfiles[i] = (uint8_t*)fopen(name, "rb"); - } - else - { - //fix tables in this case - if (table_age_5 == i) - { - table_age_5 = table_age_4; - table_age_4 = table_age_3; - table_age_3 = table_age_2; - table_age_2 = decompack->idx; - } - if (table_age_4 == i) - { - table_age_4 = table_age_3; - table_age_3 = table_age_2; - table_age_2 = decompack->idx; - } - if (table_age_3 == i) - { - table_age_3 = table_age_2; - table_age_2 = decompack->idx; - } - if (table_age_2 == i) - table_age_2 = decompack->idx; - } - decompack->idx = i; - decompack->last_table = table; - } - //do read here. - if (decompack->binfiles[decompack->idx]) - { - fseek((FILE*)(decompack->binfiles[decompack->idx]), - decompack->tableEnts[decompack->idx].location[s7r.reg4804].offset, 0); - fread(s7r.bank50, 1, ( - decompack->tableEnts[decompack->idx].location[s7r.reg4804].size), - (FILE*)(decompack->binfiles[decompack->idx])); - } -} - -//Cache Method 3: some entries are cached, others are file handles. -//use is_file to distinguish. -void GetPackData(void) -{ - Data7110* log = & - (decompack->tableEnts[decompack->idx].location[decompack->last_idx]); - if ((log->used_len + log->used_offset) < (decompack->last_offset + - (uint16_t)s7r.bank50Internal)) - { - log->used_len = s7r.bank50Internal; - log->used_offset = decompack->last_offset; - } - - decompack->last_offset = (s7r.reg4805) | (s7r.reg4806 << 8); - - decompack->last_idx = s7r.reg4804; - int32_t table = (s7r.reg4803 << 16) | (s7r.reg4802 << 8) | s7r.reg4801; - - int32_t j = 4 * s7r.reg4804; - j += s7r.DataRomOffset; - j += table; - - if (s7r.reg480B == 0) - s7r.AlignBy = 0; - else - { - switch (Memory.ROM[j]) - { - case 0x03: - s7r.AlignBy = 8; - break; - case 0x01: - s7r.AlignBy = 2; - break; - case 0x02: - s7r.AlignBy = 4; - break; - case 0x00: - default: - s7r.AlignBy = 1; - break; - } - } - decompack->last_offset *= s7r.AlignBy; - decompack->last_offset %= DECOMP_BUFFER_SIZE; - if (table != decompack->last_table) - { - int32_t i = 0; - while (i < MAX_TABLES && decompack->tableEnts[i].table != table) - i++; - if (i == MAX_TABLES) - { - FILE* fp = fopen("sp7err.out", "a"); - fclose(fp); - return; - } - decompack->idx = i; - decompack->last_table = table; - } - if (decompack->binfiles[decompack->idx]) - { - if (decompack->tableEnts[decompack->idx].is_file) - { - fseek((FILE*)decompack->binfiles[decompack->idx], - decompack->tableEnts[decompack->idx].location[s7r.reg4804].offset, 0); - fread(s7r.bank50, 1, ( - decompack->tableEnts[decompack->idx].location[s7r.reg4804].size), - (FILE*)(decompack->binfiles[decompack->idx])); - } - else - { - memcpy(s7r.bank50, - &(decompack->binfiles[decompack->idx][decompack->tableEnts[decompack->idx].location[s7r.reg4804].offset]), - decompack->tableEnts[decompack->idx].location[s7r.reg4804].size); - } - } -} - //reads SPC7110 and RTC registers. uint8_t S9xGetSPC7110(uint16_t Address) { @@ -448,40 +82,27 @@ uint8_t S9xGetSPC7110(uint16_t Address) case 0x4800: { uint16_t count = s7r.reg4809 | (s7r.reg480A << 8); - uint32_t i, j; - j = (s7r.reg4805 | (s7r.reg4806 << 8)); - j *= s7r.AlignBy; - i = j; + if (count > 0) count--; - else count = 0xFFFF; + else + count = 0xFFFF; s7r.reg4809 = 0x00ff & count; s7r.reg480A = (0xff00 & count) >> 8; - i += s7r.bank50Internal; - i %= DECOMP_BUFFER_SIZE; - s7r.reg4800 = s7r.bank50[i]; - - s7r.bank50Internal++; - s7r.bank50Internal %= DECOMP_BUFFER_SIZE; + s7r.reg4800 = spc7110dec_read(); + return s7r.reg4800; } - return s7r.reg4800; - //table register low - case 0x4801: + case 0x4801: //table register low return s7r.reg4801; - //table register middle - case 0x4802: + case 0x4802: //table register middle return s7r.reg4802; - //table register high - case 0x4803: + case 0x4803: //table register high return s7r.reg4803; - //index of pointer in table (each entry is 4 bytes) - case 0x4804: + case 0x4804: //index of pointer in table (each entry is 4 bytes) return s7r.reg4804; - //offset register low - case 0x4805: + case 0x4805: //offset register low return s7r.reg4805; - //offset register high - case 0x4806: + case 0x4806: //offset register high return s7r.reg4806; //DMA channel (not that I see this usually set, //regardless of what channel DMA is on) @@ -496,15 +117,13 @@ uint8_t S9xGetSPC7110(uint16_t Address) //this is set by the ROM, and wraps on bounds. case 0x4809: return s7r.reg4809; - //C Length high - case 0x480A: + case 0x480A: //C Length high return s7r.reg480A; //Offset enable. //if this is zero, 4805-6 are useless. Emulated by setting AlignBy to 0 case 0x480B: return s7r.reg480B; - //decompression finished: just emulated by switching each read. - case 0x480C: + case 0x480C: //decompression finished: just emulated by switching each read. s7r.reg480C ^= 0x80; return s7r.reg480C ^ 0x80; //Data access port @@ -536,7 +155,8 @@ uint8_t S9xGetSPC7110(uint16_t Address) i += r4814; if (r4814 != 0xFFFF) r4814++; - else r4814 = 0; + else + r4814 = 0; s7r.reg4815 = (uint8_t)(r4814 >> 8); s7r.reg4814 = (uint8_t)(r4814 & 0x00FF); @@ -553,8 +173,7 @@ uint8_t S9xGetSPC7110(uint16_t Address) { if (s7r.reg4818 & 0x04) { - int16_t inc; - inc = (s7r.reg4817 << 8) | s7r.reg4816; + int16_t inc = (s7r.reg4817 << 8) | s7r.reg4816; if (!(s7r.reg4818 & 0x10)) i += inc; @@ -640,31 +259,23 @@ uint8_t S9xGetSPC7110(uint16_t Address) s7r.reg4813 = ((i & 0xFF0000) >> 16); return tmp; } - else return 0; - //direct read address low - case 0x4811: + else + return 0; + case 0x4811: //direct read address low return s7r.reg4811; - //direct read address middle - case 0x4812: + case 0x4812: //direct read address middle return s7r.reg4812; - //direct read access high - case 0x4813: + case 0x4813: //direct read access high return s7r.reg4813; - //read adjust low - case 0x4814: + case 0x4814: //read adjust low return s7r.reg4814; - //read adjust high - case 0x4815: + case 0x4815: //read adjust high return s7r.reg4815; - //read increment low - case 0x4816: + case 0x4816: //read increment low return s7r.reg4816; - //read increment high - case 0x4817: + case 0x4817: //read increment high return s7r.reg4817; - //Data ROM command mode - //essentially, this controls the insane code of $4810 and $481A - case 0x4818: + case 0x4818: //Data ROM command mode; essentially, this controls the insane code of $4810 and $481A return s7r.reg4818; //read after adjust port //what this does, besides more nasty stuff like 4810, @@ -675,22 +286,14 @@ uint8_t S9xGetSPC7110(uint16_t Address) { uint32_t i = ((s7r.reg4813 << 16) | (s7r.reg4812 << 8) | s7r.reg4811); if (s7r.reg4818 & 0x08) - { - int16_t adj; - adj = ((int16_t)(s7r.reg4815 << 8)) | s7r.reg4814; - i += adj; - } + i += ((int16_t)(s7r.reg4815 << 8)) | s7r.reg4814; else - { - uint16_t adj; - adj = (s7r.reg4815 << 8) | s7r.reg4814; - i += adj; - } + i += (s7r.reg4815 << 8) | s7r.reg4814; i %= s7r.DataRomSize; i += s7r.DataRomOffset; uint8_t tmp = Memory.ROM[i]; - if (0x60 == (s7r.reg4818 & 0x60)) + if ((s7r.reg4818 & 0x60) == 0x60) { i = ((s7r.reg4813 << 16) | (s7r.reg4812 << 8) | s7r.reg4811); @@ -733,85 +336,60 @@ uint8_t S9xGetSPC7110(uint16_t Address) } return tmp; } - else return 0; - - //multiplicand low or dividend lowest - case 0x4820: + else + return 0; + case 0x4820: //multiplicand low or dividend lowest return s7r.reg4820; - //multiplicand high or divdend lower - case 0x4821: + case 0x4821: //multiplicand high or divdend lower return s7r.reg4821; - //dividend higher - case 0x4822: + case 0x4822: //dividend higher return s7r.reg4822; - //dividend highest - case 0x4823: + case 0x4823: //dividend highest return s7r.reg4823; - //multiplier low - case 0x4824: + case 0x4824: //multiplier low return s7r.reg4824; - //multiplier high - case 0x4825: + case 0x4825: //multiplier high return s7r.reg4825; - //divisor low - case 0x4826: + case 0x4826: //divisor low return s7r.reg4826; - //divisor high - case 0x4827: + case 0x4827: //divisor high return s7r.reg4827; - //result lowest - case 0x4828: + case 0x4828: //result lowest return s7r.reg4828; - //result lower - case 0x4829: + case 0x4829: //result lower return s7r.reg4829; - //result higher - case 0x482A: + case 0x482A: //result higher return s7r.reg482A; - //result highest - case 0x482B: + case 0x482B: //result highest return s7r.reg482B; - //remainder (division) low - case 0x482C: + case 0x482C: //remainder (division) low return s7r.reg482C; - //remainder (division) high - case 0x482D: + case 0x482D: //remainder (division) high return s7r.reg482D; - //signed/unsigned - case 0x482E: + case 0x482E: //signed/unsigned return s7r.reg482E; - //finished flag, emulated as an on-read toggle. - case 0x482F: + case 0x482F: //finished flag, emulated as an on-read toggle. if (s7r.reg482F) { s7r.reg482F = 0; return 0x80; } return 0; - break; - - //SRAM toggle - case 0x4830: + case 0x4830: //SRAM toggle return s7r.reg4830; - //DX bank mapping - case 0x4831: + case 0x4831: //DX bank mapping return s7r.reg4831; - //EX bank mapping - case 0x4832: + case 0x4832: //EX bank mapping return s7r.reg4832; - //FX bank mapping - case 0x4833: + case 0x4833: //FX bank mapping return s7r.reg4833; - //SRAM mapping? We have no clue! - case 0x4834: + case 0x4834: //SRAM mapping? We have no clue! return s7r.reg4834; - //RTC enable - case 0x4840: + case 0x4840: //RTC enable if (!Settings.SPC7110RTC) return Address >> 8; return s7r.reg4840; - //command/index/value of RTC (essentially, zero unless we're in read mode - case 0x4841: + case 0x4841: //command/index/value of RTC (essentially, zero unless we're in read mode if (!Settings.SPC7110RTC) return Address >> 8; if (rtc_f9.init) @@ -822,9 +400,9 @@ uint8_t S9xGetSPC7110(uint16_t Address) rtc_f9.index %= 0x10; return tmp; } - else return 0; - //RTC done flag - case 0x4842: + else + return 0; + case 0x4842: //RTC done flag if (!Settings.SPC7110RTC) return Address >> 8; s7r.reg4842 ^= 0x80; @@ -834,14 +412,21 @@ uint8_t S9xGetSPC7110(uint16_t Address) } } +static uint32_t datarom_addr(uint32_t addr) +{ + uint32_t size = Memory.CalculatedSize - 0x100000; + + while(addr >= size) + addr -= size; + return addr + 0x100000; +} + void S9xSetSPC7110(uint8_t data, uint16_t Address) { switch (Address) { //Writes to $4800 are undefined. - - //table low, middle, and high. - case 0x4801: + case 0x4801: //table low, middle, and high. s7r.reg4801 = data; break; case 0x4802: @@ -850,54 +435,44 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) case 0x4803: s7r.reg4803 = data; break; - - //table index (4 byte entries, bigendian with a multiplier byte) - case 0x4804: + case 0x4804: //table index (4 byte entries, bigendian with a multiplier byte) s7r.reg4804 = data; break; - - //offset low - case 0x4805: + case 0x4805: //offset low s7r.reg4805 = data; break; - - //offset high, starts decompression - case 0x4806: + case 0x4806: //offset high, starts decompression + { + uint32_t table = (s7r.reg4801 + (s7r.reg4802 << 8) + (s7r.reg4803 << 16)); + uint32_t index = (s7r.reg4804 << 2); + uint32_t addr = datarom_addr(table + index); + uint32_t mode = (Memory.ROM[addr + 0]); + uint32_t offset = (Memory.ROM[addr + 1] << 16) + (Memory.ROM[addr + 2] << 8) + (Memory.ROM[addr + 3]); s7r.reg4806 = data; - (*Copy7110)(); + spc7110dec_clear(mode, offset, (s7r.reg4805 + (s7r.reg4806 << 8)) << mode); s7r.bank50Internal = 0; s7r.reg480C &= 0x7F; break; - - //DMA channel register (Is it used??) - case 0x4807: + } + case 0x4807: //DMA channel register (Is it used??) s7r.reg4807 = data; break; - //C r/w? I have no idea. If you get weird values written here before a bug, //The Dumper should probably be contacted about running a test. case 0x4808: s7r.reg4808 = data; break; - - //C-Length low - case 0x4809: + case 0x4809: //C-Length low s7r.reg4809 = data; break; - //C-Length high - case 0x480A: + case 0x480A: //C-Length high s7r.reg480A = data; break; - - //Offset enable - case 0x480B: + case 0x480B: //Offset enable { s7r.reg480B = data; int32_t table = (s7r.reg4803 << 16) | (s7r.reg4802 << 8) | s7r.reg4801; - - int32_t j = 4 * s7r.reg4804; - j += s7r.DataRomOffset; - j += table; + int32_t j = 4 * s7r.reg4804 + s7r.DataRomOffset + table; if (s7r.reg480B == 0) s7r.AlignBy = 0; @@ -920,30 +495,21 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) break; } } + break; } - break; - //$4810 is probably read only. - - //Data port address low - case 0x4811: + case 0x4811: //Data port address low s7r.reg4811 = data; s7r.written |= 0x01; break; - - //data port address middle - case 0x4812: + case 0x4812: //data port address middle s7r.reg4812 = data; s7r.written |= 0x02; break; - - //data port address high - case 0x4813: + case 0x4813: //data port address high s7r.reg4813 = data; s7r.written |= 0x04; break; - - //data port adjust low (has a funky immediate increment mode) - case 0x4814: + case 0x4814: //data port adjust low (has a funky immediate increment mode) s7r.reg4814 = data; if (s7r.reg4818 & 0x02) { @@ -952,10 +518,7 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) s7r.offset_add |= 0x01; if (s7r.offset_add == 3) { - if (s7r.reg4818 & 0x10) - { - } - else + if(!(s7r.reg4818 & 0x10)) { uint32_t i = (s7r.reg4813 << 16) | (s7r.reg4812 << 8) | s7r.reg4811; if (s7r.reg4818 & 0x08) @@ -974,39 +537,25 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) s7r.offset_add |= 0x01; if (s7r.offset_add == 3) { - if (s7r.reg4818 & 0x10) - { - } - else + if(!(s7r.reg4818 & 0x10)) { uint32_t i = (s7r.reg4813 << 16) | (s7r.reg4812 << 8) | s7r.reg4811; if (s7r.reg4818 & 0x08) - { - int16_t adj; - adj = ((int16_t)(s7r.reg4815 << 8)) | s7r.reg4814; - i += adj; - } + i += ((int16_t)(s7r.reg4815 << 8)) | s7r.reg4814; else - { - uint16_t adj; - adj = (s7r.reg4815 << 8) | s7r.reg4814; - i += adj; - } + i += (s7r.reg4815 << 8) | s7r.reg4814; i %= s7r.DataRomSize; s7r.reg4811 = i & 0x00FF; s7r.reg4812 = (i & 0x00FF00) >> 8; s7r.reg4813 = ((i & 0xFF0000) >> 16); } } - } } s7r.written |= 0x08; break; - - //data port adjust high (has a funky immediate increment mode) - case 0x4815: + case 0x4815: //data port adjust high (has a funky immediate increment mode) s7r.reg4815 = data; if (s7r.reg4818 & 0x02) { @@ -1015,10 +564,7 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) s7r.offset_add |= 0x02; if (s7r.offset_add == 3) { - if (s7r.reg4818 & 0x10) - { - } - else + if(!(s7r.reg4818 & 0x10)) { uint32_t i = (s7r.reg4813 << 16) | (s7r.reg4812 << 8) | s7r.reg4811; @@ -1038,24 +584,13 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) s7r.offset_add |= 0x02; if (s7r.offset_add == 3) { - if (s7r.reg4818 & 0x10) - { - } - else + if(!(s7r.reg4818 & 0x10)) { uint32_t i = (s7r.reg4813 << 16) | (s7r.reg4812 << 8) | s7r.reg4811; if (s7r.reg4818 & 0x08) - { - int16_t adj; - adj = ((int16_t)(s7r.reg4815 << 8)) | s7r.reg4814; - i += adj; - } + i += ((int16_t)(s7r.reg4815 << 8)) | s7r.reg4814; else - { - uint16_t adj; - adj = (s7r.reg4815 << 8) | s7r.reg4814; - i += adj; - } + i += (s7r.reg4815 << 8) | s7r.reg4814; i %= s7r.DataRomSize; s7r.reg4811 = i & 0x00FF; s7r.reg4812 = (i & 0x00FF00) >> 8; @@ -1066,15 +601,12 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) } s7r.written |= 0x10; break; - //data port increment low - case 0x4816: + case 0x4816: //data port increment low s7r.reg4816 = data; break; - //data port increment high - case 0x4817: + case 0x4817: //data port increment high s7r.reg4817 = data; break; - //data port mode switches //note that it starts inactive. case 0x4818: @@ -1083,29 +615,22 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) s7r.offset_add = 0; s7r.reg4818 = data; break; - - //multiplicand low or dividend lowest - case 0x4820: + case 0x4820: //multiplicand low or dividend lowest s7r.reg4820 = data; break; - //multiplicand high or dividend lower - case 0x4821: + case 0x4821: //multiplicand high or dividend lower s7r.reg4821 = data; break; - //dividend higher - case 0x4822: + case 0x4822: //dividend higher s7r.reg4822 = data; break; - //dividend highest - case 0x4823: + case 0x4823: //dividend highest s7r.reg4823 = data; break; - //multiplier low - case 0x4824: + case 0x4824: //multiplier low s7r.reg4824 = data; break; - //multiplier high (triggers operation) - case 0x4825: + case 0x4825: //multiplier high (triggers operation) s7r.reg4825 = data; if (s7r.reg482E & 0x01) { @@ -1129,19 +654,16 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) } s7r.reg482F = 0x80; break; - //divisor low - case 0x4826: + case 0x4826: //divisor low s7r.reg4826 = data; break; - //divisor high (triggers operation) - case 0x4827: + case 0x4827: //divisor high (triggers operation) s7r.reg4827 = data; if (s7r.reg482E & 0x01) { int32_t quotient; int16_t remainder; - int32_t dividend = (int32_t)(s7r.reg4820 | (s7r.reg4821 << 8) | (s7r.reg4822 << 16) | - (s7r.reg4823 << 24)); + int32_t dividend = (int32_t)(s7r.reg4820 | (s7r.reg4821 << 8) | (s7r.reg4822 << 16) | (s7r.reg4823 << 24)); int16_t divisor = (int16_t)(s7r.reg4826 | (s7r.reg4827 << 8)); if (divisor != 0) { @@ -1164,8 +686,7 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) { uint32_t quotient; uint16_t remainder; - uint32_t dividend = (uint32_t)(s7r.reg4820 | (s7r.reg4821 << 8) | - (s7r.reg4822 << 16) | (s7r.reg4823 << 24)); + uint32_t dividend = (uint32_t)(s7r.reg4820 | (s7r.reg4821 << 8) | (s7r.reg4822 << 16) | (s7r.reg4823 << 24)); uint16_t divisor = (uint16_t)(s7r.reg4826 | (s7r.reg4827 << 8)); if (divisor != 0) { @@ -1191,42 +712,30 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) //reset: writes here nuke the whole math unit //Zero indicates unsigned math, resets with non-zero values turn on signed math case 0x482E: - s7r.reg4820 = s7r.reg4821 = s7r.reg4822 = s7r.reg4823 = s7r.reg4824 = - s7r.reg4825 = s7r.reg4826 = s7r.reg4827 = s7r.reg4828 = s7r.reg4829 = - s7r.reg482A = s7r.reg482B = s7r.reg482C = s7r.reg482D = 0; + s7r.reg4820 = s7r.reg4821 = s7r.reg4822 = s7r.reg4823 = s7r.reg4824 = s7r.reg4825 = s7r.reg4826 = s7r.reg4827 = s7r.reg4828 = s7r.reg4829 = s7r.reg482A = s7r.reg482B = s7r.reg482C = s7r.reg482D = 0; s7r.reg482E = data; break; - - //math status register possibly read only - - //SRAM toggle - case 0x4830: + //math status register possibly read only + case 0x4830: //SRAM toggle SPC7110Sram(data); s7r.reg4830 = data; break; - //Bank DX mapping - case 0x4831: + case 0x4831: //Bank DX mapping s7r.reg4831 = data; break; - //Bank EX mapping - case 0x4832: + case 0x4832: //Bank EX mapping s7r.reg4832 = data; break; - //Bank FX mapping - case 0x4833: + case 0x4833: //Bank FX mapping s7r.reg4833 = data; break; - //S-RAM mapping? who knows? - case 0x4834: + case 0x4834: //S-RAM mapping? who knows? s7r.reg4834 = data; break; - //RTC Toggle - case 0x4840: - if (0 == data) - { + case 0x4840: //RTC Toggle + if(!data) S9xUpdateRTC(); - } - if (data & 0x01) + else if(data & 0x01) { s7r.reg4842 = 0x80; rtc_f9.init = false; @@ -1234,11 +743,10 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) } s7r.reg4840 = data; break; - //RTC init/command/index register - case 0x4841: + case 0x4841: //RTC init/command/index register if (rtc_f9.init) { - if (-1 == rtc_f9.index) + if (rtc_f9.index == -1) { rtc_f9.index = data & 0x0F; break; @@ -1251,8 +759,7 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) } else { - - if (0x0D == rtc_f9.index) + if (rtc_f9.index == 0x0D) { if (data & 0x08) { @@ -1285,7 +792,7 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) } } } - if (0x0F == rtc_f9.index) + if (rtc_f9.index == 0x0F) { if (data & 0x01 && !(rtc_f9.reg[0x0F] & 0x01)) { @@ -1315,10 +822,6 @@ void S9xSetSPC7110(uint8_t data, uint16_t Address) } } break; - //writes to RTC status register aren't expected to be meaningful - default: - break; - //16 BIT MULTIPLIER: ($FF00) high byte, defval:00 } } @@ -1352,35 +855,25 @@ uint8_t S9xGetSPC7110Byte(uint32_t Address) /**********************************************************************************************/ int32_t S9xRTCDaysInMonth(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; - + if(year % 4 == 0) // DKJM2 only uses 199x - 22xx + return 29; + return 28; case 4: case 6: case 9: case 11: - mdays = 30; - break; - + return 30; default: // months 1,3,5,7,8,10,12 - mdays = 31; - break; + 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) /**********************************************************************************************/ /* S9xUpdateRTC() */ @@ -1535,296 +1028,12 @@ uint8_t* Get7110BasePtr(uint32_t Address) return &Memory.ROM[i]; } -//loads the index into memory. -//index.bin is little-endian -//format index (1)-table(3)-file offset(4)-length(4) -bool Load7110Index(char* filename) -{ - FILE* fp; - uint8_t buffer[12]; - int32_t table = 0; - uint8_t index = 0; - uint32_t offset = 0; - uint32_t size = 0; - int32_t i = 0; - fp = fopen(filename, "rb"); - if (NULL == fp) - return false; - - int32_t f_len; - while (1) - { - i = 0; - f_len = fread(buffer, 1, 12, fp); - if (f_len < 12) break; - - table = (buffer[3] << 16) | (buffer[2] << 8) | buffer[1]; - index = buffer[0]; - offset = (buffer[7] << 24) | (buffer[6] << 16) | (buffer[5] << 8) | buffer[4]; - size = (buffer[11] << 24) | (buffer[10] << 16) | (buffer[9] << 8) | buffer[8]; - while (i < MAX_TABLES && decompack->tableEnts[i].table != table - && decompack->tableEnts[i].table != 0) - i++; - if (i == MAX_TABLES) - return false; - //added - decompack->tableEnts[i].table = table; - //----- - decompack->tableEnts[i].location[index].offset = offset; - decompack->tableEnts[i].location[index].size = size; - decompack->tableEnts[i].location[index].used_len = 0; - decompack->tableEnts[i].location[index].used_offset = 0; - } - fclose(fp); - return true; -} - -//Cache 1 load function -void SPC7110Load(char* dirname) -{ - char temp_path[PATH_MAX]; - int32_t i = 0; - - decompack = (Pack7110*)malloc(sizeof(Pack7110)); - -#if !defined(_XBOX) && !defined(VITA) - getcwd(temp_path, PATH_MAX); -#endif - - memset(decompack, 0, sizeof(Pack7110)); - -#if !defined(_XBOX) && !defined(VITA) - chdir(dirname); -#endif - -#ifndef _XBOX - Load7110Index("index.bin"); -#else - // D:\\ is always app.path in Xbox - Load7110Index("d:\\index.bin"); -#endif - - for (i = 0; i < MAX_TABLES; i++) - { - if (decompack->tableEnts[i].table != 0) - { - char binname[PATH_MAX]; -#ifndef _XBOX - sprintf(binname, "%06X.bin", decompack->tableEnts[i].table); -#else - sprintf(binname, "%s%06X.bin", filename, decompack->tableEnts[i].table); -#endif - struct stat buf; - if (-1 != stat(binname, &buf)) - decompack->binfiles[i] = (uint8_t*)malloc(buf.st_size); - FILE* fp = fopen(binname, "rb"); - if (fp) - { - fread(decompack->binfiles[i], buf.st_size, 1, fp); - fclose(fp); - } - } - } - -#if !defined(_XBOX) && !defined(VITA) - chdir(temp_path); -#endif - - Copy7110 = &MovePackData; - CleanUp7110 = &Del7110Gfx; - -} - -//Cache 2 load function -void SPC7110Open(char* dirname) -{ - char temp_path[PATH_MAX]; - int32_t i = 0; - - decompack = (Pack7110*)malloc(sizeof(Pack7110)); - -#if !defined(_XBOX) && !defined(VITA) - getcwd(temp_path, PATH_MAX); -#endif - - memset(decompack, 0, sizeof(Pack7110)); - -#if !defined(_XBOX) && !defined(VITA) - chdir(dirname); -#endif - -#ifndef _XBOX - Load7110Index("index.bin"); -#else - // D:\\ is always app.path in Xbox - Load7110Index("d:\\index.bin"); -#endif - - for (i = 0; i < MAX_TABLES; i++) - decompack->binfiles[i] = NULL; - - ReadPackData(); - -#if !defined(_XBOX) && !defined(VITA) - chdir(temp_path); -#endif - - Copy7110 = &ReadPackData; - CleanUp7110 = &Close7110Gfx; -} - -//Cache 3's load function -void SPC7110Grab(char* dirname) -{ - char temp_path[PATH_MAX]; - int32_t i = 0; - - decompack = (Pack7110*)malloc(sizeof(Pack7110)); - -#if !defined(_XBOX) && !defined(VITA) - getcwd(temp_path, PATH_MAX); -#endif - - int32_t buffer_size = 1024 * 1024 * cacheMegs; //*some setting - - memset(decompack, 0, sizeof(Pack7110)); -#if !defined(_XBOX) && !defined(VITA) - chdir(dirname); -#endif - -#ifndef _XBOX - Load7110Index("index.bin"); -#else - // D:\\ is always app.path in Xbox - Load7110Index("d:\\index.bin"); -#endif - - for (i = 0; i < MAX_TABLES; i++) - { - if (decompack->tableEnts[i].table != 0) - { - char binname[PATH_MAX]; -#ifndef _XBOX - sprintf(binname, "%06X.bin", decompack->tableEnts[i].table); -#else - sprintf(binname, "%s%06X.bin", filename, decompack->tableEnts[i].table); -#endif - struct stat buf; - //add load/no load calculations here - if (-1 != stat(binname, &buf)) - { - if (buf.st_size < buffer_size) - decompack->binfiles[i] = (uint8_t*)malloc(buf.st_size); - FILE* fp = fopen(binname, "rb"); - //use them here - if (fp) - { - if (buf.st_size < buffer_size) - { - fread(decompack->binfiles[i], buf.st_size, 1, fp); - fclose(fp); - buffer_size -= buf.st_size; - decompack->tableEnts[i].is_file = false; - } - else - { - decompack->binfiles[i] = (uint8_t*)fp; - decompack->tableEnts[i].is_file = true; - } - } - } - } - } - -#if !defined(_XBOX) && !defined(VITA) - chdir(temp_path); -#endif - - Copy7110 = &GetPackData; - CleanUp7110 = &Drop7110Gfx; -} - //Cache 1 clean up function void Del7110Gfx(void) { - int32_t i; - if (Settings.SPC7110) - { - Do7110Logging(); - } - for (i = 0; i < MAX_TABLES; i++) - { - if (decompack->binfiles[i] != NULL) - { - free(decompack->binfiles[i]); - decompack->binfiles[i] = NULL; - } - } + spc7110dec_deinit(); Settings.SPC7110 = false; Settings.SPC7110RTC = false; - if (NULL != decompack) - free(decompack); - decompack = NULL; - CleanUp7110 = NULL; - Copy7110 = NULL; -} - -//Cache2 cleanup function -void Close7110Gfx(void) -{ - int32_t i; - if (Settings.SPC7110) - { - Do7110Logging(); - } - for (i = 0; i < MAX_TABLES; i++) - { - if (decompack->binfiles[i] != NULL) - { - fclose((FILE*)decompack->binfiles[i]); - decompack->binfiles[i] = NULL; - } - } - Settings.SPC7110 = false; - Settings.SPC7110RTC = false; - if (NULL != decompack) - free(decompack); - decompack = NULL; - CleanUp7110 = NULL; - Copy7110 = NULL; -} - -//cache 3's clean-up code -void Drop7110Gfx(void) -{ - int32_t i; - if (Settings.SPC7110) - { - Do7110Logging(); - } - for (i = 0; i < MAX_TABLES; i++) - { - if (decompack->binfiles[i] != NULL) - { - if (decompack->tableEnts[i].is_file) - { - fclose((FILE*)decompack->binfiles[i]); - decompack->binfiles[i] = NULL; - } - else - { - free(decompack->binfiles[i]); - decompack->binfiles[i] = NULL; - } - } - } - Settings.SPC7110 = false; - Settings.SPC7110RTC = false; - if (NULL != decompack) - free(decompack); - decompack = NULL; - CleanUp7110 = NULL; - Copy7110 = NULL; } //emulate a reset. @@ -1880,266 +1089,5 @@ void S9xSpc7110Reset(void) s7r.AlignBy = 1; s7r.bank50Internal = 0; memset(s7r.bank50, 0x00, DECOMP_BUFFER_SIZE); -} - -//outputs a cumulative log for the game. -//there's nothing really weird here, just -//reading the old log, and writing a new one. -//note the logs are explicitly little-endian, not host byte order. -void Do7110Logging(void) -{ - uint8_t ent_temp; - FILE* flog; - int32_t entries = 0; - - if (Settings.SPC7110) - { - //flush last read into logging - (*Copy7110)(); - - if (!strncmp((char*)&Memory.ROM [0xffc0], "SUPER POWER LEAG 4 ", 21)) - { -#ifdef _XBOX - flog = fopen("T:\\spl4-sp7.dat", "rb"); -#else - flog = fopen("spl4-sp7.dat", "rb"); -#endif - } - else if (!strncmp((char*)&Memory.ROM [0xffc0], "MOMOTETSU HAPPY ", 21)) - { -#ifdef _XBOX - flog = fopen("T:\\smht-sp7.dat", "rb"); -#else - flog = fopen("smht-sp7.dat", "rb"); -#endif - } - else if (!strncmp((char*)&Memory.ROM [0xffc0], "HU TENGAI MAKYO ZERO ", 21)) - { -#ifdef _XBOX - flog = fopen("T:\\feoezsp7.dat", "rb"); -#else - flog = fopen("feoezsp7.dat", "rb"); -#endif - } - else if (!strncmp((char*)&Memory.ROM [0xffc0], "JUMP TENGAIMAKYO ZERO", 21)) - { -#ifdef _XBOX - flog = fopen("T:\\sjumpsp7.dat", "rb"); -#else - flog = fopen("sjumpsp7.dat", "rb"); -#endif - } - else - { -#ifdef _XBOX - flog = fopen("T:\\misc-sp7.dat", "rb"); -#else - flog = fopen("misc-sp7.dat", "rb"); -#endif - } - - if (flog) - { - uint8_t buffer[8]; - int32_t table = 0; - uint16_t offset = 0; - uint16_t length = 0; - fseek(flog, 35, 0); - - int32_t f_len; - while (1) - { - int32_t i = 0; - Data7110* log = NULL; - f_len = fread(buffer, 1, 8, flog); - if (f_len < 8) break; - - table = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16); - offset = buffer[6] | (buffer[7] << 8); - length = buffer[4] | (buffer[5] << 8); - while (i < MAX_TABLES && log == NULL) - { - if (decompack->tableEnts[i].table == table) - { - log = &(decompack->tableEnts[i].location[(buffer[3])]); - if ((log->used_offset + log->used_len) < (offset + length)) - { - log->used_offset = offset; - log->used_len = length; - } - } - i++; - } - } - fclose(flog); - } - - - if (!strncmp((char*)&Memory.ROM [0xffc0], "SUPER POWER LEAG 4 ", 21)) - { -#ifdef _XBOX // cwd could be the dvd-rom, so write to T:\\ which is storage region for each title - flog = fopen("T:\\spl4-sp7.dat", "wb"); -#else - flog = fopen("spl4-sp7.dat", "wb"); -#endif - } - else if (!strncmp((char*)&Memory.ROM [0xffc0], "MOMOTETSU HAPPY ", 21)) - { -#ifdef _XBOX - flog = fopen("T:\\smht-sp7.dat", "wb"); -#else - flog = fopen("smht-sp7.dat", "wb"); -#endif - } - else if (!strncmp((char*)&Memory.ROM [0xffc0], "HU TENGAI MAKYO ZERO ", 21)) - { -#ifdef _XBOX - flog = fopen("T:\\feoezsp7.dat", "wb"); -#else - flog = fopen("feoezsp7.dat", "wb"); -#endif - } - else if (!strncmp((char*)&Memory.ROM [0xffc0], "JUMP TENGAIMAKYO ZERO", 21)) - { -#ifdef _XBOX - flog = fopen("T:\\sjumpsp7.dat", "wb"); -#else - flog = fopen("sjumpsp7.dat", "wb"); -#endif - } - else - { -#ifdef _XBOX - flog = fopen("T:\\misc-sp7.dat", "wb"); -#else - flog = fopen("misc-sp7.dat", "wb"); -#endif - } - //count entries - if (flog) - { - int32_t j = 0; - int32_t temp = 0; - for (j = 0; j < MAX_TABLES; j++) - { - int32_t k; - for (k = 0; k < 256; k++) - { - if (decompack->tableEnts[j].location[k].used_len != 0) - entries++; - } - } - ent_temp = entries & 0xFF; - fwrite(&ent_temp, 1, 1, flog); - ent_temp = (entries >> 8) & 0xFF; - fwrite(&ent_temp, 1, 1, flog); - ent_temp = (entries >> 16) & 0xFF; - fwrite(&ent_temp, 1, 1, flog); - ent_temp = (entries >> 24) & 0xFF; - fwrite(&ent_temp, 1, 1, flog); - fwrite(&temp, 1, 4, flog); - fwrite(&temp, 1, 4, flog); - fwrite(&temp, 1, 4, flog); - fwrite(&temp, 1, 4, flog); - fwrite(&temp, 1, 4, flog); - fwrite(&temp, 1, 4, flog); - fwrite(&temp, 1, 4, flog); - - ent_temp = 0; - fwrite(&ent_temp, 1, 1, flog); - ent_temp = 0; - fwrite(&ent_temp, 1, 1, flog); - ent_temp = 0; - fwrite(&ent_temp, 1, 1, flog); - - for (j = 0; j < MAX_TABLES; j++) - { - int32_t k; - for (k = 0; k < 256; k++) - { - if (decompack->tableEnts[j].location[k].used_len != 0) - { - ent_temp = decompack->tableEnts[j].table & 0xFF; - fwrite(&ent_temp, 1, 1, flog); //801 - ent_temp = (decompack->tableEnts[j].table >> 8) & 0xFF;; - fwrite(&ent_temp, 1, 1, flog); //802 - ent_temp = (decompack->tableEnts[j].table >> 16) & 0xFF;; - fwrite(&ent_temp, 1, 1, flog); //803 - ent_temp = k & 0xFF; - fwrite(&ent_temp, 1, 1, flog); //804 - ent_temp = decompack->tableEnts[j].location[k].used_len & 0xFF; - fwrite(&ent_temp, 1, 1, flog); //lsb of - ent_temp = (decompack->tableEnts[j].location[k].used_len >> 8) & 0xFF; - fwrite(&ent_temp, 1, 1, flog); //msb of - ent_temp = (decompack->tableEnts[j].location[k].used_offset) & 0xFF; - fwrite(&ent_temp, 1, 1, flog); //lsb of - ent_temp = (decompack->tableEnts[j].location[k].used_offset >> 8) & 0xFF; - fwrite(&ent_temp, 1, 1, flog); //msb of - } - } - } - fwrite(&temp, 1, 4, flog); - fwrite(&temp, 1, 4, flog); - fclose(flog); - } - } -} - -bool S9xSaveSPC7110RTC(S7RTC* rtc_f9) -{ - FILE* fp; - - if ((fp = fopen(S9xGetFilename("rtc"), "wb")) == NULL) - return (false); - int32_t i = 0; - uint8_t temp = 0; - for (i = 0; i < 16; i++) - fwrite(&rtc_f9->reg[i], 1, 1, fp); - temp = rtc_f9->index & 0x00FF; - fwrite(&temp, 1, 1, fp); - temp = (rtc_f9->index) >> 8; - fwrite(&temp, 1, 1, fp); - temp = (uint8_t)rtc_f9->control; - fwrite(&temp, 1, 1, fp); - temp = (uint8_t)rtc_f9->init; - fwrite(&temp, 1, 1, fp); - temp = rtc_f9->last_used & 0x00FF; - fwrite(&temp, 1, 1, fp); - temp = (rtc_f9->last_used >> 8) & 0x00FF; - fwrite(&temp, 1, 1, fp); - temp = (rtc_f9->last_used >> 16) & 0x00FF; - fwrite(&temp, 1, 1, fp); - temp = (rtc_f9->last_used >> 24) & 0x00FF;; - fwrite(&temp, 1, 1, fp); - fclose(fp); - return (true); -} - -bool S9xLoadSPC7110RTC(S7RTC* rtc_f9) -{ - FILE* fp; - - if ((fp = fopen(S9xGetFilename("rtc"), "rb")) == NULL) - return (false); - int32_t i; - for (i = 0; i < 16; i++) - fread(&(rtc_f9->reg[i]), 1, 1, fp); - uint8_t temp = 0; - fread(&temp, 1, 1, fp); - rtc_f9->index = temp; - fread(&temp, 1, 1, fp); - rtc_f9->index |= (temp << 8); - fread(&rtc_f9->control, 1, 1, fp); - fread(&rtc_f9->init, 1, 1, fp); - - fread(&temp, 1, 1, fp); - rtc_f9->last_used = temp; - fread(&temp, 1, 1, fp); - rtc_f9->last_used |= (temp << 8); - fread(&temp, 1, 1, fp); - rtc_f9->last_used |= (temp << 16); - fread(&temp, 1, 1, fp); - rtc_f9->last_used |= (temp << 24); - fclose(fp); - return (true); + spc7110dec_reset(); } diff --git a/source/spc7110.h b/source/spc7110.h index dd93d50..a5edea6 100644 --- a/source/spc7110.h +++ b/source/spc7110.h @@ -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 diff --git a/source/spc7110dec.c b/source/spc7110dec.c new file mode 100644 index 0000000..8a25684 --- /dev/null +++ b/source/spc7110dec.c @@ -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); +} diff --git a/source/spc7110dec.h b/source/spc7110dec.h new file mode 100644 index 0000000..e03a855 --- /dev/null +++ b/source/spc7110dec.h @@ -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 diff --git a/source/srtc.c b/source/srtc.c index 9e7c2e9..5de0c8a 100644 --- a/source/srtc.c +++ b/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; diff --git a/source/srtc.h b/source/srtc.h index 98fe369..2bd3490 100644 --- a/source/srtc.h +++ b/source/srtc.h @@ -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 -- cgit v1.2.3