From 2b9a9dc05b5c4abdf5dac5ceba9300734d4f1b65 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 14:47:59 -0500 Subject: Decide whether SuperFX and SA-1 chips are enabled only once per frame. This saves a few million instructions per second. (Inspired by Snes9x-Euphoria) --- source/cpuexec.cpp | 447 ++++++++++++++++++++++++++++++++++++++++++++++++++++- source/cpuexec.h | 11 +- source/dma.cpp | 8 +- 3 files changed, 459 insertions(+), 7 deletions(-) diff --git a/source/cpuexec.cpp b/source/cpuexec.cpp index c4836ec..a0c7ebc 100644 --- a/source/cpuexec.cpp +++ b/source/cpuexec.cpp @@ -111,7 +111,115 @@ extern void S9xProcessSound (unsigned int); +void S9xMainLoop_SA1_SFX (void); +void S9xMainLoop_SA1_NoSFX (void); +void S9xMainLoop_NoSA1_SFX (void); +void S9xMainLoop_NoSA1_NoSFX (void); + +/* + * This is a CATSFC modification inspired by a Snes9x-Euphoria modification. + * The emulator selects a main loop based on the chips used in an entire + * frame. This avoids the constant SA1.Executing and Settings.SuperFX checks. + * + * The original version of S9xMainLoop is S9xMainLoop_SA1_SFX below. Remember + * to propagate modifications to the SA1_NoSFX, NoSA1_SFX and NoSA1_NoSFX + * versions. + */ void S9xMainLoop (void) +{ + if (Settings.SA1) + { + if (Settings.SuperFX) S9xMainLoop_SA1_SFX (); + else /* if (!Settings.SuperFX) */ S9xMainLoop_SA1_NoSFX (); + } + else /* if (!Settings.SA1) */ + { + if (Settings.SuperFX) S9xMainLoop_NoSA1_SFX (); + else /* if (!Settings.SuperFX) */ S9xMainLoop_NoSA1_NoSFX (); + } +} + +void S9xMainLoop_SA1_SFX (void) +{ + for (;;) + { + APU_EXECUTE (); + + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + S9xOpcode_NMI (); + } + } + + CHECK_SOUND (); + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + { + if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) + CPU.IRQCycleCount=1; + } + } + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif + CPU.Cycles += CPU.MemSpeed; + + (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); + + if (SA1.Executing) + S9xSA1MainLoop (); + DO_HBLANK_CHECK_SFX(); + } + + ICPU.Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + IAPU.Registers.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus (); + if (CPU.Flags & SCAN_KEYS_FLAG) + { + S9xSyncSpeed (); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } + +#ifdef DETECT_NASTY_FX_INTERLEAVE + if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2) + { + CPU.TriedInterleavedMode2 = TRUE; + CPU.BRKTriggered = FALSE; + S9xDeinterleaveMode2 (); + } +#endif +} + +void S9xMainLoop_SA1_NoSFX (void) { for (;;) { @@ -168,7 +276,76 @@ void S9xMainLoop (void) if (SA1.Executing) S9xSA1MainLoop (); - DO_HBLANK_CHECK(); + DO_HBLANK_CHECK_NoSFX(); + } + + ICPU.Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + IAPU.Registers.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus (); + if (CPU.Flags & SCAN_KEYS_FLAG) + { + S9xSyncSpeed (); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } +} + +void S9xMainLoop_NoSA1_SFX (void) +{ + for (;;) + { + APU_EXECUTE (); + + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + S9xOpcode_NMI (); + } + } + + CHECK_SOUND (); + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + { + if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) + CPU.IRQCycleCount=1; + } + } + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif + CPU.Cycles += CPU.MemSpeed; + + (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); + + DO_HBLANK_CHECK_SFX(); } ICPU.Registers.PC = CPU.PC - CPU.PCBase; @@ -191,6 +368,75 @@ void S9xMainLoop (void) #endif } +void S9xMainLoop_NoSA1_NoSFX (void) +{ + for (;;) + { + APU_EXECUTE (); + + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + S9xOpcode_NMI (); + } + } + + CHECK_SOUND (); + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + { + if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ)) + CPU.IRQCycleCount=1; + } + } + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif + CPU.Cycles += CPU.MemSpeed; + + (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) (); + + DO_HBLANK_CHECK_NoSFX(); + } + + ICPU.Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + IAPU.Registers.PC = IAPU.PC - IAPU.RAM; + S9xAPUPackStatus (); + if (CPU.Flags & SCAN_KEYS_FLAG) + { + S9xSyncSpeed (); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } +} + void S9xSetIRQ (uint32 source) { CPU.IRQActive |= source; @@ -211,7 +457,15 @@ void S9xClearIRQ (uint32 source) CLEAR_IRQ_SOURCE (source); } -void S9xDoHBlankProcessing () +/* + * This is a CATSFC modification inspired by a Snes9x-Euphoria modification. + * The emulator selects an HBlank processor based on the chips used in an + * entire frame. This avoids the constant Settings.SuperFX checks. + * + * The original version of S9xDoHBlankProcessing is S9xDoHBlankProcessing_SFX + * below. Remember to propagate modifications to the NoSFX version. + */ +void S9xDoHBlankProcessing_SFX () { #ifdef CPU_SHUTDOWN CPU.WaitCounter++; @@ -401,4 +655,193 @@ void S9xDoHBlankProcessing () S9xReschedule (); } +void S9xDoHBlankProcessing_NoSFX () +{ +#ifdef CPU_SHUTDOWN + CPU.WaitCounter++; +#endif + switch (CPU.WhichEvent) + { + case HBLANK_START_EVENT: +#ifdef SYNC_JOYPAD_AT_HBLANK + // Re-get the controls every hblank. A resolution algorithm in + // ppu.cpp will determine with greater accuracy whether a key was + // pressed or released during the frame. + uint32 i; + for (i = 0; i < 5; i++) + { + IPPU.JoypadsAtHBlanks [i][CPU.V_Counter] = S9xReadJoypad (i); + } +#endif + if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) + IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); + + break; + + case HBLANK_END_EVENT: + +#ifndef STORM + if (Settings.SoundSync) + S9xGenerateSound (); +#endif + + CPU.Cycles -= Settings.H_Max; + if (IAPU.APUExecuting) + { + APU.Cycles -= Settings.H_Max; +#ifdef MK_APU + S9xCatchupCount(); +#endif + } + else + APU.Cycles = 0; + + CPU.NextEvent = -1; + ICPU.Scanline++; + + if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) + { + CPU.V_Counter = 0; + Memory.FillRAM[0x213F]^=0x80; + PPU.RangeTimeOver = 0; + CPU.NMIActive = FALSE; + ICPU.Frame++; + PPU.HVBeamCounterLatched = 0; + CPU.Flags |= SCAN_KEYS_FLAG; + S9xStartHDMA (); + } + + S9xProcessSound (0); + + if (PPU.VTimerEnabled && !PPU.HTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos) + { + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + + if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + // Start of V-blank + S9xEndScreenRefresh (); + IPPU.HDMA = 0; + // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. + missing.dma_this_frame = 0; + IPPU.MaxBrightness = PPU.Brightness; + PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; + + if(!PPU.ForcedBlanking) + { + PPU.OAMAddr = PPU.SavedOAMAddr; + + uint8 tmp = 0; + if(PPU.OAMPriorityRotation) + tmp = (PPU.OAMAddr&0xFE)>>1; + if((PPU.OAMFlip&1) || PPU.FirstSprite!=tmp) + { + PPU.FirstSprite=tmp; + IPPU.OBJChanged=TRUE; + } + + PPU.OAMFlip = 0; + } + + Memory.FillRAM[0x4210] = 0x80 |Model->_5A22; + if (Memory.FillRAM[0x4200] & 0x80) + { + CPU.NMIActive = TRUE; + CPU.Flags |= NMI_FLAG; + CPU.NMICycleCount = CPU.NMITriggerPoint; + } + +#ifdef OLD_SNAPSHOT_CODE + if (CPU.Flags & SAVE_SNAPSHOT_FLAG) + { + CPU.Flags &= ~SAVE_SNAPSHOT_FLAG; + Registers.PC = CPU.PC - CPU.PCBase; + S9xPackStatus (); + S9xAPUPackStatus (); + Snapshot (NULL); + } +#endif + } + + if (CPU.V_Counter == PPU.ScreenHeight + 3) + S9xUpdateJoypads (); + + if (CPU.V_Counter == FIRST_VISIBLE_LINE) + { + Memory.FillRAM[0x4210] = Model->_5A22; + CPU.Flags &= ~NMI_FLAG; + S9xStartScreenRefresh (); + } + if (CPU.V_Counter >= FIRST_VISIBLE_LINE && + CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE); + } + // Use TimerErrorCounter to skip update of SPC700 timers once + // every 128 updates. Needed because this section of code is called + // once every emulated 63.5 microseconds, which coresponds to + // 15.750KHz, but the SPC700 timers need to be updated at multiples + // of 8KHz, hence the error correction. +// IAPU.TimerErrorCounter++; +// if (IAPU.TimerErrorCounter >= ) +// IAPU.TimerErrorCounter = 0; +// else + { + if (APU.TimerEnabled [2]) + { + APU.Timer [2] += 4; + while (APU.Timer [2] >= APU.TimerTarget [2]) + { + IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; + APU.Timer [2] -= APU.TimerTarget [2]; +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + IAPU.APUExecuting = TRUE; +#endif + } + } + if (CPU.V_Counter & 1) + { + if (APU.TimerEnabled [0]) + { + APU.Timer [0]++; + if (APU.Timer [0] >= APU.TimerTarget [0]) + { + IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; + APU.Timer [0] = 0; +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + IAPU.APUExecuting = TRUE; +#endif + } + } + if (APU.TimerEnabled [1]) + { + APU.Timer [1]++; + if (APU.Timer [1] >= APU.TimerTarget [1]) + { + IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; + APU.Timer [1] = 0; +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + IAPU.APUExecuting = TRUE; +#endif + } + } + } + } + break; + + case HTIMER_BEFORE_EVENT: + case HTIMER_AFTER_EVENT: + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)) + { + S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE); + } + break; + } + + S9xReschedule (); +} diff --git a/source/cpuexec.h b/source/cpuexec.h index a094220..dab9099 100644 --- a/source/cpuexec.h +++ b/source/cpuexec.h @@ -93,9 +93,13 @@ #include "memmap.h" #include "65c816.h" -#define DO_HBLANK_CHECK() \ +#define DO_HBLANK_CHECK_SFX() \ if (CPU.Cycles >= CPU.NextEvent) \ - S9xDoHBlankProcessing (); + S9xDoHBlankProcessing_SFX (); + +#define DO_HBLANK_CHECK_NoSFX() \ + if (CPU.Cycles >= CPU.NextEvent) \ + S9xDoHBlankProcessing_NoSFX (); struct SOpcodes { #ifdef __WIN32__ @@ -126,7 +130,8 @@ START_EXTERN_C void S9xMainLoop (void); void S9xReset (void); void S9xSoftReset (void); -void S9xDoHBlankProcessing (); +void S9xDoHBlankProcessing_SFX (); +void S9xDoHBlankProcessing_NoSFX (); void S9xClearIRQ (uint32); void S9xSetIRQ (uint32); diff --git a/source/dma.cpp b/source/dma.cpp index 2addceb..96f705f 100644 --- a/source/dma.cpp +++ b/source/dma.cpp @@ -855,8 +855,12 @@ void S9xDoDMA (uint8 Channel) IAPU.APUExecuting = Settings.APUEnabled; APU_EXECUTE (); #endif - while (CPU.Cycles > CPU.NextEvent) - S9xDoHBlankProcessing (); + if (Settings.SuperFX) + while (CPU.Cycles > CPU.NextEvent) + S9xDoHBlankProcessing_SFX (); + else /* if (!Settings.SuperFX) */ + while (CPU.Cycles > CPU.NextEvent) + S9xDoHBlankProcessing_NoSFX (); if(Settings.SPC7110&&spc7110_dma) { -- cgit v1.2.3 From 2b715684087675747df7cb8995695936f20c782b Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 14:49:18 -0500 Subject: Reverse the loop in MixStereo such that instead of "for each channel, for each playback sample, add into the mix buffer", the playback sample is instead written to the mix buffer only when fully mixed from the 8 SNES sound channels. Verified working with Secret of Mana, Super Bomberman 5 and Super Mario World. --- source/soundux.cpp | 438 ++++++++++++++++++++++++++++++++++++++++++++++------- source/soundux.h | 2 +- 2 files changed, 386 insertions(+), 54 deletions(-) diff --git a/source/soundux.cpp b/source/soundux.cpp index 5e7f865..1c05e77 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -131,18 +131,20 @@ #include "memmap.h" #include "cpuexec.h" -extern int Echo [24000]; -extern int DummyEchoBuffer [SOUND_BUFFER_SIZE]; -extern int MixBuffer [SOUND_BUFFER_SIZE]; -extern int EchoBuffer [SOUND_BUFFER_SIZE]; -extern int FilterTaps [8]; +extern int32 Echo [24000]; +extern int32 DummyEchoBuffer [SOUND_BUFFER_SIZE]; +extern int32 MixBuffer [SOUND_BUFFER_SIZE]; +extern int32 EchoBuffer [SOUND_BUFFER_SIZE]; +extern int32 FilterTaps [8]; +static uint8 FilterTapDefinitionBitfield; +// In the above, bit I is set if FilterTaps[I] is non-zero. extern unsigned long Z; -extern int Loop [16]; +extern int32 Loop [16]; extern long FilterValues[4][2]; -extern int NoiseFreq [32]; +extern int32 NoiseFreq [32]; -static int noise_gen; +static int32 noise_gen; #undef ABS #define ABS(a) ((a) < 0 ? -(a) : (a)) @@ -402,15 +404,11 @@ void S9xFixSoundAfterSnapshotLoad () void S9xSetFilterCoefficient (int tap, int value) { - FilterTaps [tap & 7] = value; - SoundData.no_filter = (FilterTaps [0] == 127 || FilterTaps [0] == 0) && - FilterTaps [1] == 0 && - FilterTaps [2] == 0 && - FilterTaps [3] == 0 && - FilterTaps [4] == 0 && - FilterTaps [5] == 0 && - FilterTaps [6] == 0 && - FilterTaps [7] == 0; + FilterTaps [tap & 7] = value; + if (value == 0 || (tap == 0 && value == 127)) + FilterTapDefinitionBitfield &= ~(1 << (tap & 7)); + else + FilterTapDefinitionBitfield |= 1 << (tap & 7); } void S9xSetSoundADSR (int channel, int attack_rate, int decay_rate, @@ -891,10 +889,337 @@ void DecodeBlock (Channel *ch) ch->block_pointer += 9; } +/* + * The layout of loops in this function is optimised for outputting a few + * samples, reducing the number of memory accesses per sample-channel pair. + * For each SAMPLE, each channel is mixed into CPU registers and + * assigned to the mix buffer. + */ +static inline void MixStereo_ReversedLoop (int sample_count) +{ + int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; + int32 VL[8], VR[8]; + int32 PreviousChannelSample; + + for (uint32 I = 0; I < (uint32) sample_count; I += 2) + { + int32 OutputLeft = 0, OutputRight = 0; + + for (uint32 J = 0; J < NUM_CHANNELS; J++) + { + Channel *ch = &SoundData.channels[J]; + + if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J))) + continue; + + unsigned long freq0 = ch->frequency; + + // freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux + freq0 = freq0 * 985/1000; + + bool8 mod = pitch_mod & (1 << J); + + if (I == 0) + { + if (ch->needs_decode) + { + DecodeBlock(ch); + ch->needs_decode = FALSE; + ch->sample = ch->block[0]; + ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; + if (ch->sample_pointer == 0) + ch->sample_pointer = 1; + if (ch->sample_pointer > SOUND_DECODE_LENGTH) + ch->sample_pointer = SOUND_DECODE_LENGTH - 1; + + ch->next_sample=ch->block[ch->sample_pointer]; + ch->interpolate = 0; + + if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod) + ch->interpolate = ((ch->next_sample - ch->sample) * + (long) freq0) / (long) FIXED_POINT; + } + VL [J] = (ch->sample * ch-> left_vol_level) / 128; + VR [J] = (ch->sample * ch->right_vol_level) / 128; + } + + unsigned long freq = freq0; + + if (mod) + freq = PITCH_MOD(freq, PreviousChannelSample); + + ch->env_error += ch->erate; + if (ch->env_error >= FIXED_POINT) + { + uint32 step = ch->env_error >> FIXED_POINT_SHIFT; + + switch (ch->state) + { + case SOUND_ATTACK: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_DECAY; + if (ch->sustain_level != 8) + { + S9xSetEnvRate (ch, ch->decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * ch->sustain_level) + >> 3); + break; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); + } + break; + + case SOUND_DECAY: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= ch->envx_target) + { + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); + } + break; + + case SOUND_SUSTAIN: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + case SOUND_RELEASE: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_INCREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, -1, 0); + } + break; + + case SOUND_INCREASE_BENT_LINE: + if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) + { + while (ch->env_error >= FIXED_POINT) + { + ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + } + else + { + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + } + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, -1, 0); + } + break; + + case SOUND_DECREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx -= step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_DECREASE_EXPONENTIAL: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_GAIN: + S9xSetEnvRate (ch, 0, -1, 0); + break; + } + ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; + ch->right_vol_level = (ch->envx * ch->volume_right) / 128; + VL [J] = (ch->sample * ch-> left_vol_level) / 128; + VR [J] = (ch->sample * ch->right_vol_level) / 128; + } + + ch->count += freq; + if (ch->count >= FIXED_POINT) + { + VL [J] = ch->count >> FIXED_POINT_SHIFT; + ch->sample_pointer += VL [J]; + ch->count &= FIXED_POINT_REMAINDER; + + ch->sample = ch->next_sample; + if (ch->sample_pointer >= SOUND_DECODE_LENGTH) + { + if (JUST_PLAYED_LAST_SAMPLE(ch)) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + do + { + ch->sample_pointer -= SOUND_DECODE_LENGTH; + if (ch->last_block) + { + if (!ch->loop) + { + ch->sample_pointer = LAST_SAMPLE; + ch->next_sample = ch->sample; + break; + } + else + { + S9xAPUSetEndX (J); + ch->last_block = FALSE; + uint8 *dir = S9xGetSampleAddress (ch->sample_number); + ch->block_pointer = READ_WORD(dir + 2); + } + } + DecodeBlock (ch); + } while (ch->sample_pointer >= SOUND_DECODE_LENGTH); + if (!JUST_PLAYED_LAST_SAMPLE (ch)) + ch->next_sample = ch->block [ch->sample_pointer]; + } + else + ch->next_sample = ch->block [ch->sample_pointer]; + + if (ch->type == SOUND_SAMPLE) + { + if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod) + { + ch->interpolate = ((ch->next_sample - ch->sample) * + (long) freq) / (long) FIXED_POINT; + ch->sample = (int16) (ch->sample + (((ch->next_sample - ch->sample) * + (long) (ch->count)) / (long) FIXED_POINT)); + } + else + ch->interpolate = 0; + } + else + { + // Snes9x 1.53's SPC_DSP.cpp, by blargg + int feedback = (noise_gen << 13) ^ (noise_gen << 14); + noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); + ch->sample = (noise_gen << 17) >> 17; + ch->interpolate = 0; + } + + VL [J] = (ch->sample * ch-> left_vol_level) / 128; + VR [J] = (ch->sample * ch->right_vol_level) / 128; + } + else + { + if (ch->interpolate) + { + int32 s = (int32) ch->sample + ch->interpolate; + + CLIP16(s); + ch->sample = (int16) s; + VL [J] = (ch->sample * ch-> left_vol_level) / 128; + VR [J] = (ch->sample * ch->right_vol_level) / 128; + } + } + + OutputLeft += VL [J]; + OutputRight += VR [J]; + + if (pitch_mod & (1 << (J + 1))) + PreviousChannelSample = ch->sample * ch->envx; + +#ifndef FOREVER_FORWARD_STEREO + ch->echo_buf_ptr [I ^ Settings.ReverseStereo ] += VL [J]; + ch->echo_buf_ptr [I + (1 ^ Settings.ReverseStereo)] += VR [J]; +#else + ch->echo_buf_ptr [I ] += VL [J]; + ch->echo_buf_ptr [I + 1] += VR [J]; +#endif +stereo_exit: + ; + } +#ifndef FOREVER_FORWARD_STEREO + MixBuffer [I ^ Settings.ReverseStereo ] = OutputLeft; + MixBuffer [I + (1 ^ Settings.ReverseStereo)] = OutputRight; +#else + MixBuffer [I ] = OutputLeft; + MixBuffer [I + 1] = OutputRight; +#endif + } +} + +#ifdef __DJGPP +END_OF_FUNCTION(MixStereo_ReversedLoop); +#endif + +/* + * The layout of loops in this function is optimised for outputting a lot of + * samples, quickly ignoring channels that are muted so that they're not + * processed any further before the function returns. + * For each CHANNEL, samples are mixed into the mix buffer until the channel + * is muted or the sample count is met. + */ static inline void MixStereo (int sample_count) { - static int wave[SOUND_BUFFER_SIZE]; + static int32 wave[SOUND_BUFFER_SIZE]; int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; @@ -1502,15 +1827,22 @@ void S9xMixSamples (uint8 *buffer, int sample_count) if (!so.mute_sound) { - memset (MixBuffer, 0, sample_count * sizeof (MixBuffer [0])); if (SoundData.echo_enable) memset (EchoBuffer, 0, sample_count * sizeof (EchoBuffer [0])); #ifndef FOREVER_STEREO if (so.stereo) + { #endif - MixStereo (sample_count); + if (sample_count < 12) + MixStereo_ReversedLoop (sample_count); + else + { + memset (MixBuffer, 0, sample_count * sizeof (MixBuffer [0])); + MixStereo (sample_count); + } #ifndef FOREVER_STEREO + } else MixMono (sample_count); #endif @@ -1537,7 +1869,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) { #endif // 16-bit stereo sound with echo enabled ... - if (SoundData.no_filter) + if (FilterTapDefinitionBitfield == 0) { // ... but no filter defined. for (J = 0; J < sample_count; J++) @@ -1567,13 +1899,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count) Loop [(Z - 0) & 15] = E; E = E * FilterTaps [0]; - E += Loop [(Z - 2) & 15] * FilterTaps [1]; - E += Loop [(Z - 4) & 15] * FilterTaps [2]; - E += Loop [(Z - 6) & 15] * FilterTaps [3]; - E += Loop [(Z - 8) & 15] * FilterTaps [4]; - E += Loop [(Z - 10) & 15] * FilterTaps [5]; - E += Loop [(Z - 12) & 15] * FilterTaps [6]; - E += Loop [(Z - 14) & 15] * FilterTaps [7]; + if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] * FilterTaps [1]; + if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] * FilterTaps [2]; + if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] * FilterTaps [3]; + if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] * FilterTaps [4]; + if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] * FilterTaps [5]; + if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] * FilterTaps [6]; + if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] * FilterTaps [7]; E /= 128; Z++; @@ -1596,7 +1928,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) else { // 16-bit mono sound with echo enabled... - if (SoundData.no_filter) + if (FilterTapDefinitionBitfield == 0) { // ... no filter defined for (J = 0; J < sample_count; J++) @@ -1625,13 +1957,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count) Loop [(Z - 0) & 7] = E; E = E * FilterTaps [0]; - E += Loop [(Z - 1) & 7] * FilterTaps [1]; - E += Loop [(Z - 2) & 7] * FilterTaps [2]; - E += Loop [(Z - 3) & 7] * FilterTaps [3]; - E += Loop [(Z - 4) & 7] * FilterTaps [4]; - E += Loop [(Z - 5) & 7] * FilterTaps [5]; - E += Loop [(Z - 6) & 7] * FilterTaps [6]; - E += Loop [(Z - 7) & 7] * FilterTaps [7]; + if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 1) & 7] * FilterTaps [1]; + if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 2) & 7] * FilterTaps [2]; + if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 3) & 7] * FilterTaps [3]; + if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 4) & 7] * FilterTaps [4]; + if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 5) & 7] * FilterTaps [5]; + if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 6) & 7] * FilterTaps [6]; + if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 7) & 7] * FilterTaps [7]; E /= 128; Z++; @@ -1691,7 +2023,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) if (so.stereo) { // 8-bit stereo sound with echo enabled... - if (SoundData.no_filter) + if (FilterTapDefinitionBitfield == 0) { // ... but no filter for (J = 0; J < sample_count; J++) @@ -1720,13 +2052,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count) Loop [(Z - 0) & 15] = E; E = E * FilterTaps [0]; - E += Loop [(Z - 2) & 15] * FilterTaps [1]; - E += Loop [(Z - 4) & 15] * FilterTaps [2]; - E += Loop [(Z - 6) & 15] * FilterTaps [3]; - E += Loop [(Z - 8) & 15] * FilterTaps [4]; - E += Loop [(Z - 10) & 15] * FilterTaps [5]; - E += Loop [(Z - 12) & 15] * FilterTaps [6]; - E += Loop [(Z - 14) & 15] * FilterTaps [7]; + if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] * FilterTaps [1]; + if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] * FilterTaps [2]; + if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] * FilterTaps [3]; + if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] * FilterTaps [4]; + if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] * FilterTaps [5]; + if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] * FilterTaps [6]; + if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] * FilterTaps [7]; E /= 128; Z++; @@ -1747,7 +2079,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) else { // 8-bit mono sound with echo enabled... - if (SoundData.no_filter) + if (FilterTapDefinitionBitfield == 0) { // ... but no filter. for (J = 0; J < sample_count; J++) @@ -1775,13 +2107,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count) Loop [(Z - 0) & 7] = E; E = E * FilterTaps [0]; - E += Loop [(Z - 1) & 7] * FilterTaps [1]; - E += Loop [(Z - 2) & 7] * FilterTaps [2]; - E += Loop [(Z - 3) & 7] * FilterTaps [3]; - E += Loop [(Z - 4) & 7] * FilterTaps [4]; - E += Loop [(Z - 5) & 7] * FilterTaps [5]; - E += Loop [(Z - 6) & 7] * FilterTaps [6]; - E += Loop [(Z - 7) & 7] * FilterTaps [7]; + if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 1) & 7] * FilterTaps [1]; + if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 2) & 7] * FilterTaps [2]; + if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 3) & 7] * FilterTaps [3]; + if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 4) & 7] * FilterTaps [4]; + if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 5) & 7] * FilterTaps [5]; + if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 6) & 7] * FilterTaps [6]; + if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 7) & 7] * FilterTaps [7]; E /= 128; Z++; @@ -1894,7 +2226,7 @@ void S9xResetSound (bool8 full) so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME / (1.0 / so.playback_rate)); else so.err_rate = 0; - SoundData.no_filter = TRUE; + FilterTapDefinitionBitfield = 0; } void S9xSetPlaybackRate (uint32 playback_rate) diff --git a/source/soundux.h b/source/soundux.h index 8fb8396..b603df8 100644 --- a/source/soundux.h +++ b/source/soundux.h @@ -212,7 +212,7 @@ typedef struct // Just incase they are needed in the future, for snapshot compatibility. uint32 dummy [3]; Channel channels [NUM_CHANNELS]; - bool8 no_filter; + // bool8 no_filter; int master_volume [2]; /* range is -128 .. 127 */ int echo_volume [2]; /* range is -128 .. 127 */ int noise_hertz; -- cgit v1.2.3 From f2f7ef3fe9ac8333b1db09b023dac191ed4736fb Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 17:07:26 -0500 Subject: Fix Tools/Global hotkeys/* refusing to work by touch. --- source/nds/gui.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index 09e01ac..9dfe95b 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -3727,7 +3727,6 @@ u32 menu(u16 *screen) && current_menu != ((main_menu.options +1)->sub_menu->options + 3)->sub_menu && current_menu != (main_menu.options +3)->sub_menu && current_menu != ((main_menu.options +3)->sub_menu->options + 1)->sub_menu - && current_menu != ((main_menu.options +3)->sub_menu->options + 2)->sub_menu && current_menu != (main_menu.options +6)->sub_menu && current_menu != ((main_menu.options +6)->sub_menu->options + 2)->sub_menu) { -- cgit v1.2.3 From 6e69c6201b3072acdf111f3fd268b640fde58326 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 19:19:18 -0500 Subject: Fix uninitialised memory access in pitch modulation. --- source/soundux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/soundux.cpp b/source/soundux.cpp index 1c05e77..d7d9011 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -899,7 +899,7 @@ static inline void MixStereo_ReversedLoop (int sample_count) { int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; int32 VL[8], VR[8]; - int32 PreviousChannelSample; + int32 PreviousChannelSample = 0; for (uint32 I = 0; I < (uint32) sample_count; I += 2) { -- cgit v1.2.3 From 365a69d72ebfc986a59d269359bf04f53a18a8e5 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 19:44:37 -0500 Subject: Release 1.24. --- README.md | 2 +- source/nds/gui.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b55f80d..9877d3b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -CATSFC version 1.23, 2013-01-22 +CATSFC version 1.24, 2013-01-26 A Super Nintendo emulator for the Supercard DSTWO. diff --git a/source/nds/gui.c b/source/nds/gui.c index 9dfe95b..93b3e7b 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.23" +#define NDSSFC_VERSION "1.24" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From e473daf461ed5c32e9629f51bd1009a1270ec8db Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 20:16:02 -0500 Subject: 8 is NUM_CHANNELS. (magic constant) --- source/soundux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/soundux.cpp b/source/soundux.cpp index d7d9011..0435476 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -898,7 +898,7 @@ void DecodeBlock (Channel *ch) static inline void MixStereo_ReversedLoop (int sample_count) { int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; - int32 VL[8], VR[8]; + int32 VL[NUM_CHANNELS], VR[NUM_CHANNELS]; int32 PreviousChannelSample = 0; for (uint32 I = 0; I < (uint32) sample_count; I += 2) -- cgit v1.2.3 From dded2161378bdf0ead156f47f2473872854fc129 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 26 Jan 2013 20:31:11 -0500 Subject: Turn off the lower screen's backlight when returning from suspend during emulation. --- source/nds/entry.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 13486b0..45360a8 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -1081,6 +1081,10 @@ unsigned int S9xReadJoypad (int which1) mdelay(1); } while (inputdata.key & KEY_LID); ds2_wakeup(); + // Before starting to emulate again, turn off the lower + // screen's backlight. + mdelay(100); // needed to avoid ds2_setBacklight crashing + ds2_setBacklight(2); set_cpu_clock(clock_speed_number); } -- cgit v1.2.3 From 362b28e9372d124ac6602bfc49e9775e510ba929 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 27 Jan 2013 00:30:48 -0500 Subject: Suspend on lid-close in the menu. --- source/nds/gui.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/source/nds/gui.c b/source/nds/gui.c index 93b3e7b..ece310c 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -324,6 +324,21 @@ gui_action_type get_gui_input(void) key = getKey(); + if (key & KEY_LID) + { + ds2_setSupend(); + struct key_buf inputdata; + do { + ds2_getrawInput(&inputdata); + mdelay(1); + } while (inputdata.key & KEY_LID); + ds2_wakeup(); + // In the menu, the lower screen's backlight needs to be on, + // and it is on right away after resuming from suspend. + // mdelay(100); // needed to avoid ds2_setBacklight crashing + // ds2_setBacklight(3); + } + switch(key) { case KEY_UP: -- cgit v1.2.3 From cfa1c811c65f1b8a10d9034a5974d617cda92ec6 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 27 Jan 2013 00:45:59 -0500 Subject: Reimplement Quicksort correctly for file selection screens. Before this commit, the emulator could sometimes give a file out of its order, for example an O* file between two S* files. --- source/nds/gui.c | 69 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index ece310c..c57c660 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -435,53 +435,52 @@ void change_ext(char *src, char *buffer, char *extension) --------------------------------------------------------*/ static int sort_function(const void *dest_str_ptr, const void *src_str_ptr) { - char *dest_str = *((char **)dest_str_ptr); - char *src_str = *((char **)src_str_ptr); + char *dest_str = ((char *)dest_str_ptr); + char *src_str = ((char *)src_str_ptr); // For files and directories, . and .. sort first. - if(src_str[0] == '.') + if(src_str[0] == '.' && dest_str[0] != '.') return 1; - if(dest_str[0] == '.') + if(dest_str[0] == '.' && src_str[0] != '.') return -1; return strcasecmp(dest_str, src_str); } -static int my_array_partion(void *array, int left, int right) +static int my_array_partion(void **array, int left, int right) { - unsigned int pivot= *((unsigned int*)array + left); - - while(left < right) - { - while(sort_function((void*)((unsigned int*)array+left), (void*)((unsigned int *)array+right)) < 0) { - right--; - } - - if(right== left) break; - *((unsigned int*)array + left) = *((unsigned int*)array + right); - *((unsigned int*)array + right) = pivot; - - if(left < right) - { - left++; - if(right== left) break; - } - - while(sort_function((void*)((unsigned int*)array+right), (void*)((unsigned int *)array+left)) > 0) { - left++; - } + // Choose a pivot, left <= pivot <= right + unsigned int pivotIndex = left + (right - left) / 2; + + // Move pivot value to the end + void *temp = array[pivotIndex]; + array[pivotIndex] = array[right]; + array[right] = temp; + + // Move values that sort before the pivot value to before the new + // pivot's location + unsigned int storeIndex = left, i; + for (i = left; i <= right - 1; i++) + { + if (sort_function(array[i], array[right]) < 0) + { + temp = array[i]; + array[i] = array[storeIndex]; + array[storeIndex] = temp; + storeIndex++; + } + } - if(left== right) break; - *((unsigned int*)array + right) = *((unsigned int*)array + left); - *((unsigned int*)array + left) = pivot; - right--; - } + // Move the pivot value to its correct location + temp = array[storeIndex]; + array[storeIndex] = array[right]; + array[right] = temp; - return left; + return storeIndex; } -static void my_qsort(void *array, int left, int right) +static void my_qsort(void **array, int left, int right) { if(left < right) { @@ -748,9 +747,9 @@ static int load_file_list(struct FILE_LIST_INFO *filelist_infop) #if 0 my_qsort((void *)file_list, 0, num_files-1); #else //to support ".." directory, but take it as file - my_qsort((void *)file_list, 1, num_files-1); + my_qsort((void **)file_list, 1, num_files-1); #endif - my_qsort((void *)dir_list, 0, num_dirs-1); + my_qsort((void **)dir_list, 0, num_dirs-1); return 0; } -- cgit v1.2.3 From 4ff8eab0d01c76c58e1165e5c63f87e1f5134033 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 27 Jan 2013 15:36:49 -0500 Subject: Assign a filter-related variable right after other filter-related variables. --- source/soundux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/soundux.cpp b/source/soundux.cpp index 0435476..124ce6d 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -2188,6 +2188,7 @@ void S9xResetSound (bool8 full) FilterTaps [5] = 0; FilterTaps [6] = 0; FilterTaps [7] = 0; + FilterTapDefinitionBitfield = 0; so.mute_sound = TRUE; noise_gen = 1; so.sound_switch = 255; @@ -2226,7 +2227,6 @@ void S9xResetSound (bool8 full) so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME / (1.0 / so.playback_rate)); else so.err_rate = 0; - FilterTapDefinitionBitfield = 0; } void S9xSetPlaybackRate (uint32 playback_rate) -- cgit v1.2.3 From f0fab191e48f165c551980d724bba2f26a764795 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Tue, 29 Jan 2013 22:24:20 -0500 Subject: Prevent a file descriptor becoming unusable if the emulator configuration file is not in the correct format. --- source/nds/gui.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/nds/gui.c b/source/nds/gui.c index c57c660..fd9007b 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -4335,6 +4335,10 @@ int load_emu_config_file(void) fclose(fp); return 0; } + else + { + fclose(fp); + } } //have no confiure file, set default -- cgit v1.2.3 From f385752705de73b04cbbda735a71f14c19e241a6 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 00:33:30 -0500 Subject: memcpy vs memmove: memmove correctly handles overlapping source and destination memory buffers, but is slower than memcpy in many implementations. When memory buffers don't overlap, memcpy may be more efficient. The DS2 SDK is such an implementation, so change many memmoves into memcpys. --- source/apu.cpp | 16 ++++++++--- source/c4emu.cpp | 1 + source/cheats.cpp | 3 ++ source/cheats2.cpp | 1 + source/clip.cpp | 12 +++++--- source/gfx.cpp | 17 +++++++---- source/loadzip.cpp | 8 +++--- source/memmap.cpp | 81 ++++++++++++++++++++++++++++++++++++++--------------- source/sa1.cpp | 4 ++- source/snaporig.cpp | 6 ++-- source/snapshot.cpp | 14 ++++++--- source/srtc.cpp | 12 +++++--- 12 files changed, 125 insertions(+), 50 deletions(-) diff --git a/source/apu.cpp b/source/apu.cpp index 3c1a5d3..d60cc75 100644 --- a/source/apu.cpp +++ b/source/apu.cpp @@ -177,8 +177,12 @@ void S9xResetAPU () ZeroMemory (IAPU.CachedSamples, 0x40000); ZeroMemory (APU.OutPorts, 4); IAPU.DirectPage = IAPU.RAM; - memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); - memmove (APU.ExtraRAM, APUROM, sizeof (APUROM)); + // memmove converted: Different mallocs [Neb] + // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] + memcpy (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); + // memmove converted: Different mallocs [Neb] + // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] + memcpy (APU.ExtraRAM, APUROM, sizeof (APUROM)); IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8); APU.Cycles = 0; IAPU.Registers.YA.W = 0; @@ -874,7 +878,9 @@ void S9xSetAPUControl (uint8 byte) { if (!APU.ShowROM) { - memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); + // memmove converted: Different mallocs [Neb] + // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] + memcpy (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); APU.ShowROM = TRUE; } } @@ -883,7 +889,9 @@ void S9xSetAPUControl (uint8 byte) if (APU.ShowROM) { APU.ShowROM = FALSE; - memmove (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM)); + // memmove converted: Different mallocs [Neb] + // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] + memcpy (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM)); } } IAPU.RAM [0xf1] = byte; diff --git a/source/c4emu.cpp b/source/c4emu.cpp index a8fcce9..be08f07 100644 --- a/source/c4emu.cpp +++ b/source/c4emu.cpp @@ -878,6 +878,7 @@ void S9xSetC4 (uint8 byte, uint16 Address) if(byte != 0) printf("C4 load: non-0 written to $7f47! Wrote %02x\n", byte); if(READ_WORD(Memory.C4RAM+0x1f45) < 0x6000 || (READ_WORD(Memory.C4RAM+0x1f45) + READ_WORD(Memory.C4RAM+0x1f43)) > 0x6c00) printf("C4 load: Dest unusual! It's %04x\n", READ_WORD(Memory.C4RAM+0x1f45)); #endif + // memmove required: Can overlap arbitrarily [Neb] memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff), S9xGetMemPointer(READ_3WORD(Memory.C4RAM+0x1f40)), READ_WORD(Memory.C4RAM+0x1f43)); diff --git a/source/cheats.cpp b/source/cheats.cpp index dc388d2..9c4a8f2 100644 --- a/source/cheats.cpp +++ b/source/cheats.cpp @@ -190,8 +190,11 @@ const char *S9xGameGenieToRaw (const char *code, uint32 *address, uint8 *byte) void S9xStartCheatSearch (SCheatData *d) { + // memmove may be required: Source is usually a different malloc, but could be pointed to d->CWRAM [Neb] memmove (d->CWRAM, d->RAM, 0x20000); + // memmove may be required: Source is usually a different malloc, but could be pointed to d->CSRAM [Neb] memmove (d->CSRAM, d->SRAM, 0x10000); + // memmove may be required: Source is usually a different malloc, but could be pointed to d->CIRAM [Neb] memmove (d->CIRAM, &d->FillRAM [0x3000], 0x2000); memset ((char *) d->WRAM_BITS, 0xff, 0x20000 >> 3); memset ((char *) d->SRAM_BITS, 0xff, 0x10000 >> 3); diff --git a/source/cheats2.cpp b/source/cheats2.cpp index e5a7b0f..59855b9 100644 --- a/source/cheats2.cpp +++ b/source/cheats2.cpp @@ -128,6 +128,7 @@ void S9xDeleteCheat (uint32 which1) if (Cheat.c [which1].enabled) S9xRemoveCheat (which1); + // memmove required: Overlapping addresses [Neb] memmove (&Cheat.c [which1], &Cheat.c [which1 + 1], sizeof (Cheat.c [0]) * (Cheat.num_cheats - which1 - 1)); Cheat.num_cheats--; //MK: This used to set it to 0?? diff --git a/source/clip.cpp b/source/clip.cpp index 57204ac..7147abf 100644 --- a/source/clip.cpp +++ b/source/clip.cpp @@ -291,7 +291,8 @@ void ComputeClipWindows () if (BAND_EMPTY(Win1[0])) { B = Window2Enabled; - memmove (Bands, Win2, + // memmove converted: Different stack allocations [Neb] + memcpy (Bands, Win2, sizeof(Win2[0]) * Window2Enabled); } else @@ -355,7 +356,8 @@ void ComputeClipWindows () // use window 1 as the clipping (which // could also be empty). B = Window1Enabled; - memmove (Bands, Win1, + // memmove converted: Different stack allocations [Neb] + memcpy (Bands, Win1, sizeof(Win1[0]) * Window1Enabled); } else @@ -468,14 +470,16 @@ void ComputeClipWindows () if (Window1Enabled == 1 && BAND_EMPTY(Win1[0])) { B = Window2Enabled; - memmove (Bands, Win2, + // memmove converted: Different stack allocations [Neb] + memcpy (Bands, Win2, sizeof(Win2[0]) * Window2Enabled); } else if (Window2Enabled == 1 && BAND_EMPTY(Win2[0])) { B = Window1Enabled; - memmove (Bands, Win1, + // memmove converted: Different stack allocations [Neb] + memcpy (Bands, Win1, sizeof(Win1[0]) * Window1Enabled); } else diff --git a/source/gfx.cpp b/source/gfx.cpp index d2b8b6e..1b429c6 100644 --- a/source/gfx.cpp +++ b/source/gfx.cpp @@ -154,10 +154,12 @@ extern uint8 Mode7Depths [2]; if (IPPU.DoubleHeightPixels && ((PPU.BGMode != 5 && PPU.BGMode != 6) || !IPPU.Interlace)) \ for (uint32 y = GFX.StartY; y <= GFX.EndY; y++) \ { \ - memmove (SCREEN + (y * 2 + 1) * GFX.Pitch2, \ - SCREEN + y * 2 * GFX.Pitch2, \ - GFX.Pitch2); \ + /* memmove converted: Same malloc, non-overlapping addresses [Neb] */ \ + memcpy (SCREEN + (y * 2 + 1) * GFX.Pitch2, \ + SCREEN + y * 2 * GFX.Pitch2, \ + GFX.Pitch2); \ if(DO_DEPTH){ \ + /* memmove required: Same malloc, potentially overlapping addresses [Neb] */ \ memmove (DEPTH + (y * 2 + 1) * (GFX.PPLx2>>1), \ DEPTH + y * GFX.PPL, \ GFX.PPLx2>>1); \ @@ -1207,6 +1209,7 @@ static void DrawOBJS (bool8 OnMain = FALSE, uint8 D = 0) if(jLeft[clip][4]){ Windows[j].Value = TRUE; } else { + // memmove required: Overlapping addresses [Neb] if(jLeft[clip][4]; Windows[j].Value = TRUE; @@ -1214,6 +1217,7 @@ static void DrawOBJS (bool8 OnMain = FALSE, uint8 D = 0) } for(j=0; jRight[clip][4]; j++); if(j>=i || Windows[j].Pos!=GFX.pCurrentClip->Right[clip][4]){ + // memmove required: Overlapping addresses [Neb] if(jRight[clip][4]; Windows[j].Value = FALSE; @@ -3723,10 +3727,13 @@ void S9xUpdateScreen () // part way down the screen. Scale everything. for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) { - memmove (GFX.Screen + y * 2 * GFX.Pitch2, + // memmove converted: Same malloc, different addresses, and identical addresses at line 0 [Neb] + // DS2 DMA notes: This code path is unused [Neb] + memcpy (GFX.Screen + y * 2 * GFX.Pitch2, GFX.Screen + y * GFX.Pitch2, GFX.Pitch2); - memmove (GFX.Screen + (y * 2 + 1) * GFX.Pitch2, + // memmove converted: Same malloc, different addresses [Neb] + memcpy (GFX.Screen + (y * 2 + 1) * GFX.Pitch2, GFX.Screen + y * GFX.Pitch2, GFX.Pitch2); } diff --git a/source/loadzip.cpp b/source/loadzip.cpp index 4ee3bcb..d3e24a1 100644 --- a/source/loadzip.cpp +++ b/source/loadzip.cpp @@ -132,8 +132,7 @@ bool8 LoadZip(const char* zipname, char name[132]; unzGetCurrentFileInfo(file, &info, name,128, NULL,0, NULL,0); - int calc_size = info.uncompressed_size / 0x2000; - calc_size *= 0x2000; + int calc_size = info.uncompressed_size & ~0x1FFF; // round to lower 0x2000 if(!(info.uncompressed_size - calc_size == 512 || info.uncompressed_size == calc_size)) { port = unzGoToNextFile(file); @@ -190,8 +189,7 @@ bool8 LoadZip(const char* zipname, // assert(info.uncompressed_size <= CMemory::MAX_ROM_SIZE + 512); int FileSize = info.uncompressed_size; - int calc_size = FileSize / 0x2000; - calc_size *= 0x2000; + int calc_size = FileSize & ~0x1FFF; // round to lower 0x2000 int l = unzReadCurrentFile(file,ptr,FileSize); if(unzCloseCurrentFile(file) == UNZ_CRCERROR) @@ -224,6 +222,8 @@ bool8 LoadZip(const char* zipname, if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader) { + // memmove required: Overlapping addresses [Neb] + // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] memmove (ptr, ptr + 512, calc_size); (*headers)++; FileSize -= 512; diff --git a/source/memmap.cpp b/source/memmap.cpp index 04bc621..c1546b1 100644 --- a/source/memmap.cpp +++ b/source/memmap.cpp @@ -214,6 +214,7 @@ void S9xDeinterleaveType1(int TotalFileSize, uint8 * base) blocks [i * 2] = i + nblocks; blocks [i * 2 + 1] = i; } + // DS2 DMA notes: base may or may not be 32-byte aligned uint8 *tmp = (uint8 *) malloc (0x8000); if (tmp) { @@ -223,10 +224,14 @@ void S9xDeinterleaveType1(int TotalFileSize, uint8 * base) { if (blocks [j] == i) { - memmove (tmp, &base [blocks [j] * 0x8000], 0x8000); - memmove (&base [blocks [j] * 0x8000], + // memmove converted: Different mallocs [Neb] + memcpy (tmp, &base [blocks [j] * 0x8000], 0x8000); + // memmove converted: Different addresses, or identical for blocks[i] == blocks[j] [Neb] + // DS2 DMA notes: Don't do DMA at all if blocks[i] == blocks[j] + memcpy (&base [blocks [j] * 0x8000], &base [blocks [i] * 0x8000], 0x8000); - memmove (&base [blocks [i] * 0x8000], tmp, 0x8000); + // memmove converted: Different mallocs [Neb] + memcpy (&base [blocks [i] * 0x8000], tmp, 0x8000); uint8 b = blocks [j]; blocks [j] = blocks [i]; blocks [i] = b; @@ -250,13 +255,18 @@ void S9xDeinterleaveGD24(int TotalFileSize, uint8 * base) SET_UI_COLOR(0,255,255); } + // DS2 DMA notes: base may or may not be 32-byte aligned uint8 *tmp = (uint8 *) malloc (0x80000); if (tmp) { - memmove(tmp, &base[0x180000], 0x80000); - memmove(&base[0x180000], &base[0x200000], 0x80000); - memmove(&base[0x200000], &base[0x280000], 0x80000); - memmove(&base[0x280000], tmp, 0x80000); + // memmove converted: Different mallocs [Neb] + memcpy(tmp, &base[0x180000], 0x80000); + // memmove converted: Different addresses [Neb] + memcpy(&base[0x180000], &base[0x200000], 0x80000); + // memmove converted: Different addresses [Neb] + memcpy(&base[0x200000], &base[0x280000], 0x80000); + // memmove converted: Different mallocs [Neb] + memcpy(&base[0x280000], tmp, 0x80000); free ((char *) tmp); S9xDeinterleaveType1(TotalFileSize, base); @@ -399,10 +409,13 @@ char *CMemory::Safe (const char *s) /**********************************************************************************************/ bool8 CMemory::Init () { + // DS2 DMA notes: These would do well to be allocated with 32 extra bytes + // so they can be 32-byte aligned. [Neb] RAM = (uint8 *) malloc (0x20000); SRAM = (uint8 *) malloc (0x20000); VRAM = (uint8 *) malloc (0x10000); ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000); + // DS2 DMA notes: Can this be sped up with DMA from a block of zeroes? [Neb] memset (RAM, 0, 0x20000); memset (SRAM, 0, 0x20000); memset (VRAM, 0, 0x10000); @@ -453,7 +466,8 @@ bool8 CMemory::Init () SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); SuperFX.pvRom = (uint8 *) ROM; #endif - + + // DS2 DMA notes: Can this be sped up with DMA from a block of zeroes? [Neb] ZeroMemory (IPPU.TileCache [TILE_2BIT], MAX_2BIT_TILES * 128); ZeroMemory (IPPU.TileCache [TILE_4BIT], MAX_4BIT_TILES * 128); ZeroMemory (IPPU.TileCache [TILE_8BIT], MAX_8BIT_TILES * 128); @@ -627,6 +641,8 @@ again: ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) || (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score))) { + // memmove required: Overlapping addresses [Neb] + // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512); TotalFileSize -= 512; S9xMessage (S9X_INFO, S9X_HEADER_WARNING, @@ -871,6 +887,7 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize) _makepath (fname, drive, dir, name, ext); #ifdef __WIN32__ + // memmove required: Overlapping addresses [Neb] memmove (&ext [0], &ext[1], 4); #endif @@ -936,11 +953,13 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize) FileSize = fread (ptr, 1, maxsize + 0x200 - (ptr - ROM), ROMFile); fclose (ROMFile); - int calc_size = (FileSize / 0x2000) * 0x2000; + int calc_size = FileSize & ~0x1FFF; // round to the lower 0x2000 if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader) { + // memmove required: Overlapping addresses [Neb] + // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] memmove (ptr, ptr + 512, calc_size); HeaderCount++; FileSize -= 512; @@ -958,6 +977,7 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize) more = TRUE; ext [0]++; #ifdef __WIN32__ + // memmove required: Overlapping addresses [Neb] memmove (&ext [1], &ext [0], 4); ext [0] = '.'; #endif @@ -972,6 +992,7 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize) more = TRUE; name [len - 1]++; #ifdef __WIN32__ + // memmove required: Overlapping addresses [Neb] memmove (&ext [1], &ext [0], 4); ext [0] = '.'; #endif @@ -1180,7 +1201,8 @@ void S9xDeinterleaveType2 (bool8 reset) blocks [i] = (i & ~0xF) | ((i & 3) << 2) | ((i & 12) >> 2); } - + + // DS2 DMA notes: ROM needs to be 32-byte aligned [Neb] uint8 *tmp = (uint8 *) malloc (0x10000); if (tmp) @@ -1191,10 +1213,14 @@ void S9xDeinterleaveType2 (bool8 reset) { if (blocks [j] == i) { - memmove (tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); - memmove (&Memory.ROM [blocks [j] * 0x10000], + // memmove converted: Different mallocs [Neb] + memcpy (tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); + // memmove converted: Different addresses, or identical if blocks[i] == blocks[j] [Neb] + // DS2 DMA notes: Don't do DMA at all if blocks[i] == blocks[j] [Neb] + memcpy (&Memory.ROM [blocks [j] * 0x10000], &Memory.ROM [blocks [i] * 0x10000], 0x10000); - memmove (&Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); + // memmove converted: Different mallocs [Neb] + memcpy (&Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); uint8 b = blocks [j]; blocks [j] = blocks [i]; blocks [i] = b; @@ -1605,6 +1631,8 @@ bool8 CMemory::LoadSRAM (const char *filename) if (len - size == 512) { // S-RAM file has a header - remove it + // memmove required: Overlapping addresses [Neb] + // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] memmove (::SRAM, ::SRAM + 512, size); } if (len == size + SRTC_SRAM_PAD) @@ -1705,7 +1733,8 @@ void CMemory::ResetSpeedMap() void CMemory::WriteProtectROM () { - memmove ((void *) WriteMap, (void *) Map, sizeof (Map)); + // memmove converted: Different mallocs [Neb] + memcpy ((void *) WriteMap, (void *) Map, sizeof (Map)); for (int c = 0; c < 0x1000; c++) { if (BlockIsROM [c]) @@ -2545,8 +2574,10 @@ void CMemory::SuperFXROMMap () // block is repeated twice in each 64K block. for (c = 0; c < 64; c++) { - memmove (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); - memmove (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); + // memmove converted: Different addresses [Neb] + memcpy (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); + // memmove converted: Different addresses [Neb] + memcpy (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); } WriteProtectROM (); @@ -2612,8 +2643,10 @@ void CMemory::SA1ROMMap () WriteProtectROM (); // Now copy the map and correct it for the SA1 CPU. - memmove ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); - memmove ((void *) SA1.Map, (void *) Map, sizeof (Map)); + // memmove converted: Different mallocs [Neb] + memcpy ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); + // memmove converted: Different mallocs [Neb] + memcpy ((void *) SA1.Map, (void *) Map, sizeof (Map)); // Banks 00->3f and 80->bf for (c = 0; c < 0x400; c += 16) @@ -3025,8 +3058,10 @@ void CMemory::GNextROMMap () WriteProtectROM (); // Now copy the map and correct it for the SA1 CPU. - memmove ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); - memmove ((void *) SA1.Map, (void *) Map, sizeof (Map)); + // memmove converted: Different mallocs [Neb] + memcpy ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); + // memmove converted: Different mallocs [Neb] + memcpy ((void *) SA1.Map, (void *) Map, sizeof (Map)); // Banks 00->3f and 80->bf for (c = 0; c < 0x400; c += 16) @@ -4385,9 +4420,11 @@ void CMemory::ParseSNESHeader(uint8* RomHeader) ROMChecksum = RomHeader [0x2e] + (RomHeader [0x2f] << 8); ROMComplementChecksum = RomHeader [0x2c] + (RomHeader [0x2d] << 8); ROMRegion= RomHeader[0x29]; - memmove (ROMId, &RomHeader [0x2], 4); + // memmove converted: Different mallocs [Neb] + memcpy (ROMId, &RomHeader [0x2], 4); if(RomHeader[0x2A]==0x33) - memmove (CompanyId, &RomHeader [0], 2); + // memmove converted: Different mallocs [Neb] + memcpy (CompanyId, &RomHeader [0], 2); else sprintf(CompanyId, "%02X", RomHeader[0x2A]); } diff --git a/source/sa1.cpp b/source/sa1.cpp index 4dbf9b0..addeed7 100644 --- a/source/sa1.cpp +++ b/source/sa1.cpp @@ -742,7 +742,8 @@ void S9xSetSA1 (uint8 byte, uint32 address) if ((Memory.FillRAM [0x2230] & 0xb0) == 0xa0) { // Char conversion 2 DMA enabled - memmove (&Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, + // memmove converted: Same malloc but constant non-overlapping addresses [Neb] + memcpy (&Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM [0x2240], 16); SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; if ((SA1.in_char_dma & 3) == 0) @@ -895,6 +896,7 @@ static void S9xSA1DMA () len &= 0x3ff; d = &Memory.FillRAM [0x3000] + dst; } + // memmove required: Can overlap arbitrarily [Neb] memmove (d, s, len); Memory.FillRAM [0x2301] |= 0x20; diff --git a/source/snaporig.cpp b/source/snaporig.cpp index ac2045c..62674f2 100644 --- a/source/snaporig.cpp +++ b/source/snaporig.cpp @@ -313,12 +313,14 @@ static int ReadOrigSnapshot (STREAM snap) PPU.OBJSizeSelect = OrigPPU.OBJSizeSelect; PPU.OBJNameBase = OrigPPU.OBJNameBase; PPU.OAMReadFlip = OrigPPU.OAMReadFlip; - memmove (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData)); + // memmove converted: Different data segments [Neb] + memcpy (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData)); PPU.VTimerEnabled = OrigPPU.VTimerEnabled; PPU.HTimerEnabled = OrigPPU.HTimerEnabled; PPU.HTimerPosition = OrigPPU.HTimerPosition; PPU.Mosaic = OrigPPU.Mosaic; - memmove (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic)); + // memmove converted: Different data segments [Neb] + memcpy (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic)); PPU.Mode7HFlip = OrigPPU.Mode7HFlip; PPU.Mode7VFlip = OrigPPU.Mode7VFlip; PPU.Mode7Repeat = OrigPPU.Mode7Repeat; diff --git a/source/snapshot.cpp b/source/snapshot.cpp index ad9b131..c414dc2 100644 --- a/source/snapshot.cpp +++ b/source/snapshot.cpp @@ -1036,7 +1036,8 @@ void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, } break; case uint8_ARRAY_V: - memmove (ptr, (uint8 *) base + fields [i].offset, fields [i].size); + // memmove converted: Different mallocs [Neb] + memcpy (ptr, (uint8 *) base + fields [i].offset, fields [i].size); ptr += fields [i].size; break; case uint16_ARRAY_V: @@ -1139,7 +1140,8 @@ int UnfreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, } break; case uint8_ARRAY_V: - memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size); + // memmove converted: Different mallocs [Neb] + memcpy ((uint8 *) base + fields [i].offset, ptr, fields [i].size); ptr += fields [i].size; break; case uint16_ARRAY_V: @@ -1264,6 +1266,7 @@ void UnfreezeStructFromCopy (void *base, FreezeData *fields, int num_fields, uin } break; case uint8_ARRAY_V: + // memmove required: Source could point within dest [Neb] memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size); ptr += fields [i].size; break; @@ -1581,7 +1584,8 @@ bool8 S9xUnfreezeZSNES (const char *filename) APU.Timer [1] = t [45]; APU.Timer [2] = t [46]; - memmove (APU.ExtraRAM, &t [48], 64); + // memmove converted: Different mallocs [Neb] + memcpy (APU.ExtraRAM, &t [48], 64); // Internal ZSNES sound DSP state fread (t, 1, 1068, fs); @@ -1657,7 +1661,9 @@ bool8 S9xUnfreezeZSNES (const char *filename) SA1.Registers.PC = READ_DWORD (&t [636]); SA1.Registers.P.W = t [620] | (t [624] << 8); - memmove (&Memory.FillRAM [0x3000], t + 692, 2 * 1024); + // memmove converted: Different mallocs [Neb] + // DS2 DMA notes: This code path is not used [Neb] + memcpy (&Memory.FillRAM [0x3000], t + 692, 2 * 1024); fread (::SRAM, 1, 64 * 1024, fs); fseek (fs, 64 * 1024, SEEK_CUR); diff --git a/source/srtc.cpp b/source/srtc.cpp index 48add97..0e6f30e 100644 --- a/source/srtc.cpp +++ b/source/srtc.cpp @@ -525,12 +525,14 @@ void S9xSRTCPreSaveState () SRAM [s + 0] = rtc.needs_init; SRAM [s + 1] = rtc.count_enable; - memmove (&SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1); + // memmove converted: Different mallocs [Neb] + memcpy (&SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1); SRAM [s + 3 + MAX_RTC_INDEX] = rtc.index; SRAM [s + 4 + MAX_RTC_INDEX] = rtc.mode; #ifdef LSB_FIRST - memmove (&SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); + // memmove converted: Different mallocs [Neb] + memcpy (&SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); #else SRAM [s + 5 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 0); SRAM [s + 6 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 8); @@ -555,12 +557,14 @@ void S9xSRTCPostLoadState () rtc.needs_init = SRAM [s + 0]; rtc.count_enable = SRAM [s + 1]; - memmove (rtc.data, &SRAM [s + 2], MAX_RTC_INDEX + 1); + // memmove converted: Different mallocs [Neb] + memcpy (rtc.data, &SRAM [s + 2], MAX_RTC_INDEX + 1); rtc.index = SRAM [s + 3 + MAX_RTC_INDEX]; rtc.mode = SRAM [s + 4 + MAX_RTC_INDEX]; #ifdef LSB_FIRST - memmove (&rtc.system_timestamp, &SRAM [s + 5 + MAX_RTC_INDEX], 8); + // memmove converted: Different mallocs [Neb] + memcpy (&rtc.system_timestamp, &SRAM [s + 5 + MAX_RTC_INDEX], 8); #else rtc.system_timestamp |= (SRAM [s + 5 + MAX_RTC_INDEX] << 0); rtc.system_timestamp |= (SRAM [s + 6 + MAX_RTC_INDEX] << 8); -- cgit v1.2.3 From 60f6ffcc701c4175e31d90f950fb34f6b07a1712 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 00:36:51 -0500 Subject: When starting CATSFC, assume the backlights are both on, so don't delay 100 milliseconds and set both backlights to on. --- source/nds/entry.cpp | 4 +++- source/nds/gui.c | 10 ++++++---- source/nds/gui.h | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 45360a8..949cecf 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -540,6 +540,7 @@ int sfc_main (int argc, char **argv) #endif Settings.Paused = 1; + bool8 FirstInvocation = TRUE; while (1) { @@ -564,7 +565,8 @@ int sfc_main (int argc, char **argv) unsigned short screen[256*192]; copy_screen((void*)screen, up_screen_addr, 0, 0, 256, 192); - menu(screen); + menu(screen, FirstInvocation); + FirstInvocation = FALSE; game_disableAudio(); Settings.Paused = 0; } diff --git a/source/nds/gui.c b/source/nds/gui.c index fd9007b..b529b9f 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1682,7 +1682,7 @@ unsigned int frame_interval; /*-------------------------------------------------------- Main Menu --------------------------------------------------------*/ -u32 menu(u16 *screen) +u32 menu(u16 *screen, bool8 FirstInvocation) { gui_action_type gui_action; u32 i; @@ -3568,9 +3568,11 @@ u32 menu(u16 *screen) //----------------------------------------------------------------------------// // Menu Start ds2_setCPUclocklevel(0); - mdelay(100); // to prevent ds2_setBacklight() from crashing - ds2_setBacklight(3); - + if (!FirstInvocation) + { // assume that the backlight is already at 3 when the emulator starts + mdelay(100); // to prevent ds2_setBacklight() from crashing + ds2_setBacklight(3); + } wait_Allkey_release(0); bg_screenp= (u16*)malloc(256*192*2); diff --git a/source/nds/gui.h b/source/nds/gui.h index 87c14e4..482ceec 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -124,7 +124,7 @@ extern GAME_CONFIG game_config; /****************************************************************************** ******************************************************************************/ extern void gui_init(u32 lang_id); -extern u32 menu(u16 *original_screen); +extern u32 menu(u16 *original_screen, bool8 FirstInvocation); extern void game_disableAudio(); extern void game_set_frameskip(); extern void set_cpu_clock(u32 num); -- cgit v1.2.3 From c9c91f327a4ded2f52f13c449690a334623e0fdd Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 00:57:15 -0500 Subject: Don't initialise the ROM memory at startup, since a ROM needs to be loaded into it anyway. According to BassAceGold's timings, this should save 179 milliseconds. --- source/memmap.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/memmap.cpp b/source/memmap.cpp index c1546b1..755f7a0 100644 --- a/source/memmap.cpp +++ b/source/memmap.cpp @@ -415,11 +415,12 @@ bool8 CMemory::Init () SRAM = (uint8 *) malloc (0x20000); VRAM = (uint8 *) malloc (0x10000); ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000); - // DS2 DMA notes: Can this be sped up with DMA from a block of zeroes? [Neb] memset (RAM, 0, 0x20000); memset (SRAM, 0, 0x20000); memset (VRAM, 0, 0x10000); - memset (ROM, 0, MAX_ROM_SIZE + 0x200 + 0x8000); + // This needs to be initialised with a ROM first anyway, so don't + // bother memsetting. [Neb] + // memset (ROM, 0, MAX_ROM_SIZE + 0x200 + 0x8000); BSRAM = (uint8 *) malloc (0x80000); memset (BSRAM, 0, 0x80000); -- cgit v1.2.3 From 58a3dc9b1762ef0b1b12090d1b707a7f7fc9d9f9 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 06:10:57 -0500 Subject: Hook fast-forward into Settings.TurboSkipFrames. --- source/nds/entry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 949cecf..6fab5fc 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -403,7 +403,7 @@ void init_sfc_setting(void) #endif Settings.ApplyCheats = TRUE; Settings.TurboMode = FALSE; - Settings.TurboSkipFrames = 40; + Settings.TurboSkipFrames = 10; Settings.StretchScreenshots = 1; Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; @@ -608,7 +608,7 @@ void S9xSyncSpeed () sync_last = syncnow; sync_next = syncnow; - if(++skip_rate < 10) + if(++skip_rate < Settings.TurboSkipFrames) IPPU.RenderThisFrame = false; else { -- cgit v1.2.3 From 58948ffd1d05084f3d84bc12a2e75144741b292c Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 06:11:59 -0500 Subject: Make the audio timing more precise. * Fake out the buffer timing by sending a buffer full of silence when returning from pause. Reduces crackling introduced by the next point. * Send buffers only once every 23.22 milliseconds, not up to four buffers at once (92.88 milliseconds) and randomly thereafter. Reduces note-length jumpiness. * Audio may have trouble catching up if external jitter reaches 11.61 milliseconds. That happens if Mode 7 images or filtered modes take a long time to render, or if chips take a long time to execute. --- source/nds/entry.cpp | 216 +++++++++++++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 95 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 6fab5fc..c0c8efa 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -677,6 +677,7 @@ void S9xSyncSpeed () skip_rate = 0; ds2_setCPUclocklevel(0); if (syncdif > 0) + // TODO Turn this delay into a ProcessSound loop? udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */); set_cpu_clock(clock_speed_number); S9xProcessSound (0); @@ -709,6 +710,7 @@ void S9xSyncSpeed () if (syncdif > 0) { ds2_setCPUclocklevel(0); + // TODO Turn this delay into a ProcessSound loop? udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */); set_cpu_clock(clock_speed_number); S9xProcessSound (0); @@ -903,6 +905,9 @@ void S9xGenerateSound () } } +#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)) +unsigned int LastSoundEmissionTime = 0; + void S9xProcessSound (unsigned int) { unsigned short *audiobuff; @@ -910,143 +915,164 @@ void S9xProcessSound (unsigned int) if (so.mute_sound || !game_enable_audio) return; - if(ds2_checkAudiobuff() > 4) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT / 2) + { + LastSoundEmissionTime++; return; + } - /* Number of samples to generate now */ - int sample_count; - sample_count = so.buffer_size; -#ifndef FOREVER_16_BIT_SOUND - if (so.sixteen_bit) + unsigned int Now = getSysTime(); + if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { + if (Now - LastSoundEmissionTime >= 11719 /* 500 milliseconds */) + { + LastSoundEmissionTime = Now; + // We were probably paused. Restart sending sound with an + // empty buffer. + do { + audiobuff = (unsigned short*)ds2_getAudiobuff(); + } while (audiobuff == NULL); //There are audio queue in sending or wait to send + + memset(audiobuff, 0, DS2_BUFFER_SIZE); + + ds2_updateAudio(); + // And then the real audio. (fall through) + } + else + { + LastSoundEmissionTime += SOUND_EMISSION_INTERVAL; + } + /* Number of samples to generate now */ + int sample_count = so.buffer_size; +#ifndef FOREVER_16_BIT_SOUND + if (so.sixteen_bit) + { #endif - /* to prevent running out of buffer space, - * create less samples - */ - sample_count >>= 1; + /* to prevent running out of buffer space, + * create less samples + */ + sample_count >>= 1; #ifndef FOREVER_16_BIT_SOUND - } + } #endif - audiobuff = (unsigned short*)ds2_getAudiobuff(); - if(NULL == audiobuff) //There are audio queue in sending or wait to send - { - return; - } + do { + audiobuff = (unsigned short*)ds2_getAudiobuff(); + } while (audiobuff == NULL); //There are audio queue in sending or wait to send - /* If we need more audio samples */ - if (so.samples_mixed_so_far < sample_count) - { - /* Where to put the samples to */ + /* If we need more audio samples */ + if (so.samples_mixed_so_far < sample_count) + { + /* Where to put the samples to */ #ifndef FOREVER_16_BIT_SOUND - unsigned byte_offset = (so.play_position + - (so.sixteen_bit ? (so.samples_mixed_so_far << 1) : so.samples_mixed_so_far)) & SOUND_BUFFER_SIZE_MASK; + unsigned byte_offset = (so.play_position + + (so.sixteen_bit ? (so.samples_mixed_so_far << 1) : so.samples_mixed_so_far)) & SOUND_BUFFER_SIZE_MASK; #else - unsigned byte_offset = (so.play_position + - (so.samples_mixed_so_far << 1)) & SOUND_BUFFER_SIZE_MASK; + unsigned byte_offset = (so.play_position + + (so.samples_mixed_so_far << 1)) & SOUND_BUFFER_SIZE_MASK; #endif - //printf ("%d:", sample_count - so.samples_mixed_so_far); fflush (stdout); - if (Settings.SoundSync == 2) - { - /*memset (Buf + (byte_offset & SOUND_BUFFER_SIZE_MASK), 0, - sample_count - so.samples_mixed_so_far);*/ - } - else - { - /* Mix the missing samples */ + if (Settings.SoundSync == 2) + { + /*memset (Buf + (byte_offset & SOUND_BUFFER_SIZE_MASK), 0, + sample_count - so.samples_mixed_so_far);*/ + } + else + { + /* Mix the missing samples */ #ifndef FOREVER_16_BIT_SOUND - int bytes_so_far = so.sixteen_bit ? (so.samples_mixed_so_far << 1) : - so.samples_mixed_so_far; + int bytes_so_far = so.sixteen_bit ? (so.samples_mixed_so_far << 1) : + so.samples_mixed_so_far; #else - int bytes_so_far = so.samples_mixed_so_far << 1; + int bytes_so_far = so.samples_mixed_so_far << 1; #endif - uint32 samples_to_write = sample_count - so.samples_mixed_so_far; - do - { - int bytes_this_run = samples_to_write; + uint32 samples_to_write = sample_count - so.samples_mixed_so_far; + do + { + int bytes_this_run = samples_to_write; #ifndef FOREVER_16_BIT_SOUND - if (so.sixteen_bit) + if (so.sixteen_bit) #endif - bytes_this_run <<= 1; + bytes_this_run <<= 1; - if (byte_offset + bytes_this_run > SOUND_BUFFER_SIZE) - { - bytes_this_run = SOUND_BUFFER_SIZE - byte_offset; - } + if (byte_offset + bytes_this_run > SOUND_BUFFER_SIZE) + { + bytes_this_run = SOUND_BUFFER_SIZE - byte_offset; + } - if (bytes_so_far + bytes_this_run > so.buffer_size) - { - bytes_this_run = so.buffer_size - bytes_so_far; - if (bytes_this_run == 0) - break; - } + if (bytes_so_far + bytes_this_run > so.buffer_size) + { + bytes_this_run = so.buffer_size - bytes_so_far; + if (bytes_this_run == 0) + break; + } - int samples_this_run = bytes_this_run; + int samples_this_run = bytes_this_run; #ifndef FOREVER_16_BIT_SOUND - if (so.sixteen_bit) + if (so.sixteen_bit) #endif - samples_this_run >>= 1; + samples_this_run >>= 1; - S9xMixSamples (Buf + byte_offset, samples_this_run); - so.samples_mixed_so_far += samples_this_run; - samples_to_write -= samples_this_run; + S9xMixSamples (Buf + byte_offset, samples_this_run); + so.samples_mixed_so_far += samples_this_run; + samples_to_write -= samples_this_run; #ifndef FOREVER_16_BIT_SOUND - bytes_so_far += so.sixteen_bit ? (samples_this_run << 1) : - samples_this_run; + bytes_so_far += so.sixteen_bit ? (samples_this_run << 1) : + samples_this_run; #else - bytes_so_far += samples_this_run << 1; + bytes_so_far += samples_this_run << 1; #endif - byte_offset = (byte_offset + bytes_this_run) & SOUND_BUFFER_SIZE_MASK; - } while (samples_to_write > 0); + byte_offset = (byte_offset + bytes_this_run) & SOUND_BUFFER_SIZE_MASK; + } while (samples_to_write > 0); + } } - } -// if (!so.mute_sound) - { - unsigned bytes_to_write = sample_count; + // if (!so.mute_sound) + { + unsigned bytes_to_write = sample_count; #ifndef FOREVER_16_BIT_SOUND - if(so.sixteen_bit) + if(so.sixteen_bit) #endif - bytes_to_write <<= 1; + bytes_to_write <<= 1; - unsigned byte_offset = so.play_position; - so.play_position = (so.play_position + bytes_to_write) & SOUND_BUFFER_SIZE_MASK; /* wrap to beginning */ + unsigned byte_offset = so.play_position; + so.play_position = (so.play_position + bytes_to_write) & SOUND_BUFFER_SIZE_MASK; /* wrap to beginning */ - unsigned short *dst_pt = audiobuff; - unsigned short *dst_pt1 = dst_pt + DS2_BUFFER_SIZE; + unsigned short *dst_pt = audiobuff; + unsigned short *dst_pt1 = dst_pt + DS2_BUFFER_SIZE; - /* Feed the samples to the soundcard until nothing is left */ - for(;;) - { - int I = bytes_to_write; - if (byte_offset + I > SOUND_BUFFER_SIZE) + /* Feed the samples to the soundcard until nothing is left */ + for(;;) { - I = SOUND_BUFFER_SIZE - byte_offset; - } - if(I == 0) break; + int I = bytes_to_write; + if (byte_offset + I > SOUND_BUFFER_SIZE) + { + I = SOUND_BUFFER_SIZE - byte_offset; + } + if(I == 0) break; -// memcpy(dst_pt, (char *) Buf + byte_offset, I); -// dst_pt += I; + // memcpy(dst_pt, (char *) Buf + byte_offset, I); + // dst_pt += I; - unsigned short *src_pt= (unsigned short*)(Buf + byte_offset); - for(int m= 0; m < I/4; m++) - { - *dst_pt++= *src_pt++;//(*src_pt++) <<1; - *dst_pt1++= *src_pt++;//(*src_pt++) <<1; + unsigned short *src_pt= (unsigned short*)(Buf + byte_offset); + for(int m= 0; m < I/4; m++) + { + *dst_pt++= *src_pt++;//(*src_pt++) <<1; + *dst_pt1++= *src_pt++;//(*src_pt++) <<1; + } + + bytes_to_write -= I; + byte_offset = (byte_offset + I) & SOUND_BUFFER_SIZE_MASK; /* wrap */ } - bytes_to_write -= I; - byte_offset = (byte_offset + I) & SOUND_BUFFER_SIZE_MASK; /* wrap */ - } + ds2_updateAudio(); - ds2_updateAudio(); + /* All data sent. */ + } - /* All data sent. */ + so.samples_mixed_so_far -= sample_count; } - - so.samples_mixed_so_far -= sample_count; } /* -- cgit v1.2.3 From 30fe9eaf6ab8b0701419949a4415736675d15377 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 18:27:03 -0500 Subject: While killing time between frames, process audio instead of doing nothing. Also correctly fill the buffer with silence when returning from pause. This reduces or eliminates crackling. The emulator kills time in two circumstances: * In automatic frameskip mode, without fast forwarding, the emulator kills time if it rendered a frame early. * In manual frameskip mode, without fast forwarding, the emulator kills time to wait for the next rendered frame. --- source/nds/entry.cpp | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index c0c8efa..a55c10d 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -675,12 +675,13 @@ void S9xSyncSpeed () else // Early { skip_rate = 0; - ds2_setCPUclocklevel(0); if (syncdif > 0) - // TODO Turn this delay into a ProcessSound loop? - udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */); - set_cpu_clock(clock_speed_number); - S9xProcessSound (0); + { + do { + S9xProcessSound (0); + syncdif = sync_next - getSysTime(); + } while (syncdif > 0); + } IPPU.RenderThisFrame = TRUE; sync_next += frame_time; @@ -709,11 +710,10 @@ void S9xSyncSpeed () syncdif = sync_next - syncnow; if (syncdif > 0) { - ds2_setCPUclocklevel(0); - // TODO Turn this delay into a ProcessSound loop? - udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */); - set_cpu_clock(clock_speed_number); - S9xProcessSound (0); + do { + S9xProcessSound (0); + syncdif = sync_next - getSysTime(); + } while (syncdif > 0); // After that little delay, what time is it? syncnow = getSysTime(); } @@ -910,8 +910,6 @@ unsigned int LastSoundEmissionTime = 0; void S9xProcessSound (unsigned int) { - unsigned short *audiobuff; - if (so.mute_sound || !game_enable_audio) return; @@ -921,6 +919,8 @@ void S9xProcessSound (unsigned int) return; } + unsigned short *audiobuff; + unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { @@ -933,7 +933,18 @@ void S9xProcessSound (unsigned int) audiobuff = (unsigned short*)ds2_getAudiobuff(); } while (audiobuff == NULL); //There are audio queue in sending or wait to send - memset(audiobuff, 0, DS2_BUFFER_SIZE); + memset(audiobuff, 0, DS2_BUFFER_SIZE +#ifndef FOREVER_STEREO + << (so.stereo ? 1 : 0) +#else + << 1 +#endif +#ifndef FOREVER_16_BIT_SOUND + << (so.sixteen_bit ? 1 : 0) +#else + << 1 +#endif + ); ds2_updateAudio(); // And then the real audio. (fall through) -- cgit v1.2.3 From e61731a524028f8286f83a82686b2f4e236c1a9d Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 19:02:38 -0500 Subject: Revert the reversed stereo mixing loop. This makes it more consistent with mainline Snes9x, in case of merges from 1.53. It also didn't help much, given that the problem was trying to push 92 milliseconds of audio inside 20 milliseconds of time. This reverts commit 2b715684087675747df7cb8995695936f20c782b. --- source/soundux.cpp | 339 +---------------------------------------------------- 1 file changed, 2 insertions(+), 337 deletions(-) diff --git a/source/soundux.cpp b/source/soundux.cpp index 124ce6d..dde8a14 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -889,334 +889,6 @@ void DecodeBlock (Channel *ch) ch->block_pointer += 9; } -/* - * The layout of loops in this function is optimised for outputting a few - * samples, reducing the number of memory accesses per sample-channel pair. - * For each SAMPLE, each channel is mixed into CPU registers and - * assigned to the mix buffer. - */ -static inline void MixStereo_ReversedLoop (int sample_count) -{ - int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; - int32 VL[NUM_CHANNELS], VR[NUM_CHANNELS]; - int32 PreviousChannelSample = 0; - - for (uint32 I = 0; I < (uint32) sample_count; I += 2) - { - int32 OutputLeft = 0, OutputRight = 0; - - for (uint32 J = 0; J < NUM_CHANNELS; J++) - { - Channel *ch = &SoundData.channels[J]; - - if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J))) - continue; - - unsigned long freq0 = ch->frequency; - - // freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux - freq0 = freq0 * 985/1000; - - bool8 mod = pitch_mod & (1 << J); - - if (I == 0) - { - if (ch->needs_decode) - { - DecodeBlock(ch); - ch->needs_decode = FALSE; - ch->sample = ch->block[0]; - ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; - if (ch->sample_pointer == 0) - ch->sample_pointer = 1; - if (ch->sample_pointer > SOUND_DECODE_LENGTH) - ch->sample_pointer = SOUND_DECODE_LENGTH - 1; - - ch->next_sample=ch->block[ch->sample_pointer]; - ch->interpolate = 0; - - if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod) - ch->interpolate = ((ch->next_sample - ch->sample) * - (long) freq0) / (long) FIXED_POINT; - } - VL [J] = (ch->sample * ch-> left_vol_level) / 128; - VR [J] = (ch->sample * ch->right_vol_level) / 128; - } - - unsigned long freq = freq0; - - if (mod) - freq = PITCH_MOD(freq, PreviousChannelSample); - - ch->env_error += ch->erate; - if (ch->env_error >= FIXED_POINT) - { - uint32 step = ch->env_error >> FIXED_POINT_SHIFT; - - switch (ch->state) - { - case SOUND_ATTACK: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_DECAY; - if (ch->sustain_level != 8) - { - S9xSetEnvRate (ch, ch->decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * ch->sustain_level) - >> 3); - break; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); - } - break; - - case SOUND_DECAY: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= ch->envx_target) - { - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); - } - break; - - case SOUND_SUSTAIN: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_RELEASE: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_INCREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0); - } - break; - - case SOUND_INCREASE_BENT_LINE: - if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) - { - while (ch->env_error >= FIXED_POINT) - { - ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - } - else - { - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - } - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0); - } - break; - - case SOUND_DECREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx -= step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_DECREASE_EXPONENTIAL: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_GAIN: - S9xSetEnvRate (ch, 0, -1, 0); - break; - } - ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; - ch->right_vol_level = (ch->envx * ch->volume_right) / 128; - VL [J] = (ch->sample * ch-> left_vol_level) / 128; - VR [J] = (ch->sample * ch->right_vol_level) / 128; - } - - ch->count += freq; - if (ch->count >= FIXED_POINT) - { - VL [J] = ch->count >> FIXED_POINT_SHIFT; - ch->sample_pointer += VL [J]; - ch->count &= FIXED_POINT_REMAINDER; - - ch->sample = ch->next_sample; - if (ch->sample_pointer >= SOUND_DECODE_LENGTH) - { - if (JUST_PLAYED_LAST_SAMPLE(ch)) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - do - { - ch->sample_pointer -= SOUND_DECODE_LENGTH; - if (ch->last_block) - { - if (!ch->loop) - { - ch->sample_pointer = LAST_SAMPLE; - ch->next_sample = ch->sample; - break; - } - else - { - S9xAPUSetEndX (J); - ch->last_block = FALSE; - uint8 *dir = S9xGetSampleAddress (ch->sample_number); - ch->block_pointer = READ_WORD(dir + 2); - } - } - DecodeBlock (ch); - } while (ch->sample_pointer >= SOUND_DECODE_LENGTH); - if (!JUST_PLAYED_LAST_SAMPLE (ch)) - ch->next_sample = ch->block [ch->sample_pointer]; - } - else - ch->next_sample = ch->block [ch->sample_pointer]; - - if (ch->type == SOUND_SAMPLE) - { - if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod) - { - ch->interpolate = ((ch->next_sample - ch->sample) * - (long) freq) / (long) FIXED_POINT; - ch->sample = (int16) (ch->sample + (((ch->next_sample - ch->sample) * - (long) (ch->count)) / (long) FIXED_POINT)); - } - else - ch->interpolate = 0; - } - else - { - // Snes9x 1.53's SPC_DSP.cpp, by blargg - int feedback = (noise_gen << 13) ^ (noise_gen << 14); - noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); - ch->sample = (noise_gen << 17) >> 17; - ch->interpolate = 0; - } - - VL [J] = (ch->sample * ch-> left_vol_level) / 128; - VR [J] = (ch->sample * ch->right_vol_level) / 128; - } - else - { - if (ch->interpolate) - { - int32 s = (int32) ch->sample + ch->interpolate; - - CLIP16(s); - ch->sample = (int16) s; - VL [J] = (ch->sample * ch-> left_vol_level) / 128; - VR [J] = (ch->sample * ch->right_vol_level) / 128; - } - } - - OutputLeft += VL [J]; - OutputRight += VR [J]; - - if (pitch_mod & (1 << (J + 1))) - PreviousChannelSample = ch->sample * ch->envx; - -#ifndef FOREVER_FORWARD_STEREO - ch->echo_buf_ptr [I ^ Settings.ReverseStereo ] += VL [J]; - ch->echo_buf_ptr [I + (1 ^ Settings.ReverseStereo)] += VR [J]; -#else - ch->echo_buf_ptr [I ] += VL [J]; - ch->echo_buf_ptr [I + 1] += VR [J]; -#endif -stereo_exit: - ; - } -#ifndef FOREVER_FORWARD_STEREO - MixBuffer [I ^ Settings.ReverseStereo ] = OutputLeft; - MixBuffer [I + (1 ^ Settings.ReverseStereo)] = OutputRight; -#else - MixBuffer [I ] = OutputLeft; - MixBuffer [I + 1] = OutputRight; -#endif - } -} - -#ifdef __DJGPP -END_OF_FUNCTION(MixStereo_ReversedLoop); -#endif - -/* - * The layout of loops in this function is optimised for outputting a lot of - * samples, quickly ignoring channels that are muted so that they're not - * processed any further before the function returns. - * For each CHANNEL, samples are mixed into the mix buffer until the channel - * is muted or the sample count is met. - */ static inline void MixStereo (int sample_count) { static int32 wave[SOUND_BUFFER_SIZE]; @@ -1829,20 +1501,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count) { if (SoundData.echo_enable) memset (EchoBuffer, 0, sample_count * sizeof (EchoBuffer [0])); + memset (MixBuffer, 0, sample_count * sizeof (MixBuffer [0])); #ifndef FOREVER_STEREO if (so.stereo) - { #endif - if (sample_count < 12) - MixStereo_ReversedLoop (sample_count); - else - { - memset (MixBuffer, 0, sample_count * sizeof (MixBuffer [0])); - MixStereo (sample_count); - } + MixStereo (sample_count); #ifndef FOREVER_STEREO - } else MixMono (sample_count); #endif -- cgit v1.2.3 From d4dd98e8c180532f24de342482e54f28874f06ef Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 20:09:24 -0500 Subject: Add an option that controls which element should be more fluid, per game: video or audio. This makes most games playable, but the player can choose to get fluid audio instead of fluid video in sound-test modes or games with epic soundtracks. --- CATSFC/system/language.msg | 22 ++++++++++++++++++++-- README.md | 18 ++++++++++++++++++ source/nds/entry.cpp | 12 ++++++++++++ source/nds/gui.c | 13 ++++++++++--- source/nds/gui.h | 4 +++- source/nds/message.h | 19 +++++++++++-------- 6 files changed, 74 insertions(+), 14 deletions(-) diff --git a/CATSFC/system/language.msg b/CATSFC/system/language.msg index 126c8c2..4ae6ee6 100644 --- a/CATSFC/system/language.msg +++ b/CATSFC/system/language.msg @@ -33,6 +33,12 @@ Tools Options #MSG_MAIN_MENU_EXIT Exit +#FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE +Fluidity %s +#MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO +Prefer fluid video +#MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO +Prefer fluid audio #FMT_VIDEO_ASPECT_RATIO Aspect ratio %s #FMT_VIDEO_FAST_FORWARD @@ -40,7 +46,7 @@ Fast-forward %s #FMT_VIDEO_FRAME_SKIPPING Frame skipping %s #FMT_AUDIO_SOUND -Sound %s +Sound %s #FMT_SAVED_STATE_CREATE Create saved state %d #FMT_SAVED_STATE_LOAD @@ -227,6 +233,12 @@ STARTCHINESESIM 综合设置 #MSG_MAIN_MENU_EXIT 退出模拟器 +#FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE +Fluidity %s +#MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO +Prefer fluid video +#MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO +Prefer fluid audio #FMT_VIDEO_ASPECT_RATIO 画面 %s #FMT_VIDEO_FAST_FORWARD @@ -421,8 +433,14 @@ Outils Options #MSG_MAIN_MENU_EXIT Quitter +#FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE +Fluidité %s +#MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO +Préférer la vidéo fluide +#MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO +Préférer l'audio fluide #FMT_VIDEO_ASPECT_RATIO -Format d'image %s +Format d'image %s #FMT_VIDEO_FAST_FORWARD Avance rapide %s #FMT_VIDEO_FRAME_SKIPPING diff --git a/README.md b/README.md index 9877d3b..8b90366 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,24 @@ It is recommended to start with frame skipping 4 (Show 1 frame every 5) and go to 3 or 2 if the game doesn't run with major slowdowns with them. If you don't like the slowdowns, return to frame skipping 4 or -. +# Fluidity + +Fluidity is an option you can find under the Video & audio menu in a game. +By default, video fluidity is preferred over audio fluidity in games. + +* Preferring video fluidity makes audio skip certain notes, up to + 23 milliseconds, in order to render more video. In many games, this + difference is not audible. + Use this option if you want to play games that require precise controls or + fluid imagery more than precise audio emulation. You can also use this option + when watching game introductions, endings and cutscenes. +* Preferring audio fluidity makes video skip certain images, up to + 166 milliseconds, in order to render audio closer to 32,000 times per second. + Use this option if you want to play games mainly for their soundtracks, or in + a game's sound test mode. You can also use this option to experiment with the + green berry glitch in Super Mario World that makes TIME go over and under 100 + units constantly and makes the music play very fast. + # Hotkeys You can set buttons to press to perform certain actions. For each action, diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index a55c10d..1cf31df 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -350,6 +350,18 @@ void game_set_frameskip() Settings.SkipFrames = game_config.frameskip_value - 1 /* 1 -> 0 and so on */; } } + +void game_set_fluidity() +{ + if( game_config.SoundSync == 1) + { + Settings.SoundSync = TRUE; + } + else + { + Settings.SoundSync = FALSE; + } +} void init_sfc_setting(void) { diff --git a/source/nds/gui.c b/source/nds/gui.c index b529b9f..b6bd0f4 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -2814,6 +2814,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_0], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_1], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; + char *fluidity_options[] = { (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO], (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO] }; + char *on_off_options[] = { (char*)&msg[MSG_GENERAL_OFF], (char*)&msg[MSG_GENERAL_ON] }; char *sound_seletion[] = { (char*)&msg[MSG_AUDIO_MUTED], (char*)&msg[MSG_AUDIO_ENABLED] }; @@ -2838,8 +2840,11 @@ u32 menu(u16 *screen, bool8 FirstInvocation) /* 03 */ STRING_SELECTION_OPTION(game_disableAudio, NULL, &msg[FMT_AUDIO_SOUND], sound_seletion, &game_enable_audio, 2, NULL, ACTION_TYPE, 3), - /* 04 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, - &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 4) + /* 04 */ STRING_SELECTION_OPTION(game_set_fluidity, NULL, &msg[FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE], fluidity_options, + &game_config.SoundSync, 2, NULL, ACTION_TYPE, 4), + + /* 05 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, + &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 5) }; MAKE_MENU(graphics, NULL, NULL, NULL, NULL, 0, 0); @@ -4253,6 +4258,7 @@ void init_game_config(void) clock_speed_number = 5; game_config.graphic = 3; // By default, have a good-looking aspect ratio game_config.frameskip_value = 0; // Automatic frame skipping + game_config.SoundSync = 0; // Prefer fluid images by default game_config.backward = 0; //time backward disable game_config.backward_time = 2; //time backward granularity 1s @@ -4306,7 +4312,8 @@ void load_game_config_file(void) fread(&game_config, 1, sizeof(GAME_CONFIG), fp); clock_speed_number = game_config.clock_speed_number; - Settings.SkipFrames = (game_config.frameskip_value == 0 ? AUTO_FRAMERATE : game_config.frameskip_value - 1 /* 1 -> 0 and so on */); + game_set_frameskip(); + game_set_fluidity(); } fclose(fp); diff --git a/source/nds/gui.h b/source/nds/gui.h index 482ceec..0b91758 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -59,7 +59,8 @@ struct _GAME_CONFIG u32 HotkeyReturnToMenu; u32 HotkeyTemporaryFastForward; u32 HotkeyToggleSound; - u32 Reserved2[45]; + u32 SoundSync; + u32 Reserved2[44]; }; typedef enum @@ -127,6 +128,7 @@ extern void gui_init(u32 lang_id); extern u32 menu(u16 *original_screen, bool8 FirstInvocation); extern void game_disableAudio(); extern void game_set_frameskip(); +extern void game_set_fluidity(); extern void set_cpu_clock(u32 num); extern int load_language_msg(char *filename, u32 language); diff --git a/source/nds/message.h b/source/nds/message.h index 0aff8d9..3eb9e74 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -31,6 +31,9 @@ enum MSG MSG_MAIN_MENU_TOOLS, MSG_MAIN_MENU_OPTIONS, MSG_MAIN_MENU_EXIT, + FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE, + MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO, + MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO, FMT_VIDEO_ASPECT_RATIO, FMT_VIDEO_FAST_FORWARD, FMT_VIDEO_FRAME_SKIPPING, @@ -41,8 +44,8 @@ enum MSG FMT_CHEAT_PAGE, MSG_CHEAT_LOAD_FROM_FILE, MSG_TOOLS_SCREENSHOT_GENERAL, - MSG_TOOLS_GLOBAL_HOTKEY_GENERAL, // currently unused - MSG_TOOLS_GAME_HOTKEY_GENERAL, // currently unused + MSG_TOOLS_GLOBAL_HOTKEY_GENERAL, + MSG_TOOLS_GAME_HOTKEY_GENERAL, FMT_OPTIONS_LANGUAGE, FMT_OPTIONS_CPU_FREQUENCY, MSG_OPTIONS_CARD_CAPACITY, @@ -50,12 +53,12 @@ enum MSG MSG_OPTIONS_VERSION, MSG_SCREENSHOT_CREATE, MSG_SCREENSHOT_BROWSE, - MSG_HOTKEY_MAIN_MENU, // currently unused - MSG_HOTKEY_TEMPORARY_FAST_FORWARD, // currently unused - MSG_HOTKEY_SOUND_TOGGLE, // currently unused - MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS, // currently unused - MSG_HOTKEY_DELETE_WITH_A, // currently unused - MSG_HOTKEY_CANCEL_WITH_B, // currently unused + MSG_HOTKEY_MAIN_MENU, + MSG_HOTKEY_TEMPORARY_FAST_FORWARD, + MSG_HOTKEY_SOUND_TOGGLE, + MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS, + MSG_HOTKEY_DELETE_WITH_A, + MSG_HOTKEY_CANCEL_WITH_B, MSG_LOAD_GAME_RECENTLY_PLAYED, MSG_LOAD_GAME_FROM_CARD, MSG_LOAD_GAME_MENU_TITLE, -- cgit v1.2.3 From 25aeb83f7bf395a49742c957ada5d2b917fe62aa Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 1 Feb 2013 20:47:46 -0500 Subject: Release 1.25. --- README.md | 2 +- source/nds/gui.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8b90366..bdb75ba 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -CATSFC version 1.24, 2013-01-26 +CATSFC version 1.25, 2013-02-01 A Super Nintendo emulator for the Supercard DSTWO. diff --git a/source/nds/gui.c b/source/nds/gui.c index b6bd0f4..3933277 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.24" +#define NDSSFC_VERSION "1.25" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From 91d7bf5b9177ac8d80d586723f2b6c10a9649148 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 2 Feb 2013 01:37:16 -0500 Subject: Correct overzealous detection of buffer overruns. It was making the sound crackle constantly, like a record player. Most audible with earphones. --- source/nds/entry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 1cf31df..35ebec1 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -925,7 +925,7 @@ void S9xProcessSound (unsigned int) if (so.mute_sound || !game_enable_audio) return; - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT / 2) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) { LastSoundEmissionTime++; return; -- cgit v1.2.3 From 30e7498f225314e085323e7933309749431fc3ee Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 2 Feb 2013 01:38:32 -0500 Subject: Add the experimental branch's files to .gitignore. --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d72f81a..4a37034 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ *.zip *~ depend -[Tt]humbs.db \ No newline at end of file +[Tt]humbs.db +expsfc.* +EXPSFC/ \ No newline at end of file -- cgit v1.2.3 From 984682682c26edb5a9bbcd1e1d8f4aa6ce135596 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 2 Feb 2013 01:39:50 -0500 Subject: Release 1.26. --- README.md | 2 +- source/nds/gui.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bdb75ba..91e582f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -CATSFC version 1.25, 2013-02-01 +CATSFC version 1.26, 2013-02-02 A Super Nintendo emulator for the Supercard DSTWO. diff --git a/source/nds/gui.c b/source/nds/gui.c index 3933277..4f808b4 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.25" +#define NDSSFC_VERSION "1.26" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From 7aeebe97e72b07d60ea77041a5259086e68e2db2 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 2 Feb 2013 02:21:52 -0500 Subject: Fix an oddity in the sound when returning from a global mute. Fixes music loading in Super Mario World. --- source/nds/entry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 35ebec1..986ecce 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -922,7 +922,7 @@ unsigned int LastSoundEmissionTime = 0; void S9xProcessSound (unsigned int) { - if (so.mute_sound || !game_enable_audio) + if (!game_enable_audio) return; if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) -- cgit v1.2.3 From 02f8184fe07d99cceb85f4abd3ef0e5e3765b5ea Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sat, 2 Feb 2013 17:37:51 -0500 Subject: Make it easier to change the "high" and "low" CPU frequencies, as well as to switch to the user's chosen frequency for the game. Conflicts: source/nds/ds2_main.c source/nds/entry.cpp source/nds/gui.c --- source/nds/ds2_main.c | 5 ++++- source/nds/entry.cpp | 6 +++--- source/nds/gui.c | 54 ++++++++++++++++++++++++++++++--------------------- source/nds/gui.h | 4 +++- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/source/nds/ds2_main.c b/source/nds/ds2_main.c index f9b29d5..af81df3 100644 --- a/source/nds/ds2_main.c +++ b/source/nds/ds2_main.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "port.h" + #include #include "console.h" #include "fs_api.h" @@ -25,6 +27,7 @@ #include "ds2_timer.h" #include "ds2_malloc.h" #include "ds2sound.h" +#include "gui.h" #define BLACK_COLOR RGB15(0, 0, 0) #define WHITE_COLOR RGB15(31, 31, 31) @@ -47,7 +50,7 @@ void ddump_mem(unsigned char* addr, unsigned int len) void ds2_main(void) { int err; - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); //Initial video and audio and other input and output err = ds2io_initb(DS2_BUFFER_SIZE, SND_SAMPLE_RATE, 0, 0); if(err) goto _failure; diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 986ecce..5d79b64 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -86,7 +86,7 @@ void S9xParseDisplayArg (char **argv, int &ind, int) void S9xExit () { - ds2_setCPUclocklevel(13); // Crank it up to exit quickly + HighFrequencyCPU(); // Crank it up to exit quickly if(Settings.SPC7110) (*CleanUp7110)(); @@ -1125,7 +1125,7 @@ unsigned int S9xReadJoypad (int which1) if (inputdata.key & KEY_LID) { - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); ds2_setSupend(); do { ds2_getrawInput(&inputdata); @@ -1136,7 +1136,7 @@ unsigned int S9xReadJoypad (int which1) // screen's backlight. mdelay(100); // needed to avoid ds2_setBacklight crashing ds2_setBacklight(2); - set_cpu_clock(clock_speed_number); + GameFrequencyCPU(); } u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu; diff --git a/source/nds/gui.c b/source/nds/gui.c index 4f808b4..3942672 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1651,12 +1651,22 @@ int save_state(char* file, void* screen) return 0; } -void set_cpu_clock(u32 num) +void LowFrequencyCPU() { - u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 394 + ds2_setCPUclocklevel(0); // 60 MHz +} + +void HighFrequencyCPU() +{ + ds2_setCPUclocklevel(13); // 396 MHz +} + +void GameFrequencyCPU() +{ + u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 396 - if(num <= 5) - ds2_setCPUclocklevel(clock_speed_table[num]); + if(clock_speed_number <= 5) + ds2_setCPULevel(clock_speed_table[clock_speed_number]); } void savefast_int(void) @@ -1761,7 +1771,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void menu_exit() { - ds2_setCPUclocklevel(13); // Crank it up, leave quickly + HighFrequencyCPU(); // Crank it up, leave quickly if(gamepak_name[0] != 0) { game_config.clock_speed_number = clock_speed_number; @@ -1794,9 +1804,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int load_result = load_gamepak(line_buffer); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if(load_result == -1) { first_load = 1; @@ -1862,9 +1872,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int load_result = load_gamepak(args[1]); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if(load_result == -1) { @@ -2074,9 +2084,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_SAVED_STATE_CREATING]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int flag = save_state(tmp_filename, (void*)screen); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); //clear message draw_message(down_screen_addr, NULL, 28, 31, 227, 96, 0); if(flag < 0) @@ -2143,9 +2153,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(up_screen_addr, 36, 75, 190, COLOR_MSSG, msg[MSG_PROGRESS_SAVED_STATE_LOADING]); - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int flag = load_state(tmp_filename); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if(0 == flag) { return_value = 1; @@ -2160,9 +2170,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } else //load screen snapshot { - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); load_game_stat_snapshot(tmp_filename); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); } } else @@ -2732,7 +2742,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { if(gui_action == CURSOR_LEFT || gui_action == CURSOR_RIGHT) { - ds2_setCPUclocklevel(13); // crank it up + HighFrequencyCPU(); // crank it up if(bg_screenp != NULL) { bg_screenp_color = COLOR16(43, 11, 11); @@ -2757,7 +2767,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } save_emu_config_file(); - ds2_setCPUclocklevel(0); // and back down + LowFrequencyCPU(); // and back down wait_Allkey_release(0); } } @@ -3497,9 +3507,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) ext_pos = emu_config.latest_file[current_option_num -1]; - ds2_setCPUclocklevel(13); + HighFrequencyCPU(); int load_result = load_gamepak(ext_pos); - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if(load_result == -1) { first_load = 1; @@ -3572,7 +3582,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) //----------------------------------------------------------------------------// // Menu Start - ds2_setCPUclocklevel(0); + LowFrequencyCPU(); if (!FirstInvocation) { // assume that the backlight is already at 3 when the emulator starts mdelay(100); // to prevent ds2_setBacklight() from crashing @@ -4100,7 +4110,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) mdelay(100); // to prevent ds2_setBacklight() from crashing ds2_setBacklight(2); - set_cpu_clock(clock_speed_number); + GameFrequencyCPU(); return return_value; } @@ -4708,7 +4718,7 @@ void gui_init(u32 lang_id) { int flag; - ds2_setCPUclocklevel(13); // Crank it up. When the menu starts, -> 0. + HighFrequencyCPU(); // Crank it up. When the menu starts, -> 0. // Start with no saved state existing, as no game is loaded yet. int i; diff --git a/source/nds/gui.h b/source/nds/gui.h index 0b91758..b2eae62 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -129,7 +129,9 @@ extern u32 menu(u16 *original_screen, bool8 FirstInvocation); extern void game_disableAudio(); extern void game_set_frameskip(); extern void game_set_fluidity(); -extern void set_cpu_clock(u32 num); +extern void LowFrequencyCPU(); +extern void HighFrequencyCPU(); +extern void GameFrequencyCPU(); extern int load_language_msg(char *filename, u32 language); #ifdef __cplusplus -- cgit v1.2.3 From 8693ae1bd880a758eb2efec4fccd32f89593855d Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 04:19:11 -0500 Subject: Add SDK modifications by BassAceGold as of 2011-04-14, as well as modified DMA functions as of 2013-01-29. --- README.md | 12 + sdk-modifications/include/archdefs.h | 2356 ++++++++++++++++++++ sdk-modifications/include/bit_ops.h | 58 + sdk-modifications/include/console.h | 9 + sdk-modifications/include/directory.h | 172 ++ sdk-modifications/include/dma.h | 46 + sdk-modifications/include/ds2_cpu.h | 57 + sdk-modifications/include/ds2_cpuclock.h | 22 + sdk-modifications/include/ds2_dma.h | 124 ++ sdk-modifications/include/ds2_excpt.h | 55 + sdk-modifications/include/ds2_fcntl.h | 51 + sdk-modifications/include/ds2_malloc.h | 32 + sdk-modifications/include/ds2_mmc_api.h | 56 + sdk-modifications/include/ds2_timer.h | 50 + sdk-modifications/include/ds2_types.h | 45 + sdk-modifications/include/ds2io.h | 285 +++ sdk-modifications/include/fat.h | 118 + sdk-modifications/include/fatdir.h | 81 + sdk-modifications/include/fatdir_ex.h | 18 + sdk-modifications/include/fatfile.h | 89 + sdk-modifications/include/fatfile_ex.h | 19 + sdk-modifications/include/file_allocation_table.h | 64 + sdk-modifications/include/filetime.h | 44 + sdk-modifications/include/fs_api.h | 151 ++ sdk-modifications/include/fs_cache.h | 118 + sdk-modifications/include/fs_common.h | 129 ++ sdk-modifications/include/fs_unicode.h | 16 + sdk-modifications/include/mem_allocate.h | 47 + sdk-modifications/include/mips.h | 820 +++++++ sdk-modifications/include/mipsregs.h | 985 ++++++++ sdk-modifications/include/mmc_api.h | 56 + sdk-modifications/include/partition.h | 131 ++ sdk-modifications/include/tcm.h | 10 + sdk-modifications/libsrc/.depend | 0 sdk-modifications/libsrc/Makefile | 67 + sdk-modifications/libsrc/console/console.c | 484 ++++ sdk-modifications/libsrc/console/console.h | 9 + sdk-modifications/libsrc/console/console.mk | 10 + sdk-modifications/libsrc/console/font_dot.h | 75 + sdk-modifications/libsrc/dma/dma.h | 46 + sdk-modifications/libsrc/dma/dma.mk | 9 + sdk-modifications/libsrc/dma/dmacopy.c | 167 ++ sdk-modifications/libsrc/fs/bit_ops.h | 58 + sdk-modifications/libsrc/fs/cache.c | 273 +++ sdk-modifications/libsrc/fs/directory.c | 1005 +++++++++ sdk-modifications/libsrc/fs/directory.h | 180 ++ sdk-modifications/libsrc/fs/disc_io/disc.c | 194 ++ sdk-modifications/libsrc/fs/disc_io/disc.h | 128 ++ sdk-modifications/libsrc/fs/disc_io/disc_io.h | 83 + sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.c | 13 + sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.h | 63 + sdk-modifications/libsrc/fs/ds2_fcntl.c | 126 ++ sdk-modifications/libsrc/fs/ds2_fcntl.h | 51 + sdk-modifications/libsrc/fs/ds2_unistd.c | 18 + sdk-modifications/libsrc/fs/ds2_unistd.h | 22 + sdk-modifications/libsrc/fs/fat.h | 118 + sdk-modifications/libsrc/fs/fat_misc.c | 138 ++ sdk-modifications/libsrc/fs/fat_misc.h | 38 + sdk-modifications/libsrc/fs/fatdir.c | 672 ++++++ sdk-modifications/libsrc/fs/fatdir.h | 85 + sdk-modifications/libsrc/fs/fatdir_ex.c | 183 ++ sdk-modifications/libsrc/fs/fatdir_ex.h | 18 + sdk-modifications/libsrc/fs/fatfile.c | 889 ++++++++ sdk-modifications/libsrc/fs/fatfile.h | 89 + sdk-modifications/libsrc/fs/fatfile_ex.c | 47 + sdk-modifications/libsrc/fs/fatfile_ex.h | 19 + .../libsrc/fs/file_allocation_table.c | 330 +++ .../libsrc/fs/file_allocation_table.h | 64 + sdk-modifications/libsrc/fs/filetime.c | 146 ++ sdk-modifications/libsrc/fs/filetime.h | 44 + sdk-modifications/libsrc/fs/fs.mk | 24 + sdk-modifications/libsrc/fs/fs_api.c | 452 ++++ sdk-modifications/libsrc/fs/fs_api.h | 130 ++ sdk-modifications/libsrc/fs/fs_cache.h | 125 ++ sdk-modifications/libsrc/fs/fs_common.h | 129 ++ sdk-modifications/libsrc/fs/fs_unicode.c | 173 ++ sdk-modifications/libsrc/fs/fs_unicode.h | 16 + sdk-modifications/libsrc/fs/libfat.c | 174 ++ sdk-modifications/libsrc/fs/mem_allocate.h | 47 + sdk-modifications/libsrc/fs/partition.c | 501 +++++ sdk-modifications/libsrc/fs/partition.h | 131 ++ sdk-modifications/libsrc/key/key.c | 145 ++ sdk-modifications/libsrc/key/key.h | 31 + sdk-modifications/libsrc/key/key.mk | 10 + sdk-modifications/libsrc/zlib/README | 1 + sdk-modifications/libsrc/zlib/adler32.c | 179 ++ sdk-modifications/libsrc/zlib/compress.c | 80 + sdk-modifications/libsrc/zlib/crc32.c | 447 ++++ sdk-modifications/libsrc/zlib/crc32.h | 441 ++++ sdk-modifications/libsrc/zlib/deflate.c | 1965 ++++++++++++++++ sdk-modifications/libsrc/zlib/deflate.h | 346 +++ sdk-modifications/libsrc/zlib/gzclose.c | 25 + sdk-modifications/libsrc/zlib/gzguts.h | 196 ++ sdk-modifications/libsrc/zlib/gzlib.c | 564 +++++ sdk-modifications/libsrc/zlib/gzread.c | 584 +++++ sdk-modifications/libsrc/zlib/gzwrite.c | 593 +++++ sdk-modifications/libsrc/zlib/infback.c | 640 ++++++ sdk-modifications/libsrc/zlib/inffast.c | 340 +++ sdk-modifications/libsrc/zlib/inffast.h | 11 + sdk-modifications/libsrc/zlib/inffixed.h | 94 + sdk-modifications/libsrc/zlib/inflate.c | 1501 +++++++++++++ sdk-modifications/libsrc/zlib/inflate.h | 122 + sdk-modifications/libsrc/zlib/inftrees.c | 306 +++ sdk-modifications/libsrc/zlib/inftrees.h | 62 + sdk-modifications/libsrc/zlib/trees.c | 1224 ++++++++++ sdk-modifications/libsrc/zlib/trees.h | 128 ++ sdk-modifications/libsrc/zlib/uncompr.c | 59 + sdk-modifications/libsrc/zlib/zconf.h | 468 ++++ sdk-modifications/libsrc/zlib/zlib.h | 1732 ++++++++++++++ sdk-modifications/libsrc/zlib/zlib.mk | 10 + sdk-modifications/libsrc/zlib/zutil.c | 301 +++ sdk-modifications/libsrc/zlib/zutil.h | 254 +++ 112 files changed, 27048 insertions(+) create mode 100644 sdk-modifications/include/archdefs.h create mode 100644 sdk-modifications/include/bit_ops.h create mode 100644 sdk-modifications/include/console.h create mode 100644 sdk-modifications/include/directory.h create mode 100644 sdk-modifications/include/dma.h create mode 100644 sdk-modifications/include/ds2_cpu.h create mode 100644 sdk-modifications/include/ds2_cpuclock.h create mode 100644 sdk-modifications/include/ds2_dma.h create mode 100644 sdk-modifications/include/ds2_excpt.h create mode 100644 sdk-modifications/include/ds2_fcntl.h create mode 100644 sdk-modifications/include/ds2_malloc.h create mode 100644 sdk-modifications/include/ds2_mmc_api.h create mode 100644 sdk-modifications/include/ds2_timer.h create mode 100644 sdk-modifications/include/ds2_types.h create mode 100644 sdk-modifications/include/ds2io.h create mode 100644 sdk-modifications/include/fat.h create mode 100644 sdk-modifications/include/fatdir.h create mode 100644 sdk-modifications/include/fatdir_ex.h create mode 100644 sdk-modifications/include/fatfile.h create mode 100644 sdk-modifications/include/fatfile_ex.h create mode 100644 sdk-modifications/include/file_allocation_table.h create mode 100644 sdk-modifications/include/filetime.h create mode 100644 sdk-modifications/include/fs_api.h create mode 100644 sdk-modifications/include/fs_cache.h create mode 100644 sdk-modifications/include/fs_common.h create mode 100644 sdk-modifications/include/fs_unicode.h create mode 100644 sdk-modifications/include/mem_allocate.h create mode 100644 sdk-modifications/include/mips.h create mode 100644 sdk-modifications/include/mipsregs.h create mode 100644 sdk-modifications/include/mmc_api.h create mode 100644 sdk-modifications/include/partition.h create mode 100644 sdk-modifications/include/tcm.h create mode 100644 sdk-modifications/libsrc/.depend create mode 100644 sdk-modifications/libsrc/Makefile create mode 100644 sdk-modifications/libsrc/console/console.c create mode 100644 sdk-modifications/libsrc/console/console.h create mode 100644 sdk-modifications/libsrc/console/console.mk create mode 100644 sdk-modifications/libsrc/console/font_dot.h create mode 100644 sdk-modifications/libsrc/dma/dma.h create mode 100644 sdk-modifications/libsrc/dma/dma.mk create mode 100644 sdk-modifications/libsrc/dma/dmacopy.c create mode 100644 sdk-modifications/libsrc/fs/bit_ops.h create mode 100644 sdk-modifications/libsrc/fs/cache.c create mode 100644 sdk-modifications/libsrc/fs/directory.c create mode 100644 sdk-modifications/libsrc/fs/directory.h create mode 100644 sdk-modifications/libsrc/fs/disc_io/disc.c create mode 100644 sdk-modifications/libsrc/fs/disc_io/disc.h create mode 100644 sdk-modifications/libsrc/fs/disc_io/disc_io.h create mode 100644 sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.c create mode 100644 sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.h create mode 100644 sdk-modifications/libsrc/fs/ds2_fcntl.c create mode 100644 sdk-modifications/libsrc/fs/ds2_fcntl.h create mode 100644 sdk-modifications/libsrc/fs/ds2_unistd.c create mode 100644 sdk-modifications/libsrc/fs/ds2_unistd.h create mode 100644 sdk-modifications/libsrc/fs/fat.h create mode 100644 sdk-modifications/libsrc/fs/fat_misc.c create mode 100644 sdk-modifications/libsrc/fs/fat_misc.h create mode 100644 sdk-modifications/libsrc/fs/fatdir.c create mode 100644 sdk-modifications/libsrc/fs/fatdir.h create mode 100644 sdk-modifications/libsrc/fs/fatdir_ex.c create mode 100644 sdk-modifications/libsrc/fs/fatdir_ex.h create mode 100644 sdk-modifications/libsrc/fs/fatfile.c create mode 100644 sdk-modifications/libsrc/fs/fatfile.h create mode 100644 sdk-modifications/libsrc/fs/fatfile_ex.c create mode 100644 sdk-modifications/libsrc/fs/fatfile_ex.h create mode 100644 sdk-modifications/libsrc/fs/file_allocation_table.c create mode 100644 sdk-modifications/libsrc/fs/file_allocation_table.h create mode 100644 sdk-modifications/libsrc/fs/filetime.c create mode 100644 sdk-modifications/libsrc/fs/filetime.h create mode 100644 sdk-modifications/libsrc/fs/fs.mk create mode 100644 sdk-modifications/libsrc/fs/fs_api.c create mode 100644 sdk-modifications/libsrc/fs/fs_api.h create mode 100644 sdk-modifications/libsrc/fs/fs_cache.h create mode 100644 sdk-modifications/libsrc/fs/fs_common.h create mode 100644 sdk-modifications/libsrc/fs/fs_unicode.c create mode 100644 sdk-modifications/libsrc/fs/fs_unicode.h create mode 100644 sdk-modifications/libsrc/fs/libfat.c create mode 100644 sdk-modifications/libsrc/fs/mem_allocate.h create mode 100644 sdk-modifications/libsrc/fs/partition.c create mode 100644 sdk-modifications/libsrc/fs/partition.h create mode 100644 sdk-modifications/libsrc/key/key.c create mode 100644 sdk-modifications/libsrc/key/key.h create mode 100644 sdk-modifications/libsrc/key/key.mk create mode 100644 sdk-modifications/libsrc/zlib/README create mode 100644 sdk-modifications/libsrc/zlib/adler32.c create mode 100644 sdk-modifications/libsrc/zlib/compress.c create mode 100644 sdk-modifications/libsrc/zlib/crc32.c create mode 100644 sdk-modifications/libsrc/zlib/crc32.h create mode 100644 sdk-modifications/libsrc/zlib/deflate.c create mode 100644 sdk-modifications/libsrc/zlib/deflate.h create mode 100644 sdk-modifications/libsrc/zlib/gzclose.c create mode 100644 sdk-modifications/libsrc/zlib/gzguts.h create mode 100644 sdk-modifications/libsrc/zlib/gzlib.c create mode 100644 sdk-modifications/libsrc/zlib/gzread.c create mode 100644 sdk-modifications/libsrc/zlib/gzwrite.c create mode 100644 sdk-modifications/libsrc/zlib/infback.c create mode 100644 sdk-modifications/libsrc/zlib/inffast.c create mode 100644 sdk-modifications/libsrc/zlib/inffast.h create mode 100644 sdk-modifications/libsrc/zlib/inffixed.h create mode 100644 sdk-modifications/libsrc/zlib/inflate.c create mode 100644 sdk-modifications/libsrc/zlib/inflate.h create mode 100644 sdk-modifications/libsrc/zlib/inftrees.c create mode 100644 sdk-modifications/libsrc/zlib/inftrees.h create mode 100644 sdk-modifications/libsrc/zlib/trees.c create mode 100644 sdk-modifications/libsrc/zlib/trees.h create mode 100644 sdk-modifications/libsrc/zlib/uncompr.c create mode 100644 sdk-modifications/libsrc/zlib/zconf.h create mode 100644 sdk-modifications/libsrc/zlib/zlib.h create mode 100644 sdk-modifications/libsrc/zlib/zlib.mk create mode 100644 sdk-modifications/libsrc/zlib/zutil.c create mode 100644 sdk-modifications/libsrc/zlib/zutil.h diff --git a/README.md b/README.md index 91e582f..b67691e 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,18 @@ MIPS compiler (`gcc`), extract it to `/opt/ds2sdk`, follow the instructions, then download version 1.2 of the DS2 SDK and extract its files into `opt/ds2sdk`, overwriting version 0.13. +Additionally, you will need to add the updated `zlib`, DMA +(Direct Memory Access) and filesystem access routines provided by BassAceGold +and recompile `libds2a.a`. To do this: + +> sudo rm -r /opt/ds2sdk/libsrc/{console,dma,fs,key,zlib,Makefile} /opt/ds2sdk/include +> sudo cp -r sdk-modifications/{libsrc,include} /opt/ds2sdk +> sudo chmod -R 600 /opt/ds2sdk/{libsrc,include} +> sudo chmod -R a+rX /opt/ds2sdk/{libsrc,include} +> cd /opt/ds2sdk/libsrc +> sudo rm libds2a.a ../lib/libds2a.a +> sudo make + ## The MIPS compiler (`gcc`) You also need the MIPS compiler from the DS2 SDK. The Makefile expects it at `/opt/mipsel-4.1.2-nopic`, but you can move it diff --git a/sdk-modifications/include/archdefs.h b/sdk-modifications/include/archdefs.h new file mode 100644 index 0000000..37c61b8 --- /dev/null +++ b/sdk-modifications/include/archdefs.h @@ -0,0 +1,2356 @@ +/************************************************************************** +* * +* PROJECT : MIPS port for uC/OS-II * +* * +* MODULE : ARCHDEFS.h * +* * +* AUTHOR : Michael Anburaj * +* URL : http://geocities.com/michaelanburaj/ * +* EMAIL: michaelanburaj@hotmail.com * +* * +* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board * +* * +* TOOL-CHAIN : SDE & Cygnus * +* * +* DESCRIPTION : * +* Architecture definitions. * +* * +**************************************************************************/ + + +#ifndef __ARCHDEFS_H__ +#define __ARCHDEFS_H__ + + +/* ********************************************************************* */ +/* Module configuration */ + + +/* ********************************************************************* */ +/* Interface macro & data definition */ + +/* + * Utility defines for cross platform handling of 64bit constants. + */ + +#if !defined(Append) + #define Append(c,s) (c##s) +#endif + +#if !defined(__assembler) && !defined(MIPSAVPENV) + #if defined(NT) + #if !defined(UNS64Const) + #define UNS64Const(c) Append(c,ui64) + #endif + + #if !defined(INT64Const) + #define INT64Const(c) Append(c,i64) + #endif + #else + #if !defined(UNS64Const) + #define UNS64Const(c) Append(c,ull) + #endif + + #if !defined(INT64Const) + #define INT64Const(c) Append(c,ll) + #endif + #endif +#else /* Not C or C++ */ + #if !defined(UNS64Const) + #define UNS64Const(c) c + #endif + + #if !defined(INT64Const) + #define INT64Const(c) c + #endif +#endif /* C or C++ */ + + +/* + ************************************************************************ + * I N S T R U C T I O N F O R M A T S * + ************************************************************************ + * + * The following definitions describe each field in an instruction. There + * is one diagram for each type of instruction, with field definitions + * following the diagram for that instruction. Note that if a field of + * the same name and position is defined in an earlier diagram, it is + * not defined again in the subsequent diagram. Only new fields are + * defined for each diagram. + * + * R-Type (operate) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | rs | rt | rd | sa | | + * | Opcode | | | Tcode | func | + * | | Bcode | | sel | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnOpcode 26 +#define M_InstnOpcode (0x3f << S_InstnOpcode) +#define S_InstnRS 21 +#define M_InstnRS (0x1f << S_InstnRS) +#define S_InstnRT 16 +#define M_InstnRT (0x1f << S_InstnRT) +#define S_InstnRD 11 +#define M_InstnRD (0x1f << S_InstnRD) +#define S_InstnSA 6 +#define M_InstnSA (0x1f << S_InstnSA) +#define S_InstnTcode 6 +#define M_InstnTcode (0x3ff << S_InstnTcode) +#define S_InstnBcode 6 +#define M_InstnBcode (0xfffff << S_InstnBcode) +#define S_InstnFunc 0 +#define M_InstnFunc (0x3f << S_InstnFunc) +#define S_InstnSel 0 +#define M_InstnSel (0x7 << S_InstnSel) + +/* + * I-Type (load, store, branch, immediate) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | rt | Offset | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnOffset 0 +#define M_InstnOffset (0xffff << S_InstnOffset) + +/* + * I-Type (pref) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | hint | Offset | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnHint S_InstnRT +#define M_InstnHint M_InstnRT + +/* + * J-Type (jump) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | JIndex | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnJIndex 0 +#define M_InstnJIndex (0x03ffffff << S_InstnJIndex) + +/* + * FP R-Type (operate) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | fmt | ft | fs | fd | func | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnFmt S_InstnRS +#define M_InstnFmt M_InstnRS +#define S_InstnFT S_InstnRT +#define M_InstnFT M_InstnRT +#define S_InstnFS S_InstnRD +#define M_InstnFS M_InstnRD +#define S_InstnFD S_InstnSA +#define M_InstnFD M_InstnSA + +/* + * FP R-Type (cpu <-> cpu data movement)) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | sub | rt | fs | 0 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnSub S_InstnRS +#define M_InstnSub M_InstnRS + +/* + * FP R-Type (compare) + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | |C| | + * | Opcode | fmt | ft | fs | cc |0|A| func | + * | | | | | | |B| | + * | | | | | | |S| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnCCcmp 8 +#define M_InstnCCcmp (0x7 << S_InstnCCcmp) +#define S_InstnCABS 6 +#define M_InstnCABS (0x1 << S_InstnCABS) + +/* + * FP R-Type (FPR conditional move on FP cc) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | fmt | cc |n|t| fs | fd | func | + * | | | |d|f| | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnCC 18 +#define M_InstnCC (0x7 << S_InstnCC) +#define S_InstnND 17 +#define M_InstnND (0x1 << S_InstnND) +#define S_InstnTF 16 +#define M_InstnTF (0x1 << S_InstnTF) + +/* + * FP R-Type (3-operand operate) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | fr | ft | fs | fd | op4 | fmt3| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnFR S_InstnRS +#define M_InstnFR M_InstnRS +#define S_InstnOp4 3 +#define M_InstnOp4 (0x7 << S_InstnOp4) +#define S_InstnFmt3 0 +#define M_InstnFmt3 (0x7 << S_InstnFmt3) + +/* + * FP R-Type (Indexed load, store) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | rt | 0 | fd | func | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +/* + * FP R-Type (prefx) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | rt | hint | 0 | func | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnHintX S_InstnRD +#define M_InstnHintX M_InstnRD + +/* + * FP R-Type (GPR conditional move on FP cc) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | cc |n|t| rd | 0 | func | + * | | | |d|f| | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/* + * FP I-Type (load, store) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | ft | Offset | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/* + * FP I-Type (branch) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | fmt | cc |n|t| Offset | + * | | | |d|f| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + +/* + ************************************************************************* + * V I R T U A L A D D R E S S D E F I N I T I O N S * + ************************************************************************* + */ + +#ifdef MIPSADDR64 +#define A_K0BASE UNS64Const(0xffffffff80000000) +#define A_K1BASE UNS64Const(0xffffffffa0000000) +#define A_K2BASE UNS64Const(0xffffffffc0000000) +#define A_K3BASE UNS64Const(0xffffffffe0000000) +#define A_REGION UNS64Const(0xc000000000000000) +#define A_XKPHYS_ATTR UNS64Const(0x3800000000000000) +#else +#define A_K0BASE 0x80000000 +#define A_K1BASE 0xa0000000 +#define A_K2BASE 0xc0000000 +#define A_K3BASE 0xe0000000 +#endif +#define M_KMAPPED 0x40000000 /* KnSEG address is mapped if bit is one */ + + +#ifdef MIPS_Model64 + +#define S_VMAP64 62 +#define M_VMAP64 UNS64Const(0xc000000000000000) + +#define K_VMode11 3 +#define K_VMode10 2 +#define K_VMode01 1 +#define K_VMode00 0 + +#define S_KSEG3 29 +#define M_KSEG3 (0x7 << S_KSEG3) +#define K_KSEG3 7 + +#define S_SSEG 29 +#define M_SSEG (0x7 << S_KSEG3) +#define K_SSEG 6 + +#define S_KSSEG 29 +#define M_KSSEG (0x7 << S_KSEG3) +#define K_KSSEG 6 + +#define S_KSEG1 29 +#define M_KSEG1 (0x7 << S_KSEG3) +#define K_KSEG1 5 + +#define S_KSEG0 29 +#define M_KSEG0 (0x7 << S_KSEG3) +#define K_KSEG0 4 + +#define S_XKSEG 29 +#define M_XKSEG (0x7 << S_KSEG3) +#define K_XKSEG 3 + +#define S_USEG 31 +#define M_USEG (0x1 << S_USEG) +#define K_USEG 0 + +#define S_EjtagProbeMem 20 +#define M_EjtagProbeMem (0x1 << S_EjtagProbeMem) +#define K_EjtagProbeMem 0 + + + +#else + +#define S_KSEG3 29 +#define M_KSEG3 (0x7 << S_KSEG3) +#define K_KSEG3 7 + +#define S_KSSEG 29 +#define M_KSSEG (0x7 << S_KSSEG) +#define K_KSSEG 6 + +#define S_SSEG 29 +#define M_SSEG (0x7 << S_SSEG) +#define K_SSEG 6 + +#define S_KSEG1 29 +#define M_KSEG1 (0x7 << S_KSEG1) +#define K_KSEG1 5 + +#define S_KSEG0 29 +#define M_KSEG0 (0x7 << S_KSEG0) +#define K_KSEG0 4 + +#define S_KUSEG 31 +#define M_KUSEG (0x1 << S_KUSEG) +#define K_KUSEG 0 + +#define S_SUSEG 31 +#define M_SUSEG (0x1 << S_SUSEG) +#define K_SUSEG 0 + +#define S_USEG 31 +#define M_USEG (0x1 << S_USEG) +#define K_USEG 0 + +#define K_EjtagLower 0xff200000 +#define K_EjtagUpper 0xff3fffff + +#define S_EjtagProbeMem 20 +#define M_EjtagProbeMem (0x1 << S_EjtagProbeMem) +#define K_EjtagProbeMem 0 + +#endif + + + +/* + ************************************************************************* + * C A C H E I N S T R U C T I O N O P E R A T I O N C O D E S * + ************************************************************************* + */ + +/* + * Cache encodings + */ +#define K_CachePriI 0 /* Primary Icache */ +#define K_CachePriD 1 /* Primary Dcache */ +#define K_CachePriU 1 /* Unified primary */ +#define K_CacheTerU 2 /* Unified Tertiary */ +#define K_CacheSecU 3 /* Unified secondary */ + + +/* + * Function encodings + */ +#define S_CacheFunc 2 /* Amount to shift function encoding within 5-bit field */ +#define K_CacheIndexInv 0 /* Index invalidate */ +#define K_CacheIndexWBInv 0 /* Index writeback invalidate */ +#define K_CacheIndexLdTag 1 /* Index load tag */ +#define K_CacheIndexStTag 2 /* Index store tag */ +#define K_CacheHitInv 4 /* Hit Invalidate */ +#define K_CacheFill 5 /* Fill (Icache only) */ +#define K_CacheHitWBInv 5 /* Hit writeback invalidate */ +#define K_CacheHitWB 6 /* Hit writeback */ +#define K_CacheFetchLock 7 /* Fetch and lock */ + +#define ICIndexInv ((K_CacheIndexInv << S_CacheFunc) | K_CachePriI) +#define DCIndexWBInv ((K_CacheIndexWBInv << S_CacheFunc) | K_CachePriD) +#define DCIndexInv DCIndexWBInv +#define ICIndexLdTag ((K_CacheIndexLdTag << S_CacheFunc) | K_CachePriI) +#define DCIndexLdTag ((K_CacheIndexLdTag << S_CacheFunc) | K_CachePriD) +#define ICIndexStTag ((K_CacheIndexStTag << S_CacheFunc) | K_CachePriI) +#define DCIndexStTag ((K_CacheIndexStTag << S_CacheFunc) | K_CachePriD) +#define ICHitInv ((K_CacheHitInv << S_CacheFunc) | K_CachePriI) +#define DCHitInv ((K_CacheHitInv << S_CacheFunc) | K_CachePriD) +#define ICFill ((K_CacheFill << S_CacheFunc) | K_CachePriI) +#define DCHitWBInv ((K_CacheHitWBInv << S_CacheFunc) | K_CachePriD) +#define DCHitWB ((K_CacheHitWB << S_CacheFunc) | K_CachePriD) +#define ICFetchLock ((K_CacheFetchLock << S_CacheFunc) | K_CachePriI) +#define DCFetchLock ((K_CacheFetchLock << S_CacheFunc) | K_CachePriD) + + +/* + ************************************************************************* + * P R E F E T C H I N S T R U C T I O N H I N T S * + ************************************************************************* + */ + +#define PrefLoad 0 +#define PrefStore 1 +#define PrefLoadStreamed 4 +#define PrefStoreStreamed 5 +#define PrefLoadRetained 6 +#define PrefStoreRetained 7 +#define PrefWBInval 25 +#define PrefNudge 25 + + +/* + ************************************************************************* + * C P U R E G I S T E R D E F I N I T I O N S * + ************************************************************************* + */ + + +/* + ************************************************************************* + * S O F T W A R E G P R N A M E S * + ************************************************************************* + */ + +#define zero $0 +#define AT $1 +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define ra $31 + +/* + * The following registers are used by the AVP environment and + * are not part of the normal software definitions. + */ + +#ifdef MIPSAVPENV +#define repc $25 /* Expected exception PC */ +#define tid $30 /* Current test case address */ +#endif + + +/* + ************************************************************************* + * H A R D W A R E G P R N A M E S * + ************************************************************************* + * + * In the AVP environment, several of the `r' names are removed from the + * name space because they are used by the kernel for special purposes. + * Removing them causes assembly rather than runtime errors for tests that + * use the `r' names. + * + * - r25 (repc) is used as the expected PC on an exception + * - r26-r27 (k0, k1) are used in the exception handler + * - r30 (tid) is used as the current test address + */ + +#define r0 $0 +#define r1 $1 +#define r2 $2 +#define r3 $3 +#define r4 $4 +#define r5 $5 +#define r6 $6 +#define r7 $7 +#define r8 $8 +#define r9 $9 +#define r10 $10 +#define r11 $11 +#define r12 $12 +#define r13 $13 +#define r14 $14 +#define r15 $15 +#define r16 $16 +#define r17 $17 +#define r18 $18 +#define r19 $19 +#define r20 $20 +#define r21 $21 +#define r22 $22 +#define r23 $23 +#define r24 $24 +#ifdef MIPSAVPENV +#define r25 r25_unknown +#define r26 r26_unknown +#define r27 r27_unknown +#else +#define r25 $25 +#define r26 $26 +#define r27 $27 +#endif +#define r28 $28 +#define r29 $29 +#ifdef MIPSAVPENV +#define r30 r30_unknown +#else +#define r30 $30 +#endif +#define r31 $31 + + +/* + ************************************************************************* + * H A R D W A R E G P R I N D I C E S * + ************************************************************************* + * + * These definitions provide the index (number) of the GPR, as opposed + * to the assembler register name ($n). + */ + +#define R_r0 0 +#define R_r1 1 +#define R_r2 2 +#define R_r3 3 +#define R_r4 4 +#define R_r5 5 +#define R_r6 6 +#define R_r7 7 +#define R_r8 8 +#define R_r9 9 +#define R_r10 10 +#define R_r11 11 +#define R_r12 12 +#define R_r13 13 +#define R_r14 14 +#define R_r15 15 +#define R_r16 16 +#define R_r17 17 +#define R_r18 18 +#define R_r19 19 +#define R_r20 20 +#define R_r21 21 +#define R_r22 22 +#define R_r23 23 +#define R_r24 24 +#define R_r25 25 +#define R_r26 26 +#define R_r27 27 +#define R_r28 28 +#define R_r29 29 +#define R_r30 30 +#define R_r31 31 +#define R_hi 32 /* Hi register */ +#define R_lo 33 /* Lo register */ + + +/* + ************************************************************************* + * S O F T W A R E G P R M A S K S * + ************************************************************************* + * + * These definitions provide the bit mask corresponding to the GPR number + */ + +#define M_AT (1<<1) +#define M_v0 (1<<2) +#define M_v1 (1<<3) +#define M_a0 (1<<4) +#define M_a1 (1<<5) +#define M_a2 (1<<6) +#define M_a3 (1<<7) +#define M_t0 (1<<8) +#define M_t1 (1<<9) +#define M_t2 (1<<10) +#define M_t3 (1<<11) +#define M_t4 (1<<12) +#define M_t5 (1<<13) +#define M_t6 (1<<14) +#define M_t7 (1<<15) +#define M_s0 (1<<16) +#define M_s1 (1<<17) +#define M_s2 (1<<18) +#define M_s3 (1<<19) +#define M_s4 (1<<20) +#define M_s5 (1<<21) +#define M_s6 (1<<22) +#define M_s7 (1<<23) +#define M_t8 (1<<24) +#define M_t9 (1<<25) +#define M_k0 (1<<26) +#define M_k1 (1<<27) +#define M_gp (1<<28) +#define M_sp (1<<29) +#define M_fp (1<<30) +#define M_ra (1<<31) + + +/* + ************************************************************************* + * C P 0 R E G I S T E R D E F I N I T I O N S * + ************************************************************************* + * Each register has the following definitions: + * + * C0_rrr The register number (as a $n value) + * R_C0_rrr The register index (as an integer corresponding + * to the register number) + * + * Each field in a register has the following definitions: + * + * S_rrrfff The shift count required to right-justify + * the field. This corresponds to the bit + * number of the right-most bit in the field. + * M_rrrfff The Mask required to isolate the field. + * + * Register diagrams included below as comments correspond to the + * MIPS32 and MIPS64 architecture specifications. Refer to other + * sources for register diagrams for older architectures. + */ + + +/* + ************************************************************************ + * I N D E X R E G I S T E R ( 0 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |P| 0 | Index | Index + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Index $0 +#define R_C0_Index 0 +#define C0_INX C0_Index /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_IndexP 31 /* Probe failure (R)*/ +#define M_IndexP (0x1 << S_IndexP) + +#define S_IndexIndex 0 /* TLB index (R/W)*/ +#define M_IndexIndex (0x3f << S_IndexIndex) + +#define M_Index0Fields 0x7fffffc0 +#define M_IndexRFields 0x80000000 + + +/* + ************************************************************************ + * R A N D O M R E G I S T E R ( 1 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Index | Random + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Random $1 +#define R_C0_Random 1 +#define C0_RAND $1 /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_RandomIndex 0 /* TLB random index (R)*/ +#define M_RandomIndex (0x3f << S_RandomIndex) + +#define M_Random0Fields 0xffffffc0 +#define M_RandomRFields 0x0000003f + + +/* + ************************************************************************ + * E N T R Y L O 0 R E G I S T E R ( 2 ) * + ************************************************************************ + * + * 6 6 6 6 5 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 2 1 0 9 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Fill (0) //| 0 | PFN | C |D|V|G| EntryLo0 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_EntryLo0 $2 +#define R_C0_EntryLo0 2 +#define C0_TLBLO_0 C0_EntryLo0 /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_EntryLoPFN 6 /* PFN (R/W) */ +#define M_EntryLoPFN (0xffffff << S_EntryLoPFN) +#define S_EntryLoC 3 /* Coherency attribute (R/W) */ +#define M_EntryLoC (0x7 << S_EntryLoC) +#define S_EntryLoD 2 /* Dirty (R/W) */ +#define M_EntryLoD (0x1 << S_EntryLoD) +#define S_EntryLoV 1 /* Valid (R/W) */ +#define M_EntryLoV (0x1 << S_EntryLoV) +#define S_EntryLoG 0 /* Global (R/W) */ +#define M_EntryLoG (0x1 << S_EntryLoG) +#define M_EntryLoOddPFN (0x1 << S_EntryLoPFN) /* Odd PFN bit */ +#define S_EntryLo_RS K_PageAlign /* Right-justify PFN */ +#define S_EntryLo_LS S_EntryLoPFN /* Position PFN to appropriate position */ + +#define M_EntryLo0Fields 0x00000000 +#define M_EntryLoRFields 0xc0000000 +#define M_EntryLo0Fields64 UNS64Const(0x0000000000000000) +#define M_EntryLoRFields64 UNS64Const(0xffffffffc0000000) + +/* + * Cache attribute values in the C field of EntryLo and the + * K0 field of Config + */ +#define K_CacheAttrCWTnWA 0 /* Cacheable, write-thru, no write allocate */ +#define K_CacheAttrCWTWA 1 /* Cacheable, write-thru, write allocate */ +#define K_CacheAttrU 2 /* Uncached */ +#define K_CacheAttrC 3 /* Cacheable */ +#define K_CacheAttrCN 3 /* Cacheable, non-coherent */ +#define K_CacheAttrCCE 4 /* Cacheable, coherent, exclusive */ +#define K_CacheAttrCCS 5 /* Cacheable, coherent, shared */ +#define K_CacheAttrCCU 6 /* Cacheable, coherent, update */ +#define K_CacheAttrUA 7 /* Uncached accelerated */ + + +/* + ************************************************************************ + * E N T R Y L O 1 R E G I S T E R ( 3 ) * + ************************************************************************ + * + * 6 6 6 6 5 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 2 1 0 9 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Fill (0) //| 0 | PFN | C |D|V|G| EntryLo1 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_EntryLo1 $3 +#define R_C0_EntryLo1 3 +#define C0_TLBLO_1 C0_EntryLo1 /* OBSOLETE - DO NOT USE IN NEW CODE */ + +/* + * Field definitions are as given for EntryLo0 above + */ + + +/* + ************************************************************************ + * C O N T E X T R E G I S T E R ( 4 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // PTEBase | BadVPN<31:13> | 0 | Context + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Context $4 +#define R_C0_Context 4 +#define C0_CTXT C0_Context /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_ContextPTEBase 23 /* PTE base (R/W) */ +#define M_ContextPTEBase (0x1ff << S_ContextPTEBase) +#define S_ContextBadVPN 4 /* BadVPN2 (R) */ +#define M_ContextBadVPN (0x7ffff << S_ContextBadVPN) +#define S_ContextBadVPN_LS 9 /* Position BadVPN to bit 31 */ +#define S_ContextBadVPN_RS 13 /* Right-justify shifted BadVPN field */ + +#define M_Context0Fields 0x0000000f +#define M_ContextRFields 0x007ffff0 +#define M_Context0Fields64 UNS64Const(0x000000000000000f) +#define M_ContextRFields64 UNS64Const(0x00000000007ffff0) + + +/* + ************************************************************************ + * P A G E M A S K R E G I S T E R ( 5 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Mask | 0 | PageMask + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_PageMask $5 +#define R_C0_PageMask 5 /* Mask (R/W) */ +#define C0_PGMASK C0_PageMask /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_PageMaskMask 13 +#define M_PageMaskMask (0xfff << S_PageMaskMask) + +#define M_PageMask0Fields 0xfe001fff +#define M_PageMaskRFields 0x00000000 + +/* + * Values in the Mask field + */ +#define K_PageMask4K 0x000 /* K_PageMasknn values are values for use */ +#define K_PageMask16K 0x003 /* with KReqPageAttributes or KReqPageMask macros */ +#define K_PageMask64K 0x00f +#define K_PageMask256K 0x03f +#define K_PageMask1M 0x0ff +#define K_PageMask4M 0x3ff +#define K_PageMask16M 0xfff + +#define M_PageMask4K (K_PageMask4K << S_PageMaskMask) /* M_PageMasknn values are masks */ +#define M_PageMask16K (K_PageMask16K << S_PageMaskMask) /* in position in the PageMask register */ +#define M_PageMask64K (K_PageMask64K << S_PageMaskMask) +#define M_PageMask256K (K_PageMask256K << S_PageMaskMask) +#define M_PageMask1M (K_PageMask1M << S_PageMaskMask) +#define M_PageMask4M (K_PageMask4M << S_PageMaskMask) +#define M_PageMask16M (K_PageMask16M << S_PageMaskMask) + + +/* + ************************************************************************ + * W I R E D R E G I S T E R ( 6 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Index | Wired + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Wired $6 +#define R_C0_Wired 6 +#define C0_TLBWIRED C0_Wired /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_WiredIndex 0 /* TLB wired boundary (R/W) */ +#define M_WiredIndex (0x3f << S_WiredIndex) + +#define M_Wired0Fields 0xffffffc0 +#define M_WiredRFields 0x00000000 + + +/* + ************************************************************************ + * B A D V A D D R R E G I S T E R ( 8 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // Bad Virtual Address | BadVAddr + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_BadVAddr $8 +#define R_C0_BadVAddr 8 +#define C0_BADVADDR C0_BadVAddr /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_BadVAddrOddPage K_PageSize /* Even/Odd VA bit for pair of PAs */ + +#define M_BadVAddr0Fields 0x00000000 +#define M_BadVAddrRFields 0xffffffff +#define M_BadVAddr0Fields64 UNS64Const(0x0000000000000000) +#define M_BadVAddrRFields64 UNS64Const(0xffffffffffffffff) + +/* + ************************************************************************ + * C O U N T R E G I S T E R ( 9 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Count Value | Count + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Count $9 +#define R_C0_Count 9 +#define C0_COUNT C0_Count /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_Count0Fields 0x00000000 +#define M_CountRFields 0x00000000 + + +/* + ************************************************************************ + * E N T R Y H I R E G I S T E R ( 1 0 ) * + ************************************************************************ + * + * 6 6 6 6 5 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 2 1 0 9 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | R | Fill // VPN2 | 0 | ASID | EntryHi + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_EntryHi $10 +#define R_C0_EntryHi 10 +#define C0_TLBHI C0_EntryHi /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_EntryHiR64 62 /* Region (R/W) */ +#define M_EntryHiR64 UNS64Const(0xc000000000000000) +#define S_EntryHiVPN2 13 /* VPN/2 (R/W) */ +#define M_EntryHiVPN2 (0x7ffff << S_EntryHiVPN2) +#define M_EntryHiVPN264 UNS64Const(0x000000ffffffe000) +#define S_EntryHiASID 0 /* ASID (R/W) */ +#define M_EntryHiASID (0xff << S_EntryHiASID) +#define S_EntryHiVPN_Shf S_EntryHiVPN2 + +#define M_EntryHi0Fields 0x00001f00 +#define M_EntryHiRFields 0x00000000 +#define M_EntryHi0Fields64 UNS64Const(0x0000000000001f00) +#define M_EntryHiRFields64 UNS64Const(0x3fffff0000000000) + + +/* + ************************************************************************ + * C O M P A R E R E G I S T E R ( 1 1 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Compare Value | Compare + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Compare $11 +#define R_C0_Compare 11 +#define C0_COMPARE C0_Compare /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_Compare0Fields 0x00000000 +#define M_CompareRFields 0x00000000 + + +/* + ************************************************************************ + * S T A T U S R E G I S T E R ( 1 2 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |C|C|C|C|R|F|R|M|P|B|T|S|M| | R |I|I|I|I|I|I|I|I|K|S|U|U|R|E|E|I| + * |U|U|U|U|P|R|E|X|X|E|S|R|M| | s |M|M|M|M|M|M|M|M|X|X|X|M|s|R|X|E| Status + * |3|2|1|0| | | | | |V| | |I| | v |7|6|5|4|3|2|1|0| | | | |v|L|L| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Status $12 +#define R_C0_Status 12 +#define C0_SR C0_Status /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_StatusCU 28 /* Coprocessor enable (R/W) */ +#define M_StatusCU (0xf << S_StatusCU) +#define S_StatusCU3 31 +#define M_StatusCU3 (0x1 << S_StatusCU3) +#define S_StatusCU2 30 +#define M_StatusCU2 (0x1 << S_StatusCU2) +#define S_StatusCU1 29 +#define M_StatusCU1 (0x1 << S_StatusCU1) +#define S_StatusCU0 28 +#define M_StatusCU0 (0x1 << S_StatusCU0) +#define S_StatusRP 27 /* Enable reduced power mode (R/W) */ +#define M_StatusRP (0x1 << S_StatusRP) +#define S_StatusFR 26 /* Enable 64-bit FPRs (MIPS64 only) (R/W) */ +#define M_StatusFR (0x1 << S_StatusFR) +#define S_StatusRE 25 /* Enable reverse endian (R/W) */ +#define M_StatusRE (0x1 << S_StatusRE) +#define S_StatusMX 24 /* Enable access to MDMX resources (MIPS64 only) (R/W) */ +#define M_StatusMX (0x1 << S_StatusMX) +#define S_StatusPX 23 /* Enable access to 64-bit instructions/data (MIPS64 only) (R/W) */ +#define M_StatusPX (0x1 << S_StatusPX) +#define S_StatusBEV 22 /* Enable Boot Exception Vectors (R/W) */ +#define M_StatusBEV (0x1 << S_StatusBEV) +#define S_StatusTS 21 /* Denote TLB shutdown (R/W) */ +#define M_StatusTS (0x1 << S_StatusTS) +#define S_StatusSR 20 /* Denote soft reset (R/W) */ +#define M_StatusSR (0x1 << S_StatusSR) +#define S_StatusNMI 19 +#define M_StatusNMI (0x1 << S_StatusNMI) /* Denote NMI (R/W) */ +#define S_StatusIM 8 /* Interrupt mask (R/W) */ +#define M_StatusIM (0xff << S_StatusIM) +#define S_StatusIM7 15 +#define M_StatusIM7 (0x1 << S_StatusIM7) +#define S_StatusIM6 14 +#define M_StatusIM6 (0x1 << S_StatusIM6) +#define S_StatusIM5 13 +#define M_StatusIM5 (0x1 << S_StatusIM5) +#define S_StatusIM4 12 +#define M_StatusIM4 (0x1 << S_StatusIM4) +#define S_StatusIM3 11 +#define M_StatusIM3 (0x1 << S_StatusIM3) +#define S_StatusIM2 10 +#define M_StatusIM2 (0x1 << S_StatusIM2) +#define S_StatusIM1 9 +#define M_StatusIM1 (0x1 << S_StatusIM1) +#define S_StatusIM0 8 +#define M_StatusIM0 (0x1 << S_StatusIM0) +#define S_StatusKX 7 /* Enable access to extended kernel addresses (MIPS64 only) (R/W) */ +#define M_StatusKX (0x1 << S_StatusKX) +#define S_StatusSX 6 /* Enable access to extended supervisor addresses (MIPS64 only) (R/W) */ +#define M_StatusSX (0x1 << S_StatusSX) +#define S_StatusUX 5 /* Enable access to extended user addresses (MIPS64 only) (R/W) */ +#define M_StatusUX (0x1 << S_StatusUX) +#define S_StatusKSU 3 /* Two-bit current mode (R/W) */ +#define M_StatusKSU (0x3 << S_StatusKSU) +#define S_StatusUM 4 /* User mode if supervisor mode not implemented (R/W) */ +#define M_StatusUM (0x1 << S_StatusUM) +#define S_StatusSM 3 /* Supervisor mode (R/W) */ +#define M_StatusSM (0x1 << S_StatusSM) +#define S_StatusERL 2 /* Denotes error level (R/W) */ +#define M_StatusERL (0x1 << S_StatusERL) +#define S_StatusEXL 1 /* Denotes exception level (R/W) */ +#define M_StatusEXL (0x1 << S_StatusEXL) +#define S_StatusIE 0 /* Enables interrupts (R/W) */ +#define M_StatusIE (0x1 << S_StatusIE) + +#define M_Status0Fields 0x00040000 +#define M_StatusRFields 0x058000e0 /* FR, MX, PX, KX, SX, UX unused in MIPS32 */ +#define M_Status0Fields64 0x00040000 +#define M_StatusRFields64 0x00000000 + +/* + * Values in the KSU field + */ +#define K_StatusKSU_U 2 /* User mode in KSU field */ +#define K_StatusKSU_S 1 /* Supervisor mode in KSU field */ +#define K_StatusKSU_K 0 /* Kernel mode in KSU field */ + + +/* + ************************************************************************ + * C A U S E R E G I S T E R ( 1 3 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |B| | C | |I|W| |I|I|I|I|I|I|I|I| | | R | + * |D| | E | Rsvd |V|P| Rsvd |P|P|P|P|P|P|P|P| | ExcCode | s | Cause + * | | | | | | | |7|6|5|4|3|2|1|0| | | v | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Cause $13 +#define R_C0_Cause 13 +#define C0_CAUSE C0_Cause /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_CauseBD 31 +#define M_CauseBD (0x1 << S_CauseBD) +#define S_CauseCE 28 +#define M_CauseCE (0x3<< S_CauseCE) +#define S_CauseIV 23 +#define M_CauseIV (0x1 << S_CauseIV) +#define S_CauseWP 22 +#define M_CauseWP (0x1 << S_CauseWP) +#define S_CauseIP 8 +#define M_CauseIP (0xff << S_CauseIP) +#define S_CauseIPEXT 10 +#define M_CauseIPEXT (0x3f << S_CauseIPEXT) +#define S_CauseIP7 15 +#define M_CauseIP7 (0x1 << S_CauseIP7) +#define S_CauseIP6 14 +#define M_CauseIP6 (0x1 << S_CauseIP6) +#define S_CauseIP5 13 +#define M_CauseIP5 (0x1 << S_CauseIP5) +#define S_CauseIP4 12 +#define M_CauseIP4 (0x1 << S_CauseIP4) +#define S_CauseIP3 11 +#define M_CauseIP3 (0x1 << S_CauseIP3) +#define S_CauseIP2 10 +#define M_CauseIP2 (0x1 << S_CauseIP2) +#define S_CauseIP1 9 +#define M_CauseIP1 (0x1 << S_CauseIP1) +#define S_CauseIP0 8 +#define M_CauseIP0 (0x1 << S_CauseIP0) +#define S_CauseExcCode 2 +#define M_CauseExcCode (0x1f << S_CauseExcCode) + +#define M_Cause0Fields 0x4f3f0083 +#define M_CauseRFields 0xb000fc7c + +/* + * Values in the CE field + */ +#define K_CauseCE0 0 /* Coprocessor 0 in the CE field */ +#define K_CauseCE1 1 /* Coprocessor 1 in the CE field */ +#define K_CauseCE2 2 /* Coprocessor 2 in the CE field */ +#define K_CauseCE3 3 /* Coprocessor 3 in the CE field */ + +/* + * Values in the ExcCode field + */ +#define EX_INT 0 /* Interrupt */ +#define EXC_INT (EX_INT << S_CauseExcCode) +#define EX_MOD 1 /* TLB modified */ +#define EXC_MOD (EX_MOD << S_CauseExcCode) +#define EX_TLBL 2 /* TLB exception (load or ifetch) */ +#define EXC_TLBL (EX_TLBL << S_CauseExcCode) +#define EX_TLBS 3 /* TLB exception (store) */ +#define EXC_TLBS (EX_TLBS << S_CauseExcCode) +#define EX_ADEL 4 /* Address error (load or ifetch) */ +#define EXC_ADEL (EX_ADEL << S_CauseExcCode) +#define EX_ADES 5 /* Address error (store) */ +#define EXC_ADES (EX_ADES << S_CauseExcCode) +#define EX_IBE 6 /* Instruction Bus Error */ +#define EXC_IBE (EX_IBE << S_CauseExcCode) +#define EX_DBE 7 /* Data Bus Error */ +#define EXC_DBE (EX_DBE << S_CauseExcCode) +#define EX_SYS 8 /* Syscall */ +#define EXC_SYS (EX_SYS << S_CauseExcCode) +#define EX_SYSCALL EX_SYS +#define EXC_SYSCALL EXC_SYS +#define EX_BP 9 /* Breakpoint */ +#define EXC_BP (EX_BP << S_CauseExcCode) +#define EX_BREAK EX_BP +#define EXC_BREAK EXC_BP +#define EX_RI 10 /* Reserved instruction */ +#define EXC_RI (EX_RI << S_CauseExcCode) +#define EX_CPU 11 /* CoProcessor Unusable */ +#define EXC_CPU (EX_CPU << S_CauseExcCode) +#define EX_OV 12 /* OVerflow */ +#define EXC_OV (EX_OV << S_CauseExcCode) +#define EX_TR 13 /* Trap instruction */ +#define EXC_TR (EX_TR << S_CauseExcCode) +#define EX_TRAP EX_TR +#define EXC_TRAP EXC_TR +#define EX_FPE 15 /* floating point exception */ +#define EXC_FPE (EX_FPE << S_CauseExcCode) +#define EX_C2E 18 /* COP2 exception */ +#define EXC_C2E (EX_C2E << S_CauseExcCode) +#define EX_MDMX 22 /* MDMX exception */ +#define EXC_MDMX (EX_MDMX << S_CauseExcCode) +#define EX_WATCH 23 /* Watch exception */ +#define EXC_WATCH (EX_WATCH << S_CauseExcCode) +#define EX_MCHECK 24 /* Machine check exception */ +#define EXC_MCHECK (EX_MCHECK << S_CauseExcCode) +#define EX_CacheErr 30 /* Cache error caused re-entry to Debug Mode */ +#define EXC_CacheErr (EX_CacheErr << S_CauseExcCode) + + +/* + ************************************************************************ + * E P C R E G I S T E R ( 1 4 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // Exception PC | EPC + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_EPC $14 +#define R_C0_EPC 14 + +#define M_EPC0Fields 0x00000000 +#define M_EPCRFields 0x00000000 +#define M_EPC0Fields64 UNS64Const(0x0000000000000000) +#define M_EPCRFields64 UNS64Const(0x0000000000000000) + +/* + ************************************************************************ + * P R I D R E G I S T E R ( 1 5 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Company Opts | Company ID | Procesor ID | Revision | PRId + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_PRId $15 +#define R_C0_PRId 15 +#define C0_PRID C0_PRID /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_PRIdCoOpt 24 /* Company options (R) */ +#define M_PRIdCoOpt (0xff << S_PRIdCoOpt) +#define S_PRIdCoID 16 /* Company ID (R) */ +#define M_PRIdCoID (0xff << S_PRIdCoID) +#define S_PRIdImp 8 /* Implementation ID (R) */ +#define M_PRIdImp (0xff << S_PRIdImp) +#define S_PRIdRev 0 /* Revision (R) */ +#define M_PRIdRev (0xff << S_PRIdRev) + +#define M_PRId0Fields 0x00000000 +#define M_PRIdRFields 0xffffffff +/* + * Values in the Company ID field + */ +#define K_PRIdCoID_MIPS 1 +#define K_PRIdCoID_Broadcom 2 +#define K_PRIdCoID_Alchemy 3 +#define K_PRIdCoID_SiByte 4 +#define K_PRIdCoID_SandCraft 5 +#define K_PRIdCoID_Philips 6 +#define K_PRIdCoID_NextAvailable 7 /* Next available encoding */ + + +/* + * Values in the implementation number field + */ +#define K_PRIdImp_Jade 0x80 +#define K_PRIdImp_Opal 0x81 +#define K_PRIdImp_Ruby 0x82 +#define K_PRIdImp_JadeLite 0x83 +#define K_PRIdImp_4KEc 0x84 /* Emerald with TLB MMU */ +#define K_PRIdImp_4KEmp 0x85 /* Emerald with FM MMU */ +#define K_PRIdImp_4KSc 0x86 /* Coral */ + +#define K_PRIdImp_R3000 0x01 +#define K_PRIdImp_R4000 0x04 +#define K_PRIdImp_R10000 0x09 +#define K_PRIdImp_R4300 0x0b +#define K_PRIdImp_R5000 0x23 +#define K_PRIdImp_R5200 0x28 +#define K_PRIdImp_R5400 0x54 + +/* + ************************************************************************ + * C O N F I G R E G I S T E R ( 1 6 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |M| |B| A | A | | K | Config + * | | Reserved for Implementations|E| T | R | Reserved | 0 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Config $16 +#define R_C0_Config 16 +#define C0_CONFIG C0_Config /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_ConfigMore 31 /* Additional config registers present (R) */ +#define M_ConfigMore (0x1 << S_ConfigMore) +#define S_ConfigImpl 16 /* Implementation-specific fields */ +#define M_ConfigImpl (0x7fff << S_ConfigImpl) +#define S_ConfigBE 15 /* Denotes big-endian operation (R) */ +#define M_ConfigBE (0x1 << S_ConfigBE) +#define S_ConfigAT 13 /* Architecture type (R) */ +#define M_ConfigAT (0x3 << S_ConfigAT) +#define S_ConfigAR 10 /* Architecture revision (R) */ +#define M_ConfigAR (0x7 << S_ConfigAR) +#define S_ConfigMT 7 /* MMU Type (R) */ +#define M_ConfigMT (0x7 << S_ConfigMT) +#define S_ConfigK0 0 /* Kseg0 coherency algorithm (R/W) */ +#define M_ConfigK0 (0x7 << S_ConfigK0) + +/* + * The following definitions are technically part of the "reserved for + * implementations" field, but are the semi-standard definition used in + * fixed-mapping MMUs to control the cacheability of kuseg and kseg2/3 + * references. For that reason, they are included here, but may be + * overridden by true implementation-specific definitions + */ +#define S_ConfigK23 28 /* Kseg2/3 coherency algorithm (FM MMU only) (R/W) */ +#define M_ConfigK23 (0x7 << S_ConfigK23) +#define S_ConfigKU 25 /* Kuseg coherency algorithm (FM MMU only) (R/W) */ +#define M_ConfigKU (0x7 << S_ConfigKU) + +#define M_Config0Fields 0x00000078 +#define M_ConfigRFields 0x8000ff80 + +/* + * Values in the AT field + */ +#define K_ConfigAT_MIPS32 0 /* MIPS32 */ +#define K_ConfigAT_MIPS64S 1 /* MIPS64 with 32-bit addresses */ +#define K_ConfigAT_MIPS64 2 /* MIPS64 with 32/64-bit addresses */ + +/* + * Values in the MT field + */ +#define K_ConfigMT_NoMMU 0 /* No MMU */ +#define K_ConfigMT_TLBMMU 1 /* Standard TLB MMU */ +#define K_ConfigMT_BATMMU 2 /* Standard BAT MMU */ +#define K_ConfigMT_FMMMU 3 /* Standard Fixed Mapping MMU */ + + +/* + ************************************************************************ + * C O N F I G 1 R E G I S T E R ( 1 6, SELECT 1 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |M| MMU Size | IS | IL | IA | DS | DL | DA |C|M|P|W|C|E|F| Config1 + * | | | | | | | | |2|D|C|R|A|P|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Config1 $16,1 +#define R_C0_Config1 16 + +#define S_Config1More 31 /* Additional Config registers present (R) */ +#define M_Config1More (0x1 << S_Config1More) +#define S_Config1MMUSize 25 /* Number of MMU entries - 1 (R) */ +#define M_Config1MMUSize (0x3f << S_Config1MMUSize) +#define S_Config1IS 22 /* Icache sets per way (R) */ +#define M_Config1IS (0x7 << S_Config1IS) +#define S_Config1IL 19 /* Icache line size (R) */ +#define M_Config1IL (0x7 << S_Config1IL) +#define S_Config1IA 16 /* Icache associativity - 1 (R) */ +#define M_Config1IA (0x7 << S_Config1IA) +#define S_Config1DS 13 /* Dcache sets per way (R) */ +#define M_Config1DS (0x7 << S_Config1DS) +#define S_Config1DL 10 /* Dcache line size (R) */ +#define M_Config1DL (0x7 << S_Config1DL) +#define S_Config1DA 7 /* Dcache associativity (R) */ +#define M_Config1DA (0x7 << S_Config1DA) +#define S_Config1C2 6 /* Coprocessor 2 present (R) */ +#define M_Config1C2 (0x1 << S_Config1C2) +#define S_Config1MD 5 /* Denotes MDMX present (R) */ +#define M_Config1MD (0x1 << S_Config1MD) +#define S_Config1PC 4 /* Denotes performance counters present (R) */ +#define M_Config1PC (0x1 << S_Config1PC) +#define S_Config1WR 3 /* Denotes watch registers present (R) */ +#define M_Config1WR (0x1 << S_Config1WR) +#define S_Config1CA 2 /* Denotes MIPS-16 present (R) */ +#define M_Config1CA (0x1 << S_Config1CA) +#define S_Config1EP 1 /* Denotes EJTAG present (R) */ +#define M_Config1EP (0x1 << S_Config1EP) +#define S_Config1FP 0 /* Denotes floating point present (R) */ +#define M_Config1FP (0x1 << S_Config1FP) + +#define M_Config10Fields 0x00000060 +#define M_Config1RFields 0x7fffff9f + +/* + * The following macro generates a table that is indexed + * by the Icache or Dcache sets field in Config1 and + * contains the decoded value of sets per way + */ +#define Config1CacheSets() \ + HALF(64); \ + HALF(128); \ + HALF(256); \ + HALF(512); \ + HALF(1024); \ + HALF(2048); \ + HALF(4096); \ + HALF(8192); + +/* + * The following macro generates a table that is indexed + * by the Icache or Dcache line size field in Config1 and + * contains the decoded value of the cache line size, in bytes + */ +#define Config1CacheLineSize() \ + HALF(0); \ + HALF(4); \ + HALF(8); \ + HALF(16); \ + HALF(32); \ + HALF(64); \ + HALF(128); \ + HALF(256); + + +/* + ************************************************************************ + * C O N F I G 2 R E G I S T E R ( 1 6, SELECT 2 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |M| | | | | | | | | | | | |S|T| Config1 + * | | | | | | | | | | | | | |M|L| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Config2 $16,2 +#define R_C0_Config2 16 + +#define S_Config2More 31 /* Additional Config registers present (R) */ +#define M_Config2More (0x1 << S_Config2More) +#define S_Config2SM 1 /* Denotes SmartMIPS ASE present (R) */ +#define M_Config2SM (0x1 << S_Config2SM) +#define S_Config2TL 0 /* Denotes Tracing Logic present (R) */ +#define M_Config2TL (0x1 << S_Config2TL) + +#define M_Config20Fields 0xfffffffc +#define M_Config2RFields 0x00000003 + +/* + ************************************************************************ + * L L A D D R R E G I S T E R ( 1 7 ) * + ************************************************************************ + * + * 6 6 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // LL Physical Address | LLAddr + * +-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_LLAddr $17 +#define R_C0_LLAddr 17 +#define C0_LLADDR C0_LLAddr /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_LLAddr0Fields 0x00000000 +#define M_LLAddrRFields 0x00000000 +#define M_LLAddr0Fields64 UNS64Const(0x0000000000000000) +#define M_LLAddrRFields64 UNS64Const(0x0000000000000000) + + +/* + ************************************************************************ + * W A T C H L O R E G I S T E R ( 1 8 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // Watch Virtual Address |I|R|W| WatchLo + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_WatchLo $18 +#define R_C0_WatchLo 18 +#define C0_WATCHLO C0_WatchLo /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_WatchLoVAddr 3 /* Watch virtual address (R/W) */ +#define M_WatchLoVAddr (0x1fffffff << S_WatchLoVAddr) +#define S_WatchLoI 2 /* Enable Istream watch (R/W) */ +#define M_WatchLoI (0x1 << S_WatchLoI) +#define S_WatchLoR 1 /* Enable data read watch (R/W) */ +#define M_WatchLoR (0x1 << S_WatchLoR) +#define S_WatchLoW 0 /* Enable data write watch (R/W) */ +#define M_WatchLoW (0x1 << S_WatchLoW) + +#define M_WatchLo0Fields 0x00000000 +#define M_WatchLoRFields 0x00000000 +#define M_WatchLo0Fields64 UNS64Const(0x0000000000000000) +#define M_WatchLoRFields64 UNS64Const(0x0000000000000000) + +#define M_WatchLoEnables (M_WatchLoI | M_WatchLoR | M_WatchLoW) + + +/* + ************************************************************************ + * W A T C H H I R E G I S T E R ( 1 9 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |M|G| Rsvd | ASID | Rsvd | Mask | 0 | WatchHi + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_WatchHi $19 +#define R_C0_WatchHi 19 +#define C0_WATCHHI C0_WatchHi /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_WatchHiM 31 /* Denotes additional Watch registers present (R) */ +#define M_WatchHiM (0x1 << S_WatchHiM) +#define S_WatchHiG 30 /* Enable ASID-independent Watch match (R/W) */ +#define M_WatchHiG (0x1 << S_WatchHiG) +#define S_WatchHiASID 16 /* ASID value to match (R/W) */ +#define M_WatchHiASID (0xff << S_WatchHiASID) +#define S_WatchHiMask 3 /* Address inhibit mask (R/W) */ +#define M_WatchHiMask (0x1ff << S_WatchHiMask) + +#define M_WatchHi0Fields 0x3f00f007 +#define M_WatchHiRFields 0x80000000 + + +/* + ************************************************************************ + * X C O N T E X T R E G I S T E R ( 2 0 ) * + ************************************************************************ + * + * 6 // 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // PTEBase | R | BadVPN2<39:13> | 0 | XContext + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_XContext $20 +#define R_C0_XContext 20 +#define C0_EXTCTXT C0_XContext /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_XContextBadVPN2 4 /* BadVPN2 (R) */ +#define S_XContextBadVPN S_XContextBadVPN2 + +#define M_XContext0Fields 0x0000000f + + +/* + ************************************************************************ + * D E B U G R E G I S T E R ( 2 3 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |D|D|N|L|D|H|C|I|M|C|D|I|D|D| | |N|S| |D|D|D|D|D|D| + * |B|M|o|S|o|a|o|B|C|a|B|E|D|D|EJTAG|DExcCode |o|S| |I|I|D|D|B|S| + * |D| |D|N|z|l|u|u|h|c|u|X|B|B| ver | |S|t| |N|B|B|B|p|S| + * | | |C|M|e|t|n|s|e|h|s|I|S|L| | |S| | 0 |T| |S|L| | | Debug + * | | |R| | | |t|E|c|e|E| |I|I| | |t| | | | | | | | | + * | | | | | | |D|P|k|E|P| |m|m| | | | | | | | | | | | + * | | | | | | |M| |P|P| | |p|p| | | | | | | | | | | | + * | | | | | | | | | | | | |r|r| | | | | | | | | | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Debug $23 /* EJTAG */ +#define R_C0_Debug 23 + +#define S_DebugDBD 31 /* Debug branch delay (R) */ +#define M_DebugDBD (0x1 << S_DebugDBD) +#define S_DebugDM 30 /* Debug mode (R) */ +#define M_DebugDM (0x1 << S_DebugDM) +#define S_DebugNoDCR 29 /* No debug control register present (R) */ +#define M_DebugNoDCR (0x1 << S_DebugNoDCR) +#define S_DebugLSNM 28 /* Load/Store Normal Memory (R/W) */ +#define M_DebugLSNM (0x1 << S_DebugLSNM) +#define S_DebugDoze 27 /* Doze (R) */ +#define M_DebugDoze (0x1 << S_DebugDoze) +#define S_DebugHalt 26 /* Halt (R) */ +#define M_DebugHalt (0x1 << S_DebugHalt) +#define S_DebugCountDM 25 /* Count register behavior in debug mode (R/W) */ +#define M_DebugCountDM (0x1 << S_DebugCountDM) +#define S_DebugIBusEP 24 /* Imprecise Instn Bus Error Pending (R/W) */ +#define M_DebugIBusEP (0x1 << S_DebugIBusEP) +#define S_DebugMCheckP 23 /* Imprecise Machine Check Pending (R/W) */ +#define M_DebugMCheckP (0x1 << S_DebugMCheckP) +#define S_DebugCacheEP 22 /* Imprecise Cache Error Pending (R/W) */ +#define M_DebugCacheEP (0x1 << S_DebugCacheEP) +#define S_DebugDBusEP 21 /* Imprecise Data Bus Error Pending (R/W) */ +#define M_DebugDBusEP (0x1 << S_DebugDBusEP) +#define S_DebugIEXI 20 /* Imprecise Exception Inhibit (R/W) */ +#define M_DebugIEXI (0x1 << S_DebugIEXI) +#define S_DebugDDBSImpr 19 /* Debug data break store imprecise (R) */ +#define M_DebugDDBSImpr (0x1 << S_DebugDDBSImpr) +#define S_DebugDDBLImpr 18 /* Debug data break load imprecise (R) */ +#define M_DebugDDBLImpr (0x1 << S_DebugDDBLImpr) +#define S_DebugEJTAGver 15 /* EJTAG version number (R) */ +#define M_DebugEJTAGver (0x7 << S_DebugEJTAGver) +#define S_DebugDExcCode 10 /* Debug exception code (R) */ +#define M_DebugDExcCode (0x1f << S_DebugDExcCode) +#define S_DebugNoSSt 9 /* No single step implemented (R) */ +#define M_DebugNoSSt (0x1 << S_DebugNoSSt) +#define S_DebugSSt 8 /* Single step enable (R/W) */ +#define M_DebugSSt (0x1 << S_DebugSSt) +#define S_DebugDINT 5 /* Debug interrupt (R) */ +#define M_DebugDINT (0x1 << S_DebugDINT) +#define S_DebugDIB 4 /* Debug instruction break (R) */ +#define M_DebugDIB (0x1 << S_DebugDIB) +#define S_DebugDDBS 3 /* Debug data break store (R) */ +#define M_DebugDDBS (0x1 << S_DebugDDBS) +#define S_DebugDDBL 2 /* Debug data break load (R) */ +#define M_DebugDDBL (0x1 << S_DebugDDBL) +#define S_DebugDBp 1 /* Debug breakpoint (R) */ +#define M_DebugDBp (0x1 << S_DebugDBp) +#define S_DebugDSS 0 /* Debug single step (R) */ +#define M_DebugDSS (0x1 << S_DebugDSS) + +#define M_Debug0Fields 0x01f000c0 +#define M_DebugRFields 0xec0ffe3f + + +/* + ************************************************************************ + * D E P C R E G I S T E R ( 2 4 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // EJTAG Debug Exception PC | DEPC + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + +#define C0_DEPC $24 +#define R_C0_DEPC 24 + +#define M_DEEPC0Fields 0x00000000 +#define M_DEEPCRFields 0x00000000 +#define M_DEEPC0Fields64 UNS64Const(0x0000000000000000) +#define M_DEEPCRFields64 UNS64Const(0x0000000000000000) + + +/* + ************************************************************************ + * P E R F C N T R E G I S T E R ( 2 5 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | |I| | | |E| + * |M| 0 | Event |E|U|S|K|X| PerfCnt + * | | | | | | | |L| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Event Count | PerfCnt + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_PerfCnt $25 +#define R_C0_PerfCnt 25 +#define C0_PRFCNT0 C0_PerfCnt /* OBSOLETE - DO NOT USE IN NEW CODE */ +#define C0_PRFCNT1 C0_PerfCnt /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_PerfCntM 31 /* More performance counters exist (R) */ +#define M_PerfCntM (1 << S_PerfCntM) +#define S_PerfCntEvent 5 /* Enabled event (R/W) */ +#define M_PerfCntEvent (0x3f << S_PerfCntEvent) +#define S_PerfCntIE 4 /* Interrupt Enable (R/W) */ +#define M_PerfCntIE (1 << S_PerfCntIE) +#define S_PerfCntU 3 /* Enable counting in User Mode (R/W) */ +#define M_PerfCntU (1 << S_PerfCntU) +#define S_PerfCntS 2 /* Enable counting in Supervisor Mode (R/W) */ +#define M_PerfCntS (1 << S_PerfCntS) +#define S_PerfCntK 1 /* Enable counting in Kernel Mode (R/W) */ +#define M_PerfCntK (1 << S_PerfCntK) +#define S_PerfCntEXL 0 /* Enable counting while EXL==1 (R/W) */ +#define M_PerfCntEXL (1 << S_PerfCntEXL) + +#define M_PerfCnt0Fields 0x7ffff800 +#define M_PerfCntRFields 0x80000000 + + +/* + ************************************************************************ + * E R R C T L R E G I S T E R ( 2 6 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Error Control | ErrCtl + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_ErrCtl $26 +#define R_C0_ErrCtl 26 +#define C0_ECC $26 /* OBSOLETE - DO NOT USE IN NEW CODE */ +#define R_C0_ECC 26 /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_ErrCtl0Fields 0x00000000 +#define M_ErrCtlRFields 0x00000000 + + +/* + ************************************************************************ + * C A C H E E R R R E G I S T E R ( 2 7 ) * CacheErr + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Cache Error Control | CacheErr + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_CacheErr $27 +#define R_C0_CacheErr 27 +#define C0_CACHE_ERR C0_CacheErr /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_CacheErr0Fields 0x00000000 +#define M_CachErrRFields 0x00000000 + + +/* + ************************************************************************ + * T A G L O R E G I S T E R ( 2 8 ) * TagLo + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TagLo | TagLo + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_TagLo $28 +#define R_C0_TagLo 28 +#define C0_TAGLO C0_TagLo /* OBSOLETE - DO NOT USE IN NEW CODE */ + +/* + * Some implementations use separate TagLo registers for the + * instruction and data caches. In those cases, the following + * definitions can be used in relevant code + */ + +#define C0_ITagLo $28,0 +#define C0_DTagLo $28,2 + +#define M_TagLo0Fields 0x00000000 +#define M_TagLoRFields 0x00000000 + + +/* + ************************************************************************ + * D A T A L O R E G I S T E R ( 2 8, SELECT 1 ) * DataLo + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | DataLo | DataLo + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_DataLo $28,1 +#define R_C0_DataLo 28 + +/* + * Some implementations use separate DataLo registers for the + * instruction and data caches. In those cases, the following + * definitions can be used in relevant code + */ + +#define C0_IDataLo $28,1 +#define C0_DDataLo $28,3 + +#define M_DataLo0Fields 0x00000000 +#define M_DataLoRFields 0xffffffff + + +/* + ************************************************************************ + * T A G H I R E G I S T E R ( 2 9 ) * TagHi + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TagHi | TagHi + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_TagHi $29 +#define R_C0_TagHi 29 +#define C0_TAGHI C0_TagHi /* OBSOLETE - DO NOT USE IN NEW CODE */ + +/* + * Some implementations use separate TagHi registers for the + * instruction and data caches. In those cases, the following + * definitions can be used in relevant code + */ + +#define C0_ITagHi $29,0 +#define C0_DTagHi $29,2 + +#define M_TagHi0Fields 0x00000000 +#define M_TagHiRFields 0x00000000 + + +/* + ************************************************************************ + * D A T A H I R E G I S T E R ( 2 9, SELECT 1 ) * DataHi + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | DataHi | DataHi + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_DataHi $29,1 +#define R_C0_DataHi 29 + +/* + * Some implementations use separate DataHi registers for the + * instruction and data caches. In those cases, the following + * definitions can be used in relevant code + */ + +#define C0_IDataHi $29,1 +#define C0_DDataHi $29,3 + +#define M_DataHi0Fields 0x00000000 +#define M_DataHiRFields 0xffffffff + + +/* + ************************************************************************ + * E R R O R E P C R E G I S T E R ( 3 0 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // Error PC | ErrorEPC + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_ErrorEPC $30 +#define R_C0_ErrorEPC 30 +#define C0_ERROR_EPC C0_ErrorEPC /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_ErrorEPC0Fields 0x00000000 +#define M_ErrorEPCRFields 0x00000000 +#define M_ErrorEPC0Fields64 UNS64Const(0x0000000000000000) +#define M_ErrorEPCRFields64 UNS64Const(0x0000000000000000) + + +/* + ************************************************************************ + * D E S A V E R E G I S T E R ( 3 1 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // EJTAG Register Save Value | DESAVE + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_DESAVE $31 +#define R_C0_DESAVE 31 + +#define M_DESAVE0Fields 0x00000000 +#define M_DESAVERFields 0x00000000 +#define M_DESAVE0Fields64 UNS64Const(0x0000000000000000) +#define M_DESAVERFields64 UNS64Const(0x0000000000000000) + + +/* + ************************************************************************* + * C P 1 R E G I S T E R D E F I N I T I O N S * + ************************************************************************* + */ + + +/* + ************************************************************************* + * H A R D W A R E F P R N A M E S * + ************************************************************************* + */ + +#define fp0 $f0 +#define fp1 $f1 +#define fp2 $f2 +#define fp3 $f3 +#define fp4 $f4 +#define fp5 $f5 +#define fp6 $f6 +#define fp7 $f7 +#define fp8 $f8 +#define fp9 $f9 +#define fp10 $f10 +#define fp11 $f11 +#define fp12 $f12 +#define fp13 $f13 +#define fp14 $f14 +#define fp15 $f15 +#define fp16 $f16 +#define fp17 $f17 +#define fp18 $f18 +#define fp19 $f19 +#define fp20 $f20 +#define fp21 $f21 +#define fp22 $f22 +#define fp23 $f23 +#define fp24 $f24 +#define fp25 $f25 +#define fp26 $f26 +#define fp27 $f27 +#define fp28 $f28 +#define fp29 $f29 +#define fp30 $f30 +#define fp31 $f31 + +/* + * The following definitions are used to convert an FPR name + * into the corresponding even or odd name, respectively. + * This is used in macro substitution in the AVPs. + */ + +#define fp1_even $f0 +#define fp3_even $f2 +#define fp5_even $f4 +#define fp7_even $f6 +#define fp9_even $f8 +#define fp11_even $f10 +#define fp13_even $f12 +#define fp15_even $f14 +#define fp17_even $f16 +#define fp19_even $f18 +#define fp21_even $f20 +#define fp23_even $f22 +#define fp25_even $f24 +#define fp27_even $f26 +#define fp29_even $f28 +#define fp31_even $f30 + +#define fp0_odd $f1 +#define fp2_odd $f3 +#define fp4_odd $f5 +#define fp6_odd $f7 +#define fp8_odd $f9 +#define fp10_odd $f11 +#define fp12_odd $f13 +#define fp14_odd $f15 +#define fp16_odd $f17 +#define fp18_odd $f19 +#define fp20_odd $f21 +#define fp22_odd $f23 +#define fp24_odd $f25 +#define fp26_odd $f27 +#define fp28_odd $f29 +#define fp30_odd $f31 + + +/* + ************************************************************************* + * H A R D W A R E F P R I N D I C E S * + ************************************************************************* + * + * These definitions provide the index (number) of the FPR, as opposed + * to the assembler register name ($n). + */ + +#define R_fp0 0 +#define R_fp1 1 +#define R_fp2 2 +#define R_fp3 3 +#define R_fp4 4 +#define R_fp5 5 +#define R_fp6 6 +#define R_fp7 7 +#define R_fp8 8 +#define R_fp9 9 +#define R_fp10 10 +#define R_fp11 11 +#define R_fp12 12 +#define R_fp13 13 +#define R_fp14 14 +#define R_fp15 15 +#define R_fp16 16 +#define R_fp17 17 +#define R_fp18 18 +#define R_fp19 19 +#define R_fp20 20 +#define R_fp21 21 +#define R_fp22 22 +#define R_fp23 23 +#define R_fp24 24 +#define R_fp25 25 +#define R_fp26 26 +#define R_fp27 27 +#define R_fp28 28 +#define R_fp29 29 +#define R_fp30 30 +#define R_fp31 31 + + +/* + ************************************************************************* + * H A R D W A R E F C R N A M E S * + ************************************************************************* + */ + +#define fc0 $0 +#define fc25 $25 +#define fc26 $26 +#define fc28 $28 +#define fc31 $31 + + +/* + ************************************************************************* + * H A R D W A R E F C R I N D I C E S * + ************************************************************************* + * + * These definitions provide the index (number) of the FCR, as opposed + * to the assembler register name ($n). + */ + +#define R_fc0 0 +#define R_fc25 25 +#define R_fc26 26 +#define R_fc28 28 +#define R_fc31 31 + + +/* + ************************************************************************* + * H A R D W A R E F C C N A M E S * + ************************************************************************* + */ + +#define cc0 $fcc0 +#define cc1 $fcc1 +#define cc2 $fcc2 +#define cc3 $fcc3 +#define cc4 $fcc4 +#define cc5 $fcc5 +#define cc6 $fcc6 +#define cc7 $fcc7 + + +/* + ************************************************************************* + * H A R D W A R E F C C I N D I C E S * + ************************************************************************* + * + * These definitions provide the index (number) of the CC, as opposed + * to the assembler register name ($n). + */ + +#define R_cc0 0 +#define R_cc1 1 +#define R_cc2 2 +#define R_cc3 3 +#define R_cc4 4 +#define R_cc5 5 +#define R_cc6 6 +#define R_cc7 7 + + +/* + ************************************************************************ + * I M P L E M E N T A T I O N R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Reserved for Additional|3|P|D|S| Implementation| Revision | FIR + * | Configuration Bits |D|S| | | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FIR $0 +#define R_C1_FIR 0 + +#define S_FIRConfigS 16 +#define M_FIRConfigS (0x1 << S_FIRConfigS) +#define S_FIRConfigD 17 +#define M_FIRConfigD (0x1 << S_FIRConfigD) +#define S_FIRConfigPS 18 +#define M_FIRConfigPS (0x1 << S_FIRConfigPS) +#define S_FIRConfig3D 19 +#define M_FIRConfig3D (0x1 << S_FIRConfig3D) +#define M_FIRConfigAll (M_FIRConfigS|M_FIRConfigD|M_FIRConfigPS|M_FIRConfig3D) + +#define S_FIRImp 8 +#define M_FIRImp (0xff << S_FIRImp) + +#define S_FIRRev 0 +#define M_FIRRev (0xff << S_FIRRev) + +#define M_FIR0Fields 0xfff00000 +#define M_FIRRFields 0x000fffff + +/* + ************************************************************************ + * C O N D I T I O N C O D E S R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | CC | FCCR + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FCCR $25 +#define R_C1_FCCR 25 + +#define S_FCCRCC 0 +#define M_FCCRCC (0xff << S_FCCRCC) +#define S_FCCRCC7 7 +#define M_FCCRCC7 (0x1 << S_FCCRCC7) +#define S_FCCRCC6 6 +#define M_FCCRCC6 (0x1 << S_FCCRCC6) +#define S_FCCRCC5 5 +#define M_FCCRCC5 (0x1 << S_FCCRCC5) +#define S_FCCRCC4 4 +#define M_FCCRCC4 (0x1 << S_FCCRCC4) +#define S_FCCRCC3 3 +#define M_FCCRCC3 (0x1 << S_FCCRCC3) +#define S_FCCRCC2 2 +#define M_FCCRCC2 (0x1 << S_FCCRCC2) +#define S_FCCRCC1 1 +#define M_FCCRCC1 (0x1 << S_FCCRCC1) +#define S_FCCRCC0 0 +#define M_FCCRCC0 (0x1 << S_FCCRCC0) + +#define M_FCCR0Fields 0xffffff00 +#define M_FCCRRFields 0x000000ff + + +/* + ************************************************************************ + * E X C E P T I O N S R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Cause | 0 | Flags | 0 | FEXR + * | |E|V|Z|O|U|I| |V|Z|O|U|I| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FEXR $26 +#define R_C1_FEXR 26 + +#define S_FEXRExc 12 +#define M_FEXRExc (0x3f << S_FEXRExc) +#define S_FEXRExcE 17 +#define M_FEXRExcE (0x1 << S_FEXRExcE) +#define S_FEXRExcV 16 +#define M_FEXRExcV (0x1 << S_FEXRExcV) +#define S_FEXRExcZ 15 +#define M_FEXRExcZ (0x1 << S_FEXRExcZ) +#define S_FEXRExcO 14 +#define M_FEXRExcO (0x1 << S_FEXRExcO) +#define S_FEXRExcU 13 +#define M_FEXRExcU (0x1 << S_FEXRExcU) +#define S_FEXRExcI 12 +#define M_FEXRExcI (0x1 << S_FEXRExcI) + +#define S_FEXRFlg 2 +#define M_FEXRFlg (0x1f << S_FEXRFlg) +#define S_FEXRFlgV 6 +#define M_FEXRFlgV (0x1 << S_FEXRFlgV) +#define S_FEXRFlgZ 5 +#define M_FEXRFlgZ (0x1 << S_FEXRFlgZ) +#define S_FEXRFlgO 4 +#define M_FEXRFlgO (0x1 << S_FEXRFlgO) +#define S_FEXRFlgU 3 +#define M_FEXRFlgU (0x1 << S_FEXRFlgU) +#define S_FEXRFlgI 2 +#define M_FEXRFlgI (0x1 << S_FEXRFlgI) + +#define M_FEXR0Fields 0xfffc0f83 +#define M_FEXRRFields 0x00000000 + + +/* + ************************************************************************ + * E N A B L E S R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Enables | 0 |F|RM | FENR + * | |V|Z|O|U|I| |S| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FENR $28 +#define R_C1_FENR 28 + +#define S_FENREna 7 +#define M_FENREna (0x1f << S_FENREna) +#define S_FENREnaV 11 +#define M_FENREnaV (0x1 << S_FENREnaV) +#define S_FENREnaZ 10 +#define M_FENREnaZ (0x1 << S_FENREnaZ) +#define S_FENREnaO 9 +#define M_FENREnaO (0x1 << S_FENREnaO) +#define S_FENREnaU 8 +#define M_FENREnaU (0x1 << S_FENREnaU) +#define S_FENREnaI 7 +#define M_FENREnaI (0x1 << S_FENREnaI) + +#define S_FENRFS 2 +#define M_FENRFS (0x1 << S_FENRFS) + +#define S_FENRRM 0 +#define M_FENRRM (0x3 << S_FENRRM) + +#define M_FENR0Fields 0xfffff078 +#define M_FENRRFields 0x00000000 + + +/* + ************************************************************************ + * C O N T R O L / S T A T U S R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | FCC |F|C|Imp| 0 | Cause | Enables | Flags | RM| FCSR + * |7|6|5|4|3|2|1|S|C| | |E|V|Z|O|U|I|V|Z|O|U|I|V|Z|O|U|I| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FCSR $31 +#define R_C1_FCSR 31 + +#define S_FCSRFCC7_1 25 /* Floating point condition codes 7..1 (R/W) */ +#define M_FCSRFCC7_1 (0x7f << S_FCSRFCC7_1) +#define S_FCSRCC7 31 +#define M_FCSRCC7 (0x1 << S_FCSRCC7) +#define S_FCSRCC6 30 +#define M_FCSRCC6 (0x1 << S_FCSRCC6) +#define S_FCSRCC5 29 +#define M_FCSRCC5 (0x1 << S_FCSRCC5) +#define S_FCSRCC4 28 +#define M_FCSRCC4 (0x1 << S_FCSRCC4) +#define S_FCSRCC3 27 +#define M_FCSRCC3 (0x1 << S_FCSRCC3) +#define S_FCSRCC2 26 +#define M_FCSRCC2 (0x1 << S_FCSRCC2) +#define S_FCSRCC1 25 +#define M_FCSRCC1 (0x1 << S_FCSRCC1) + +#define S_FCSRFS 24 /* Flush denorms to zero (R/W) */ +#define M_FCSRFS (0x1 << S_FCSRFS) + +#define S_FCSRCC0 23 /* Floating point condition code 0 (R/W) */ +#define M_FCSRCC0 (0x1 << S_FCSRCC0) +#define S_FCSRCC S_FCSRCC0 +#define M_FCSRCC M_FCSRCC0 + +#define S_FCSRImpl 21 /* Implementation-specific control bits (R/W) */ +#define M_FCSRImpl (0x3 << S_FCSRImpl) + +#define S_FCSRExc 12 /* Exception cause (R/W) */ +#define M_FCSRExc (0x3f << S_FCSRExc) +#define S_FCSRExcE 17 +#define M_FCSRExcE (0x1 << S_FCSRExcE) +#define S_FCSRExcV 16 +#define M_FCSRExcV (0x1 << S_FCSRExcV) +#define S_FCSRExcZ 15 +#define M_FCSRExcZ (0x1 << S_FCSRExcZ) +#define S_FCSRExcO 14 +#define M_FCSRExcO (0x1 << S_FCSRExcO) +#define S_FCSRExcU 13 +#define M_FCSRExcU (0x1 << S_FCSRExcU) +#define S_FCSRExcI 12 +#define M_FCSRExcI (0x1 << S_FCSRExcI) + +#define S_FCSREna 7 /* Exception enable (R/W) */ +#define M_FCSREna (0x1f << S_FCSREna) +#define S_FCSREnaV 11 +#define M_FCSREnaV (0x1 << S_FCSREnaV) +#define S_FCSREnaZ 10 +#define M_FCSREnaZ (0x1 << S_FCSREnaZ) +#define S_FCSREnaO 9 +#define M_FCSREnaO (0x1 << S_FCSREnaO) +#define S_FCSREnaU 8 +#define M_FCSREnaU (0x1 << S_FCSREnaU) +#define S_FCSREnaI 7 +#define M_FCSREnaI (0x1 << S_FCSREnaI) + +#define S_FCSRFlg 2 /* Exception flags (R/W) */ +#define M_FCSRFlg (0x1f << S_FCSRFlg) +#define S_FCSRFlgV 6 +#define M_FCSRFlgV (0x1 << S_FCSRFlgV) +#define S_FCSRFlgZ 5 +#define M_FCSRFlgZ (0x1 << S_FCSRFlgZ) +#define S_FCSRFlgO 4 +#define M_FCSRFlgO (0x1 << S_FCSRFlgO) +#define S_FCSRFlgU 3 +#define M_FCSRFlgU (0x1 << S_FCSRFlgU) +#define S_FCSRFlgI 2 +#define M_FCSRFlgI (0x1 << S_FCSRFlgI) + +#define S_FCSRRM 0 /* Rounding mode (R/W) */ +#define M_FCSRRM (0x3 << S_FCSRRM) + +#define M_FCSR0Fields 0x001c0000 +#define M_FCSRRFields 0x00000000 + +/* + * Values in the rounding mode field (of both FCSR and FCCR) + */ +#define K_FCSRRM_RN 0 +#define K_FCSRRM_RZ 1 +#define K_FCSRRM_RP 2 +#define K_FCSRRM_RM 3 + + +/* ********************************************************************* */ +/* Interface function definition */ + + +/* ********************************************************************* */ + +#endif /* __ARCHDEFS_H__ */ diff --git a/sdk-modifications/include/bit_ops.h b/sdk-modifications/include/bit_ops.h new file mode 100644 index 0000000..f823db7 --- /dev/null +++ b/sdk-modifications/include/bit_ops.h @@ -0,0 +1,58 @@ +/* + bit_ops.h + Functions for dealing with conversion of data between types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _BIT_OPS_H +#define _BIT_OPS_H + +/*----------------------------------------------------------------- +Functions to deal with little endian values stored in u8 arrays +-----------------------------------------------------------------*/ +static inline u16 u8array_to_u16 (const u8* item, int offset) { + return ( item[offset] | (item[offset + 1] << 8)); +} + +static inline u32 u8array_to_u32 (const u8* item, int offset) { + return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); +} + +static inline void u16_to_u8array (u8* item, int offset, u16 value) { + item[offset] = (u8)value; + item[offset + 1] = (u8)(value >> 8); +} + +static inline void u32_to_u8array (u8* item, int offset, u32 value) { + item[offset] = (u8)value; + item[offset + 1] = (u8)(value >> 8); + item[offset + 2] = (u8)(value >> 16); + item[offset + 3] = (u8)(value >> 24); +} + +#endif // _BIT_OPS_H diff --git a/sdk-modifications/include/console.h b/sdk-modifications/include/console.h new file mode 100644 index 0000000..f6d74a4 --- /dev/null +++ b/sdk-modifications/include/console.h @@ -0,0 +1,9 @@ +#ifndef __CONSOLE_H__ +#define __CONSOLE_H__ +#include "ds2io.h" + +extern int ConsoleInit(unsigned short front_color, unsigned short background_color, enum SCREEN_ID screen, unsigned int buf_size); + +extern int cprintf(const char *format, ...); + +#endif //__CONSOLE_H__ diff --git a/sdk-modifications/include/directory.h b/sdk-modifications/include/directory.h new file mode 100644 index 0000000..00046a9 --- /dev/null +++ b/sdk-modifications/include/directory.h @@ -0,0 +1,172 @@ +/* + directory.h + Reading, writing and manipulation of the directory structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _DIRECTORY_H +#define _DIRECTORY_H + +#include + +#include "fs_common.h" +#include "partition.h" + +#define DIR_ENTRY_DATA_SIZE 0x20 +#define MAX_FILENAME_LENGTH 256 +#define MAX_ALIAS_LENGTH 13 +#define LFN_ENTRY_LENGTH 13 +#define FAT16_ROOT_DIR_CLUSTER 0 + +#define DIR_SEPARATOR '/' + +// File attributes +#define ATTRIB_ARCH 0x20 // Archive +#define ATTRIB_DIR 0x10 // Directory +#define ATTRIB_LFN 0x0F // Long file name +#define ATTRIB_VOL 0x08 // Volume +#define ATTRIB_SYS 0x04 // System +#define ATTRIB_HID 0x02 // Hidden +#define ATTRIB_RO 0x01 // Read only + +typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE; + +typedef struct { + u32 cluster; + u32 sector; + s32 offset; +} DIR_ENTRY_POSITION; + +typedef struct { + u8 entryData[DIR_ENTRY_DATA_SIZE]; + DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry + char d_name[MAX_FILENAME_LENGTH + MAX_FILENAME_LENGTH*2]; //Store name string using UTF8 coding + //u16 unicodeFilename[MAX_FILENAME_LENGTH]; +} DIR_ENTRY; + +// Directory entry offsets +enum DIR_ENTRY_offset { + DIR_ENTRY_name = 0x00, + DIR_ENTRY_extension = 0x08, + DIR_ENTRY_attributes = 0x0B, + DIR_ENTRY_reserved = 0x0C, + DIR_ENTRY_cTime_ms = 0x0D, + DIR_ENTRY_cTime = 0x0E, + DIR_ENTRY_cDate = 0x10, + DIR_ENTRY_aDate = 0x12, + DIR_ENTRY_clusterHigh = 0x14, + DIR_ENTRY_mTime = 0x16, + DIR_ENTRY_mDate = 0x18, + DIR_ENTRY_cluster = 0x1A, + DIR_ENTRY_fileSize = 0x1C +}; + +/* +Returns true if the file specified by entry is a directory +*/ +static inline bool _FAT_directory_isDirectory (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) != 0); +} + +static inline bool _FAT_directory_isWritable (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO) == 0); +} + +static inline bool _FAT_directory_isDot (DIR_ENTRY* entry) { + return ((entry->d_name[0] == '.') && ((entry->d_name[1] == '\0') || + ((entry->d_name[1] == '.') && entry->d_name[2] == '\0'))); +} + +/* +Reads the first directory entry from the directory starting at dirCluster +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); + +/* +Reads the next directory entry after the one already pointed to by entry +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Gets the directory entry corrsponding to the supplied path +entry will be destroyed even if no directory entry is found +pathEnd specifies the end of the path string, for cutting strings short if needed + specify NULL to use the full length of path + pathEnd is only a suggestion, and the path string will be searched up until the next PATH_SEPARATOR + after pathEND. +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd); + +/* +Changes the current directory to the one specified by path +Returns true on success, false on failure +*/ +bool _FAT_directory_chdir (PARTITION* partition, const char* path); + +/* +Removes the directory entry specified by entry +Assumes that entry is valid +Returns true on success, false on failure +*/ +bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Add a directory entry to the directory specified by dirCluster +The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are +updated with the new directory entry position and alias. +Returns true on success, false on failure +*/ +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); + +/* +Get the start cluster of a file from it's entry data +*/ +u32 _FAT_directory_entryGetCluster (const u8* entryData); + +/* +Fill in the file name and entry data of DIR_ENTRY* entry. +Assumes that the entry's dataStart and dataEnd are correct +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry); + +/* +Fill in a stat struct based on a file entry +*/ +void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st); + +#endif // _DIRECTORY_H diff --git a/sdk-modifications/include/dma.h b/sdk-modifications/include/dma.h new file mode 100644 index 0000000..f6ff230 --- /dev/null +++ b/sdk-modifications/include/dma.h @@ -0,0 +1,46 @@ +#ifndef __DMA_H__ +#define __DMA_H__ + +//register a DMA transfer request +//ch: channel id request, there are 6 channles, +//irq_handler: the DMA interruption handle +//arg: argument to the handle +//mode: DMA mode, such as port width, address increased/fixed, and so on +//type: DMA request type +extern int dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg, + unsigned int mode, unsigned int type); + +//start DMA transfer, must request a DMA first +//ch: channel id +//srcAddr: DMA source address +//dstAddr: DMA destination address +//count: DMA transfer count, the total bytes due the mode in dma_request +extern void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr, + unsigned int count); + +//Stop DMA transfer +extern void dma_stop(int ch); + +//Wait DMA transfer over +extern int dma_wait_finish(int ch); + + +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bytes. + * size is in bytes and must be a multiple of 32. + * Both src and dest must be aligned to 32 bytes. + * Returns 0 on failure, non-zero on success. + */ +extern int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size); +// Blocks of 16 bytes, aligned to 16 bytes +extern int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size); +// Blocks of 4 bytes, aligned to 4 bytes +extern int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size); +// Blocks of 2 bytes, aligned to 2 bytes +extern int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size); +extern int dma_isBusy(int ch); +extern int dma_isFree(int ch); +extern int dma_getFree(void); + +#endif //__DMA_H__ + diff --git a/sdk-modifications/include/ds2_cpu.h b/sdk-modifications/include/ds2_cpu.h new file mode 100644 index 0000000..d4b7144 --- /dev/null +++ b/sdk-modifications/include/ds2_cpu.h @@ -0,0 +1,57 @@ +#ifndef __DS2_CPU_H__ +#define __DS2_CPU_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//exception handle + + +//cache operationr +//invalidate instruction cache +extern void __icache_invalidate_all(void); + +//invalidate data cache +extern void __dcache_invalidate_all(void); + +//data cache writeback +extern void __dcache_writeback_all(void); + +//data cache writeback and invalidate +extern void _dcache_wback_inv(unsigned long addr, unsigned long size); + + +//interruption operation +//clear CPU's interrupt state and enable global interrupt +extern void sti(void); + +//disable global interrupt +extern void cli(void); + +//disable global interrupt and store the global interrupt state +//return: interrupt state +extern unsigned int spin_lock_irqsave(void); + +//restore global interrupt state +extern void spin_unlock_irqrestore(unsigned int val); + + +//CPU frequence +//There are 14 levels, 0 to 13, 13 level have the highest clock frequence +extern int ds2_setCPUclocklevel(unsigned int num); + +//print colock frequence CPU +extern void printf_clock(void); + +//delay n us +extern void udelay(unsigned int usec); + +//delay n ms +extern void mdelay(unsigned int msec); + +#ifdef __cplusplus +} +#endif + +#endif //__DS2_CPU_H__ diff --git a/sdk-modifications/include/ds2_cpuclock.h b/sdk-modifications/include/ds2_cpuclock.h new file mode 100644 index 0000000..058ba99 --- /dev/null +++ b/sdk-modifications/include/ds2_cpuclock.h @@ -0,0 +1,22 @@ +#ifndef _DS2_CPUCLOCK_H__ +#define _DS2_CPUCLOCK_H__ + + +#define CPU_MAX_LEVEL_EX 18 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int ds2_getCPUClock(void); +extern int ds2_setCPULevel(unsigned int level); +extern void ds2_udelay(unsigned int usec); +extern void ds2_mdelay(unsigned int msec); + +//#define ds2_setCPUclocklevel ds2_setCPULevel + +#ifdef __cplusplus +} +#endif + +#endif //__DS2_CPUCLOCK_H__ diff --git a/sdk-modifications/include/ds2_dma.h b/sdk-modifications/include/ds2_dma.h new file mode 100644 index 0000000..c7cd267 --- /dev/null +++ b/sdk-modifications/include/ds2_dma.h @@ -0,0 +1,124 @@ +#ifndef _DS2_DMA_H__ +#define _DS2_DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define MAX_DMA_NUM 6 /* max 6 channels */ + + +// DMA request source register +#define DMAC_DRSR_RS_BIT 0 +#define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) + + +// DMA channel command register +#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ +#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ + +#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ +#define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) +#define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) +#define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) + +#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ +#define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) +#define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) + +#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ +#define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) + +#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ + + +//detect if channel has completed job +#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ +#define DMAC_BASE 0xB3020000 +#define REG32(addr) *((volatile u32 *)(addr)) +#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ +#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) + +#define ds2_DMA_isBusy(n) \ + !( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) + + +/* +Copy modes + +*/ + +#define DMA_MODE32BYTE DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM + +#define DMA_MODE16BYTE DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM + +#define DMA_MODE32BIT DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_32BIT + +#define DMA_MODE16BIT DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BIT + +#define DMA_MODE8BIT DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_8 | \ + DMAC_DCMD_DS_8BIT | DMAC_DCMD_TM + +#define DMA_MODECOPY DMAC_DCMD_SAI + + + +extern int _dmaCopy(int ch, void *dest, void *src, unsigned int size, unsigned int flags); + +//copy from 32 bit source to 32 bit dest +//data must be 32 byte aligned +#define ds2_DMAcopy_32Byte(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE32BYTE) + +//copy from 16 bit source to 16 bit dest +//data must be 16 byte aligned +#define ds2_DMAcopy_16Byte(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE16BYTE); + +//copy from 32 bit source to 32 bit dest +//data must be 32 bit aligned +#define ds2_DMAcopy_32Bit(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE32BIT); + +//copy from 16 bit source to 16 bit dest +//data must be 16 bit aligned +#define ds2_DMAcopy_16Bit(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE16BIT) + +//copy from 8 bit source to 8 bit dest +//data must be 8 bit aligned +#define ds2_DMAcopy_8Bit(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE8BIT) + + + +//Stop DMA transfer +extern void dma_stop(int ch); + +#define ds2_DMA_stop(ch)\ + dma_stop(ch) + +//Wait DMA transfer over +extern int dma_wait_finish(int ch); + +#define ds2_DMA_wait(ch)\ + dma_wait_finish(ch) + + + +#ifdef __cplusplus +} +#endif + +#endif //__DMA_H__ + diff --git a/sdk-modifications/include/ds2_excpt.h b/sdk-modifications/include/ds2_excpt.h new file mode 100644 index 0000000..08fe77e --- /dev/null +++ b/sdk-modifications/include/ds2_excpt.h @@ -0,0 +1,55 @@ +#ifndef __DS2_EXCPT_H__ +#define __DS2_EXCPT_H__ + +#include +extern unsigned int Process_RA; +extern unsigned int Process_SP; + +#define SAVE_PROCESS_REGISTER() \ + do{ unsigned int sr ; \ + sr = read_c0_status(); \ + write_c0_status((sr&(~1))); \ + __asm__ __volatile__( \ + "sw $31,0x00(%0)\n\t" \ + "sw $29,0x00(%1)\n\t" \ + : \ + : "r" (&Process_RA),"r" (&Process_SP)); \ + write_c0_status(sr); \ + }while(0) + +#define RESTORE_PROCESS_REGISTER() \ + __asm__ __volatile__( \ + "lw $31,0x00(%0)\n\t" \ + "lw $29,0x00(%1)\n\t" \ + : \ + : "r" (&Process_RA),"r" (&Process_SP)) + +inline static void excpt_exit(x) \ +{ + unsigned int sr; + sr = read_c0_status(); + write_c0_status(sr & (~1)); + __asm__ __volatile__("lw $2,0x00(%0)\n\t" :: "r" (&x)); + RESTORE_PROCESS_REGISTER(); + write_c0_status(sr); + __asm__ __volatile__( + "jr $31\n\t" + "nop\n\t" + ); +} + +typedef void (*PFun_Exception_Handler)(unsigned int); + +//Setup handle to process the exception +//except_index: exception number +//except_handle: handle to process the exception +//arg: argument to the handle +extern int Setup_except_handle(unsigned int except_index, PFun_Exception_Handler except_handle, unsigned int arg); + +//Add a write watched exception, if the CPU write the addr, a exception will +// generated, the watch exception's number is 23 +//addr: address to be watched +extern void add_watch_point(unsigned int addr); + +#endif //__DS2_EXCPT_H__ + diff --git a/sdk-modifications/include/ds2_fcntl.h b/sdk-modifications/include/ds2_fcntl.h new file mode 100644 index 0000000..2c69221 --- /dev/null +++ b/sdk-modifications/include/ds2_fcntl.h @@ -0,0 +1,51 @@ +#ifndef __libc_fcntl_h__ +#define __libc_fcntl_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define O_RDONLY (1 << 0) +#define O_WRONLY (2 << 0) +#define O_RDWR (3 << 0) +#define O_APPEND (1 << 2) +#define O_CREAT (1 << 3) +#define O_DSYNC (1 << 4) +#define O_EXCL (1 << 5) +#define O_NOCTTY (1 << 6) +#define O_NONBLOCK (1 << 7) +#define O_RSYNC (1 << 8) +#define O_SYNC (1 << 9) +#define O_TRUNC (1 << 10) +#define O_CREATE O_CREAT + +#define O_ACCMODE 0x3 + +#define F_CLOEXEC (1 << 11) + +#define F_DUPFD 1 +#define F_GETFD 2 +#define F_SETFD 3 +#define F_GETFL 4 +#define F_SETFL 5 +#define F_GETLK 6 +#define F_SETLK 7 +#define F_SETLKW 8 +#define F_GETOWN 9 +#define F_SETOWN 10 +#define _F_LAST F_SETOWN + +#define _F_FILE_DESC (F_CLOEXEC) +#define _O_FILE_CREATE (O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC) +#define _O_FILE_STATUS (O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC) +#define _O_UNSUPPORTED (0) + +extern int open(const char* path, int oflag, ...); +extern int fcntl(int fildes, int cmd, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk-modifications/include/ds2_malloc.h b/sdk-modifications/include/ds2_malloc.h new file mode 100644 index 0000000..5f158f7 --- /dev/null +++ b/sdk-modifications/include/ds2_malloc.h @@ -0,0 +1,32 @@ +#ifndef __DS2_MALLOC_H__ +#define __DS2_MALLOC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void heapInit(unsigned int start, unsigned int end); + +extern void* Drv_alloc(unsigned int nbytes); +extern void Drv_deAlloc(void* address); +extern void* Drv_realloc(void* address, unsigned int nbytes); +extern void* Drv_calloc(unsigned int nmem, unsigned int size); + +#ifdef __cplusplus +} +#endif + +#define malloc Drv_alloc +#define calloc Drv_calloc +#define realloc Drv_realloc +#define free Drv_deAlloc + +#ifdef __cplusplus +#include +inline void* operator new ( size_t s ) { return malloc( s ); } +inline void* operator new[] ( size_t s ) { return malloc( s ); } +inline void operator delete ( void* p ) { free( p ); } +inline void operator delete[] ( void* p ) { free( p ); } +#endif + +#endif //__DS2_MALLOC_H__ diff --git a/sdk-modifications/include/ds2_mmc_api.h b/sdk-modifications/include/ds2_mmc_api.h new file mode 100644 index 0000000..28e75ef --- /dev/null +++ b/sdk-modifications/include/ds2_mmc_api.h @@ -0,0 +1,56 @@ +#ifndef __MMC_API_H__ +#define __MMC_API_H__ + +/* Error codes */ +enum mmc_result_t { + MMC_NO_RESPONSE = -1, + MMC_NO_ERROR = 0, + MMC_ERROR_OUT_OF_RANGE, + MMC_ERROR_ADDRESS, + MMC_ERROR_BLOCK_LEN, + MMC_ERROR_ERASE_SEQ, + MMC_ERROR_ERASE_PARAM, + MMC_ERROR_WP_VIOLATION, + MMC_ERROR_CARD_IS_LOCKED, + MMC_ERROR_LOCK_UNLOCK_FAILED, + MMC_ERROR_COM_CRC, + MMC_ERROR_ILLEGAL_COMMAND, + MMC_ERROR_CARD_ECC_FAILED, + MMC_ERROR_CC, + MMC_ERROR_GENERAL, + MMC_ERROR_UNDERRUN, + MMC_ERROR_OVERRUN, + MMC_ERROR_CID_CSD_OVERWRITE, + MMC_ERROR_STATE_MISMATCH, + MMC_ERROR_HEADER_MISMATCH, + MMC_ERROR_TIMEOUT, + MMC_ERROR_CRC, + MMC_ERROR_DRIVER_FAILURE, +}; + + +/* Get card's sectors*/ + +extern unsigned int MMC_GetSize(void); + + +/* initialize MMC/SD card */ +extern int MMC_Initialize(void); + +/* read a single block from MMC/SD card */ +extern int MMC_ReadBlock(unsigned int blockaddr, unsigned char *recbuf); + +/* read multi blocks from MMC/SD card */ +extern int MMC_ReadMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); + +/* write a block to MMC/SD card */ +extern int MMC_WriteBlock(unsigned int blockaddr, unsigned char *recbuf); + +/* write multi blocks to MMC/SD card */ +extern int MMC_WriteMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); + +/* detect MMC/SD card */ +extern int MMC_DetectStatus(void); + +#endif /* __MMC_API_H__ */ + diff --git a/sdk-modifications/include/ds2_timer.h b/sdk-modifications/include/ds2_timer.h new file mode 100644 index 0000000..3e5c3bc --- /dev/null +++ b/sdk-modifications/include/ds2_timer.h @@ -0,0 +1,50 @@ +#ifndef __DS2_TIMER_H__ +#define __DS2_TIMER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +* Function: register a timer interruptting periodly +* channel: timer id, from 0 to 1 +* period: interrupt period, unit is us, period < 2.5s +* handle: interrupt handle, if handle = NULL, the timer will not generate interrupt +* arg: argument to the interrupt handle +*/ +extern int initTimer(unsigned int channel, unsigned int period, void (*handle)(unsigned int), int arg); + +/* +* Function: set the timer run +*/ +extern void runTimer(unsigned int channel); + +/* +* Function: stop timer +*/ +extern void stopTimer(unsigned int channel); + +/* +* Function: reset timer +*/ +extern void resetTimer(unsigned int channel); + +/* +* Function: read value of timer +*/ +extern unsigned int readTimer(unsigned int channel); + + +#define SYSTIME_UNIT 42667 +/* +* Function: get the elapsed time since DS2 started +* it's uint is 42.667us, it will overflow after 50.9 horus since DS2 started +*/ +extern unsigned int getSysTime(void); + +#ifdef __cplusplus +} +#endif + +#endif //__DS2_TIMER_H__ + diff --git a/sdk-modifications/include/ds2_types.h b/sdk-modifications/include/ds2_types.h new file mode 100644 index 0000000..3ec59bf --- /dev/null +++ b/sdk-modifications/include/ds2_types.h @@ -0,0 +1,45 @@ +#ifndef __DS2_TYPES_H__ +#define __DS2_TYPES_H__ + +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef s8 +#define s8 char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef s16 +#define s16 short +#endif + +#ifndef u32 +#define u32 unsigned int +#endif + +#ifndef s32 +#define s32 int +#endif + +#ifndef u64 +#define u64 unsigned long long +#endif + +#ifndef s64 +#define s64 long long +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#endif //__DS2_TYPES_H__ diff --git a/sdk-modifications/include/ds2io.h b/sdk-modifications/include/ds2io.h new file mode 100644 index 0000000..1d3be5b --- /dev/null +++ b/sdk-modifications/include/ds2io.h @@ -0,0 +1,285 @@ +#ifndef __DS2IO_H__ +#define __DS2IO_H__ + +#ifndef BIT +#define BIT(a) (1< +#include "partition.h" +#include "directory.h" +#include "file_allocation_table.h" +//#include "unicode/unicode.h" +#include "fatdir_ex.h" +#include "fatfile_ex.h" + +//typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM} PARTITION_INTERFACE; + +struct IO_INTERFACE_STRUCT ; + +/* +Initialise any inserted block-devices. +Add the fat device driver to the devoptab, making it available for standard file functions. +cacheSize: The number of pages to allocate for each inserted block-device +setAsDefaultDevice: if true, make this the default device driver for file operations +*/ +bool fatInit (u32 cacheSize, bool setAsDefaultDevice); + +/* +Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. +*/ +bool fatInitDefault (void); + +/* +Special initialize for RPG card +*/ +bool fatInitRPG (void); + +/* +Mount the device specified by partitionNumber +PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice +PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +*/ +bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize); + +/* +Mount a partition on a custom device +*/ +bool fatMountCustomInterface (struct IO_INTERFACE_STRUCT* device, u32 cacheSize); + +/* +Unmount the partition specified by partitionNumber +If there are open files, it will fail +*/ +bool fatUnmount (PARTITION_INTERFACE partitionNumber); + + +/* +Forcibly unmount the partition specified by partitionNumber +Any open files on the partition will become invalid +The cache will be invalidated, and any unflushed writes will be lost +*/ +bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber); + +/* +Set the default device for access by fat: and fat0: +PD_DEFAULT is unallowed. +Doesn't do anything useful on GBA, since there is only one device +*/ +bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber); + +#ifdef __cplusplus +} +#endif + +#endif // _LIBFAT_H diff --git a/sdk-modifications/include/fatdir.h b/sdk-modifications/include/fatdir.h new file mode 100644 index 0000000..529e401 --- /dev/null +++ b/sdk-modifications/include/fatdir.h @@ -0,0 +1,81 @@ +/* + fatdir.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-08-13 - Chishm + * Moved all externally visible directory related functions to fatdir + * Added _FAT_mkdir_r + + 2006-08-14 - Chishm + * Added directory iterator functions + + 2007-01-10 - Chishm + * Updated directory iterator functions for DevkitPro r20 +*/ + + +#ifndef _FATDIR_H +#define _FATDIR_H + +//#include +#include +//#include +#include "fs_common.h" +#include "directory.h" + +typedef struct { + PARTITION* partition; + DIR_ENTRY currentEntry; + u32 startCluster; + u32 posEntry; + bool inUse; + bool validEntry; +} DIR_STATE_STRUCT; + +extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); + +extern int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); + +extern int _FAT_unlink_r (struct _reent *r, const char *name); + +extern int _FAT_chdir_r (struct _reent *r, const char *name); + +extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); + +extern int _FAT_mkdir_r (struct _reent *r, const char *path, int mode); + +/* +Directory iterator functions +*/ +extern DIR_STATE_STRUCT* _FAT_diropen_r(struct _reent *r, DIR_STATE_STRUCT *dirState, const char *path); +extern int _FAT_dirreset_r (struct _reent *r, DIR_STATE_STRUCT *dirState); +extern int _FAT_dirnext_r (struct _reent *r, DIR_STATE_STRUCT *dirState, struct stat *filestat); +extern int _FAT_dirclose_r (struct _reent *r, DIR_STATE_STRUCT *dirState); + + +#endif // _FATDIR_H diff --git a/sdk-modifications/include/fatdir_ex.h b/sdk-modifications/include/fatdir_ex.h new file mode 100644 index 0000000..fbac46f --- /dev/null +++ b/sdk-modifications/include/fatdir_ex.h @@ -0,0 +1,18 @@ +#ifndef _FATDIR_EX_H_ +#define _FATDIR_EX_H_ + +#include "fatdir.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int dirnextl (DIR_ITER *dirState, char *filename, char *longFilename, struct stat *filestat); +int renamex( const char *oldName, const char *newName ); + +#ifdef __cplusplus +} +#endif + + +#endif//_FATDIR_EX_H_ diff --git a/sdk-modifications/include/fatfile.h b/sdk-modifications/include/fatfile.h new file mode 100644 index 0000000..4869562 --- /dev/null +++ b/sdk-modifications/include/fatfile.h @@ -0,0 +1,89 @@ +/* + fatfile.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-07-17 - Chishm + * Made all path inputs const char* + * Added _FAT_rename_r + + 2006-07-24 - Chishm + * Removed padding workaround from FILE_STRUCT + + 2006-08-13 - Chishm + * Moved all externally visible directory related functions to fatdir +*/ + + +#ifndef _FATFILE_H +#define _FATFILE_H + +//#include +#include + +#include "fs_common.h" +#include "partition.h" +#include "directory.h" + +typedef struct { + u32 cluster; + u32 sector; + s32 byte; +} FILE_POSITION; + +typedef struct { + int fd; + u32 filesize; + u32 startCluster; + u32 currentPosition; + FILE_POSITION rwPosition; + FILE_POSITION appendPosition; + bool read; + bool write; + bool append; + bool inUse; + PARTITION* partition; + DIR_ENTRY_POSITION dirEntryStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + DIR_ENTRY_POSITION dirEntryEnd; // Always points to the file's alias entry +} FILE_STRUCT; + +extern int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags); + +extern int _FAT_close_r (struct _reent *r, int fd); + +extern int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len); + +extern int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len); + +extern int _FAT_seek_r (struct _reent *r, int fd,int pos, int dir); + +extern int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st); + +#endif // _FATFILE_H diff --git a/sdk-modifications/include/fatfile_ex.h b/sdk-modifications/include/fatfile_ex.h new file mode 100644 index 0000000..c434b63 --- /dev/null +++ b/sdk-modifications/include/fatfile_ex.h @@ -0,0 +1,19 @@ +#ifndef _FATFILE_EX_H_ +#define _FATFILE_EX_H_ + +#include +#include "fatfile.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int freadex( void * buffer, int _size, int _n, FILE * f ); +int fwritex( const void * buffer, int _size, int _n, FILE * f ); + +#ifdef __cplusplus +} +#endif + + +#endif//_FATFILE_EX_H_ diff --git a/sdk-modifications/include/file_allocation_table.h b/sdk-modifications/include/file_allocation_table.h new file mode 100644 index 0000000..4fb4149 --- /dev/null +++ b/sdk-modifications/include/file_allocation_table.h @@ -0,0 +1,64 @@ +/* + file_allocation_table.h + Reading, writing and manipulation of the FAT structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-10-01 - Chishm + * Added _FAT_fat_linkFreeClusterCleared to clear a cluster when it is allocated +*/ + +#ifndef _FAT_H +#define _FAT_H + +#include "fs_common.h" +#include "partition.h" + +#define CLUSTER_EOF_16 0xFFFF +#define CLUSTER_EOF 0x0FFFFFFF +#define CLUSTER_FREE 0x0000 +#define CLUSTER_FIRST 0x0002 + +#define CLUSTERS_PER_FAT12 4085 +#define CLUSTERS_PER_FAT16 65525 + + +u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster); + +u32 _FAT_fat_linkFreeCluster(PARTITION* partition, u32 cluster); +u32 _FAT_fat_linkFreeClusterCleared (PARTITION* partition, u32 cluster); + +bool _FAT_fat_clearLinks (PARTITION* partition, u32 cluster); + +u32 _FAT_fat_lastCluster (PARTITION* partition, u32 cluster); + +static inline u32 _FAT_fat_clusterToSector (PARTITION* partition, u32 cluster) { + return (cluster >= 2) ? ((cluster - 2) * partition->sectorsPerCluster) + partition->dataStart : partition->rootDirStart; +} + +#endif // _FAT_H diff --git a/sdk-modifications/include/filetime.h b/sdk-modifications/include/filetime.h new file mode 100644 index 0000000..fa651a7 --- /dev/null +++ b/sdk-modifications/include/filetime.h @@ -0,0 +1,44 @@ +/* + filetime.h + Conversion of file time and date values to various other types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _FILETIME_H +#define _FILETIME_H + +#include "fs_common.h" +#include + +u16 _FAT_filetime_getTimeFromRTC (void); +u16 _FAT_filetime_getDateFromRTC (void); + +time_t _FAT_filetime_to_time_t (u16 time, u16 date); + + +#endif // _FILETIME_H diff --git a/sdk-modifications/include/fs_api.h b/sdk-modifications/include/fs_api.h new file mode 100644 index 0000000..b3431b6 --- /dev/null +++ b/sdk-modifications/include/fs_api.h @@ -0,0 +1,151 @@ +#ifndef __FS_API_H__ +#define __FS_API_H__ +//v1.0 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/stat.h" +#include "fatfile.h" +#include "fatdir.h" + + +#define mode_t unsigned int +#define size_t unsigned int + +extern int fat_init(void); + +extern FILE_STRUCT* fat_fopen(const char *file, const char *mode); + +extern size_t fat_fread(void *buf, size_t size, size_t count, FILE_STRUCT *fp); + +extern size_t fat_fwrite(const void *buf, size_t size, size_t count, FILE_STRUCT *fp); + +extern int fat_fclose(FILE_STRUCT *fp); + +extern int fat_fseek(FILE_STRUCT *fp, long offset, int whence); + +extern long fat_ftell(FILE_STRUCT *fp); + +extern int fat_feof(FILE_STRUCT *fp); + +extern int fat_ferror(FILE_STRUCT *fp); + +extern void fat_clearerr(FILE_STRUCT *fp); + +extern int fat_fflush(FILE_STRUCT *fp); + +extern int fat_fgetc(FILE_STRUCT *fp); + +extern char* fat_fgets(char *buf, int n, FILE_STRUCT *fp); + +extern int fat_fputc(int ch, FILE_STRUCT *fp); + +extern int fat_fputs(const char *s, FILE_STRUCT *fp); + +extern int fat_remove(const char *filename); + +extern int fat_rename(const char *oldName, const char *newName); + +extern int fat_setHidden(const char *name, unsigned char hide); + +extern int fat_isHidden(struct stat *st); + +extern int fat_getShortName(const char *fullName, char *outName); + +extern void fat_rewind(FILE_STRUCT *fp); + +extern int fat_fstat(int fildes, struct stat *buf); + +extern int fat_fprintf(void* fp, const char *format, ...); + +extern int fat_fscanf(FILE_STRUCT *fp, const char *format, ...); + +extern DIR_STATE_STRUCT* fat_opendir(const char *name); + +extern DIR_ENTRY* fat_readdir(DIR_STATE_STRUCT *dirp); + +extern long fat_telldir(DIR_STATE_STRUCT *dirp); + +extern void fat_seekdir(DIR_STATE_STRUCT *dirp, long int loc); + +extern int fat_closedir(DIR_STATE_STRUCT *dirp); + +extern int fat_chdir(const char *path); + +extern char* fat_getcwd(char *buf, size_t size); + +extern int fat_mkdir(const char *path, mode_t mode); + +extern int fat_rmdir(const char *path); + +extern int fat_lstat(const char *path, struct stat *buf); + +extern DIR_ENTRY* fat_readdir_ex(DIR_STATE_STRUCT *dirp, struct stat *statbuf); + +#ifndef SEEK_SET +#define SEEK_SET 0 /* Seek from beginning of file. */ +#endif + +#ifndef SEEK_CUR +#define SEEK_CUR 1 /* Seek from current position. */ +#endif + +#ifndef SEEK_END +#define SEEK_END 2 /* Seek from end of file. */ +#endif + +//#define S_ISDIR(st) (st.st_mode & S_IFDIR) + +#define FILE FILE_STRUCT +#define fopen fat_fopen +#define fread fat_fread +#define fwrite fat_fwrite +#define fclose fat_fclose +#define fgets fat_fgets +#define fseek fat_fseek +#define ftell fat_ftell +#define feof fat_feof +#define ferror fat_ferror +#define fclearerr fat_clearerr +#define fflush fat_fflush +#define fgetc fat_fgetc +#define fgets fat_fgets +#define fputc fat_fputc +#define fputs fat_fputs +#define fprintf fat_fprintf +#define fscanf fat_fscanf +#define remove fat_remove + +#define DIR DIR_STATE_STRUCT +#define dirent DIR_ENTRY +#define opendir fat_opendir +#define readdir fat_readdir +#define telldir fat_telldir +#define seekdir fat_seekdir +#define closedir fat_closedir +#define chdir fat_chdir +#define getcwd fat_getcwd +#define mkdir fat_mkdir +#define rmdir fat_rmdir + +#define lstat fat_lstat +#define fstat fat_fstat + +#define S_ISHID(st_mode) ((st_mode & S_IHIDDEN) != 0) + +//the extended version of readdir_ex +#define readdir_ex fat_readdir_ex + +#define MAX_PATH 512 +#define MAX_FILE 512 + +//Misc function +extern bool fat_getDiskSpaceInfo( char * diskName, unsigned int *total, unsigned int *used, unsigned int *freeSpace ); + +#ifdef __cplusplus +} +#endif + +#endif //__FS_API_H__ diff --git a/sdk-modifications/include/fs_cache.h b/sdk-modifications/include/fs_cache.h new file mode 100644 index 0000000..b0ab9be --- /dev/null +++ b/sdk-modifications/include/fs_cache.h @@ -0,0 +1,118 @@ +/* + cache.h + The cache is not visible to the user. It should be flushed + when any file is closed or changes are made to the filesystem. + + This cache implements a least-used-page replacement policy. This will + distribute sectors evenly over the pages, so if less than the maximum + pages are used at once, they should all eventually remain in the cache. + This also has the benefit of throwing out old sectors, so as not to keep + too many stale pages around. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _CACHE_H +#define _CACHE_H + +#include "fs_common.h" +#include "disc_io/disc_io.h" + +#define CACHE_PAGE_SIZE BYTES_PER_READ + +typedef struct { + u32 sector; + u32 count; + bool dirty; +} CACHE_ENTRY; + +typedef struct { + const IO_INTERFACE* disc; + u32 numberOfPages; + CACHE_ENTRY* cacheEntries; + u8* pages; +} CACHE; + + +/* +Read data from a sector in the cache +If the sector is not in the cache, it will be swapped in +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, u32 sector, u32 offset, u32 size); + +/* +Write data to a sector in the cache +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); + +/* +Write data to a sector in the cache, zeroing the sector first +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); + +/* +Read a full sector from the cache +*/ +static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, u32 sector) { + return _FAT_cache_readPartialSector (cache, buffer, sector, 0, BYTES_PER_READ); +} + +/* +Write a full sector to the cache +*/ +static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, u32 sector) { + return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ); +} + +/* +Write any dirty sectors back to disc and clear out the contents of the cache +*/ +bool _FAT_cache_flush (CACHE* cache); + +/* +Clear out the contents of the cache without writing any dirty sectors first +*/ +void _FAT_cache_invalidate (CACHE* cache); + +CACHE* _FAT_cache_constructor (u32 numberOfPages, const IO_INTERFACE* discInterface); + +void _FAT_cache_destructor (CACHE* cache); + +#endif // _CACHE_H diff --git a/sdk-modifications/include/fs_common.h b/sdk-modifications/include/fs_common.h new file mode 100644 index 0000000..c482775 --- /dev/null +++ b/sdk-modifications/include/fs_common.h @@ -0,0 +1,129 @@ +/* + common.h + Common definitions and included files for the FATlib + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _COMMON_H +#define _COMMON_H + +// When compiling for NDS, make sure NDS is defined +#ifndef NDS + #if defined ARM9 || defined ARM7 + #define NDS + #endif +#endif + +#if 0 +#ifdef NDS + #include +#else + #include "gba_types.h" +#endif +#endif + +#define BYTES_PER_READ 512 + +#ifndef NULL + #define NULL 0 +#endif + +#ifndef bool +#define bool int +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef u32 +#define u32 unsigned long +#endif + +#ifndef s32 +#define s32 long +#endif + +struct _reent +{ + /* FILE is a big struct and may change over time. To try to achieve binary + compatibility with future versions, put stdin,stdout,stderr here. + These are pointers into member __sf defined below. */ +// __FILE *_stdin, *_stdout, *_stderr; /* XXX */ + + int _errno; /* local copy of errno */ + +// int _inc; /* used by tmpnam */ + +// char *_emergency; + +// int __sdidinit; /* 1 means stdio has been init'd */ + +// int _current_category; /* unused */ +// _CONST char *_current_locale; /* unused */ + +// struct _mprec *_mp; + +// void _EXFNPTR(__cleanup, (struct _reent *)); + +// int _gamma_signgam; + + /* used by some fp conversion routines */ +// int _cvtlen; /* should be size_t */ +// char *_cvtbuf; + +// struct _rand48 *_r48; +// struct __tm *_localtime_buf; +// char *_asctime_buf; + + /* signal info */ +// void (**(_sig_func))(int); + + /* atexit stuff */ +// struct _atexit *_atexit; +// struct _atexit _atexit0; + +// struct _glue __sglue; /* root of glue chain */ +// __FILE *__sf; /* file descriptors */ +// struct _misc_reent *_misc; /* strtok, multibyte states */ +// char *_signal_buf; /* strsignal */ +}; + +#endif // _COMMON_H diff --git a/sdk-modifications/include/fs_unicode.h b/sdk-modifications/include/fs_unicode.h new file mode 100644 index 0000000..45e9d0a --- /dev/null +++ b/sdk-modifications/include/fs_unicode.h @@ -0,0 +1,16 @@ +#ifndef __FS_UNICODE_H__ +#define __FS_UNICODE_H__ + +extern void _FAT_utf8_to_unicode16( const char* src, u16* dest ); + +extern void _FAT_unicode16_to_utf8( const u16* src, char* dest); + +extern u32 _unistrnlen( const u16* unistr, u32 maxlen ); + +extern int _unistrncmp( const u16 * src, const u16 * dest, u32 maxlen ); + +extern const u16 * _unistrchr( const u16 * str, u16 unichar ); + +int _uniisalnum( u8 ch ); + +#endif //__FS_UNICODE_H__ diff --git a/sdk-modifications/include/mem_allocate.h b/sdk-modifications/include/mem_allocate.h new file mode 100644 index 0000000..844f6df --- /dev/null +++ b/sdk-modifications/include/mem_allocate.h @@ -0,0 +1,47 @@ +/* + mem_allocate.h + Memory allocation and destruction calls + Replace these calls with custom allocators if + malloc is unavailable + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _MEM_ALLOCATE_H +#define _MEM_ALLOCATE_H + +#include "ds2_malloc.h" + +static inline void* _FAT_mem_allocate (size_t size) { + return ((void*)malloc (size)); +} + +static inline void _FAT_mem_free (void* mem) { + return (free ((void*)mem)); +} + +#endif // _MEM_ALLOCATE_H diff --git a/sdk-modifications/include/mips.h b/sdk-modifications/include/mips.h new file mode 100644 index 0000000..3792565 --- /dev/null +++ b/sdk-modifications/include/mips.h @@ -0,0 +1,820 @@ +/************************************************************************** +* * +* PROJECT : MIPS port for uC/OS-II * +* * +* MODULE : MIPS.h * +* * +* AUTHOR : Michael Anburaj * +* URL : http://geocities.com/michaelanburaj/ * +* EMAIL: michaelanburaj@hotmail.com * +* * +* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board * +* * +* TOOL-CHAIN : SDE & Cygnus * +* * +* DESCRIPTION : * +* MIPS processor definitions. * +* The basic CPU definitions are found in the file archdefs.h, which * +* is included by mips.h. * +* * +* mips.h implements aliases for some of the definitions in archdefs.h * +* and adds various definitions. * +* * +**************************************************************************/ + + +#ifndef __MIPS_H__ +#define __MIPS_H__ + +#include "archdefs.h" + + +/* ********************************************************************* */ +/* Module configuration */ + + +/* ********************************************************************* */ +/* Interface macro & data definition */ + +#ifndef MSK +#define MSK(n) ((1 << (n)) - 1) +#endif + +/* CPU registers */ +#define SYS_CPUREG_ZERO 0 +#define SYS_CPUREG_AT 1 +#define SYS_CPUREG_V0 2 +#define SYS_CPUREG_V1 3 +#define SYS_CPUREG_A0 4 +#define SYS_CPUREG_A1 5 +#define SYS_CPUREG_A2 6 +#define SYS_CPUREG_A3 7 +#define SYS_CPUREG_T0 8 +#define SYS_CPUREG_T1 9 +#define SYS_CPUREG_T2 10 +#define SYS_CPUREG_T3 11 +#define SYS_CPUREG_T4 12 +#define SYS_CPUREG_T5 13 +#define SYS_CPUREG_T6 14 +#define SYS_CPUREG_T7 15 +#define SYS_CPUREG_S0 16 +#define SYS_CPUREG_S1 17 +#define SYS_CPUREG_S2 18 +#define SYS_CPUREG_S3 19 +#define SYS_CPUREG_S4 20 +#define SYS_CPUREG_S5 21 +#define SYS_CPUREG_S6 22 +#define SYS_CPUREG_S7 23 +#define SYS_CPUREG_T8 24 +#define SYS_CPUREG_T9 25 +#define SYS_CPUREG_K0 26 +#define SYS_CPUREG_K1 27 +#define SYS_CPUREG_GP 28 +#define SYS_CPUREG_SP 29 +#define SYS_CPUREG_S8 30 +#define SYS_CPUREG_FP SYS_CPUREG_S8 +#define SYS_CPUREG_RA 31 + + +/* CPU register fp ($30) has an alias s8 */ +#define s8 fp + + +/* Aliases for System Control Coprocessor (CP0) registers */ +#define C0_INDEX C0_Index +#define C0_RANDOM C0_Random +#define C0_ENTRYLO0 C0_EntryLo0 +#define C0_ENTRYLO1 C0_EntryLo1 +#define C0_CONTEXT C0_Context +#define C0_PAGEMASK C0_PageMask +#define C0_WIRED C0_Wired +#define C0_BADVADDR C0_BadVAddr +#define C0_COUNT C0_Count +#define C0_ENTRYHI C0_EntryHi +#define C0_COMPARE C0_Compare +#define C0_STATUS C0_Status +#define C0_CAUSE C0_Cause + +#ifdef C0_PRID /* ArchDefs has an obsolete def. of C0_PRID */ +#undef C0_PRID +#endif +#define C0_PRID C0_PRId + +#define C0_CONFIG C0_Config +#define C0_CONFIG1 C0_Config1 +#define C0_LLADDR C0_LLAddr +#define C0_WATCHLO C0_WatchLo +#define C0_WATCHHI C0_WatchHi +#define C0_DEBUG C0_Debug +#define C0_PERFCNT C0_PerfCnt +#define C0_ERRCTL C0_ErrCtl +#define C0_CACHEERR C0_CacheErr +#define C0_TAGLO C0_TagLo +#define C0_DATALO C0_DataLo +#define C0_TAGHI C0_TagHi +#define C0_DATAHI C0_DataHi +#define C0_ERROREPC C0_ErrorEPC +#if 0 +#define C0_DESAVE C0_DESAVE +#define C0_EPC C0_EPC +#define C0_DEPC C0_DEPC +#endif + +/* System Control Coprocessor (CP0) registers select fields */ +#define C0_INDEX_SEL 0 /* TLB Index */ +#define C0_RANDOM_SEL 0 /* TLB Random */ +#define C0_TLBLO0_SEL 0 /* TLB EntryLo0 */ +#define C0_TLBLO1_SEL 0 /* TLB EntryLo1 */ +#define C0_CONTEXT_SEL 0 /* Context */ +#define C0_PAGEMASK_SEL 0 /* TLB PageMask */ +#define C0_WIRED_SEL 0 /* TLB Wired */ +#define C0_BADVADDR_SEL 0 /* Bad Virtual Address */ +#define C0_COUNT_SEL 0 /* Count */ +#define C0_ENTRYHI_SEL 0 /* TLB EntryHi */ +#define C0_COMPARE_SEL 0 /* Compare */ +#define C0_STATUS_SEL 0 /* Processor Status */ +#define C0_CAUSE_SEL 0 /* Exception Cause */ +#define C0_EPC_SEL 0 /* Exception PC */ +#define C0_PRID_SEL 0 /* Processor Revision Indentifier */ +#define C0_CONFIG_SEL 0 /* Config */ +#define C0_CONFIG1_SEL 1 /* Config1 */ +#define C0_LLADDR_SEL 0 /* LLAddr */ +#define C0_WATCHLO_SEL 0 /* WatchpointLo */ +#define C0_WATCHHI_SEL 0 /* WatchpointHi */ +#define C0_DEBUG_SEL 0 /* EJTAG Debug Register */ +#define C0_DEPC_SEL 0 /* Program counter at last EJTAG debug exception */ +#define C0_PERFCNT_SEL 0 /* Performance counter interface */ +#define C0_ERRCTL_SEL 0 /* ERRCTL */ +#define C0_CACHEERR_SEL 0 /* CacheErr */ +#define C0_TAGLO_SEL 0 /* TagLo */ +#define C0_DATALO_SEL 1 /* DataLo */ +#define C0_DTAGLO_SEL 2 /* DTagLo */ +#define C0_TAGHI_SEL 0 /* TagHi */ +#define C0_DATAHI_SEL 1 /* DataHi */ +#define C0_DTAGHI_SEL 2 /* DTagHi */ +#define C0_ERROREPC_SEL 0 /* ErrorEPC */ +#define C0_DESAVE_SEL 0 /* EJTAG dbg exc. save register */ + + +/* C0_CONFIG register encoding */ + +#define C0_CONFIG_M_SHF S_ConfigMore +#define C0_CONFIG_M_MSK M_ConfigMore +#define C0_CONFIG_M_BIT C0_CONFIG_M_MSK + +#define C0_CONFIG_BE_SHF S_ConfigBE +#define C0_CONFIG_BE_MSK M_ConfigBE +#define C0_CONFIG_BE_BIT C0_CONFIG_BE_MSK + +#define C0_CONFIG_AT_SHF S_ConfigAT +#define C0_CONFIG_AT_MSK M_ConfigAT +#define C0_CONFIG_AT_MIPS32 K_ConfigAT_MIPS32 +#define C0_CONFIG_AT_MIPS64_32ADDR K_ConfigAT_MIPS64S +#define C0_CONFIG_AT_MIPS64 K_ConfigAT_MIPS64 + +#define C0_CONFIG_AR_SHF S_ConfigAR +#define C0_CONFIG_AR_MSK M_ConfigAR + +#define C0_CONFIG_MT_SHF S_ConfigMT +#define C0_CONFIG_MT_MSK M_ConfigMT +#define C0_CONFIG_MT_NONE K_ConfigMT_NoMMU +#define C0_CONFIG_MT_TLB K_ConfigMT_TLBMMU +#define C0_CONFIG_MT_BAT K_ConfigMT_BATMMU +#define C0_CONFIG_MT_NON_STD K_ConfigMT_FMMMU + +#define C0_CONFIG_K0_SHF S_ConfigK0 +#define C0_CONFIG_K0_MSK M_ConfigK0 +#define C0_CONFIG_K0_WTHRU_NOALLOC K_CacheAttrCWTnWA +#define C0_CONFIG_K0_WTHRU_ALLOC K_CacheAttrCWTWA +#define C0_CONFIG_K0_UNCACHED K_CacheAttrU +#define C0_CONFIG_K0_NONCOHERENT K_CacheAttrCN +#define C0_CONFIG_K0_COHERENTXCL K_CacheAttrCCE +#define C0_CONFIG_K0_COHERENTXCLW K_CacheAttrCCS +#define C0_CONFIG_K0_COHERENTUPD K_CacheAttrCCU +#define C0_CONFIG_K0_UNCACHED_ACCEL K_CacheAttrUA + + +/* WC field. + * + * This feature is present specifically to support configuration + * testing of the core in a lead vehicle, and is not supported + * in any other environment. Attempting to use this feature + * outside of the scope of a lead vehicle is a violation of the + * MIPS Architecture, and may cause unpredictable operation of + * the processor. + */ +#define C0_CONFIG_WC_SHF 19 +#define C0_CONFIG_WC_MSK (MSK(1) << C0_CONFIG_WC_SHF) +#define C0_CONFIG_WC_BIT C0_CONFIG_WC_MSK + + +/* C0_CONFIG1 register encoding */ + +#define C0_CONFIG1_MMUSIZE_SHF S_Config1MMUSize +#define C0_CONFIG1_MMUSIZE_MSK M_Config1MMUSize + +#define C0_CONFIG1_IS_SHF S_Config1IS +#define C0_CONFIG1_IS_MSK M_Config1IS + +#define C0_CONFIG1_IL_SHF S_Config1IL +#define C0_CONFIG1_IL_MSK M_Config1IL + +#define C0_CONFIG1_IA_SHF S_Config1IA +#define C0_CONFIG1_IA_MSK M_Config1IA + +#define C0_CONFIG1_DS_SHF S_Config1DS +#define C0_CONFIG1_DS_MSK M_Config1DS + +#define C0_CONFIG1_DL_SHF S_Config1DL +#define C0_CONFIG1_DL_MSK M_Config1DL + +#define C0_CONFIG1_DA_SHF S_Config1DA +#define C0_CONFIG1_DA_MSK M_Config1DA + +#define C0_CONFIG1_WR_SHF S_Config1WR +#define C0_CONFIG1_WR_MSK M_Config1WR +#define C0_CONFIG1_WR_BIT C0_CONFIG1_WR_MSK + +#define C0_CONFIG1_CA_SHF S_Config1CA +#define C0_CONFIG1_CA_MSK M_Config1CA +#define C0_CONFIG1_CA_BIT C0_CONFIG1_CA_MSK + +#define C0_CONFIG1_EP_SHF S_Config1EP +#define C0_CONFIG1_EP_MSK M_Config1EP +#define C0_CONFIG1_EP_BIT C0_CONFIG1_EP_MSK + +#define C0_CONFIG1_FP_SHF S_Config1FP +#define C0_CONFIG1_FP_MSK M_Config1FP +#define C0_CONFIG1_FP_BIT C0_CONFIG1_FP_MSK + + +/* C0_STATUS register encoding */ + +#define C0_STATUS_CU3_SHF S_StatusCU3 +#define C0_STATUS_CU3_MSK M_StatusCU3 +#define C0_STATUS_CU3_BIT C0_STATUS_CU3_MSK + +#define C0_STATUS_CU2_SHF S_StatusCU2 +#define C0_STATUS_CU2_MSK M_StatusCU2 +#define C0_STATUS_CU2_BIT C0_STATUS_CU2_MSK + +#define C0_STATUS_CU1_SHF S_StatusCU1 +#define C0_STATUS_CU1_MSK M_StatusCU1 +#define C0_STATUS_CU1_BIT C0_STATUS_CU1_MSK + +#define C0_STATUS_CU0_SHF S_StatusCU1 +#define C0_STATUS_CU0_MSK M_StatusCU1 +#define C0_STATUS_CU0_BIT C0_STATUS_CU0_MSK + +#define C0_STATUS_RP_SHF S_StatusRP +#define C0_STATUS_RP_MSK M_StatusRP +#define C0_STATUS_RP_BIT C0_STATUS_RP_MSK + +#define C0_STATUS_FR_SHF S_StatusFR +#define C0_STATUS_FR_MSK M_StatusFR +#define C0_STATUS_FR_BIT C0_STATUS_FR_MSK + +#define C0_STATUS_RE_SHF S_StatusRE +#define C0_STATUS_RE_MSK M_StatusRE +#define C0_STATUS_RE_BIT C0_STATUS_RE_MSK + +#define C0_STATUS_BEV_SHF S_StatusBEV +#define C0_STATUS_BEV_MSK M_StatusBEV +#define C0_STATUS_BEV_BIT C0_STATUS_BEV_MSK + +#define C0_STATUS_TS_SHF S_StatusTS +#define C0_STATUS_TS_MSK M_StatusTS +#define C0_STATUS_TS_BIT C0_STATUS_TS_MSK + +#define C0_STATUS_SR_SHF S_StatusSR +#define C0_STATUS_SR_MSK M_StatusSR +#define C0_STATUS_SR_BIT C0_STATUS_SR_MSK + +#define C0_STATUS_NMI_SHF S_StatusNMI +#define C0_STATUS_NMI_MSK M_StatusNMI +#define C0_STATUS_NMI_BIT C0_STATUS_NMI_MSK + +#define C0_STATUS_IM_SHF S_StatusIM +#define C0_STATUS_IM_MSK M_StatusIM +/* Note that the the definitions below indicate the interrupt number + * rather than the mask. + * (0..1 for SW interrupts and 2...7 for HW interrupts) + */ +#define C0_STATUS_IM_SW0 (S_StatusIM0 - S_StatusIM) +#define C0_STATUS_IM_SW1 (S_StatusIM1 - S_StatusIM) +#define C0_STATUS_IM_HW0 (S_StatusIM2 - S_StatusIM) +#define C0_STATUS_IM_HW1 (S_StatusIM3 - S_StatusIM) +#define C0_STATUS_IM_HW2 (S_StatusIM4 - S_StatusIM) +#define C0_STATUS_IM_HW3 (S_StatusIM5 - S_StatusIM) +#define C0_STATUS_IM_HW4 (S_StatusIM6 - S_StatusIM) +#define C0_STATUS_IM_HW5 (S_StatusIM7 - S_StatusIM) + +/* Max interrupt code */ +#define C0_STATUS_IM_MAX C0_STATUS_IM_HW5 + +#define C0_STATUS_KSU_SHF S_StatusKSU +#define C0_STATUS_KSU_MSK M_StatusKSU + +#define C0_STATUS_UM_SHF S_StatusUM +#define C0_STATUS_UM_MSK M_StatusUM +#define C0_STATUS_UM_BIT C0_STATUS_UM_MSK + +#define C0_STATUS_ERL_SHF S_StatusERL +#define C0_STATUS_ERL_MSK M_StatusERL +#define C0_STATUS_ERL_BIT C0_STATUS_ERL_MSK + +#define C0_STATUS_EXL_SHF S_StatusEXL +#define C0_STATUS_EXL_MSK M_StatusEXL +#define C0_STATUS_EXL_BIT C0_STATUS_EXL_MSK + +#define C0_STATUS_IE_SHF S_StatusIE +#define C0_STATUS_IE_MSK M_StatusIE +#define C0_STATUS_IE_BIT C0_STATUS_IE_MSK + + +/* C0_PRID register encoding */ + +#define C0_PRID_OPT_SHF S_PRIdCoOpt +#define C0_PRID_OPT_MSK M_PRIdCoOpt + +#define C0_PRID_COMP_SHF S_PRIdCoID +#define C0_PRID_COMP_MSK M_PRIdCoID +#define C0_PRID_COMP_MIPS K_PRIdCoID_MIPS +#define C0_PRID_COMP_NOT_MIPS32_64 0 + +#define C0_PRID_PRID_SHF S_PRIdImp +#define C0_PRID_PRID_MSK M_PRIdImp + +/* Jade */ +#define C0_PRID_PRID_4Kc K_PRIdImp_Jade +#define C0_PRID_PRID_4Kmp K_PRIdImp_JadeLite /* 4Km/4Kp */ +/* Emerald */ +#define C0_PRID_PRID_4KEc K_PRIdImp_4KEc +#define C0_PRID_PRID_4KEmp K_PRIdImp_4KEmp +/* Coral */ +#define C0_PRID_PRID_4KSc K_PRIdImp_4KSc +/* Opal */ +#define C0_PRID_PRID_5K K_PRIdImp_Opal +/* Ruby */ +#define C0_PRID_PRID_20Kc K_PRIdImp_Ruby +/* Other CPUs */ +#define C0_PRID_PRID_R4000 K_PRIdImp_R4000 +#define C0_PRID_PRID_RM52XX K_PRIdImp_R5200 +#define C0_PRID_PRID_RM70XX 0x27 + +#define C0_PRID_REV_SHF S_PRIdRev +#define C0_PRID_REV_MSK M_PRIdRev + + +#define MIPS_4Kc ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4Kc << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_4Kmp ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4Kmp << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_4KEc ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4KEc << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_4KEmp ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4KEmp << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_4KSc ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4KSc << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_5K ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_5K << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_20Kc ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_20Kc << \ + C0_PRID_PRID_SHF) \ + ) + +#define QED_RM52XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_RM52XX << \ + C0_PRID_PRID_SHF) \ + ) + +#define QED_RM70XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_RM70XX << \ + C0_PRID_PRID_SHF) \ + ) + +/* C0_ENTRYHI register encoding */ + +#define C0_ENTRYHI_VPN2_SHF S_EntryHiVPN2 +#define C0_ENTRYHI_VPN2_MSK M_EntryHiVPN2 + +#define C0_ENTRYHI_ASID_SHF S_EntryHiASID +#define C0_ENTRYHI_ASID_MSK M_EntryHiASID + + +/* C0_CAUSE register encoding */ + +#define C0_CAUSE_BD_SHF S_CauseBD +#define C0_CAUSE_BD_MSK M_CauseBD +#define C0_CAUSE_BD_BIT C0_CAUSE_BD_MSK + +#define C0_CAUSE_CE_SHF S_CauseCE +#define C0_CAUSE_CE_MSK M_CauseCE + +#define C0_CAUSE_IV_SHF S_CauseIV +#define C0_CAUSE_IV_MSK M_CauseIV +#define C0_CAUSE_IV_BIT C0_CAUSE_IV_MSK + +#define C0_CAUSE_WP_SHF S_CauseWP +#define C0_CAUSE_WP_MSK M_CauseWP +#define C0_CAUSE_WP_BIT C0_CAUSE_WP_MSK + +#define C0_CAUSE_IP_SHF S_CauseIP +#define C0_CAUSE_IP_MSK M_CauseIP + +#define C0_CAUSE_CODE_SHF S_CauseExcCode +#define C0_CAUSE_CODE_MSK M_CauseExcCode + +#define C0_CAUSE_CODE_INT EX_INT +#define C0_CAUSE_CODE_MOD EX_MOD +#define C0_CAUSE_CODE_TLBL EX_TLBL +#define C0_CAUSE_CODE_TLBS EX_TLBS +#define C0_CAUSE_CODE_ADEL EX_ADEL +#define C0_CAUSE_CODE_ADES EX_ADES +#define C0_CAUSE_CODE_IBE EX_IBE +#define C0_CAUSE_CODE_DBE EX_DBE +#define C0_CAUSE_CODE_SYS EX_SYS +#define C0_CAUSE_CODE_BP EX_BP +#define C0_CAUSE_CODE_RI EX_RI +#define C0_CAUSE_CODE_CPU EX_CPU +#define C0_CAUSE_CODE_OV EX_OV +#define C0_CAUSE_CODE_TR EV_TR +#define C0_CAUSE_CODE_FPE EX_FPE +#define C0_CAUSE_CODE_WATCH EX_WATCH +#define C0_CAUSE_CODE_MCHECK EX_MCHECK + +/* Max cause code */ +#define C0_CAUSE_CODE_MAX EX_MCHECK + + +/* C0_PAGEMASK register encoding */ +#define C0_PAGEMASK_MASK_SHF S_PageMaskMask +#define C0_PAGEMASK_MASK_MSK M_PageMaskMask +#define C0_PAGEMASK_MASK_4K K_PageMask4K +#define C0_PAGEMASK_MASK_16K K_PageMask16K +#define C0_PAGEMASK_MASK_64K K_PageMask64K +#define C0_PAGEMASK_MASK_256K K_PageMask256K +#define C0_PAGEMASK_MASK_1M K_PageMask1M +#define C0_PAGEMASK_MASK_4M K_PageMask4M +#define C0_PAGEMASK_MASK_16M K_PageMask16M + + +/* C0_ENTRYLO0 register encoding (equiv. to C0_ENTRYLO1) */ +#define C0_ENTRYLO0_PFN_SHF S_EntryLoPFN +#define C0_ENTRYLO0_PFN_MSK M_EntryLoPFN + +#define C0_ENTRYLO0_C_SHF S_EntryLoC +#define C0_ENTRYLO0_C_MSK M_EntryLoC + +#define C0_ENTRYLO0_D_SHF S_EntryLoD +#define C0_ENTRYLO0_D_MSK M_EntryLoD + +#define C0_ENTRYLO0_V_SHF S_EntryLoV +#define C0_ENTRYLO0_V_MSK M_EntryLoV + +#define C0_ENTRYLO0_G_SHF S_EntryLoG +#define C0_ENTRYLO0_G_MSK M_EntryLoG + + +/* FPU (CP1) FIR register encoding */ +#define C1_FIR_3D_SHF S_FIRConfig3D +#define C1_FIR_3D_MSK M_FIRConfig3D + +#define C1_FIR_PS_SHF S_FIRConfigPS +#define C1_FIR_PS_MSK M_FIRConfigPS + +#define C1_FIR_D_SHF S_FIRConfigD +#define C1_FIR_D_MSK M_FIRConfigD + +#define C1_FIR_S_SHF S_FIRConfigS +#define C1_FIR_S_MSK M_FIRConfigS + +#define C1_FIR_PRID_SHF S_FIRImp +#define C1_FIR_PRID_MSK M_FIRImp + +#define C1_FIR_REV_SHF S_FIRRev +#define C1_FIR_REV_MSK M_FIRRev + + +/* FPU (CP1) FCSR control/status register */ +#define C1_FCSR_FCC_SHF S_FCSRFCC7_1 +#define C1_FCSR_FCC_MSK M_FCSRFCC7_1 + +#define C1_FCSR_FS_SHF S_FCSRFS +#define C1_FCSR_FS_MSK M_FCSRFS +#define C1_FCSR_FS_BIT C1_FCSR_FS_MSK + +#define C1_FCSR_CC_SHF S_FCSRCC +#define C1_FCSR_CC_MSK M_FCSRCC + +#define C1_FCSR_IMPL_SHF S_FCSRImpl +#define C1_FCSR_IMPL_MSK M_FCSRImpl + +#define C1_FCSR_EXC_SHF S_FCSRExc +#define C1_FCSR_EXC_MSK M_FCSRExc + +#define C1_FCSR_ENA_SHF S_FCSREna +#define C1_FCSR_ENA_MSK M_FCSREna + +#define C1_FCSR_FLG_SHF S_FCSRFlg +#define C1_FCSR_FLG_MSK M_FCSRFlg + +#define C1_FCSR_RM_SHF S_FCSRRM +#define C1_FCSR_RM_MSK M_FCSRRM +#define C1_FCSR_RM_RN K_FCSRRM_RN +#define C1_FCSR_RM_RZ K_FCSRRM_RZ +#define C1_FCSR_RM_RP K_FCSRRM_RP +#define C1_FCSR_RM_RM K_FCSRRM_RM + + + +/* cache operations */ + +#define CACHE_OP( code, type ) ( ((code) << 2) | (type) ) + +#define ICACHE_INDEX_INVALIDATE CACHE_OP(0x0, 0) +#define ICACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 0) +#define ICACHE_INDEX_STORE_TAG CACHE_OP(0x2, 0) +#define DCACHE_INDEX_WRITEBACK_INVALIDATE CACHE_OP(0x0, 1) +#define DCACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 1) +#define DCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 1) +#define SCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 3) + +#define ICACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 0) +#define ICACHE_ADDR_FILL CACHE_OP(0x5, 0) +#define ICACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 0) +#define DCACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 1) +#define DCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 1) +#define DCACHE_ADDR_HIT_WRITEBACK CACHE_OP(0x6, 1) +#define DCACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 1) + +#define SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 3) + +/* Workaround for bug in early revisions of MIPS 4K family of + * processors. Only relevant in early engineering samples of test + * chips (RTL revision <= 3.0). + * + * The bug is described in : + * + * MIPS32 4K(tm) Processor Core Family RTL Errata Sheet + * MIPS Document No: MD00003 + * + * The bug is identified as : C16 + */ +#ifndef SET_MIPS0 +#define SET_MIPS0() +#define SET_PUSH() +#define SET_POP() +#endif +#define ICACHE_INVALIDATE_WORKAROUND(reg) \ +SET_PUSH(); \ +SET_MIPS0(); \ + la reg, 999f; \ +SET_POP(); \ + cache ICACHE_ADDR_FILL, 0(reg); \ + sync; \ + nop; nop; nop; nop; \ +999: + +/* EMPTY_PIPELINE is used for the below cache invalidation operations. + * When $I is invalidated, there will still be operations in the + * pipeline. We make sure these are 'nop' operations. + */ +#define EMPTY_PIPELINE nop; nop; nop; nop + +#define ICACHE_INDEX_INVALIDATE_OP(index,scratch) \ + ICACHE_INVALIDATE_WORKAROUND(scratch); \ + cache ICACHE_INDEX_INVALIDATE, 0(index); \ + EMPTY_PIPELINE + +#define ICACHE_ADDR_INVALIDATE_OP(addr,scratch) \ + ICACHE_INVALIDATE_WORKAROUND(scratch); \ + cache ICACHE_ADDR_HIT_INVALIDATE, 0(addr); \ + EMPTY_PIPELINE + +/* The sync used in the below macro is there in case we are installing + * a new instruction (flush $D, sync, invalidate $I sequence). + */ +#define SCACHE_ADDR_HIT_WB_INVALIDATE_OP(reg) \ + cache SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE, 0(reg); \ + sync; \ + EMPTY_PIPELINE + +/* Config1 cache field decoding */ +#define CACHE_CALC_SPW(s) ( 64 << (s) ) +#define CACHE_CALC_LS(l) ( (l) ? 2 << (l) : 0 ) +#define CACHE_CALC_BPW(l,s) ( CACHE_CALC_LS(l) * CACHE_CALC_SPW(s) ) +#define CACHE_CALC_ASSOC(a) ( (a) + 1 ) + + +/**** Move from/to Coprocessor operations ****/ + +/* We use ssnop instead of nop operations in order to handle + * superscalar CPUs. + * The "sll zero,zero,1" notation is compiler backwards compatible. + */ +#define SSNOP sll zero,zero,1 +#define NOPS SSNOP; SSNOP; SSNOP; SSNOP + +#define MFLO(dst) \ + mflo dst;\ + NOPS + +/* Workaround for bug in early revisions of MIPS 4K family of + * processors. + * + * This concerns the nop instruction before mtc0 in the + * MTC0 macro below. + * + * The bug is described in : + * + * MIPS32 4K(tm) Processor Core Family RTL Errata Sheet + * MIPS Document No: MD00003 + * + * The bug is identified as : C27 + */ + +#define MTC0(src, dst) \ + nop; \ + mtc0 src,dst;\ + NOPS + +#define DMTC0(src, dst) \ + nop; \ + dmtc0 src,dst;\ + NOPS + +#define MFC0(dst, src) \ + mfc0 dst,src;\ + NOPS + +#define DMFC0(dst, src) \ + dmfc0 dst,src;\ + NOPS + +#define MFC0_SEL_OPCODE(dst, src, sel)\ + .##word (0x40000000 | ((dst)<<16) | ((src)<<11) | (sel));\ + NOPS + +#define MTC0_SEL_OPCODE(dst, src, sel)\ + .##word (0x40800000 | ((dst)<<16) | ((src)<<11) | (sel));\ + NOPS + +#define LDC1(dst, src, offs)\ + .##word (0xd4000000 | ((src)<<21) | ((dst)<<16) | (offs)) + +#define SDC1(src, dst, offs)\ + .##word (0xf4000000 | ((dst)<<21) | ((src)<<16) | (offs)) + + +/* Instruction opcode fields */ +#define OPC_SPECIAL 0x0 +#define OPC_REGIM 0x1 +#define OPC_J 0x2 +#define OPC_JAL 0x3 +#define OPC_BEQ 0x4 +#define OPC_BNE 0x5 +#define OPC_BLEZ 0x6 +#define OPC_BGTZ 0x7 +#define OPC_COP1 0x11 +#define OPC_JALX 0x1D +#define OPC_BEQL 0x14 +#define OPC_BNEL 0x15 +#define OPC_BLEZL 0x16 +#define OPC_BGTZL 0x17 + +/* Instruction function fields */ +#define FUNC_JR 0x8 +#define FUNC_JALR 0x9 + +/* Instruction rt fields */ +#define RT_BLTZ 0x0 +#define RT_BGEZ 0x1 +#define RT_BLTZL 0x2 +#define RT_BGEZL 0x3 +#define RT_BLTZAL 0x10 +#define RT_BGEZAL 0x11 +#define RT_BLTZALL 0x12 +#define RT_BGEZALL 0x13 + +/* Instruction rs fields */ +#define RS_BC1 0x08 + +/* Access macros for instruction fields */ +#define MIPS_OPCODE( instr) ((instr) >> 26) +#define MIPS_FUNCTION(instr) ((instr) & MSK(6)) +#define MIPS_RT(instr) (((instr) >> 16) & MSK(5)) +#define MIPS_RS(instr) (((instr) >> 21) & MSK(5)) +#define MIPS_OFFSET(instr) ((instr) & 0xFFFF) +#define MIPS_TARGET(instr) ((instr) & MSK(26)) + +/* Instructions */ +#define OPCODE_DERET 0x4200001f +#define OPCODE_BREAK 0x0005000d +#define OPCODE_NOP 0 +#define OPCODE_JUMP(addr) ( (OPC_J << 26) | (((addr) >> 2) & 0x3FFFFFF) ) + +#define DERET .##word OPCODE_DERET + +/* MIPS16e opcodes and instruction field access macros */ + +#define MIPS16E_OPCODE(inst) (((inst) >> 11) & 0x1f) +#define MIPS16E_I8_FUNCTION(inst) (((inst) >> 8) & 0x7) +#define MIPS16E_X(inst) (((inst) >> 26) & 0x1) +#define MIPS16E_RR_FUNCTION(inst) (((inst) >> 0) & 0x1f) +#define MIPS16E_RY(inst) (((inst) >> 5) & 0x3) +#define MIPS16E_OPC_EXTEND 0x1e +#define MIPS16E_OPC_JAL_X 0x03 +#define MIPS16E_OPC_B 0x02 +#define MIPS16E_OPC_BEQZ 0x04 +#define MIPS16E_OPC_BNEZ 0x05 +#define MIPS16E_OPC_I8 0x0c +#define MIPS16E_I8_FUNC_BTEQZ 0x00 +#define MIPS16E_I8_FUNC_BTNEZ 0x01 +#define MIPS16E_X_JALX 0x01 +#define MIPS16E_OPC_RR 0x1d +#define MIPS16E_RR_FUNC_JALRC 0x00 +#define MIPS16E_RR_RY_JRRX 0x00 +#define MIPS16E_RR_RY_JRRA 0x01 +#define MIPS16E_RR_RY_JALR 0x02 +#define MIPS16E_RR_RY_JRCRX 0x04 +#define MIPS16E_RR_RY_JRCRA 0x05 +#define MIPS16E_RR_RY_JALRC 0x06 + +#define MIPS16E_OPCODE_BREAK 0xE805 +#define MIPS16E_OPCODE_NOP 0x6500 + +/* MIPS reset vector */ +#define MIPS_RESET_VECTOR 0x1fc00000 + +/* Clock periods per count register increment */ +#define MIPS4K_COUNT_CLK_PER_CYCLE 2 +#define MIPS5K_COUNT_CLK_PER_CYCLE 2 +#define MIPS20Kc_COUNT_CLK_PER_CYCLE 1 + + +/**** MIPS 4K/5K families specific fields of CONFIG register ****/ + +#define C0_CONFIG_MIPS4K5K_K23_SHF S_ConfigK23 +#define C0_CONFIG_MIPS4K5K_K23_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_K23_SHF) + +#define C0_CONFIG_MIPS4K5K_KU_SHF S_ConfigKU +#define C0_CONFIG_MIPS4K5K_KU_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_KU_SHF) + + +/**** MIPS 20Kc specific fields of CONFIG register ****/ + +#define C0_CONFIG_MIPS20KC_EC_SHF 28 +#define C0_CONFIG_MIPS20KC_EC_MSK (MSK(3) << C0_CONFIG_MIPS20KC_EC_SHF) + +#define C0_CONFIG_MIPS20KC_DD_SHF 27 +#define C0_CONFIG_MIPS20KC_DD_MSK (MSK(1) << C0_CONFIG_MIPS20KC_DD_SHF) +#define C0_CONFIG_MIPS20KC_DD_BIT C0_CONFIG_MIPS20KC_DD_MSK + +#define C0_CONFIG_MIPS20KC_LP_SHF 26 +#define C0_CONFIG_MIPS20KC_LP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_LP_SHF) +#define C0_CONFIG_MIPS20KC_LP_BIT C0_CONFIG_MIPS20KC_LP_MSK + +#define C0_CONFIG_MIPS20KC_SP_SHF 25 +#define C0_CONFIG_MIPS20KC_SP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_SP_SHF) +#define C0_CONFIG_MIPS20KC_SP_BIT C0_CONFIG_MIPS20KC_SP_MSK + +#define C0_CONFIG_MIPS20KC_TI_SHF 24 +#define C0_CONFIG_MIPS20KC_TI_MSK (MSK(1) << C0_CONFIG_MIPS20KC_TI_SHF) +#define C0_CONFIG_MIPS20KC_TI_BIT C0_CONFIG_MIPS20KC_TI_MSK + + +/* ********************************************************************* */ +/* Interface function definition */ + + +/* ********************************************************************* */ + +#endif /* #ifndef __MIPS_H__ */ diff --git a/sdk-modifications/include/mipsregs.h b/sdk-modifications/include/mipsregs.h new file mode 100644 index 0000000..5eaac44 --- /dev/null +++ b/sdk-modifications/include/mipsregs.h @@ -0,0 +1,985 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. + * Modified for further R[236]000 support by Paul M. Antoine, 1996. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2003 Maciej W. Rozycki + */ +#ifndef _ASM_MIPSREGS_H +#define _ASM_MIPSREGS_H + +#include +#include + +/* + * The following macros are especially useful for __asm__ + * inline assembler. + */ +#ifndef __STR +#define __STR(x) #x +#endif +#ifndef STR +#define STR(x) __STR(x) +#endif + +/* + * Configure language + */ +#ifdef __ASSEMBLY__ +#define _ULCAST_ +#else +#define _ULCAST_ (unsigned long) +#endif + +/* + * Coprocessor 0 register names + */ +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONF $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_INFO $7 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_DEBUG $23 +#define CP0_DEPC $24 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 +#define CP0_DESAVE $31 + +/* + * R4640/R4650 cp0 register names. These registers are listed + * here only for completeness; without MMU these CPUs are not useable + * by Linux. A future ELKS port might take make Linux run on them + * though ... + */ +#define CP0_IBASE $0 +#define CP0_IBOUND $1 +#define CP0_DBASE $2 +#define CP0_DBOUND $3 +#define CP0_CALG $17 +#define CP0_IWATCH $18 +#define CP0_DWATCH $19 + +/* + * Coprocessor 0 Set 1 register names + */ +#define CP0_S1_DERRADDR0 $26 +#define CP0_S1_DERRADDR1 $27 +#define CP0_S1_INTCONTROL $20 + +/* + * TX39 Series + */ +#define CP0_TX39_CACHE $7 + +/* + * Coprocessor 1 (FPU) register names + */ +#define CP1_REVISION $0 +#define CP1_STATUS $31 + +/* + * FPU Status Register Values + */ +/* + * Status Register Values + */ + +#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */ +#define FPU_CSR_COND 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND0 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND1 0x02000000 /* $fcc1 */ +#define FPU_CSR_COND2 0x04000000 /* $fcc2 */ +#define FPU_CSR_COND3 0x08000000 /* $fcc3 */ +#define FPU_CSR_COND4 0x10000000 /* $fcc4 */ +#define FPU_CSR_COND5 0x20000000 /* $fcc5 */ +#define FPU_CSR_COND6 0x40000000 /* $fcc6 */ +#define FPU_CSR_COND7 0x80000000 /* $fcc7 */ + +/* + * X the exception cause indicator + * E the exception enable + * S the sticky/flag bit +*/ +#define FPU_CSR_ALL_X 0x0003f000 +#define FPU_CSR_UNI_X 0x00020000 +#define FPU_CSR_INV_X 0x00010000 +#define FPU_CSR_DIV_X 0x00008000 +#define FPU_CSR_OVF_X 0x00004000 +#define FPU_CSR_UDF_X 0x00002000 +#define FPU_CSR_INE_X 0x00001000 + +#define FPU_CSR_ALL_E 0x00000f80 +#define FPU_CSR_INV_E 0x00000800 +#define FPU_CSR_DIV_E 0x00000400 +#define FPU_CSR_OVF_E 0x00000200 +#define FPU_CSR_UDF_E 0x00000100 +#define FPU_CSR_INE_E 0x00000080 + +#define FPU_CSR_ALL_S 0x0000007c +#define FPU_CSR_INV_S 0x00000040 +#define FPU_CSR_DIV_S 0x00000020 +#define FPU_CSR_OVF_S 0x00000010 +#define FPU_CSR_UDF_S 0x00000008 +#define FPU_CSR_INE_S 0x00000004 + +/* rounding mode */ +#define FPU_CSR_RN 0x0 /* nearest */ +#define FPU_CSR_RZ 0x1 /* towards zero */ +#define FPU_CSR_RU 0x2 /* towards +Infinity */ +#define FPU_CSR_RD 0x3 /* towards -Infinity */ + + +/* + * Values for PageMask register + */ +#ifdef CONFIG_CPU_VR41XX + +/* Why doesn't stupidity hurt ... */ + +#define PM_1K 0x00000000 +#define PM_4K 0x00001800 +#define PM_16K 0x00007800 +#define PM_64K 0x0001f800 +#define PM_256K 0x0007f800 + +#else + +#define PM_4K 0x00000000 +#define PM_16K 0x00006000 +#define PM_64K 0x0001e000 +#define PM_256K 0x0007e000 +#define PM_1M 0x001fe000 +#define PM_4M 0x007fe000 +#define PM_16M 0x01ffe000 +#define PM_64M 0x07ffe000 +#define PM_256M 0x1fffe000 + +#endif + +/* + * Values used for computation of new tlb entries + */ +#define PL_4K 12 +#define PL_16K 14 +#define PL_64K 16 +#define PL_256K 18 +#define PL_1M 20 +#define PL_4M 22 +#define PL_16M 24 +#define PL_64M 26 +#define PL_256M 28 + +/* + * R4x00 interrupt enable / cause bits + */ +#define IE_SW0 (_ULCAST_(1) << 8) +#define IE_SW1 (_ULCAST_(1) << 9) +#define IE_IRQ0 (_ULCAST_(1) << 10) +#define IE_IRQ1 (_ULCAST_(1) << 11) +#define IE_IRQ2 (_ULCAST_(1) << 12) +#define IE_IRQ3 (_ULCAST_(1) << 13) +#define IE_IRQ4 (_ULCAST_(1) << 14) +#define IE_IRQ5 (_ULCAST_(1) << 15) + +/* + * R4x00 interrupt cause bits + */ +#define C_SW0 (_ULCAST_(1) << 8) +#define C_SW1 (_ULCAST_(1) << 9) +#define C_IRQ0 (_ULCAST_(1) << 10) +#define C_IRQ1 (_ULCAST_(1) << 11) +#define C_IRQ2 (_ULCAST_(1) << 12) +#define C_IRQ3 (_ULCAST_(1) << 13) +#define C_IRQ4 (_ULCAST_(1) << 14) +#define C_IRQ5 (_ULCAST_(1) << 15) + +/* + * Bitfields in the R4xx0 cp0 status register + */ +#define ST0_IE 0x00000001 +#define ST0_EXL 0x00000002 +#define ST0_ERL 0x00000004 +#define ST0_KSU 0x00000018 +# define KSU_USER 0x00000010 +# define KSU_SUPERVISOR 0x00000008 +# define KSU_KERNEL 0x00000000 +#define ST0_UX 0x00000020 +#define ST0_SX 0x00000040 +#define ST0_KX 0x00000080 +#define ST0_DE 0x00010000 +#define ST0_CE 0x00020000 + +/* + * Bitfields in the R[23]000 cp0 status register. + */ +#define ST0_IEC 0x00000001 +#define ST0_KUC 0x00000002 +#define ST0_IEP 0x00000004 +#define ST0_KUP 0x00000008 +#define ST0_IEO 0x00000010 +#define ST0_KUO 0x00000020 +/* bits 6 & 7 are reserved on R[23]000 */ +#define ST0_ISC 0x00010000 +#define ST0_SWC 0x00020000 +#define ST0_CM 0x00080000 + +/* + * Bits specific to the R4640/R4650 + */ +#define ST0_UM (_ULCAST_(1) << 4) +#define ST0_IL (_ULCAST_(1) << 23) +#define ST0_DL (_ULCAST_(1) << 24) + +/* + * Bitfields in the TX39 family CP0 Configuration Register 3 + */ +#define TX39_CONF_ICS_SHIFT 19 +#define TX39_CONF_ICS_MASK 0x00380000 +#define TX39_CONF_ICS_1KB 0x00000000 +#define TX39_CONF_ICS_2KB 0x00080000 +#define TX39_CONF_ICS_4KB 0x00100000 +#define TX39_CONF_ICS_8KB 0x00180000 +#define TX39_CONF_ICS_16KB 0x00200000 + +#define TX39_CONF_DCS_SHIFT 16 +#define TX39_CONF_DCS_MASK 0x00070000 +#define TX39_CONF_DCS_1KB 0x00000000 +#define TX39_CONF_DCS_2KB 0x00010000 +#define TX39_CONF_DCS_4KB 0x00020000 +#define TX39_CONF_DCS_8KB 0x00030000 +#define TX39_CONF_DCS_16KB 0x00040000 + +#define TX39_CONF_CWFON 0x00004000 +#define TX39_CONF_WBON 0x00002000 +#define TX39_CONF_RF_SHIFT 10 +#define TX39_CONF_RF_MASK 0x00000c00 +#define TX39_CONF_DOZE 0x00000200 +#define TX39_CONF_HALT 0x00000100 +#define TX39_CONF_LOCK 0x00000080 +#define TX39_CONF_ICE 0x00000020 +#define TX39_CONF_DCE 0x00000010 +#define TX39_CONF_IRSIZE_SHIFT 2 +#define TX39_CONF_IRSIZE_MASK 0x0000000c +#define TX39_CONF_DRSIZE_SHIFT 0 +#define TX39_CONF_DRSIZE_MASK 0x00000003 + +/* + * Status register bits available in all MIPS CPUs. + */ +#define ST0_IM 0x0000ff00 +#define STATUSB_IP0 8 +#define STATUSF_IP0 (_ULCAST_(1) << 8) +#define STATUSB_IP1 9 +#define STATUSF_IP1 (_ULCAST_(1) << 9) +#define STATUSB_IP2 10 +#define STATUSF_IP2 (_ULCAST_(1) << 10) +#define STATUSB_IP3 11 +#define STATUSF_IP3 (_ULCAST_(1) << 11) +#define STATUSB_IP4 12 +#define STATUSF_IP4 (_ULCAST_(1) << 12) +#define STATUSB_IP5 13 +#define STATUSF_IP5 (_ULCAST_(1) << 13) +#define STATUSB_IP6 14 +#define STATUSF_IP6 (_ULCAST_(1) << 14) +#define STATUSB_IP7 15 +#define STATUSF_IP7 (_ULCAST_(1) << 15) +#define STATUSB_IP8 0 +#define STATUSF_IP8 (_ULCAST_(1) << 0) +#define STATUSB_IP9 1 +#define STATUSF_IP9 (_ULCAST_(1) << 1) +#define STATUSB_IP10 2 +#define STATUSF_IP10 (_ULCAST_(1) << 2) +#define STATUSB_IP11 3 +#define STATUSF_IP11 (_ULCAST_(1) << 3) +#define STATUSB_IP12 4 +#define STATUSF_IP12 (_ULCAST_(1) << 4) +#define STATUSB_IP13 5 +#define STATUSF_IP13 (_ULCAST_(1) << 5) +#define STATUSB_IP14 6 +#define STATUSF_IP14 (_ULCAST_(1) << 6) +#define STATUSB_IP15 7 +#define STATUSF_IP15 (_ULCAST_(1) << 7) +#define ST0_CH 0x00040000 +#define ST0_SR 0x00100000 +#define ST0_TS 0x00200000 +#define ST0_BEV 0x00400000 +#define ST0_RE 0x02000000 +#define ST0_FR 0x04000000 +#define ST0_CU 0xf0000000 +#define ST0_CU0 0x10000000 +#define ST0_CU1 0x20000000 +#define ST0_CU2 0x40000000 +#define ST0_CU3 0x80000000 +#define ST0_XX 0x80000000 /* MIPS IV naming */ + +/* + * Bitfields and bit numbers in the coprocessor 0 cause register. + * + * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. + */ +#define CAUSEB_EXCCODE 2 +#define CAUSEF_EXCCODE (_ULCAST_(31) << 2) +#define CAUSEB_IP 8 +#define CAUSEF_IP (_ULCAST_(255) << 8) +#define CAUSEB_IP0 8 +#define CAUSEF_IP0 (_ULCAST_(1) << 8) +#define CAUSEB_IP1 9 +#define CAUSEF_IP1 (_ULCAST_(1) << 9) +#define CAUSEB_IP2 10 +#define CAUSEF_IP2 (_ULCAST_(1) << 10) +#define CAUSEB_IP3 11 +#define CAUSEF_IP3 (_ULCAST_(1) << 11) +#define CAUSEB_IP4 12 +#define CAUSEF_IP4 (_ULCAST_(1) << 12) +#define CAUSEB_IP5 13 +#define CAUSEF_IP5 (_ULCAST_(1) << 13) +#define CAUSEB_IP6 14 +#define CAUSEF_IP6 (_ULCAST_(1) << 14) +#define CAUSEB_IP7 15 +#define CAUSEF_IP7 (_ULCAST_(1) << 15) +#define CAUSEB_IV 23 +#define CAUSEF_IV (_ULCAST_(1) << 23) +#define CAUSEB_CE 28 +#define CAUSEF_CE (_ULCAST_(3) << 28) +#define CAUSEB_BD 31 +#define CAUSEF_BD (_ULCAST_(1) << 31) + +/* + * Bits in the coprocessor 0 config register. + */ +/* Generic bits. */ +#define CONF_CM_CACHABLE_NO_WA 0 +#define CONF_CM_CACHABLE_WA 1 +#define CONF_CM_UNCACHED 2 +#define CONF_CM_CACHABLE_NONCOHERENT 3 +#define CONF_CM_CACHABLE_CE 4 +#define CONF_CM_CACHABLE_COW 5 +#define CONF_CM_CACHABLE_CUW 6 +#define CONF_CM_CACHABLE_ACCELERATED 7 +#define CONF_CM_CMASK 7 +#define CONF_BE (_ULCAST_(1) << 15) + +/* Bits common to various processors. */ +#define CONF_CU (_ULCAST_(1) << 3) +#define CONF_DB (_ULCAST_(1) << 4) +#define CONF_IB (_ULCAST_(1) << 5) +#define CONF_DC (_ULCAST_(7) << 6) +#define CONF_IC (_ULCAST_(7) << 9) +#define CONF_EB (_ULCAST_(1) << 13) +#define CONF_EM (_ULCAST_(1) << 14) +#define CONF_SM (_ULCAST_(1) << 16) +#define CONF_SC (_ULCAST_(1) << 17) +#define CONF_EW (_ULCAST_(3) << 18) +#define CONF_EP (_ULCAST_(15)<< 24) +#define CONF_EC (_ULCAST_(7) << 28) +#define CONF_CM (_ULCAST_(1) << 31) + +/* Bits specific to the R4xx0. */ +#define R4K_CONF_SW (_ULCAST_(1) << 20) +#define R4K_CONF_SS (_ULCAST_(1) << 21) +#define R4K_CONF_SB (_ULCAST_(3) << 22) + +/* Bits specific to the R5000. */ +#define R5K_CONF_SE (_ULCAST_(1) << 12) +#define R5K_CONF_SS (_ULCAST_(3) << 20) + +/* Bits specific to the R10000. */ +#define R10K_CONF_DN (_ULCAST_(3) << 3) +#define R10K_CONF_CT (_ULCAST_(1) << 5) +#define R10K_CONF_PE (_ULCAST_(1) << 6) +#define R10K_CONF_PM (_ULCAST_(3) << 7) +#define R10K_CONF_EC (_ULCAST_(15)<< 9) +#define R10K_CONF_SB (_ULCAST_(1) << 13) +#define R10K_CONF_SK (_ULCAST_(1) << 14) +#define R10K_CONF_SS (_ULCAST_(7) << 16) +#define R10K_CONF_SC (_ULCAST_(7) << 19) +#define R10K_CONF_DC (_ULCAST_(7) << 26) +#define R10K_CONF_IC (_ULCAST_(7) << 29) + +/* Bits specific to the VR41xx. */ +#define VR41_CONF_CS (_ULCAST_(1) << 12) +#define VR41_CONF_M16 (_ULCAST_(1) << 20) +#define VR41_CONF_AD (_ULCAST_(1) << 23) + +/* Bits specific to the R30xx. */ +#define R30XX_CONF_FDM (_ULCAST_(1) << 19) +#define R30XX_CONF_REV (_ULCAST_(1) << 22) +#define R30XX_CONF_AC (_ULCAST_(1) << 23) +#define R30XX_CONF_RF (_ULCAST_(1) << 24) +#define R30XX_CONF_HALT (_ULCAST_(1) << 25) +#define R30XX_CONF_FPINT (_ULCAST_(7) << 26) +#define R30XX_CONF_DBR (_ULCAST_(1) << 29) +#define R30XX_CONF_SB (_ULCAST_(1) << 30) +#define R30XX_CONF_LOCK (_ULCAST_(1) << 31) + +/* Bits specific to the TX49. */ +#define TX49_CONF_DC (_ULCAST_(1) << 16) +#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */ +#define TX49_CONF_HALT (_ULCAST_(1) << 18) +#define TX49_CONF_CWFON (_ULCAST_(1) << 27) + +/* Bits specific to the MIPS32/64 PRA. */ +#define MIPS_CONF_MT (_ULCAST_(7) << 7) +#define MIPS_CONF_AR (_ULCAST_(7) << 10) +#define MIPS_CONF_AT (_ULCAST_(3) << 13) +#define MIPS_CONF_M (_ULCAST_(1) << 31) + +/* + * R10000 performance counter definitions. + * + * FIXME: The R10000 performance counter opens a nice way to implement CPU + * time accounting with a precission of one cycle. I don't have + * R10000 silicon but just a manual, so ... + */ + +/* + * Events counted by counter #0 + */ +#define CE0_CYCLES 0 +#define CE0_INSN_ISSUED 1 +#define CE0_LPSC_ISSUED 2 +#define CE0_S_ISSUED 3 +#define CE0_SC_ISSUED 4 +#define CE0_SC_FAILED 5 +#define CE0_BRANCH_DECODED 6 +#define CE0_QW_WB_SECONDARY 7 +#define CE0_CORRECTED_ECC_ERRORS 8 +#define CE0_ICACHE_MISSES 9 +#define CE0_SCACHE_I_MISSES 10 +#define CE0_SCACHE_I_WAY_MISSPREDICTED 11 +#define CE0_EXT_INTERVENTIONS_REQ 12 +#define CE0_EXT_INVALIDATE_REQ 13 +#define CE0_VIRTUAL_COHERENCY_COND 14 +#define CE0_INSN_GRADUATED 15 + +/* + * Events counted by counter #1 + */ +#define CE1_CYCLES 0 +#define CE1_INSN_GRADUATED 1 +#define CE1_LPSC_GRADUATED 2 +#define CE1_S_GRADUATED 3 +#define CE1_SC_GRADUATED 4 +#define CE1_FP_INSN_GRADUATED 5 +#define CE1_QW_WB_PRIMARY 6 +#define CE1_TLB_REFILL 7 +#define CE1_BRANCH_MISSPREDICTED 8 +#define CE1_DCACHE_MISS 9 +#define CE1_SCACHE_D_MISSES 10 +#define CE1_SCACHE_D_WAY_MISSPREDICTED 11 +#define CE1_EXT_INTERVENTION_HITS 12 +#define CE1_EXT_INVALIDATE_REQ 13 +#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14 +#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15 + +/* + * These flags define in which priviledge mode the counters count events + */ +#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */ +#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */ +#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */ +#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */ + +#ifndef __ASSEMBLY__ + +#define CAUSE_EXCCODE(x) ((CAUSEF_EXCCODE & (x->cp0_cause)) >> CAUSEB_EXCCODE) +#define CAUSE_EPC(x) (x->cp0_epc + (((x->cp0_cause & CAUSEF_BD) >> CAUSEB_BD) << 2)) + +/* + * Functions to access the r10k performance counter and control registers + */ +#define read_r10k_perf_cntr(counter) \ +({ unsigned int __res; \ + __asm__ __volatile__( \ + "mfpc\t%0, "STR(counter) \ + : "=r" (__res)); \ + __res;}) + +#define write_r10k_perf_cntr(counter,val) \ + __asm__ __volatile__( \ + "mtpc\t%0, "STR(counter) \ + : : "r" (val)); + +#define read_r10k_perf_cntl(counter) \ +({ unsigned int __res; \ + __asm__ __volatile__( \ + "mfps\t%0, "STR(counter) \ + : "=r" (__res)); \ + __res;}) + +#define write_r10k_perf_cntl(counter,val) \ + __asm__ __volatile__( \ + "mtps\t%0, "STR(counter) \ + : : "r" (val)); + +/* + * Macros to access the system control coprocessor + */ + +#define __read_32bit_c0_register(source, sel) \ +({ int __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __read_64bit_c0_register(source, sel) \ +({ unsigned long __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmfc0\t%0, " #source "\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_c0_register(register, sel, value) \ +do { \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mtc0\t%z0, " #register "\n\t" \ + : : "Jr" (value)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ +} while (0) + +#define __write_64bit_c0_register(register, sel, value) \ +do { \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmtc0\t%z0, " #register "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ +} while (0) + +#define __read_ulong_c0_register(reg, sel) \ + ((sizeof(unsigned long) == 4) ? \ + __read_32bit_c0_register(reg, sel) : \ + __read_64bit_c0_register(reg, sel)) + +#define __write_ulong_c0_register(reg, sel, val) \ +do { \ + if (sizeof(unsigned long) == 4) \ + __write_32bit_c0_register(reg, sel, val); \ + else \ + __write_64bit_c0_register(reg, sel, val); \ +} while (0) + +/* + * These versions are only needed for systems with more than 38 bits of + * physical address space running the 32-bit kernel. That's none atm :-) + */ +#define __read_64bit_c0_split(source, sel) \ +({ \ + unsigned long long val; \ + unsigned long flags; \ + \ + local_irq_save(flags); \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%M0, " #source "\n\t" \ + "dsll\t%L0, %M0, 32\n\t" \ + "dsrl\t%M0, %M0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + ".set\tmips0" \ + : "=r" (val)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%M0, " #source ", " #sel "\n\t" \ + "dsll\t%L0, %M0, 32\n\t" \ + "dsrl\t%M0, %M0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + ".set\tmips0" \ + : "=r" (val)); \ + local_irq_restore(flags); \ + \ + val; \ +}) + +#define __write_64bit_c0_split(source, sel, val) \ +do { \ + unsigned long flags; \ + \ + local_irq_save(flags); \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ + "or\t%L0, %L0, %M0\n\t" \ + "dmtc0\t%L0, " #source "\n\t" \ + ".set\tmips0" \ + : : "r" (val)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ + "or\t%L0, %L0, %M0\n\t" \ + "dmtc0\t%L0, " #source ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "r" (val)); \ + local_irq_restore(flags); \ +} while (0) + +#define read_c0_index() __read_32bit_c0_register($0, 0) +#define write_c0_index(val) __write_32bit_c0_register($0, 0, val) + +#define read_c0_entrylo0() __read_ulong_c0_register($2, 0) +#define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val) + +#define read_c0_entrylo1() __read_ulong_c0_register($3, 0) +#define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val) + +#define read_c0_conf() __read_32bit_c0_register($3, 0) +#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) + +#define read_c0_context() __read_ulong_c0_register($4, 0) +#define write_c0_context(val) __write_ulong_c0_register($4, 0, val) + +#define read_c0_pagemask() __read_32bit_c0_register($5, 0) +#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) + +#define read_c0_wired() __read_32bit_c0_register($6, 0) +#define write_c0_wired(val) __write_32bit_c0_register($6, 0, val) + +#define read_c0_info() __read_32bit_c0_register($7, 0) + +#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */ +#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val) + +#define read_c0_count() __read_32bit_c0_register($9, 0) +#define write_c0_count(val) __write_32bit_c0_register($9, 0, val) + +#define read_c0_entryhi() __read_ulong_c0_register($10, 0) +#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val) + +#define read_c0_compare() __read_32bit_c0_register($11, 0) +#define write_c0_compare(val) __write_32bit_c0_register($11, 0, val) + +#define read_c0_status() __read_32bit_c0_register($12, 0) +#define write_c0_status(val) __write_32bit_c0_register($12, 0, val) + +#define read_c0_cause() __read_32bit_c0_register($13, 0) +#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) + +#define read_c0_prid() __read_32bit_c0_register($15, 0) + +#define read_c0_config() __read_32bit_c0_register($16, 0) +#define read_c0_config1() __read_32bit_c0_register($16, 1) +#define read_c0_config2() __read_32bit_c0_register($16, 2) +#define read_c0_config3() __read_32bit_c0_register($16, 3) +#define write_c0_config(val) __write_32bit_c0_register($16, 0, val) +#define write_c0_config1(val) __write_32bit_c0_register($16, 1, val) +#define write_c0_config2(val) __write_32bit_c0_register($16, 2, val) +#define write_c0_config3(val) __write_32bit_c0_register($16, 3, val) + +/* + * The WatchLo register. There may be upto 8 of them. + */ +#define read_c0_watchlo0() __read_ulong_c0_register($18, 0) +#define read_c0_watchlo1() __read_ulong_c0_register($18, 1) +#define read_c0_watchlo2() __read_ulong_c0_register($18, 2) +#define read_c0_watchlo3() __read_ulong_c0_register($18, 3) +#define read_c0_watchlo4() __read_ulong_c0_register($18, 4) +#define read_c0_watchlo5() __read_ulong_c0_register($18, 5) +#define read_c0_watchlo6() __read_ulong_c0_register($18, 6) +#define read_c0_watchlo7() __read_ulong_c0_register($18, 7) +#define write_c0_watchlo0(val) __write_ulong_c0_register($18, 0, val) +#define write_c0_watchlo1(val) __write_ulong_c0_register($18, 1, val) +#define write_c0_watchlo2(val) __write_ulong_c0_register($18, 2, val) +#define write_c0_watchlo3(val) __write_ulong_c0_register($18, 3, val) +#define write_c0_watchlo4(val) __write_ulong_c0_register($18, 4, val) +#define write_c0_watchlo5(val) __write_ulong_c0_register($18, 5, val) +#define write_c0_watchlo6(val) __write_ulong_c0_register($18, 6, val) +#define write_c0_watchlo7(val) __write_ulong_c0_register($18, 7, val) + +/* + * The WatchHi register. There may be upto 8 of them. + */ +#define read_c0_watchhi0() __read_32bit_c0_register($19, 0) +#define read_c0_watchhi1() __read_32bit_c0_register($19, 1) +#define read_c0_watchhi2() __read_32bit_c0_register($19, 2) +#define read_c0_watchhi3() __read_32bit_c0_register($19, 3) +#define read_c0_watchhi4() __read_32bit_c0_register($19, 4) +#define read_c0_watchhi5() __read_32bit_c0_register($19, 5) +#define read_c0_watchhi6() __read_32bit_c0_register($19, 6) +#define read_c0_watchhi7() __read_32bit_c0_register($19, 7) + +#define write_c0_watchhi0(val) __write_32bit_c0_register($19, 0, val) +#define write_c0_watchhi1(val) __write_32bit_c0_register($19, 1, val) +#define write_c0_watchhi2(val) __write_32bit_c0_register($19, 2, val) +#define write_c0_watchhi3(val) __write_32bit_c0_register($19, 3, val) +#define write_c0_watchhi4(val) __write_32bit_c0_register($19, 4, val) +#define write_c0_watchhi5(val) __write_32bit_c0_register($19, 5, val) +#define write_c0_watchhi6(val) __write_32bit_c0_register($19, 6, val) +#define write_c0_watchhi7(val) __write_32bit_c0_register($19, 7, val) + +#define read_c0_xcontext() __read_ulong_c0_register($20, 0) +#define write_c0_xcontext(val) __write_ulong_c0_register($20, 0, val) + +#define read_c0_intcontrol() __read_32bit_c0_register($20, 1) +#define write_c0_intcontrol(val) __write_32bit_c0_register($20, 1, val) + +#define read_c0_framemask() __read_32bit_c0_register($21, 0) +#define write_c0_framemask(val) __write_32bit_c0_register($21, 0, val) + +#define read_c0_debug() __read_32bit_c0_register($23, 0) +#define write_c0_debug(val) __write_32bit_c0_register($23, 0, val) + +#define read_c0_depc() __read_ulong_c0_register($24, 0) +#define write_c0_depc(val) __write_ulong_c0_register($24, 0, val) + +#define read_c0_ecc() __read_32bit_c0_register($26, 0) +#define write_c0_ecc(val) __write_32bit_c0_register($26, 0, val) + +#define read_c0_derraddr0() __read_ulong_c0_register($26, 1) +#define write_c0_derraddr0(val) __write_ulong_c0_register($26, 1, val) + +#define read_c0_cacheerr() __read_32bit_c0_register($27, 0) + +#define read_c0_derraddr1() __read_ulong_c0_register($27, 1) +#define write_c0_derraddr1(val) __write_ulong_c0_register($27, 1, val) + +#define read_c0_taglo() __read_32bit_c0_register($28, 0) +#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val) + +#define read_c0_taghi() __read_32bit_c0_register($29, 0) +#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val) + +#define read_c0_errorepc() __read_ulong_c0_register($30, 0) +#define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val) + +#define read_c0_epc() __read_ulong_c0_register($14, 0) +#define write_c0_epc(val) __write_ulong_c0_register($14, 0, val) + +#if 1 +/* + * Macros to access the system control coprocessor + */ +#define read_32bit_cp0_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "mfc0\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +#define read_32bit_cp0_set1_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "cfc0\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +/* + * For now use this only with interrupts disabled! + */ +#define read_64bit_cp0_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmfc0\t%0,"STR(source)"\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + __res;}) + +#define write_32bit_cp0_register(register,value) \ + __asm__ __volatile__( \ + "mtc0\t%0,"STR(register)"\n\t" \ + "nop" \ + : : "r" (value)); + +#define write_32bit_cp0_set1_register(register,value) \ + __asm__ __volatile__( \ + "ctc0\t%0,"STR(register)"\n\t" \ + "nop" \ + : : "r" (value)); + +#define write_64bit_cp0_register(register,value) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmtc0\t%0,"STR(register)"\n\t" \ + ".set\tmips0" \ + : : "r" (value)) + +/* + * This should be changed when we get a compiler that support the MIPS32 ISA. + */ +#define read_mips32_cp0_config1() \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tnoreorder\n\t" \ + ".set\tnoat\n\t" \ + "#.set\tmips64\n\t" \ + "#mfc0\t$1, $16, 1\n\t" \ + "#.set\tmips0\n\t" \ + ".word\t0x40018001\n\t" \ + "move\t%0,$1\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" \ + :"=r" (__res)); \ + __res;}) + +#endif +/* + * Macros to access the floating point coprocessor control registers + */ +#define read_32bit_cp1_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "cfc1\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +/* TLB operations. */ +static inline void tlb_probe(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbp\n\t" + ".set reorder"); +} + +static inline void tlb_read(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbr\n\t" + ".set reorder"); +} + +static inline void tlb_write_indexed(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbwi\n\t" + ".set reorder"); +} + +static inline void tlb_write_random(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbwr\n\t" + ".set reorder"); +} + +/* + * Manipulate bits in a c0 register. + */ +#define __BUILD_SET_C0(name,register) \ +static inline unsigned int \ +set_c0_##name(unsigned int set) \ +{ \ + unsigned int res; \ + \ + res = read_c0_##name(); \ + res |= set; \ + write_c0_##name(res); \ + \ + return res; \ +} \ + \ +static inline unsigned int \ +clear_c0_##name(unsigned int clear) \ +{ \ + unsigned int res; \ + \ + res = read_c0_##name(); \ + res &= ~clear; \ + write_c0_##name(res); \ + \ + return res; \ +} \ + \ +static inline unsigned int \ +change_c0_##name(unsigned int change, unsigned int new) \ +{ \ + unsigned int res; \ + \ + res = read_c0_##name(); \ + res &= ~change; \ + res |= (new & change); \ + write_c0_##name(res); \ + \ + return res; \ +} + +__BUILD_SET_C0(status,CP0_STATUS) +__BUILD_SET_C0(cause,CP0_CAUSE) +__BUILD_SET_C0(config,CP0_CONFIG) + +#define set_cp0_status(x) set_c0_status(x) +#define set_cp0_cause(x) set_c0_cause(x) +#define set_cp0_config(x) set_c0_config(x) + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_MIPSREGS_H */ diff --git a/sdk-modifications/include/mmc_api.h b/sdk-modifications/include/mmc_api.h new file mode 100644 index 0000000..28e75ef --- /dev/null +++ b/sdk-modifications/include/mmc_api.h @@ -0,0 +1,56 @@ +#ifndef __MMC_API_H__ +#define __MMC_API_H__ + +/* Error codes */ +enum mmc_result_t { + MMC_NO_RESPONSE = -1, + MMC_NO_ERROR = 0, + MMC_ERROR_OUT_OF_RANGE, + MMC_ERROR_ADDRESS, + MMC_ERROR_BLOCK_LEN, + MMC_ERROR_ERASE_SEQ, + MMC_ERROR_ERASE_PARAM, + MMC_ERROR_WP_VIOLATION, + MMC_ERROR_CARD_IS_LOCKED, + MMC_ERROR_LOCK_UNLOCK_FAILED, + MMC_ERROR_COM_CRC, + MMC_ERROR_ILLEGAL_COMMAND, + MMC_ERROR_CARD_ECC_FAILED, + MMC_ERROR_CC, + MMC_ERROR_GENERAL, + MMC_ERROR_UNDERRUN, + MMC_ERROR_OVERRUN, + MMC_ERROR_CID_CSD_OVERWRITE, + MMC_ERROR_STATE_MISMATCH, + MMC_ERROR_HEADER_MISMATCH, + MMC_ERROR_TIMEOUT, + MMC_ERROR_CRC, + MMC_ERROR_DRIVER_FAILURE, +}; + + +/* Get card's sectors*/ + +extern unsigned int MMC_GetSize(void); + + +/* initialize MMC/SD card */ +extern int MMC_Initialize(void); + +/* read a single block from MMC/SD card */ +extern int MMC_ReadBlock(unsigned int blockaddr, unsigned char *recbuf); + +/* read multi blocks from MMC/SD card */ +extern int MMC_ReadMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); + +/* write a block to MMC/SD card */ +extern int MMC_WriteBlock(unsigned int blockaddr, unsigned char *recbuf); + +/* write multi blocks to MMC/SD card */ +extern int MMC_WriteMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); + +/* detect MMC/SD card */ +extern int MMC_DetectStatus(void); + +#endif /* __MMC_API_H__ */ + diff --git a/sdk-modifications/include/partition.h b/sdk-modifications/include/partition.h new file mode 100644 index 0000000..0777b54 --- /dev/null +++ b/sdk-modifications/include/partition.h @@ -0,0 +1,131 @@ +/* + partition.h + Functions for mounting and dismounting partitions + on various block devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _PARTITION_H +#define _PARTITION_H + +#include "fs_common.h" + +#include "disc_io/disc.h" +#include "fs_cache.h" + +// Device name +extern const char* DEVICE_NAME; + +// Filesystem type +typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; + +#ifdef NDS +typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM} PARTITION_INTERFACE; +#else +typedef enum {PI_CART_SLOT} PARTITION_INTERFACE; +#endif + +typedef struct { + u32 fatStart; + u32 sectorsPerFat; + u32 lastCluster; + u32 firstFree; +} FAT; + +typedef struct { + const IO_INTERFACE* disc; + CACHE* cache; + // Info about the partition + bool readOnly; // If this is set, then do not try writing to the disc + FS_TYPE filesysType; + u32 totalSize; + u32 rootDirStart; + u32 rootDirCluster; + u32 numberOfSectors; + u32 dataStart; + u32 bytesPerSector; + u32 sectorsPerCluster; + u32 bytesPerCluster; + FAT fat; + // Values that may change after construction + u32 cwdCluster; // Current working directory cluser + u32 openFileCount; +} PARTITION; + +/* +Mount the device specified by partitionDevice +PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice +PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +*/ +bool _FAT_partition_mount (PARTITION_INTERFACE partitionNumber, u32 cacheSize); + +/* +Mount a partition on a custom device +*/ +bool _FAT_partition_mountCustomInterface (const IO_INTERFACE* device, u32 cacheSize); + + +/* +Free Mount a partition on a custom device +*/ +bool _FAT_partition_freeMount( int partitionNumber, const IO_INTERFACE* device, u32 cacheSize); + + +/* +Unmount the partition specified by partitionNumber +If there are open files, it will fail +*/ +bool _FAT_partition_unmount (PARTITION_INTERFACE partitionNumber); + +/* +Forcibly unmount the partition specified by partitionNumber +Any open files on the partition will become invalid +The cache will be invalidated, and any unflushed writes will be lost +*/ +bool _FAT_partition_unsafeUnmount (PARTITION_INTERFACE partitionNumber); + +/* +Set the default device for access by fat: and fat0:, +based on the device number +*/ +bool _FAT_partition_setDefaultInterface (PARTITION_INTERFACE partitionNumber); + +/* +Set the default device for access by fat: and fat0:, +based on the partition pointer +*/ +bool _FAT_partition_setDefaultPartition (PARTITION* partition); + +/* +Return the partition specified in a path +For instance, "fat0:", "fat:", "/" and "fat:/" will all +return the default partition +*/ +PARTITION* _FAT_partition_getPartitionFromPath (const char* path); + +#endif // _PARTITION_H diff --git a/sdk-modifications/include/tcm.h b/sdk-modifications/include/tcm.h new file mode 100644 index 0000000..4de3333 --- /dev/null +++ b/sdk-modifications/include/tcm.h @@ -0,0 +1,10 @@ +#ifndef __TCM_H +#define __TCM_H + +/* +* Function: makes cpu to idle state. It will be waken up by RTC in the next second. +* Of course, it can be waken up by keys at any time. +*/ +int enable_enter_idle(void); + +#endif diff --git a/sdk-modifications/libsrc/.depend b/sdk-modifications/libsrc/.depend new file mode 100644 index 0000000..e69de29 diff --git a/sdk-modifications/libsrc/Makefile b/sdk-modifications/libsrc/Makefile new file mode 100644 index 0000000..6e2b4ab --- /dev/null +++ b/sdk-modifications/libsrc/Makefile @@ -0,0 +1,67 @@ + +CURR_DIR = ${shell pwd} +#CROSS :=# +#CROSS := /opt/mipsel-4.1.2-nopic/bin/ +CROSS := /opt/mipsel-4.1.2-nopic/bin/ + + +CC = $(CROSS)mipsel-linux-gcc +AR = $(CROSS)mipsel-linux-ar rcsv + +TOPDIR = . +CONSOLE_DIR = $(TOPDIR)/console +FS_DIR = $(TOPDIR)/fs +KEY_DIR = $(TOPDIR)/key +ZLIB_DIR = $(TOPDIR)/zlib +DMA_DIR = $(TOPDIR)/dma + +SRC := + +SSRC := + +INCLUDES := -I../include + +INC := $(INCLUDES) + +CFLAGS := -mips32 -O3 -mno-abicalls -fno-pic -fno-builtin \ + -fno-exceptions -ffunction-sections -mlong-calls\ + -fomit-frame-pointer -msoft-float -G 4 + +include $(CONSOLE_DIR)/console.mk +include $(FS_DIR)/fs.mk +include $(KEY_DIR)/key.mk +include $(ZLIB_DIR)/zlib.mk +include $(DMA_DIR)/dma.mk + +#OBJS := $(addsuffix .o , $(basename $(notdir $(SRC)))) +#SOBJS := $(addsuffix .o , $(basename $(notdir $(SSRC)))) + +OBJS := $(SRC:.c=.o) +SOBJS := $(SSRC:.S=.o) + +all : depend libds2a.a + +libds2a.a : $(OBJS) $(SOBJS) + $(AR) $@ $(OBJS) $(SOBJS) + cp $@ ../lib + +clrscreen: + @clear + @clear + +clean : + rm -rf $(OBJS) $(SOBJS) *.a + rm -f depend + +.c.o : + $(CC) $(CFLAGS) $(INC) -o $@ -c $< +.cpp.o : + $(CC) $(CFLAGS) $(INC) -fno-rtti -fvtable-gc -o $@ -c $< +.S.o : + $(CC) $(CFLAGS) $(INC) -D_ASSEMBLER_ -D__ASSEMBLY__ -o $@ -c $< + +depend : Makefile + $(CC) -MM $(CFLAGS) $(INC) $(SSRC) $(SRC) > $@ + +sinclude depend + diff --git a/sdk-modifications/libsrc/console/console.c b/sdk-modifications/libsrc/console/console.c new file mode 100644 index 0000000..f455ac5 --- /dev/null +++ b/sdk-modifications/libsrc/console/console.c @@ -0,0 +1,484 @@ +//console.c + +#include +#include +#include "ds2io.h" +#include "memory.h" +#include "font_dot.h" + +#define STRING_SIZE 2048 + +#define CONSOLE_WIDTH 32 +#define CONSOLE_HEIGHT 24 +#define TAB_SIZE 3 + +static void ConsoleView(void); +static void ConsoleDrawfontall(void); + +static int console_init_done = 0; +static unsigned short f_color; +static unsigned short b_color; +static enum SCREEN_ID console_id; + +static int print_row; +static int print_col; +static int print_row_saved; +static int print_col_saved; + +static unsigned char* console_buf; +static unsigned int console_buf_size; +static unsigned char* console_buf_front; +static unsigned char* console_buf_end; +static unsigned char* console_print_header; +static unsigned short* console_screen; +static unsigned char* print_header_saved; + +static void ConsoleFlush(void) +{ + unsigned short* screen_addr; + enum SCREEN_ID id; + + if(console_id & UP_MASK) { + screen_addr = up_screen_addr; + id = UP_SCREEN; + } + else { + screen_addr = down_screen_addr; + id = DOWN_SCREEN; + } + + memcpy((void*)screen_addr, (void*)console_screen, SCREEN_WIDTH*SCREEN_HEIGHT*2); + ds2_flipScreen(id, 1); +} + +static void ConsoleClearscreen(void) +{ + unsigned short *scr; + unsigned int i; + + scr = console_screen; + i = 0; + while(i < SCREEN_WIDTH*SCREEN_HEIGHT) + scr[i++] = b_color; +} + +static void ConsoleMovewin(int dir, int sw_screen) +{ + unsigned char *pt; + + if(dir || sw_screen) + ConsoleClearscreen(); + + //switch to another screen to dispaly text + if(sw_screen) + { + ConsoleFlush(); + //now up screen + if(console_id & UP_MASK) { + console_screen = down_screen_addr; + console_id = DOWN_SCREEN; + } + //switch to up screen + else + { + console_screen = up_screen_addr; + console_id = UP_SCREEN; + } + } + + pt = console_print_header + dir*CONSOLE_WIDTH; + + //screen scroll down + if(dir > 0) + { + if(console_buf_end > console_print_header) { + if(pt > console_buf_end) + pt = console_buf_end; + console_print_header = pt; + } + else if(console_buf_end < console_print_header) { + if((pt - console_buf) >= console_buf_size) { + pt -= console_buf_size; + if(pt > console_buf_end) + pt = console_buf_end; + } + console_print_header = pt; + } + } + //screen scroll up + else if(dir < 0) + { + if(console_buf_front > console_print_header) { + if(pt < console_buf) { + pt += console_buf_size; + if(pt < console_buf_front) + pt = console_buf_front; + } + console_print_header = pt; + } + else if(console_buf_front < console_print_header) { + if(pt < console_buf_front) + pt = console_buf_front; + console_print_header = pt; + } + } + + if(dir || sw_screen) + { + print_row_saved = 0; //redraw entire screen + print_col_saved = 0; + + ConsoleDrawfontall(); + ConsoleFlush(); + } +} + +void ConsoleClr(int mode) +{ + unsigned char *pt, *pt_end; + unsigned int i; + + //Clear current screen buffer + if(0 == mode) + { + if(print_col > 0) { + console_buf_end += CONSOLE_WIDTH; + if((console_buf_end - console_buf) >= console_buf_size) + console_buf_end -= console_buf_size; + } + + console_print_header = console_buf_end; + print_row = 0; + print_col = 0; + print_row_saved = 0; + print_col_saved = 0; + } + //Clear all + else if(1 == mode) + { + console_buf_front = console_buf; + console_buf_end = console_buf; + console_print_header = console_buf; + print_row = 0; + print_col = 0; + print_row_saved = 0; + print_col_saved = 0; + + pt = console_buf; + pt_end = console_buf + console_buf_size; + while(pt < pt_end) + { + pt[0] = '\0'; + pt += CONSOLE_WIDTH; + } + } + + ConsoleClearscreen(); + ConsoleFlush(); +} + +//Draw part of the screen +static void ConsoleDrawfont(void) +{ + unsigned char *pt, *dot_map; + unsigned char ch, dot; + unsigned short *dst, *pt_r; + unsigned int row, col; + unsigned int x, j, k; + + pt_r = console_screen; + row = print_row_saved; + col = print_col_saved; + x = col*8; + + pt = console_print_header + row * CONSOLE_WIDTH; + + while(row != print_row || col != print_col) + { + ch = pt[col++] & 0x7F; + //'\n' + if('\n' == ch || '\0' == ch || col > CONSOLE_WIDTH) { + pt += CONSOLE_WIDTH; + if((pt - console_buf) >= console_buf_size) pt -= console_buf_size; + col = 0; + row += 1; + x = 0; + } + //character not '\n' nor '\0' + else { + dot_map = (unsigned char*)font_map[ch]; + + for(j= 0; j < 8; j++) + { + dot = *dot_map++; + dst = pt_r + (row*8+j)*SCREEN_WIDTH + x; + for(k = 0; k < 8; k++) + *dst++ = (dot & (0x80>>k)) ? f_color : b_color; + } + x += 8; + } + } +} + +//Redraw the hole screen +static void ConsoleDrawfontall(void) +{ + unsigned char *pt, *end_pt, *dot_map; + unsigned int i, j, k; + unsigned char ch, dot; + unsigned short *dst, *pt_r; + unsigned int x, y; + + //Clear screen to b_color + pt_r = console_screen; + i = 0; + while(i < SCREEN_WIDTH*SCREEN_HEIGHT) + pt_r[i++] = b_color; + + pt = console_print_header; + end_pt = console_buf_end; + x = 0; + y = 0; + i = 0; + while(pt != end_pt) + { + ch = pt[i++] & 0x7F; + //'\n' + if('\n' == ch || '\0' == ch || i > CONSOLE_WIDTH) { + pt += CONSOLE_WIDTH; + if((pt - console_buf) >= console_buf_size) pt -= console_buf_size; + i = 0; + x = 0; + y += 1; + if(y >= CONSOLE_HEIGHT) break; + } + //character not '\n' nor '\0' + else { + dot_map = (unsigned char*)font_map[ch]; + + for(j= 0; j < 8; j++) + { + dot = *dot_map++; + dst = pt_r + (y*8+j)*SCREEN_WIDTH + x; + for(k = 0; k < 8; k++) + *dst++ = (dot & (0x80>>k)) ? f_color : b_color; + } + x += 8; + } + } +} + +static void ConsoleNewline(void) +{ + print_row += 1; + if(print_row >= CONSOLE_HEIGHT) + { + print_row -= 1; + console_print_header += CONSOLE_WIDTH; + if((console_print_header - console_buf) >= console_buf_size) + console_print_header = console_buf; + + print_row_saved = 0; + print_col_saved = 0; + + ConsoleClearscreen(); + } + + console_buf_end += CONSOLE_WIDTH; + if((console_buf_end - console_buf) >= console_buf_size) + console_buf_end = console_buf; + + //scrollback + if(console_buf_end == console_buf_front) + { + console_buf_front += CONSOLE_WIDTH; + if((console_buf_front - console_buf) >= console_buf_size) + console_buf_front = console_buf; + + console_buf_end[0] = '\0'; + } +} + +static void ConsolePrintchar(unsigned char ch) +{ + int i; + + if(print_col >= CONSOLE_WIDTH) { + print_col = 0; + ConsoleNewline(); + } + + switch(ch) { + case 9: //'\t' + if((print_col + TAB_SIZE) < CONSOLE_WIDTH) + { + i = print_col % TAB_SIZE; + i = TAB_SIZE - i; + while(i--) + { + console_buf_end[print_col] = ' '; + print_col += 1; + } + } + break; + case 10: //'\n' + case 13: //'\r' + console_buf_end[print_col] = '\n'; + print_col = 0; + ConsoleNewline(); + break; + default: + console_buf_end[print_col] = ch; + if(ch != '\0') + print_col += 1; + break; + } +} + +void ConsolePrintstring(unsigned char* string) +{ + unsigned char *pt; + unsigned char ch; + + print_row_saved = print_row; + print_col_saved = print_col; + console_print_header = print_header_saved; +//cprintf("print_row %d; print_col %d; [%s]\n", print_row, print_col, string); + pt = string; + do + { + ch = *pt++; + ConsolePrintchar(ch); + } + while ('\0' != ch); + + print_header_saved = console_print_header; + + ConsoleDrawfont(); + ConsoleFlush(); +} + +//--------------------------------------------------------------------------------- +//parameter: +// front_color: color of character +// background_color: background color +// screen: UP-up screen used as output, DOWN-down screen used as output, +// using only one screen at a time +// buf_size: buffer size to hold the output, it's unit is screen +//--------------------------------------------------------------------------------- +int ConsoleInit(unsigned short front_color, unsigned short background_color, enum SCREEN_ID screen, unsigned int buf_size) +{ + unsigned char *pt; + unsigned int size; + unsigned short **scr_ppt; + + console_init_done = 0; + f_color = front_color; + b_color = background_color; + + + //Using only one screen at a time + if(screen & UP_MASK) + console_id = UP_SCREEN; + else + console_id = DOWN_SCREEN; + + if(!buf_size) buf_size = 1; + size = buf_size *CONSOLE_WIDTH *CONSOLE_HEIGHT; + + pt = (unsigned char*)Drv_alloc(size); + if(NULL == pt) + return -1; //there is something error + + console_buf = pt; + memset(console_buf, 0, size); + + print_row = 0; + print_col = 0; + print_row_saved = print_row; + print_col_saved = print_col; + console_buf_size = size; + console_buf_front = console_buf; + console_buf_end = console_buf; + console_print_header = console_buf; + print_header_saved = console_print_header; + + console_screen = (unsigned short*)Drv_alloc(SCREEN_WIDTH * SCREEN_HEIGHT*2); + if(NULL == console_screen) { + Drv_deAlloc((void*)console_buf); + return -1; + } + + ConsoleClr(1); + + console_init_done = 1; + + regist_escape_key(ConsoleView, (KEY_L | KEY_R | KEY_A | KEY_B | KEY_X)); + return 0; +} + +void ConsoleView(void) +{ + unsigned int key; + +cprintf("enter console mode\n"); + + do { + key = getKey(); + + switch(key) + { + //screen scroll down 1 line + case KEY_UP: + ConsoleMovewin(-1, 0); + break; + + //screen scroll up 1 line + case KEY_DOWN: + ConsoleMovewin(1, 0); + break; + + //screen scroll done (CONSOLE_HEIGHT-1) line + case KEY_LEFT: + ConsoleMovewin(-(CONSOLE_HEIGHT-1), 0); + break; + + //screen scroll up (CONSOLE_HEIGHT-1) line + case KEY_RIGHT: + ConsoleMovewin(CONSOLE_HEIGHT-1, 0); + break; + + //switch screen + case KEY_B: +cprintf("switch to another screen\n"); + ConsoleMovewin(0, 1); + break; + + default: break; + } + + mdelay(20); + } while(key != KEY_Y); + +cprintf("exit console mode\n"); +} + +int printf(const char *format, ...) +{ + char string[STRING_SIZE]; + int ret; + va_list ap; + + if(!console_init_done) + return 0; + + va_start (ap, format); + ret = vsnprintf(string, STRING_SIZE, format, ap); + va_end (ap); + + ConsolePrintstring(string); + + return ret; +} + + diff --git a/sdk-modifications/libsrc/console/console.h b/sdk-modifications/libsrc/console/console.h new file mode 100644 index 0000000..f6d74a4 --- /dev/null +++ b/sdk-modifications/libsrc/console/console.h @@ -0,0 +1,9 @@ +#ifndef __CONSOLE_H__ +#define __CONSOLE_H__ +#include "ds2io.h" + +extern int ConsoleInit(unsigned short front_color, unsigned short background_color, enum SCREEN_ID screen, unsigned int buf_size); + +extern int cprintf(const char *format, ...); + +#endif //__CONSOLE_H__ diff --git a/sdk-modifications/libsrc/console/console.mk b/sdk-modifications/libsrc/console/console.mk new file mode 100644 index 0000000..b8a436e --- /dev/null +++ b/sdk-modifications/libsrc/console/console.mk @@ -0,0 +1,10 @@ +#console.mk + +SRC += $(CONSOLE_DIR)/console.c + +SSRC += + +INC += -I$(CONSOLE_DIR) + +CFLAGS += + diff --git a/sdk-modifications/libsrc/console/font_dot.h b/sdk-modifications/libsrc/console/font_dot.h new file mode 100644 index 0000000..cdf6067 --- /dev/null +++ b/sdk-modifications/libsrc/console/font_dot.h @@ -0,0 +1,75 @@ +#ifndef __FONT_DOT_H__ +#define __FONT_DOT_H__ + +//version 0.1 +//modified ''', '(',')',';','?','[',']','^','_''`','{','}','~' + +const unsigned char font_map[128][8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x08, 0x78, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, + 0x7c, 0x64, 0x44, 0x44, 0x64, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x70, 0x50, 0x50, 0x70, 0x00, + 0x24, 0x24, 0x1c, 0x08, 0x3f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x16, 0x1a, 0x12, 0x12, 0x16, 0x34, 0x20, 0x00, 0x3c, 0x24, 0x24, 0x66, 0x24, 0x3c, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x1c, 0x3c, 0x3c, 0x1c, 0x0c, 0x04, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, 0x00, + 0x54, 0x54, 0x34, 0x14, 0x14, 0x14, 0x14, 0x14, 0x08, 0x08, 0x08, 0x7f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x08, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7c, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x7e, 0x28, 0x7e, 0x28, 0x28, 0x00, + 0x1c, 0x2c, 0x28, 0x18, 0x0c, 0x2c, 0x3c, 0x08, 0x64, 0x68, 0x68, 0x7c, 0x1c, 0x1c, 0x2c, 0x00, + 0x30, 0x30, 0x3c, 0x28, 0x58, 0x50, 0x3c, 0x00, 0x30, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, //''' + 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x04, 0x40, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, + 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, + 0x18, 0x24, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00, 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, + 0x18, 0x24, 0x04, 0x08, 0x10, 0x20, 0x3c, 0x00, 0x18, 0x24, 0x04, 0x18, 0x04, 0x24, 0x18, 0x00, + 0x08, 0x18, 0x28, 0x48, 0x7c, 0x08, 0x08, 0x00, 0x3c, 0x20, 0x38, 0x04, 0x04, 0x24, 0x18, 0x00, + 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00, 0x3c, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x00, + 0x18, 0x24, 0x24, 0x18, 0x24, 0x24, 0x18, 0x00, 0x18, 0x24, 0x24, 0x1c, 0x04, 0x04, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, //';' + 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7c, 0x00, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x10, 0x24, 0x24, 0x08, 0x10, 0x10, 0x00, 0x10, //'?' + 0x38, 0x4c, 0x54, 0x5c, 0x54, 0x44, 0x38, 0x00, 0x10, 0x10, 0x28, 0x28, 0x38, 0x28, 0x6c, 0x00, + 0x78, 0x24, 0x38, 0x24, 0x24, 0x24, 0x78, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, + 0x78, 0x24, 0x24, 0x24, 0x24, 0x24, 0x78, 0x00, 0x7c, 0x24, 0x20, 0x38, 0x20, 0x24, 0x7c, 0x00, + 0x7c, 0x24, 0x28, 0x38, 0x28, 0x20, 0x70, 0x00, 0x38, 0x40, 0x40, 0x40, 0x5c, 0x48, 0x30, 0x00, + 0x76, 0x24, 0x24, 0x3c, 0x24, 0x24, 0x76, 0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, + 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x60, 0x74, 0x28, 0x30, 0x30, 0x28, 0x28, 0x6c, 0x00, + 0x70, 0x20, 0x20, 0x20, 0x20, 0x24, 0x7c, 0x00, 0x66, 0x3c, 0x3c, 0x3c, 0x34, 0x24, 0x66, 0x00, + 0x6e, 0x24, 0x34, 0x34, 0x2c, 0x24, 0x74, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, + 0x78, 0x24, 0x24, 0x38, 0x20, 0x20, 0x70, 0x00, 0x38, 0x44, 0x44, 0x44, 0x74, 0x4c, 0x38, 0x0c, + 0x78, 0x24, 0x38, 0x28, 0x24, 0x24, 0x76, 0x00, 0x1c, 0x24, 0x20, 0x18, 0x04, 0x24, 0x38, 0x00, + 0x7c, 0x54, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x66, 0x24, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00, + 0x6c, 0x28, 0x28, 0x28, 0x28, 0x10, 0x10, 0x00, 0x7e, 0x52, 0x52, 0x2c, 0x2c, 0x24, 0x24, 0x00, + 0x6c, 0x28, 0x28, 0x10, 0x28, 0x28, 0x6c, 0x00, 0x6c, 0x28, 0x28, 0x10, 0x10, 0x10, 0x38, 0x00, + 0x7c, 0x48, 0x10, 0x10, 0x20, 0x24, 0x7c, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, + 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x04, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, //']' + 0x10, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, + 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x38, 0x48, 0x3c, 0x00, //'a' + 0x60, 0x20, 0x38, 0x24, 0x24, 0x24, 0x38, 0x00, 0x00, 0x00, 0x1c, 0x24, 0x20, 0x20, 0x1c, 0x00, + 0x0c, 0x04, 0x1c, 0x24, 0x24, 0x24, 0x1e, 0x00, 0x00, 0x00, 0x18, 0x24, 0x3c, 0x20, 0x1c, 0x00, + 0x0c, 0x10, 0x3c, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x3c, 0x28, 0x38, 0x20, 0x3c, 0x3c, + 0x60, 0x20, 0x38, 0x24, 0x24, 0x24, 0x76, 0x00, 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00, + 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x38, 0x60, 0x20, 0x2c, 0x28, 0x30, 0x28, 0x6c, 0x00, + 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x78, 0x54, 0x54, 0x54, 0x54, 0x00, + 0x00, 0x00, 0x78, 0x24, 0x24, 0x24, 0x76, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, + 0x00, 0x00, 0x78, 0x24, 0x24, 0x24, 0x38, 0x70, 0x00, 0x00, 0x1c, 0x24, 0x24, 0x24, 0x1c, 0x0e, + 0x00, 0x00, 0x34, 0x18, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x3c, 0x20, 0x18, 0x04, 0x3c, 0x00, + 0x10, 0x10, 0x38, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x6c, 0x24, 0x24, 0x24, 0x1e, 0x00, + 0x00, 0x00, 0x6c, 0x28, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x6f, 0x2a, 0x2a, 0x36, 0x14, 0x00, + 0x00, 0x00, 0x7c, 0x28, 0x10, 0x28, 0x7c, 0x00, 0x00, 0x00, 0x7c, 0x28, 0x10, 0x10, 0x20, 0x60, + 0x00, 0x00, 0x3c, 0x08, 0x08, 0x10, 0x3c, 0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x10, 0x10, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x20, 0x10, 0x10, 0x08, 0x10, 0x10, 0x20, + 0x00, 0x00, 0x20, 0x54, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + +#endif //__FONT_DOT_H__ + diff --git a/sdk-modifications/libsrc/dma/dma.h b/sdk-modifications/libsrc/dma/dma.h new file mode 100644 index 0000000..f6ff230 --- /dev/null +++ b/sdk-modifications/libsrc/dma/dma.h @@ -0,0 +1,46 @@ +#ifndef __DMA_H__ +#define __DMA_H__ + +//register a DMA transfer request +//ch: channel id request, there are 6 channles, +//irq_handler: the DMA interruption handle +//arg: argument to the handle +//mode: DMA mode, such as port width, address increased/fixed, and so on +//type: DMA request type +extern int dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg, + unsigned int mode, unsigned int type); + +//start DMA transfer, must request a DMA first +//ch: channel id +//srcAddr: DMA source address +//dstAddr: DMA destination address +//count: DMA transfer count, the total bytes due the mode in dma_request +extern void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr, + unsigned int count); + +//Stop DMA transfer +extern void dma_stop(int ch); + +//Wait DMA transfer over +extern int dma_wait_finish(int ch); + + +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bytes. + * size is in bytes and must be a multiple of 32. + * Both src and dest must be aligned to 32 bytes. + * Returns 0 on failure, non-zero on success. + */ +extern int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size); +// Blocks of 16 bytes, aligned to 16 bytes +extern int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size); +// Blocks of 4 bytes, aligned to 4 bytes +extern int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size); +// Blocks of 2 bytes, aligned to 2 bytes +extern int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size); +extern int dma_isBusy(int ch); +extern int dma_isFree(int ch); +extern int dma_getFree(void); + +#endif //__DMA_H__ + diff --git a/sdk-modifications/libsrc/dma/dma.mk b/sdk-modifications/libsrc/dma/dma.mk new file mode 100644 index 0000000..0edf343 --- /dev/null +++ b/sdk-modifications/libsrc/dma/dma.mk @@ -0,0 +1,9 @@ +#dma.mk + +SRC += $(DMA_DIR)/dmacopy.c + +SSRC += + +INC += -I$(DMA_DIR) + +CFLAGS += \ No newline at end of file diff --git a/sdk-modifications/libsrc/dma/dmacopy.c b/sdk-modifications/libsrc/dma/dmacopy.c new file mode 100644 index 0000000..2c5a2b1 --- /dev/null +++ b/sdk-modifications/libsrc/dma/dmacopy.c @@ -0,0 +1,167 @@ +#include +#include "dma.h" +#include "ds2_types.h" + +#define MAX_DMA_NUM 6 /* max 6 channels */ + + +// DMA request source register +#define DMAC_DRSR_RS_BIT 0 +#define DMAC_DRSR_RS_MASK (0x2f << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_UART0OUT (20 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_UART0IN (21 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SSIOUT (22 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_SSIIN (23 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_AICOUT (24 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_AICIN (25 << DMAC_DRSR_RS_BIT) + #define DMAC_DRSR_RS_MSCOUT (26 << DMAC_DRSR_RS_BIT) //SD0 + #define DMAC_DRSR_RS_MSCIN (27 << DMAC_DRSR_RS_BIT) + + +// DMA channel command register +#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ +#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ +#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ +#define DMAC_DCMD_SWDH_MASK (0x03 << DMAC_DCMD_SWDH_BIT) + #define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) + #define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) + #define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) +#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ +#define DMAC_DCMD_DWDH_MASK (0x03 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) +#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ +#define DMAC_DCMD_DS_MASK (0x07 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) + #define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ +#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ + +#define DMAC_BASE 0xB3020000 +#define REG32(addr) *((volatile u32 *)(addr)) +#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ +#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) + +#define __dmac_channel_transmit_end_detected(n) \ + ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) + +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bytes. + * size is in bytes and must be a multiple of 32. + * Both src and dest must be aligned to 32 bytes. + * Returns 0 on failure, non-zero on success. + */ +int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size){ + int test = 0; + if(!(test = dma_request(ch, NULL, 0, + //increment dest addr, increment source addr + DMAC_DCMD_DAI | DMAC_DCMD_SAI | + //set src width 32 bytes, set dest width 32 bytes + DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | + //set copy mode to 32 bytes, copy in blocks + DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM, + //auto request type + DMAC_DRSR_RS_AUTO))) + { + dma_start(ch, (unsigned int)src, (unsigned int)dest, size); + } + return test; +} + +/* + +int sampleUsage(in ch, void *dest, void *src, unsigned int size){ + //channel 0 is used for mmc stuff, so its best to avoid using it + + //initialize and start copy + if(dma_copy32Byte(ch, dest, src, size)){ + dma_wait_finish(ch);//wait for copy to finish + dma_stop(ch);//must stop after transfer is done to reset channel + return 0; + } + return -1; +} + +*/ + +/* + * Copy 'size' bytes from src to dest, in blocks of 16 bytes. + * size is in bytes and must be a multiple of 16. + * Both src and dest must be aligned to 16 bytes. + * Returns 0 on failure, non-zero on success. + */ +int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size){ + int test = 0; + if(!(test = dma_request(ch, NULL, 0, + DMAC_DCMD_DAI | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_16 | + DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM, + DMAC_DRSR_RS_AUTO))) + { + dma_start(ch, (unsigned int)src, (unsigned int)dest, size); + } + + return test; +} + +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bits (4 bytes). + * size is in bytes and must be a multiple of 4. + * Both src and dest must be aligned to 32 bits (4 bytes). + * Returns 0 on failure, non-zero on success. + */ +int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size){ + int test = 0; + if(!(test = dma_request(ch, NULL, 0, + DMAC_DCMD_DAI | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | + DMAC_DCMD_DS_32BIT | DMAC_DCMD_TM, + DMAC_DRSR_RS_AUTO))) + { + dma_start(ch, (unsigned int)src, (unsigned int)dest, size); + } + + return test; +} + +/* + * Copy 'size' bytes from src to dest, in blocks of 16 bits (2 bytes). + * size is in bytes and must be a multiple of 2. + * Both src and dest must be aligned to 16 bits (2 bytes). + * Returns 0 on failure, non-zero on success. + */ +int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size){ + int test = 0; + + if(!(test = dma_request(ch, NULL, 0, + DMAC_DCMD_DAI | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | + DMAC_DCMD_DS_16BIT, + DMAC_DRSR_RS_AUTO))) + { + dma_start(ch, (unsigned int)src, (unsigned int)dest, size); + } + + return test; +} + + +//returns if a channel is still copying +int dma_isBusy(int ch){ + if(ch < 1 || ch >= MAX_DMA_NUM) + return 0; + + return !__dmac_channel_transmit_end_detected(ch); +} + +//returns the first non busy channel +int dma_getFree(void){ + int i; + for(i = 1; i < MAX_DMA_NUM; i++){ + if(!dma_isBusy(i)) + return i; + } + return -1; +} diff --git a/sdk-modifications/libsrc/fs/bit_ops.h b/sdk-modifications/libsrc/fs/bit_ops.h new file mode 100644 index 0000000..f823db7 --- /dev/null +++ b/sdk-modifications/libsrc/fs/bit_ops.h @@ -0,0 +1,58 @@ +/* + bit_ops.h + Functions for dealing with conversion of data between types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _BIT_OPS_H +#define _BIT_OPS_H + +/*----------------------------------------------------------------- +Functions to deal with little endian values stored in u8 arrays +-----------------------------------------------------------------*/ +static inline u16 u8array_to_u16 (const u8* item, int offset) { + return ( item[offset] | (item[offset + 1] << 8)); +} + +static inline u32 u8array_to_u32 (const u8* item, int offset) { + return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); +} + +static inline void u16_to_u8array (u8* item, int offset, u16 value) { + item[offset] = (u8)value; + item[offset + 1] = (u8)(value >> 8); +} + +static inline void u32_to_u8array (u8* item, int offset, u32 value) { + item[offset] = (u8)value; + item[offset + 1] = (u8)(value >> 8); + item[offset + 2] = (u8)(value >> 16); + item[offset + 3] = (u8)(value >> 24); +} + +#endif // _BIT_OPS_H diff --git a/sdk-modifications/libsrc/fs/cache.c b/sdk-modifications/libsrc/fs/cache.c new file mode 100644 index 0000000..2c66e1f --- /dev/null +++ b/sdk-modifications/libsrc/fs/cache.c @@ -0,0 +1,273 @@ +/* + cache.c + The cache is not visible to the user. It should be flushed + when any file is closed or changes are made to the filesystem. + + This cache implements a least-used-page replacement policy. This will + distribute sectors evenly over the pages, so if less than the maximum + pages are used at once, they should all eventually remain in the cache. + This also has the benefit of throwing out old sectors, so as not to keep + too many stale pages around. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "fs_common.h" +#include "fs_cache.h" +#include "disc_io/disc.h" + +#include "mem_allocate.h" + +#define CACHE_FREE 0xFFFFFFFF + +CACHE* _FAT_cache_constructor (u32 numberOfPages, const IO_INTERFACE* discInterface) { + CACHE* cache; + u32 i; + CACHE_ENTRY* cacheEntries; + + if (numberOfPages < 2) { + numberOfPages = 2; + } + + cache = (CACHE*) _FAT_mem_allocate (sizeof(CACHE)); + if (cache == NULL) { + return NULL; + } + + cache->disc = discInterface; + cache->numberOfPages = numberOfPages; + + + cacheEntries = (CACHE_ENTRY*) _FAT_mem_allocate ( sizeof(CACHE_ENTRY) * numberOfPages); + if (cacheEntries == NULL) { + _FAT_mem_free (cache); + return NULL; + } + + for (i = 0; i < numberOfPages; i++) { + cacheEntries[i].sector = CACHE_FREE; + cacheEntries[i].count = 0; + cacheEntries[i].dirty = 0; + } + + cache->cacheEntries = cacheEntries; + + cache->pages = (u8*) _FAT_mem_allocate ( CACHE_PAGE_SIZE * numberOfPages); + if (cache->pages == NULL) { + _FAT_mem_free (cache->cacheEntries); + _FAT_mem_free (cache); + return NULL; + } + + return cache; +} + +void _FAT_cache_destructor (CACHE* cache) { + // Clear out cache before destroying it + _FAT_cache_flush(cache); + + // Free memory in reverse allocation order + _FAT_mem_free (cache->pages); + _FAT_mem_free (cache->cacheEntries); + _FAT_mem_free (cache); + + return; +} + +/* +Retrieve a sector's page from the cache. If it is not found in the cache, +load it into the cache and return the page it was loaded to. +Return CACHE_FREE on error. +*/ +static u32 _FAT_cache_getSector (CACHE* cache, u32 sector) { + u32 i; + CACHE_ENTRY* cacheEntries = cache->cacheEntries; + u32 numberOfPages = cache->numberOfPages; + + u32 leastUsed = 0; + u32 lowestCount = 0xFFFFFFFF; + + for (i = 0; (i < numberOfPages) && (cacheEntries[i].sector != sector); i++) { + // While searching for the desired sector, also search for the leased used page + if ( (cacheEntries[i].sector == CACHE_FREE) || (cacheEntries[i].count < lowestCount) ) { + leastUsed = i; + lowestCount = cacheEntries[i].count; + } + } + + // If it found the sector in the cache, return it + if ((i < numberOfPages) && (cacheEntries[i].sector == sector)) { + // Increment usage counter + cacheEntries[i].count += 1; + return i; + } + + // If it didn't, replace the least used cache page with the desired sector + if ((cacheEntries[leastUsed].sector != CACHE_FREE) && (0xC33CA55A == cacheEntries[leastUsed].dirty)) { + // Write the page back to disc if it has been written to + if (!_FAT_disc_writeSectors (cache->disc, cacheEntries[leastUsed].sector, 1, cache->pages + CACHE_PAGE_SIZE * leastUsed)) { + return CACHE_FREE; + } + cacheEntries[leastUsed].dirty = 0; + } + + // Load the new sector into the cache + if (!_FAT_disc_readSectors (cache->disc, sector, 1, cache->pages + CACHE_PAGE_SIZE * leastUsed)) { + return CACHE_FREE; + } + cacheEntries[leastUsed].sector = sector; + // Increment the usage count, don't reset it + // This creates a paging policy of least used PAGE, not sector + cacheEntries[leastUsed].count += 1; + return leastUsed; +} + +/* +Reads some data from a cache page, determined by the sector number +*/ +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, u32 sector, u32 offset, u32 size) { + u32 page; + + if (offset + size > BYTES_PER_READ) { + return false; + } + + page = _FAT_cache_getSector (cache, sector); + if (page == CACHE_FREE) { + return false; + } + + memcpy (buffer, cache->pages + (CACHE_PAGE_SIZE * page) + offset, size); + return true; +} + +/* +Writes some data to a cache page, making sure it is loaded into memory first. +*/ +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size) { + u32 page; + + if (offset + size > BYTES_PER_READ) { + return false; + } + + page = _FAT_cache_getSector (cache, sector); + if (page == CACHE_FREE) { + return false; + } + + memcpy (cache->pages + (CACHE_PAGE_SIZE * page) + offset, buffer, size); + cache->cacheEntries[page].dirty = 0xC33CA55A; + + return true; +} + +/* +some where call _FAT_cache_writePartialSector to cache sector m , but later, another +place(in fwrite function) directly write data to sector m, in this case, need to +cancel the dirty state of sector m +*/ +void _FAT_cache_writePartialSector_check (CACHE* cache, u32 sector, u32 num, const void* buffer) +{ + u32 i, m; + CACHE_ENTRY* cacheEntries = cache->cacheEntries; + u32 numberOfPages = cache->numberOfPages; + + m = 0; + while(m++ < num) + { + for (i = 0; i < numberOfPages; i++) + { + if(cacheEntries[i].sector == sector) + break; + } + + if(i >= numberOfPages) + return; + + //cache the data + memcpy (cache->pages + (CACHE_PAGE_SIZE * i), buffer, CACHE_PAGE_SIZE); + //cancel the dirty state + cache->cacheEntries[i].dirty = 0; + + sector += 1; + buffer += CACHE_PAGE_SIZE; + } +} + +/* +Writes some data to a cache page, zeroing out the page first +*/ +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size) { + u32 page; + + if (offset + size > BYTES_PER_READ) { + return false; + } + + page = _FAT_cache_getSector (cache, sector); + if (page == CACHE_FREE) { + return false; + } + + memset (cache->pages + (CACHE_PAGE_SIZE * page), 0, CACHE_PAGE_SIZE); + memcpy (cache->pages + (CACHE_PAGE_SIZE * page) + offset, buffer, size); + cache->cacheEntries[page].dirty = 0xC33CA55A; + + return true; +} + + +/* +Flushes all dirty pages to disc, clearing the dirty flag. +Also resets all pages' page count to 0. +*/ +bool _FAT_cache_flush (CACHE* cache) { + u32 i; + + for (i = 0; i < cache->numberOfPages; i++) { + if (0xC33CA55A == cache->cacheEntries[i].dirty) { + if (!_FAT_disc_writeSectors (cache->disc, cache->cacheEntries[i].sector, 1, cache->pages + CACHE_PAGE_SIZE * i)) { + return CACHE_FREE; + } + } + cache->cacheEntries[i].count = 0; + cache->cacheEntries[i].dirty = 0; + } + + _FAT_disc_clearStatus( cache->disc ); + return true; +} + +void _FAT_cache_invalidate (CACHE* cache) { + int i; + for (i = 0; i < cache->numberOfPages; i++) { + cache->cacheEntries[i].sector = CACHE_FREE; + cache->cacheEntries[i].count = 0; + cache->cacheEntries[i].dirty = 0; + } +} + diff --git a/sdk-modifications/libsrc/fs/directory.c b/sdk-modifications/libsrc/fs/directory.c new file mode 100644 index 0000000..b30cccc --- /dev/null +++ b/sdk-modifications/libsrc/fs/directory.c @@ -0,0 +1,1005 @@ +/* + directory.c + Reading, writing and manipulation of the directory structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-08-14 - Chishm + * entryFromPath correctly finds "" and "." now + + 2006-08-17 - Chishm + * entryFromPath doesn't look for "" anymore - use "." to refer to the current directory + + 2006-08-19 - Chishm + * Fixed entryFromPath bug when looking for "." in root directory + + 2006-10-01 - Chishm + * Now clears the whole new cluster when linking in more clusters for a directory + + 2006-10-28 - Chishm + * stat returns the hostType for the st_dev value +*/ +//version 1.1 +//Note: fix bug in _FAT_directory_isValidAlias() + +#include +#include + +#include "directory.h" +#include "fs_common.h" +#include "partition.h" +#include "file_allocation_table.h" +#include "bit_ops.h" +#include "filetime.h" +#include "fs_unicode.h" + +// Directory entry codes +#define DIR_ENTRY_LAST 0x00 +#define DIR_ENTRY_FREE 0xE5 + + +// Long file name directory entry +enum LFN_offset { + LFN_offset_ordinal = 0x00, // Position within LFN + LFN_offset_char0 = 0x01, + LFN_offset_char1 = 0x03, + LFN_offset_char2 = 0x05, + LFN_offset_char3 = 0x07, + LFN_offset_char4 = 0x09, + LFN_offset_flag = 0x0B, // Should be equal to ATTRIB_LFN + LFN_offset_reserved1 = 0x0C, // Always 0x00 + LFN_offset_checkSum = 0x0D, // Checksum of short file name (alias) + LFN_offset_char5 = 0x0E, + LFN_offset_char6 = 0x10, + LFN_offset_char7 = 0x12, + LFN_offset_char8 = 0x14, + LFN_offset_char9 = 0x16, + LFN_offset_char10 = 0x18, + LFN_offset_reserved2 = 0x1A, // Always 0x0000 + LFN_offset_char11 = 0x1C, + LFN_offset_char12 = 0x1E +}; +const int LFN_offset_table[13]={0x01,0x03,0x05,0x07,0x09,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E}; + +#define LFN_END 0x40 +#define LFN_DEL 0x80 + +static char* strupr(char* a) +{ + char *str; + + str = a; + while(*str) + { + if(*str >= 'a' && *str <= 'z') *str -= 0x20; + str += 1; + } + + return a; +} + +static char* strlwr(char *a){ + char *str; + + str = a; + while(*str) + { + if((*str) >= 'A' && (*str) <= 'Z') (*str) = ((*str) -'A' + 'a'); + str++; + } + return a; +} + +bool _FAT_directory_isValidLfn (const char* name) { + u32 i; + u32 nameLength; + // Make sure the name is short enough to be valid + if ( strnlen(name, MAX_FILENAME_LENGTH) >= MAX_FILENAME_LENGTH) { + return false; + } + // Make sure it doesn't contain any invalid characters + if (strpbrk (name, "\\/:*?\"<>|") != NULL) { + return false; + } + + nameLength = strnlen(name, MAX_FILENAME_LENGTH); + // Make sure the name doesn't contain any control codes + for (i = 0; i < nameLength; i++) { + if ((unsigned char)name[i] < 0x20) { + return false; + } + } + // Otherwise it is valid + return true; +} +bool _FAT_directory_isValidAlias (const char* name) { + return false;//disables this function to preserve file name casing + + u32 i; + u32 nameLength; + const char* dot; + + // Make sure the name is short enough to be valid + if ( strnlen(name, MAX_ALIAS_LENGTH) >= MAX_ALIAS_LENGTH) { + return false; + } + // Make sure it doesn't contain any invalid characters + if (strpbrk (name, "\\/:;*?\"<>|&+,=[]") != NULL) { + return false; + } + + // + if (strpbrk (name, " ") != NULL) { + return false; + } + + nameLength = strnlen(name, MAX_ALIAS_LENGTH); + // Make sure the name doesn't contain any control codes + //if name isn't all capitals, then it is not a valid short name + for (i = 0; i < nameLength; i++) { + if (name[i] < 0x5A && name[i]!=0x20) { + return false; + } + } + + dot = strchr ( name, '.'); + // Make sure there is only one '.' + if ((dot != NULL) && (strrchr ( name, '.') != dot)) { + return false; + } + // If there is a '.': + if (dot != NULL) { + // Make sure the filename portion is 1-8 characters long + if (((dot - 1 - name) > 8) || ((dot - 1 - name) < 1)) { + return false; + } + // Make sure the extension is 1-3 characters long, if it exists + if ((strnlen(dot + 1, MAX_ALIAS_LENGTH) > 3) || (strnlen(dot + 1, MAX_ALIAS_LENGTH) < 1)) { + return false; + } + } else { + // Make sure the entire file name is 1-8 characters long + if ((nameLength > 8) || (nameLength < 1)) { + return false; + } + } + + // Since we made it through all those tests, it must be valid + return true; +} + +static bool _FAT_directory_entryGetAlias (const u8* entryData, char* destName) { + int i=0; + int j=0; + + destName[0] = '\0'; + if (entryData[0] != DIR_ENTRY_FREE) { + if (entryData[0] == '.') { + destName[0] = '.'; + if (entryData[1] == '.') { + destName[1] = '.'; + destName[2] = '\0'; + } else { + destName[1] = '\0'; + } + } else { + // Copy the filename from the dirEntry to the string + for (i = 0; (i < 8) && (entryData[DIR_ENTRY_name + i] != ' '); i++) { + destName[i] = entryData[DIR_ENTRY_name + i]; + } + // Copy the extension from the dirEntry to the string + if (entryData[DIR_ENTRY_extension] != ' ') { + destName[i++] = '.'; + for ( j = 0; (j < 3) && (entryData[DIR_ENTRY_extension + j] != ' '); j++) { + destName[i++] = entryData[DIR_ENTRY_extension + j]; + } + } + destName[i] = '\0'; + } + } + + return (destName[0] != '\0'); +} + +u32 _FAT_directory_entryGetCluster (const u8* entryData) { + return u8array_to_u16(entryData,DIR_ENTRY_cluster) | (u8array_to_u16(entryData, DIR_ENTRY_clusterHigh) << 16); +} + +static bool _FAT_directory_incrementDirEntryPosition (PARTITION* partition, DIR_ENTRY_POSITION* entryPosition, bool extendDirectory) { + DIR_ENTRY_POSITION position; + position = *entryPosition; + u32 tempCluster; + + // Increment offset, wrapping at the end of a sector + ++ position.offset; + if (position.offset == BYTES_PER_READ / DIR_ENTRY_DATA_SIZE) { + position.offset = 0; + // Increment sector when wrapping + ++ position.sector; + // But wrap at the end of a cluster + if ((position.sector == partition->sectorsPerCluster) && (position.cluster != FAT16_ROOT_DIR_CLUSTER)) { + position.sector = 0; + // Move onto the next cluster, making sure there is another cluster to go to + tempCluster = _FAT_fat_nextCluster(partition, position.cluster); + if (tempCluster == CLUSTER_EOF) { + if (extendDirectory) { + tempCluster = _FAT_fat_linkFreeClusterCleared (partition, position.cluster); + if (tempCluster == CLUSTER_FREE) { + return false; // This will only happen if the disc is full + } + } else { + return false; // Got to the end of the directory, not extending it + } + } + position.cluster = tempCluster; + } else if ((position.cluster == FAT16_ROOT_DIR_CLUSTER) && (position.sector == (partition->dataStart - partition->rootDirStart))) { + return false; // Got to end of root directory, can't extend it + } + } + *entryPosition = position; + return true; +} + +bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) { + DIR_ENTRY_POSITION entryStart; + DIR_ENTRY_POSITION entryEnd; + + u8 entryData[0x20]; + + bool notFound, found; + u32 maxSectors; + int lfnPos; + u8 lfnChkSum, chkSum; + char* filename; + u16 unicodeFilename[256]; + bool lfnExists; + + int i; + + lfnChkSum = 0; + + entryStart = entry->dataEnd; + + // Make sure we are using the correct root directory, in case of FAT32 + if (entryStart.cluster == FAT16_ROOT_DIR_CLUSTER) { + entryStart.cluster = partition->rootDirCluster; + } + + entryEnd = entryStart; + filename = entry->d_name; + //unicodeFilename = entry->unicodeFilename; + memset( unicodeFilename, 0, 512 ); + + // Can only be FAT16_ROOT_DIR_CLUSTER if it is the root directory on a FAT12 or FAT16 partition + if (entryStart.cluster == FAT16_ROOT_DIR_CLUSTER) { + maxSectors = partition->dataStart - partition->rootDirStart; + } else { + maxSectors = partition->sectorsPerCluster; + } + + lfnExists = false; + + found = false; + notFound = false; + + while (!found && !notFound) { + if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) { + notFound = true; + } + + _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + if (entryData[DIR_ENTRY_attributes] == ATTRIB_LFN) { + // It's an LFN + if (entryData[LFN_offset_ordinal] & LFN_DEL) { + lfnExists = false; + } else if (entryData[LFN_offset_ordinal] & LFN_END) { + // Last part of LFN, make sure it isn't deleted using previous if(Thanks MoonLight) + entryStart = entryEnd; // This is the start of a directory entry + lfnExists = true; + //filename[(entryData[LFN_offset_ordinal] & ~LFN_END) * 13] = '\0'; // Set end of lfn to null character + unicodeFilename[(entryData[LFN_offset_ordinal] & ~LFN_END) * 13] = 0x0000; + lfnChkSum = entryData[LFN_offset_checkSum]; + } if (lfnChkSum != entryData[LFN_offset_checkSum]) { + lfnExists = false; + } + //unicodeFilename[0] = 0x0000; + if (lfnExists) { + lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; + for (i = 0; i < 13; i++) { + unicodeFilename[lfnPos + i] = u8array_to_u16( entryData, LFN_offset_table[i]); + // | entryData[LFN_offset_table[i]+1]<<8; // modify this for unicode support; + } + } + } else if (entryData[DIR_ENTRY_attributes] & ATTRIB_VOL) { + // This is a volume name, don't bother with it + } else if (entryData[0] == DIR_ENTRY_LAST) { + notFound = true; + } else if ((entryData[0] != DIR_ENTRY_FREE) && (entryData[0] > 0x20) && !(entryData[DIR_ENTRY_attributes] & ATTRIB_VOL)) { + if (lfnExists) { + // Calculate file checksum + chkSum = 0; + for (i=0; i < 11; i++) { + // NOTE: The operation is an unsigned char rotate right + chkSum = ((chkSum & 1) ? 0x80 : 0) + (chkSum >> 1) + entryData[i]; + } + if (chkSum != lfnChkSum) { + lfnExists = false; + //filename[0] = '\0'; + //unicodeFilename[0] = 0x0000; // move this line to below(1) + } + } + //short name + if (!lfnExists) { + entryStart = entryEnd; + unicodeFilename[0] = 0x0000; // (1)make sure clear previous search junk + // get alias anyway + _FAT_directory_entryGetAlias (entryData, filename); + strlwr(filename);//convert to lowercase characters + } + //long name + else + { + _FAT_unicode16_to_utf8 (unicodeFilename, filename); + } + + found = true; + } + } + + // If no file is found, return false + if (notFound) { + return false; + } else { + // Fill in the directory entry struct + entry->dataStart = entryStart; + entry->dataEnd = entryEnd; + memcpy (entry->entryData, entryData, DIR_ENTRY_DATA_SIZE); + return true; + } +} + +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster) { + entry->dataStart.cluster = dirCluster; + entry->dataStart.sector = 0; + entry->dataStart.offset = -1; // Start before the beginning of the directory + + entry->dataEnd = entry->dataStart; + + return _FAT_directory_getNextEntry (partition, entry); +} + +bool _FAT_directory_getRootEntry (PARTITION* partition, DIR_ENTRY* entry) { + entry->dataStart.cluster = 0; + entry->dataStart.sector = 0; + entry->dataStart.offset = 0; + + entry->dataEnd = entry->dataStart; + + memset (entry->d_name, '\0', MAX_FILENAME_LENGTH); + entry->d_name[0] = '.'; + + memset (entry->entryData, 0, DIR_ENTRY_DATA_SIZE); + memset (entry->entryData, ' ', 11); + entry->entryData[0] = '.'; + + entry->entryData[DIR_ENTRY_attributes] = ATTRIB_DIR; + + u16_to_u8array (entry->entryData, DIR_ENTRY_cluster, partition->rootDirCluster); + u16_to_u8array (entry->entryData, DIR_ENTRY_clusterHigh, partition->rootDirCluster >> 16); + + return true; +} + +bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) { + DIR_ENTRY_POSITION entryStart; + DIR_ENTRY_POSITION entryEnd; + entryStart = entry->dataStart; + entryEnd = entry->dataEnd; + bool entryStillValid; + bool finished; + + int i; + int lfnPos; + + u8 entryData[DIR_ENTRY_DATA_SIZE]; + + memset (entry->d_name, '\0', MAX_FILENAME_LENGTH); + + // Create an empty directory entry to overwrite the old ones with + for ( entryStillValid = true, finished = false; + entryStillValid && !finished; + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &entryStart, false)) + { + _FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, + entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + if ((entryStart.cluster == entryEnd.cluster) + && (entryStart.sector == entryEnd.sector) + && (entryStart.offset == entryEnd.offset)) { + // Copy the entry data and stop, since this is the last section of the directory entry + memcpy (entry->entryData, entryData, DIR_ENTRY_DATA_SIZE); + finished = true; + } else { + // Copy the long file name data + lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; + for (i = 0; i < 13; i++) { + entry->d_name[lfnPos + i] = entryData[LFN_offset_table[i]]; // modify this for unicode support; + } + } + } + + if (!entryStillValid) { + return false; + } + + if ((entryStart.cluster == entryEnd.cluster) + && (entryStart.sector == entryEnd.sector) + && (entryStart.offset == entryEnd.offset)) { + // Since the entry doesn't have a long file name, extract the short filename + if (!_FAT_directory_entryGetAlias (entry->entryData, entry->d_name)) { + return false; + } + } + + return true; +} + +bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd) { + size_t dirnameLength; + const char* pathPosition; + const char* nextPathPosition; + + //size_t uniDirnameLength; + //u16 uniPath[MAX_FILENAME_LENGTH]; + //const u16 * uniPathPosition; + //const u16 * uniNextPathPosition; + + u32 dirCluster; + bool foundFile; + + //char alias[MAX_ALIAS_LENGTH]; + + bool found, notFound; + + //_FAT_utf8_to_unicode16( path, uniPath ); + pathPosition = path; + //uniPathPosition = uniPath; + + found = false; + notFound = false; + + if (pathEnd == NULL) { + // Set pathEnd to the end of the path string + pathEnd = strchr (path, '\0'); + } + + if (pathPosition[0] == DIR_SEPARATOR) { + // Start at root directory + dirCluster = partition->rootDirCluster; + // Consume separator(s) + while (pathPosition[0] == DIR_SEPARATOR) { + pathPosition++; + } + + //while (uniPathPosition[0] == (unsigned short)DIR_SEPARATOR) { + // uniPathPosition++; + //} + + if (pathPosition >= pathEnd) { + _FAT_directory_getRootEntry (partition, entry); + found = true; + } + } else { + // Start in current working directory + dirCluster = partition->cwdCluster; + } + + // If the path is only specifying a directory in the form "." + // and this is the root directory, return it + //if ((dirCluster == partition->rootDirCluster) && (strncasecmp(".", pathPosition, 2) == 0)) { + if ((dirCluster == partition->rootDirCluster) && strlen(pathPosition) == 1 && (strcasecmp(".", pathPosition) == 0)) { + _FAT_directory_getRootEntry (partition, entry); + found = true; + } + + while (!found && !notFound) { + // Get the name of the next required subdirectory within the path + nextPathPosition = strchr (pathPosition, DIR_SEPARATOR); + //uniNextPathPosition = _unistrchr( uniPathPosition, (unsigned short)DIR_SEPARATOR ); + if (nextPathPosition != NULL) { + dirnameLength = nextPathPosition - pathPosition; + } else { + dirnameLength = strlen(pathPosition); + } + //if (uniNextPathPosition != 0x0000) { + // uniDirnameLength = uniNextPathPosition - uniPathPosition; + //} else { + // uniDirnameLength = _unistrnlen(uniPathPosition, MAX_FILENAME_LENGTH); + //} + + if (dirnameLength > MAX_FILENAME_LENGTH) { + // The path is too long to bother with + return false; + } + //if( uniDirnameLength > MAX_FILENAME_LENGTH ) { + // return false; + //} + + // Look for the directory within the path + foundFile = _FAT_directory_getFirstEntry (partition, entry, dirCluster); + + while (foundFile && !found && !notFound) { // It hasn't already found the file + // Check if the filename matches + //if ((uniDirnameLength == _unistrnlen(entry->unicodeFilename, MAX_FILENAME_LENGTH)) + // && (_unistrncmp(entry->unicodeFilename, uniPathPosition, uniDirnameLength) == 0)) { + // found = true; + //} + + //if(!strncasecmp(entry->d_name, pathPosition, dirnameLength)) + if(strlen(entry->d_name) == dirnameLength && !strncasecmp(entry->d_name, pathPosition, dirnameLength)) + found = true; + + // Check if the alias matches + //_FAT_directory_entryGetAlias (entry->entryData, alias); + //if ((dirnameLength == strnlen(alias, MAX_ALIAS_LENGTH)) + // && (strncasecmp(alias, pathPosition, dirnameLength) == 0)) { + // found = true; + //} + + if (found && !(entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) && (nextPathPosition != NULL)) { + // Make sure that we aren't trying to follow a file instead of a directory in the path + found = false; + } + + if (!found) { + foundFile = _FAT_directory_getNextEntry (partition, entry); + } + } + + if (!foundFile) { + // Check that the search didn't get to the end of the directory + notFound = true; + found = false; + } else if ((nextPathPosition == NULL) || (nextPathPosition >= pathEnd)) { + // Check that we reached the end of the path + found = true; + } else if (entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) { + dirCluster = _FAT_directory_entryGetCluster (entry->entryData); + pathPosition = nextPathPosition; + //uniPathPosition = uniNextPathPosition; + // Consume separator(s) + while (pathPosition[0] == DIR_SEPARATOR) { + pathPosition++; + } + //while (uniPathPosition[0] == (unsigned short)DIR_SEPARATOR) { + // uniPathPosition++; + //} + // The requested directory was found + if (pathPosition >= pathEnd) { + found = true; + } else { + found = false; + } + } + } + + if (found && !notFound) { + return true; + } else { + return false; + } +} + +bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry) { + DIR_ENTRY_POSITION entryStart; + DIR_ENTRY_POSITION entryEnd; + entryStart = entry->dataStart; + entryEnd = entry->dataEnd; + bool entryStillValid; + bool finished; + + u8 entryData[DIR_ENTRY_DATA_SIZE]; + + // Create an empty directory entry to overwrite the old ones with + for ( entryStillValid = true, finished = false; + entryStillValid && !finished; + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &entryStart, false)) + { + _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + entryData[0] = DIR_ENTRY_FREE; + _FAT_cache_writePartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + if ((entryStart.cluster == entryEnd.cluster) && (entryStart.sector == entryEnd.sector) && (entryStart.offset == entryEnd.offset)) { + finished = true; + } + } + + if (!entryStillValid) { + return false; + } + + return true; +} + +static bool _FAT_directory_findEntryGap (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster, u32 size) { + DIR_ENTRY_POSITION gapStart; + DIR_ENTRY_POSITION gapEnd; + + u8 entryData[DIR_ENTRY_DATA_SIZE]; + + u32 dirEntryRemain; + + bool endOfDirectory, entryStillValid; + + // Scan Dir for free entry + gapEnd.offset = 0; + gapEnd.sector = 0; + gapEnd.cluster = dirCluster; + + gapStart = gapEnd; + + entryStillValid = true; + dirEntryRemain = size; + endOfDirectory = false; + + while (entryStillValid && !endOfDirectory && (dirEntryRemain > 0)) { + _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector, gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + if (entryData[0] == DIR_ENTRY_LAST) { + gapStart = gapEnd; + -- dirEntryRemain; + endOfDirectory = true; + } else if (entryData[0] == DIR_ENTRY_FREE) { + if (dirEntryRemain == size) { + gapStart = gapEnd; + } + -- dirEntryRemain; + } else { + dirEntryRemain = size; + } + + if (!endOfDirectory && (dirEntryRemain > 0)) { + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &gapEnd, true); + } + } + + // Make sure the scanning didn't fail + if (!entryStillValid) { + return false; + } + + // Save the start entry, since we know it is valid + entry->dataStart = gapStart; + + if (endOfDirectory) { + memset (entryData, DIR_ENTRY_LAST, DIR_ENTRY_DATA_SIZE); + dirEntryRemain += 1; // Increase by one to take account of End Of Directory Marker + while ((dirEntryRemain > 0) && entryStillValid) { + // Get the gapEnd before incrementing it, so the second to last one is saved + entry->dataEnd = gapEnd; + // Increment gapEnd, moving onto the next entry + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &gapEnd, true); + -- dirEntryRemain; + // Fill the entry with blanks + _FAT_cache_writePartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector, gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + } + if (!entryStillValid) { + return false; + } + } else { + entry->dataEnd = gapEnd; + } + + return true; +} + +static bool _FAT_directory_entryExists (PARTITION* partition, const char* name, u32 dirCluster) { + DIR_ENTRY tempEntry; + bool foundFile; + //char alias[MAX_ALIAS_LENGTH]; + u32 dirnameLength; + //u16 unicodeName[MAX_FILENAME_LENGTH]; + + dirnameLength = strnlen(name, MAX_FILENAME_LENGTH); + + if (dirnameLength >= MAX_FILENAME_LENGTH) { + return false; + } + + //_FAT_utf8_to_unicode16( name, unicodeName ); + + // Make sure the entry doesn't already exist + foundFile = _FAT_directory_getFirstEntry (partition, &tempEntry, dirCluster); + + while (foundFile) { // It hasn't already found the file + // Check if the filename matches + //if (/*(dirnameLength == _unistrnlen(tempEntry.unicodeFilename, MAX_FILENAME_LENGTH))*/ + // //&& (strcasecmp(tempEntry.filename, name) == 0)) { + // /*&&*/ (_unistrncmp( unicodeName, tempEntry.unicodeFilename, MAX_FILENAME_LENGTH ) == 0 )) + //{ + // return true; + //} + //if(!strncasecmp(name, tempEntry.d_name, dirnameLength)) + if(!strcasecmp(name, tempEntry.d_name)) + return true; + + // Check if the alias matches + //_FAT_directory_entryGetAlias (tempEntry.entryData, alias); + //if ((dirnameLength == strnlen(alias, MAX_ALIAS_LENGTH)) + // && (strcasecmp(alias, name) == 0)) { + // return true; + //} + foundFile = _FAT_directory_getNextEntry (partition, &tempEntry); + } + return false; +} + + + +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster) { + u32 entrySize; + u8 lfnEntry[DIR_ENTRY_DATA_SIZE]; + s32 i,j; // Must be signed for use when decrementing in for loop + char *tmpCharPtr; + DIR_ENTRY_POSITION curEntryPos; + bool entryStillValid; + u8 aliasCheckSum = 0; + char alias [MAX_ALIAS_LENGTH]; + u16 unicodeFilename[256]; + + // Make sure the filename is not 0 length + if (strnlen (entry->d_name, MAX_FILENAME_LENGTH) < 1) { + return false; + } + // Make sure the filename is at least a valid LFN + if ( !(_FAT_directory_isValidLfn (entry->d_name))) { + return false; + } + + // Remove trailing spaces + for (i = strlen (entry->d_name) - 1; (i > 0) && (entry->d_name[i] == ' '); --i) { + entry->d_name[i] = '\0'; + } + // Remove leading spaces + for (i = 0; (i < strlen (entry->d_name)) && (entry->d_name[i] == ' '); ++i) ; + if (i > 0) { + memmove (entry->d_name, entry->d_name + i, strlen (entry->d_name + i)); + } + + // Remove junk in filename + i = strlen (entry->d_name); + memset (entry->d_name + i, '\0', MAX_FILENAME_LENGTH - i); + + // Make sure the entry doesn't already exist + if (_FAT_directory_entryExists (partition, entry->d_name, dirCluster)) { + return false; + } + + // Clear out alias, so we can generate a new one + memset (entry->entryData, ' ', 11); + + if ( strncmp(entry->d_name, ".", MAX_FILENAME_LENGTH) == 0) { + // "." entry + entry->entryData[0] = '.'; + entrySize = 1; + } else if ( strncmp(entry->d_name, "..", MAX_FILENAME_LENGTH) == 0) { + // ".." entry + entry->entryData[0] = '.'; + entry->entryData[1] = '.'; + entrySize = 1; + }else if (_FAT_directory_isValidAlias (entry->d_name)) { + entrySize = 1; + // Copy into alias + for (i = 0, j = 0; (j < 8) && (entry->d_name[i] != '.') && (entry->d_name[i] != '\0'); i++, j++) { + entry->entryData[j] = entry->d_name[i]; + } + while (j < 8) { + entry->entryData[j] = ' '; + ++ j; + } + if (entry->d_name[i] == '.') { + // Copy extension + ++ i; + while ((entry->d_name[i] != '\0') && (j < 11)) { + entry->entryData[j] = entry->d_name[i]; + ++ i; + ++ j; + } + } + while (j < 11) { + entry->entryData[j] = ' '; + ++ j; + } + // Short filename + strupr (entry->d_name); + }else { + // Long filename needed + //memset( entry->unicodeFilename, 0, 512 ); + //_FAT_utf8_to_unicode16( (const char*)entry->d_name, entry->unicodeFilename ); + memset( unicodeFilename, 0, 512 ); + _FAT_utf8_to_unicode16( (const char*)entry->d_name, unicodeFilename ); + + //entrySize = ((strnlen (entry->filename, MAX_FILENAME_LENGTH) + LFN_ENTRY_LENGTH - 1) / LFN_ENTRY_LENGTH) + 1; + //entrySize = ((_unistrnlen( entry->unicodeFilename, MAX_FILENAME_LENGTH ) + LFN_ENTRY_LENGTH - 1) / LFN_ENTRY_LENGTH) + 1; + entrySize = ((_unistrnlen( unicodeFilename, MAX_FILENAME_LENGTH ) + LFN_ENTRY_LENGTH - 1) / LFN_ENTRY_LENGTH) + 1; + + // Generate alias + tmpCharPtr = strrchr (entry->d_name, '.'); + if (tmpCharPtr == NULL) { + tmpCharPtr = strrchr (entry->d_name, '\0'); + } + for (i = 0, j = 0; (j < 6) && (entry->d_name + i < tmpCharPtr); i++) { + if ( _uniisalnum((u8)(entry->d_name[i]))) { + alias[j] = entry->d_name[i]; + ++ j; + } + } + while (j < 8) { + alias[j] = '_'; + ++ j; + } + tmpCharPtr = strrchr (entry->d_name, '.'); + if (tmpCharPtr != NULL) { + alias[8] = '.'; + // Copy extension + while ((tmpCharPtr != '\0') && (j < 12)) { + alias[j] = tmpCharPtr[0]; + ++ tmpCharPtr; + ++ j; + } + alias[j] = '\0'; + } else { + for (j = 8; j < MAX_ALIAS_LENGTH; j++) { + alias[j] = '\0'; + } + } + + // Get a valid tail number + alias[5] = '~'; + i = 0; + do { + i++; + alias[6] = '0' + ((i / 10) % 10); // 10's digit + alias[7] = '0' + (i % 10); // 1's digit + } while (_FAT_directory_entryExists (partition, alias, dirCluster) && (i < 100)); + if (i == 100) { + // Couldn't get a tail number + return false; + } + + // Make it upper case + strupr (alias); + + // Now copy it into the directory entry data + memcpy (entry->entryData, alias, 8); + memcpy (entry->entryData + 8, alias + 9, 3); + for (i = 0; i < 10; i++) { + if (entry->entryData[i] < 0x20) { + // Replace null and control characters with spaces + entry->entryData[i] = 0x20; + } + } + // Generate alias checksum + for (i=0; i < 11; i++) + { + // NOTE: The operation is an unsigned char rotate right + aliasCheckSum = ((aliasCheckSum & 1) ? 0x80 : 0) + (aliasCheckSum >> 1) + entry->entryData[i]; + } + + } + + // Find or create space for the entry + if (_FAT_directory_findEntryGap (partition, entry, dirCluster, entrySize) == false) { + return false; + } + + // Write out directory entry + curEntryPos = entry->dataStart; + + for (entryStillValid = true, i = entrySize; entryStillValid && i > 0; + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &curEntryPos, false), -- i ) + { + if (i > 1) { + // Long filename entry + lfnEntry[LFN_offset_ordinal] = (i - 1) | (i == entrySize ? LFN_END : 0); + for (j = 0; j < 13; j++) { + //if (entry->unicodeFilename[(i - 2) * 13 + j] == '\0') { + if (unicodeFilename[(i - 2) * 13 + j] == '\0') { + //if ((j > 1) && (entry->unicodeFilename[(i - 2) * 13 + (j-1)] == '\0')) { + if ((j > 1) && (unicodeFilename[(i - 2) * 13 + (j-1)] == '\0')) { + u16_to_u8array (lfnEntry, LFN_offset_table[j], 0xffff); // Padding + } else { + u16_to_u8array (lfnEntry, LFN_offset_table[j], 0x0000); // Terminating null character + } + } else { + //u16_to_u8array (lfnEntry, LFN_offset_table[j], entry->unicodeFilename[(i - 2) * 13 + j]); + u16_to_u8array (lfnEntry, LFN_offset_table[j], unicodeFilename[(i - 2) * 13 + j]); + } + } + + lfnEntry[LFN_offset_checkSum] = aliasCheckSum; + lfnEntry[LFN_offset_flag] = ATTRIB_LFN; + lfnEntry[LFN_offset_reserved1] = 0; + u16_to_u8array (lfnEntry, LFN_offset_reserved2, 0); + _FAT_cache_writePartialSector (partition->cache, lfnEntry, _FAT_fat_clusterToSector(partition, curEntryPos.cluster) + curEntryPos.sector, curEntryPos.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + } else { + // Alias & file data + _FAT_cache_writePartialSector (partition->cache, entry->entryData, _FAT_fat_clusterToSector(partition, curEntryPos.cluster) + curEntryPos.sector, curEntryPos.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + } + } + + return true; +} + +bool _FAT_directory_chdir (PARTITION* partition, const char* path) { + DIR_ENTRY entry; + + if (!_FAT_directory_entryFromPath (partition, &entry, path, NULL)) { + return false; + } + + if (!(entry.entryData[DIR_ENTRY_attributes] & ATTRIB_DIR)) { + return false; + } + + partition->cwdCluster = _FAT_directory_entryGetCluster (entry.entryData); + + return true; +} + +void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st) { + // Fill in the stat struct + // Some of the values are faked for the sake of compatibility + st->st_dev = _FAT_disc_hostType(partition->disc); // The device is the 32bit ioType value + st->st_ino = (ino_t)(_FAT_directory_entryGetCluster(entry->entryData)); // The file serial number is the start cluster + st->st_mode = (_FAT_directory_isDirectory(entry) ? S_IFDIR : S_IFREG) | + (S_IRUSR | S_IRGRP | S_IROTH) | + (_FAT_directory_isWritable (entry) ? (S_IWUSR | S_IWGRP | S_IWOTH) : 0) | + (_FAT_directory_isHidden (entry) ? S_IHIDDEN : 0); // Mode bits based on dirEntry ATTRIB byte + st->st_nlink = 1; // Always one hard link on a FAT file + st->st_uid = 1; // Faked for FAT + st->st_gid = 2; // Faked for FAT + st->st_rdev = st->st_dev; + st->st_size = u8array_to_u32 (entry->entryData, DIR_ENTRY_fileSize); // File size + st->st_atime = _FAT_filetime_to_time_t ( + 0, + u8array_to_u16 (entry->entryData, DIR_ENTRY_aDate) + ); + //st->st_spare1 = _FAT_directory_isHidden (entry); + st->st_mtime = _FAT_filetime_to_time_t ( + u8array_to_u16 (entry->entryData, DIR_ENTRY_mTime), + u8array_to_u16 (entry->entryData, DIR_ENTRY_mDate) + ); + //st->st_spare2 = 0; + st->st_ctime = _FAT_filetime_to_time_t ( + u8array_to_u16 (entry->entryData, DIR_ENTRY_cTime), + u8array_to_u16 (entry->entryData, DIR_ENTRY_cDate) + ); + //st->st_spare3 = 0; + st->st_blksize = BYTES_PER_READ; // Prefered file I/O block size + st->st_blocks = (st->st_size + BYTES_PER_READ - 1) / BYTES_PER_READ; // File size in blocks +// st->st_spare4[0] = 0; +// st->st_spare4[1] = 0; +} diff --git a/sdk-modifications/libsrc/fs/directory.h b/sdk-modifications/libsrc/fs/directory.h new file mode 100644 index 0000000..654c5d2 --- /dev/null +++ b/sdk-modifications/libsrc/fs/directory.h @@ -0,0 +1,180 @@ +/* + directory.h + Reading, writing and manipulation of the directory structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _DIRECTORY_H +#define _DIRECTORY_H + +#include + +#include "fs_common.h" +#include "partition.h" + +#define DIR_ENTRY_DATA_SIZE 0x20 +#define MAX_FILENAME_LENGTH 256 +#define MAX_ALIAS_LENGTH 13 +#define LFN_ENTRY_LENGTH 13 +#define FAT16_ROOT_DIR_CLUSTER 0 + +#define DIR_SEPARATOR '/' + +// File attributes +#define S_IHIDDEN 0x00200000 + + +#define ATTRIB_ARCH 0x20 // Archive +#define ATTRIB_DIR 0x10 // Directory +#define ATTRIB_LFN 0x0F // Long file name +#define ATTRIB_VOL 0x08 // Volume +#define ATTRIB_SYS 0x04 // System +#define ATTRIB_HID 0x02 // Hidden +#define ATTRIB_RO 0x01 // Read only + +typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE; + +typedef struct { + u32 cluster; + u32 sector; + s32 offset; +} DIR_ENTRY_POSITION; + +typedef struct { + u8 entryData[DIR_ENTRY_DATA_SIZE]; + DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry + char d_name[MAX_FILENAME_LENGTH + MAX_FILENAME_LENGTH*2]; //Store name string using UTF8 coding + //u16 unicodeFilename[MAX_FILENAME_LENGTH]; +} DIR_ENTRY; + +// Directory entry offsets +enum DIR_ENTRY_offset { + DIR_ENTRY_name = 0x00, + DIR_ENTRY_extension = 0x08, + DIR_ENTRY_attributes = 0x0B, + DIR_ENTRY_reserved = 0x0C, + DIR_ENTRY_cTime_ms = 0x0D, + DIR_ENTRY_cTime = 0x0E, + DIR_ENTRY_cDate = 0x10, + DIR_ENTRY_aDate = 0x12, + DIR_ENTRY_clusterHigh = 0x14, + DIR_ENTRY_mTime = 0x16, + DIR_ENTRY_mDate = 0x18, + DIR_ENTRY_cluster = 0x1A, + DIR_ENTRY_fileSize = 0x1C +}; + +/* +Returns true if the file specified by entry is a directory +*/ +static inline bool _FAT_directory_isDirectory (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) != 0); +} + +static inline bool _FAT_directory_isWritable (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO) == 0); +} + +static inline bool _FAT_directory_isDot (DIR_ENTRY* entry) { + return ((entry->d_name[0] == '.') && ((entry->d_name[1] == '\0') || + ((entry->d_name[1] == '.') && entry->d_name[2] == '\0'))); +} + +static inline bool _FAT_directory_isHidden (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_HID) != 0); +} + + +/* +Reads the first directory entry from the directory starting at dirCluster +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); + +/* +Reads the next directory entry after the one already pointed to by entry +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Gets the directory entry corrsponding to the supplied path +entry will be destroyed even if no directory entry is found +pathEnd specifies the end of the path string, for cutting strings short if needed + specify NULL to use the full length of path + pathEnd is only a suggestion, and the path string will be searched up until the next PATH_SEPARATOR + after pathEND. +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd); + +/* +Changes the current directory to the one specified by path +Returns true on success, false on failure +*/ +bool _FAT_directory_chdir (PARTITION* partition, const char* path); + +/* +Removes the directory entry specified by entry +Assumes that entry is valid +Returns true on success, false on failure +*/ +bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Add a directory entry to the directory specified by dirCluster +The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are +updated with the new directory entry position and alias. +Returns true on success, false on failure +*/ +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); + +/* +Get the start cluster of a file from it's entry data +*/ +u32 _FAT_directory_entryGetCluster (const u8* entryData); + +/* +Fill in the file name and entry data of DIR_ENTRY* entry. +Assumes that the entry's dataStart and dataEnd are correct +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry); + +/* +Fill in a stat struct based on a file entry +*/ +void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st); + +#endif // _DIRECTORY_H diff --git a/sdk-modifications/libsrc/fs/disc_io/disc.c b/sdk-modifications/libsrc/fs/disc_io/disc.c new file mode 100644 index 0000000..8b50953 --- /dev/null +++ b/sdk-modifications/libsrc/fs/disc_io/disc.c @@ -0,0 +1,194 @@ +/* + + disc.c + + uniformed io-interface to work with Chishm's FAT library + + Written by MightyMax + + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2005-11-06 - Chishm + * Added WAIT_CR modifications for NDS + + 2006-02-03 www.neoflash.com + * Added SUPPORT_* defines, comment out any of the SUPPORT_* defines in disc_io.h to remove support + for the given interface and stop code being linked to the binary + + * Added support for MK2 MMC interface + + * Added disc_Cache* functions + + 2006-02-05 - Chishm + * Added Supercard SD support + + 2006-02-26 - Cytex + * Added EFA2 support + + 2006-05-18 - Chishm + * Rewritten for FATlib disc.c + + 2006-06-19 - Chishm + * Changed read and write interface to accept a u32 instead of a u8 for the number of sectors + + 2006-07-11 - Chishm + * Removed disc_Cache* functions, since there is now a proper unified cache + * Removed SUPPORT_* defines + * Rewrote device detection functions + * First libfat release + + 2006-07-25 - Chishm + * Changed IO_INTERFACEs to const + + 2006-08-02 - Chishm + * Added NinjaDS +*/ + +#include "disc.h" +#include "disc_io.h" + +// Include known io-interfaces: +//#include "io_dldi.h" +//#include "io_mpcf.h" +//#include "io_m3cf.h" +//#include "io_m3sd.h" +//#include "io_sccf.h" +//#include "io_scsd.h" +//#include "io_fcsr.h" +//#include "io_nmmc.h" +//#include "io_efa2.h" +//#include "io_mmcf.h" +//#include "io_njsd.h" +//#include "io_acekard.h" +//#include "io_rpg_nand.h" +//#include "io_rpg_sd.h" +//#include "iointerface_sc.h" +#include "io_ds2_mmcf.h" + +const IO_INTERFACE* ioInterfaces[] = { + //&_io_dldi, + //&_io_fcsr, +#ifdef NDS + // Place Slot 1 (DS Card) interfaces here + //&_io_rpg_sd, //&_io_rpg_nand, /*&_io_acekard, */ + // Place Slot 2 (GBA Cart) interfaces here + //&_io_scsd, &_io_mpcf, &_io_m3cf, &_io_sccf, &_io_m3sd, &_io_fcsr + // Experimental Slot 2 interfaces + //, &_io_mmcf, &_io_efa2 + &_io_ds2_mmcf, +#endif +}; + +/* + + Hardware level disc funtions + +*/ + + +const IO_INTERFACE* _FAT_disc_gbaSlotFindInterface (void) +{ + // If running on an NDS, make sure the correct CPU can access + // the GBA cart. First implemented by SaTa. +#ifdef NDS + #ifdef ARM9 + REG_EXMEMCNT &= ~ARM7_OWNS_ROM; + #endif + #ifdef ARM7 + REG_EXMEMCNT |= ARM7_OWNS_ROM; + #endif +#endif + + int i; + + for (i = 0; i < (sizeof(ioInterfaces) / sizeof(IO_INTERFACE*)); i++) { + if ((ioInterfaces[i]->features & FEATURE_SLOT_GBA) && (ioInterfaces[i]->fn_startup())) { + return ioInterfaces[i]; + } + } + return NULL; +} + +#ifdef NDS +/* + * Check the DS card slot for a valid memory card interface + * If an interface is found, it is set as the default interace + * and it returns true. Otherwise the default interface is left + * untouched and it returns false. + */ +const IO_INTERFACE* _FAT_disc_dsSlotFindInterface (void) +{ +#ifdef ARM9 + REG_EXMEMCNT &= ~ARM7_OWNS_CARD; +#endif +#ifdef ARM7 + REG_EXMEMCNT |= ARM7_OWNS_CARD; +#endif + int i; + + for (i = 0; i < (sizeof(ioInterfaces) / sizeof(IO_INTERFACE*)); i++) { + if ((ioInterfaces[i]->features & FEATURE_SLOT_NDS) && (ioInterfaces[i]->fn_startup())) { + return ioInterfaces[i]; + } + } + + return NULL; +} +#endif + +/* + * When running on an NDS, check the either slot for a valid memory + * card interface. + * When running on a GBA, call _FAT_disc_gbaSlotFindInterface + * If an interface is found, it is set as the default interace + * and it returns true. Otherwise the default interface is left + * untouched and it returns false. + */ +#ifdef NDS +const IO_INTERFACE* _FAT_disc_findInterface (void) +{ +#ifdef ARM9 + REG_EXMEMCNT &= ~(ARM7_OWNS_CARD | ARM7_OWNS_ROM); +#endif +#ifdef ARM7 + REG_EXMEMCNT |= (ARM7_OWNS_CARD | ARM7_OWNS_ROM); +#endif + + int i; + + for (i = 0; i < (sizeof(ioInterfaces) / sizeof(IO_INTERFACE*)); i++) { + if (ioInterfaces[i]->fn_startup()) { + return ioInterfaces[i]; + } + } + + return NULL; +} +#else +const IO_INTERFACE* _FAT_disc_findInterface (void) +{ + return _FAT_disc_gbaSlotFindInterface(); +} +#endif diff --git a/sdk-modifications/libsrc/fs/disc_io/disc.h b/sdk-modifications/libsrc/fs/disc_io/disc.h new file mode 100644 index 0000000..2129359 --- /dev/null +++ b/sdk-modifications/libsrc/fs/disc_io/disc.h @@ -0,0 +1,128 @@ +/* + disc.h + Interface to the low level disc functions. Used by the higher level + file system code. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + +*/ +#ifndef _DISC_H +#define _DISC_H + +#include "../fs_common.h" +#include "disc_io.h" + +/* +Search for a block based device in the GBA slot. +Return a pointer to a usable interface if one is found, +NULL if not. +*/ +extern const IO_INTERFACE* _FAT_disc_gbaSlotFindInterface (void); + +/* +Search for a block based device in the DS slot. +Return a pointer to a usable interface if one is found, +NULL if not. +*/ +#ifdef NDS +extern const IO_INTERFACE* _FAT_disc_dsSlotFindInterface (void); +#endif + +/* +Search for a block based device in the both slots. +Return a pointer to a usable interface if one is found, +NULL if not. +*/ +extern const IO_INTERFACE* _FAT_disc_findInterface (void); + +/* +Check if a disc is inserted +Return true if a disc is inserted and ready, false otherwise +*/ +static inline bool _FAT_disc_isInserted (const IO_INTERFACE* disc) { + return disc->fn_isInserted(); +} + +/* +Read numSectors sectors from a disc, starting at sector. +numSectors is between 1 and 256 +sector is from 0 to 2^28 +buffer is a pointer to the memory to fill +*/ +//return non-zero is sucess +static inline bool _FAT_disc_readSectors (const IO_INTERFACE* disc, unsigned long sector, unsigned long numSectors, void* buffer) { + return disc->fn_readSectors (sector, numSectors, buffer); +} + +/* +Write numSectors sectors to a disc, starting at sector. +numSectors is between 1 and 256 +sector is from 0 to 2^28 +buffer is a pointer to the memory to read from +*/ +//return non-zero is sucess +static inline bool _FAT_disc_writeSectors (const IO_INTERFACE* disc, unsigned long sector, unsigned long numSectors, const void* buffer) { + return disc->fn_writeSectors (sector, numSectors, buffer); +} + +/* +Reset the card back to a ready state +*/ +static inline bool _FAT_disc_clearStatus (const IO_INTERFACE* disc) { + return disc->fn_clearStatus(); +} + +/* +Initialise the disc to a state ready for data reading or writing +*/ +static inline bool _FAT_disc_startup (const IO_INTERFACE* disc) { + return disc->fn_startup(); +} + +/* +Put the disc in a state ready for power down. +Complete any pending writes and disable the disc if necessary +*/ +static inline bool _FAT_disc_shutdown (const IO_INTERFACE* disc) { + return disc->fn_shutdown(); +} + +/* +Return a 32 bit value unique to each type of interface +*/ +static inline unsigned long _FAT_disc_hostType (const IO_INTERFACE* disc) { + return disc->ioType; +} + +/* +Return a 32 bit value that specifies the capabilities of the disc +*/ +static inline unsigned long _FAT_disc_features (const IO_INTERFACE* disc) { + return disc->features; +} + +#endif // _DISC_H diff --git a/sdk-modifications/libsrc/fs/disc_io/disc_io.h b/sdk-modifications/libsrc/fs/disc_io/disc_io.h new file mode 100644 index 0000000..6ac0c31 --- /dev/null +++ b/sdk-modifications/libsrc/fs/disc_io/disc_io.h @@ -0,0 +1,83 @@ +/* + disc_io.h + Interface template for low level disc functions. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-07-16 - Chishm + * Renamed _CF_USE_DMA to _IO_USE_DMA + * Renamed _CF_ALLOW_UNALIGNED to _IO_ALLOW_UNALIGNED +*/ + +#ifndef _DISC_IO_H +#define _DISC_IO_H + +#include "../fs_common.h" + +//---------------------------------------------------------------------- +// Customisable features + +// Use DMA to read the card, remove this line to use normal reads/writes +// #define _IO_USE_DMA + +// Allow buffers not alligned to 16 bits when reading files. +// Note that this will slow down access speed, so only use if you have to. +// It is also incompatible with DMA +//#define _IO_ALLOW_UNALIGNED + +#define _IO_USE_DMA + +#if defined _IO_USE_DMA && defined _IO_ALLOW_UNALIGNED + #error You can't use both DMA and unaligned memory +#endif + +#define FEATURE_MEDIUM_CANREAD 0x00000001 +#define FEATURE_MEDIUM_CANWRITE 0x00000002 +#define FEATURE_SLOT_GBA 0x00000010 +#define FEATURE_SLOT_NDS 0x00000020 + +typedef bool (* FN_MEDIUM_STARTUP)(void) ; +typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; +typedef bool (* FN_MEDIUM_READSECTORS)(unsigned long sector, unsigned long numSectors, void* buffer) ; +typedef bool (* FN_MEDIUM_WRITESECTORS)(unsigned long sector, unsigned long numSectors, const void* buffer) ; +typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; +typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; + +struct IO_INTERFACE_STRUCT { + unsigned long ioType ; + unsigned long features ; + FN_MEDIUM_STARTUP fn_startup ; + FN_MEDIUM_ISINSERTED fn_isInserted ; + FN_MEDIUM_READSECTORS fn_readSectors ; + FN_MEDIUM_WRITESECTORS fn_writeSectors ; + FN_MEDIUM_CLEARSTATUS fn_clearStatus ; + FN_MEDIUM_SHUTDOWN fn_shutdown ; +} ; + +typedef struct IO_INTERFACE_STRUCT IO_INTERFACE ; + +#endif // define _DISC_IO_H diff --git a/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.c b/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.c new file mode 100644 index 0000000..c432d84 --- /dev/null +++ b/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.c @@ -0,0 +1,13 @@ +//io_ds2_mmcf.c +#include "io_ds2_mmcf.h" + +const IO_INTERFACE _io_ds2_mmcf = { + DEVICE_TYPE_DS2_MMCF, + FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE, + (FN_MEDIUM_STARTUP)&_MMC_StartUp, + (FN_MEDIUM_ISINSERTED)&_MMC_IsInserted, + (FN_MEDIUM_READSECTORS)&_MMC_ReadSectors, + (FN_MEDIUM_WRITESECTORS)&_MMC_WriteSectors, + (FN_MEDIUM_CLEARSTATUS)&_MMC_ClearStatus, + (FN_MEDIUM_SHUTDOWN)&_MMC_ShutDown +}; diff --git a/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.h b/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.h new file mode 100644 index 0000000..334a9bc --- /dev/null +++ b/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.h @@ -0,0 +1,63 @@ +#ifndef __IO_DS2_H__ +#define __IO_DS2_H__ + +// 'DS2F' +#define DEVICE_TYPE_DS2_MMCF 0x46434D4D + +#include "disc_io.h" +#include "ds2_mmc_api.h" + +// export interface +extern const IO_INTERFACE _io_ds2_mmcf ; + +/* initialize MMC/SD card */ +static inline bool _MMC_StartUp(void) +{ + return MMC_Initialize(); +} + +/* read multi blocks from MMC/SD card */ +/* read a single block from MMC/SD card */ +static inline bool _MMC_ReadSectors(u32 sector, u32 numSectors, void* buffer) +{ + int flag; + + if(numSectors > 1) + flag= MMC_ReadMultiBlock(sector, numSectors, (unsigned char*)buffer); + else + flag= MMC_ReadBlock(sector, (unsigned char*)buffer); + return (flag==MMC_NO_ERROR); +} + +/* write multi blocks from MMC/SD card */ +/* write a single block from MMC/SD card */ +static inline bool _MMC_WriteSectors(u32 sector, u32 numSectors, const void* buffer) +{ + int flag; + + if(numSectors > 1) + flag= MMC_WriteMultiBlock(sector, numSectors, (unsigned char*)buffer); + else + flag= MMC_WriteBlock(sector, (unsigned char*)buffer); + + return (flag==MMC_NO_ERROR); +} + +static inline bool _MMC_ClearStatus(void) +{ + return true; +} + +static inline bool _MMC_ShutDown(void) +{ + return true; +} + +static inline bool _MMC_IsInserted(void) +{ + return true; +} + + +#endif //__IO_DS2_H__ + diff --git a/sdk-modifications/libsrc/fs/ds2_fcntl.c b/sdk-modifications/libsrc/fs/ds2_fcntl.c new file mode 100644 index 0000000..0fc00d7 --- /dev/null +++ b/sdk-modifications/libsrc/fs/ds2_fcntl.c @@ -0,0 +1,126 @@ +#include +#include +#include "ds2_fcntl.h" +#include "fs_api.h" +#include "ds2_malloc.h" + + +/*typedef struct { + FILE_STRUCT* stream; + int flags; +} _fd_t; + +_fd_t* _fd_list = NULL; +int _fd_count = 0;*/ + +int open(const char* path, int oflag, ... ) { + if(oflag & _O_UNSUPPORTED) { + errno = EINVAL; + return -1; + } + // TODO - Deal more correctly with certain flags. + FILE_STRUCT* tempFile = fat_fopen(path, "rb"); + if(oflag & O_CREAT) { + if(tempFile == NULL) + tempFile = fat_fopen(path, "wb"); + if(tempFile == NULL) + return -1; + } else if(tempFile == NULL) { + return -1; + } else if(oflag & O_TRUNC) { + tempFile = fat_fopen(path, "wb"); + if(tempFile == NULL) + return -1; + } + fat_fclose(tempFile); + + char tempMode[16]; + if((oflag & 0x3) == O_RDONLY) { + sprintf(tempMode, "rb"); + } else if((oflag & 0x3) == O_WRONLY) { + if(oflag & O_APPEND) + sprintf(tempMode, "ab"); + else + sprintf(tempMode, "wb"); + } else if((oflag & 0x3) == O_RDWR) { + if(oflag & O_APPEND) + sprintf(tempMode, "ab+"); + else + sprintf(tempMode, "rb+"); + } + + tempFile = fat_fopen(path, tempMode); + if(tempFile == NULL) + return -1; + + return tempFile -> fd; +} + +int fcntl(int fildes, int cmd, ...) { + /*if((fildes < 0) || (fildes >= _fd_count) || (_fd_list[fildes].stream == NULL)) { + errno = EINVAL; + return -1; + } + if((cmd <= 0) || (cmd > _F_LAST)) { + errno = EINVAL; + return -1; + } + + va_list ap; + + int arg; + void* flock; + switch(cmd) { + case F_SETFD: + case F_SETOWN: + va_start(ap, cmd); + arg = va_arg(ap, int); + va_end(ap); + break; + case F_GETLK: + case F_SETLK: + va_start(ap, cmd); + flock = va_arg(ap, void*); + va_end(ap); + break; + } + + switch(cmd) { + case F_DUPFD: // Duplicate file descriptors not supported. + errno = EINVAL; + return -1; + case F_GETFD: + return (_fd_list[fildes].flags & _F_FILE_DESC); + case F_SETFD: + arg &= _F_FILE_DESC; + _fd_list[fildes].flags &= ~_F_FILE_DESC; + _fd_list[fildes].flags |= arg; + return 0; + case F_GETFL: + return (_fd_list[fildes].flags & (O_ACCMODE | _O_FILE_STATUS)); + case F_SETFL: + arg &= (O_ACCMODE | _O_FILE_STATUS); + if(arg & _O_UNSUPPORTED) { + errno = EINVAL; + return -1; + } + if((arg & O_ACCMODE) != (_fd_list[fildes].flags & O_ACCMODE)) { + errno = EINVAL; + return -1; + } + _fd_list[fildes].flags &= ~(O_ACCMODE | _O_FILE_STATUS); + _fd_list[fildes].flags |= arg; + return 0; + case F_GETOWN: + case F_SETOWN: + errno = -1; + return -1; + case F_GETLK: + case F_SETLK: + case F_SETLKW: + return -1; + } + + errno = EINVAL;*/ + return -1; +} diff --git a/sdk-modifications/libsrc/fs/ds2_fcntl.h b/sdk-modifications/libsrc/fs/ds2_fcntl.h new file mode 100644 index 0000000..2c69221 --- /dev/null +++ b/sdk-modifications/libsrc/fs/ds2_fcntl.h @@ -0,0 +1,51 @@ +#ifndef __libc_fcntl_h__ +#define __libc_fcntl_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define O_RDONLY (1 << 0) +#define O_WRONLY (2 << 0) +#define O_RDWR (3 << 0) +#define O_APPEND (1 << 2) +#define O_CREAT (1 << 3) +#define O_DSYNC (1 << 4) +#define O_EXCL (1 << 5) +#define O_NOCTTY (1 << 6) +#define O_NONBLOCK (1 << 7) +#define O_RSYNC (1 << 8) +#define O_SYNC (1 << 9) +#define O_TRUNC (1 << 10) +#define O_CREATE O_CREAT + +#define O_ACCMODE 0x3 + +#define F_CLOEXEC (1 << 11) + +#define F_DUPFD 1 +#define F_GETFD 2 +#define F_SETFD 3 +#define F_GETFL 4 +#define F_SETFL 5 +#define F_GETLK 6 +#define F_SETLK 7 +#define F_SETLKW 8 +#define F_GETOWN 9 +#define F_SETOWN 10 +#define _F_LAST F_SETOWN + +#define _F_FILE_DESC (F_CLOEXEC) +#define _O_FILE_CREATE (O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC) +#define _O_FILE_STATUS (O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC) +#define _O_UNSUPPORTED (0) + +extern int open(const char* path, int oflag, ...); +extern int fcntl(int fildes, int cmd, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk-modifications/libsrc/fs/ds2_unistd.c b/sdk-modifications/libsrc/fs/ds2_unistd.c new file mode 100644 index 0000000..8625eba --- /dev/null +++ b/sdk-modifications/libsrc/fs/ds2_unistd.c @@ -0,0 +1,18 @@ +#include "ds2_unistd.h" +#include "fs_api.h" + +int close(int fildes) { + return _FAT_close_r (&__REENT, fildes); +} + +int lseek(int fildes, int offset, int whence) { + return _FAT_seek_r (&__REENT, fildes, (int)offset, whence); +} + +int read(int fildes, void* buf, size_t len) { + return _FAT_read_r (&__REENT, fildes, (char*)buf, len); +} + +int write(int fildes, const void* buf, size_t len) { + return _FAT_write_r (&__REENT, fildes, (const char*)buf, len); +} diff --git a/sdk-modifications/libsrc/fs/ds2_unistd.h b/sdk-modifications/libsrc/fs/ds2_unistd.h new file mode 100644 index 0000000..f5efdb1 --- /dev/null +++ b/sdk-modifications/libsrc/fs/ds2_unistd.h @@ -0,0 +1,22 @@ +#ifndef __libc_unistd_h__ +#define __libc_unistd_h__ + +#include "fs_common.h" +#include "fatfile.h" +#include "fs_api.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern int close(int fildes); +extern int lseek(int fildes, int offset, int whence); +extern int read(int fildes, void* buf, size_t len); +extern int write(int fildes, const void* buf, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk-modifications/libsrc/fs/fat.h b/sdk-modifications/libsrc/fs/fat.h new file mode 100644 index 0000000..3ddbac3 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fat.h @@ -0,0 +1,118 @@ +/* + fat.h + Simple functionality for startup, mounting and unmounting of FAT-based devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-07-14 + * fatInitialise renamed to fatInit + + 2006-07-16 - Chishm + * Added fatInitDefault +*/ + + +#ifndef _LIBFAT_H +#define _LIBFAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +// When compiling for NDS, make sure NDS is defined +#ifndef NDS + #define NDS +#endif + +#include +#include "partition.h" +#include "directory.h" +#include "file_allocation_table.h" +#include "unicode/unicode.h" +#include "fatdir_ex.h" +#include "fatfile_ex.h" + +//typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM} PARTITION_INTERFACE; + +struct IO_INTERFACE_STRUCT ; + +/* +Initialise any inserted block-devices. +Add the fat device driver to the devoptab, making it available for standard file functions. +cacheSize: The number of pages to allocate for each inserted block-device +setAsDefaultDevice: if true, make this the default device driver for file operations +*/ +bool fatInit (u32 cacheSize, bool setAsDefaultDevice); + +/* +Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. +*/ +bool fatInitDefault (void); + +/* +Special initialize for RPG card +*/ +bool fatInitRPG (void); + +/* +Mount the device specified by partitionNumber +PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice +PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +*/ +bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize); + +/* +Mount a partition on a custom device +*/ +bool fatMountCustomInterface (struct IO_INTERFACE_STRUCT* device, u32 cacheSize); + +/* +Unmount the partition specified by partitionNumber +If there are open files, it will fail +*/ +bool fatUnmount (PARTITION_INTERFACE partitionNumber); + + +/* +Forcibly unmount the partition specified by partitionNumber +Any open files on the partition will become invalid +The cache will be invalidated, and any unflushed writes will be lost +*/ +bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber); + +/* +Set the default device for access by fat: and fat0: +PD_DEFAULT is unallowed. +Doesn't do anything useful on GBA, since there is only one device +*/ +bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber); + +#ifdef __cplusplus +} +#endif + +#endif // _LIBFAT_H diff --git a/sdk-modifications/libsrc/fs/fat_misc.c b/sdk-modifications/libsrc/fs/fat_misc.c new file mode 100644 index 0000000..c0f62ac --- /dev/null +++ b/sdk-modifications/libsrc/fs/fat_misc.c @@ -0,0 +1,138 @@ +//fat_misc.c +//v1.0 + +#include "fat_misc.h" +#include "fs_api.h" + +static unsigned int _usedSecNums; + +static int strFindFromEnd( char *str,char strValue ) +{ + int pos = 0,i = 0,strNum = 0; + while(1) + { + if( (*str)!=0 ) + { + strNum++; + str++; + } + else + { + break; + } + } + pos = strNum; + for( i=0;i MAX_FILENAME_LENGTH ) + return false; + + DIR_STATE_STRUCT *dir; dir = fat_opendir((const char*)dirPath); + if (dir == NULL) + return false; + struct stat stat_buf; + DIR_ENTRY *currentEntry; + char* filename; + + while(fat_readdir_ex(dir, &stat_buf) != NULL) + { + filename = currentEntry->d_name; + + if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) + continue; + + if (!(stat_buf.st_mode & S_IFDIR)) { + size += (stat_buf.st_size+511)/512; + _usedSecNums +=(stat_buf.st_size+511)/512; + } + else if (includeSubdirs) + { + // calculate the size recursively + unsigned int subDirSize = 0; + char dirPathBuffer[MAX_FILENAME_LENGTH]; + + memset( dirPathBuffer,0,MAX_FILENAME_LENGTH ); + strcpy( dirPathBuffer,dirPath ); + memset( dirPath,0,MAX_FILENAME_LENGTH ); + sprintf( dirPath,"%s%s",dirPathBuffer,filename ); + int succ = getDirSize( dirPath, includeSubdirs, &subDirSize ); + if( succ ) { + size += (subDirSize+511)/512; + _usedSecNums +=(subDirSize+511)/512; + } + memset( dirPath,0,MAX_FILENAME_LENGTH ); + strcpy( dirPath,dirPathBuffer ); + } + } + + fat_closedir(dir); + + *dirSize = size; + return true; +} + +int fat_getDiskTotalSpace( char * diskName, unsigned int * diskSpace ) +{ + if( !strcmp("",diskName) ) + return false; + + unsigned int len = strlen(diskName); + if( *(diskName+len-1) != '/' ){ + *(diskName+len) = '/'; + } + + PARTITION * diskPartition = _FAT_partition_getPartitionFromPath( diskName ); + if( NULL == diskPartition ) + return false; + + *diskSpace = (unsigned int)diskPartition->numberOfSectors; + return true; +} + +int fat_getDiskSpaceInfo( char * diskName, unsigned int * total, unsigned int * used, unsigned int * freeSpace ) +{ + _usedSecNums = 0; + + if( !strcmp("",diskName) ) + return -1; + if( !fat_getDiskTotalSpace(diskName, total) ) + return -1; + if( !getDirSize(diskName, true, used) ) + return -1; + + *used = _usedSecNums; + if( *total <= *used ){ + *freeSpace = 0; + }else{ + *freeSpace = *total - *used; + } + + return 0; +} diff --git a/sdk-modifications/libsrc/fs/fat_misc.h b/sdk-modifications/libsrc/fs/fat_misc.h new file mode 100644 index 0000000..05db0bb --- /dev/null +++ b/sdk-modifications/libsrc/fs/fat_misc.h @@ -0,0 +1,38 @@ +/*-------------------------------------------------------------------------------- +Copyright (C) 2007 Acekard, www.acekard.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +---------------------------------------------------------------------------------*/ +#ifndef __FAT_MISC_H__ +#define __FAT_MISC_H__ + +#include "fs_common.h" +#include "directory.h" + typedef enum _SRC_FILE_MODE +{ + SFM_COPY = 0, + SFM_CUT = 1 +}SRC_FILE_MODE; + + +extern bool fat_getDiskSpaceInfo( char * diskName, unsigned int *total, unsigned int *used, unsigned int *freeSpace ); + +#endif //__FAT_MISC_H__ diff --git a/sdk-modifications/libsrc/fs/fatdir.c b/sdk-modifications/libsrc/fs/fatdir.c new file mode 100644 index 0000000..dc9b914 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fatdir.c @@ -0,0 +1,672 @@ +/* + fatdir.c + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-08-13 - Chishm + * Moved all externally visible directory related functions to fatdir + * Added _FAT_mkdir_r + + 2006-08-14 - Chishm + * Added directory iterator functions + + 2006-08-19 - Chishm + * Updated dirnext return values to return correctly + + 2006-10-01 - Chishm + * Now clears the whole cluster when creating a new directory, bug found by Hermes + + 2007-01-10 - Chishm + * Updated directory iterator functions for DevkitPro r20 +*/ + +/* + 2010.06.30 + * Modify _FAT_diropen_r, +*/ + +#include +#include +#include +#include +#include + +#include "fatdir.h" + +#include "fs_cache.h" +#include "file_allocation_table.h" +#include "partition.h" +#include "directory.h" +#include "bit_ops.h" +#include "filetime.h" +#include "fs_unicode.h" + + +int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) { + PARTITION* partition = NULL; + + DIR_ENTRY dirEntry; + + // Get the partition this file is on + partition = _FAT_partition_getPartitionFromPath (path); + + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + // Search for the file on the disc + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) { + r->_errno = ENOENT; + return -1; + } + + // Fill in the stat struct + _FAT_directory_entryStat (partition, &dirEntry, st); + + return 0; +} + +int _FAT_getshortname_r (struct _reent *r, const char *name, char *outName) { + PARTITION* partition = NULL; + DIR_ENTRY DirEntry; + u32 dirCluster; + + // Get the partition this directory is on + partition = _FAT_partition_getPartitionFromPath (name); + + if (partition == NULL) { + r->_errno = ENODEV; + return 1; + } + + // Move the path pointer to the start of the actual path + if (strchr (name, ':') != NULL) { + name = strchr (name, ':') + 1; + } + if (strchr (name, ':') != NULL) { + r->_errno = EINVAL; + return 1; + } + + // Search for the file on the disc + if (!_FAT_directory_entryFromPath (partition, &DirEntry, name, NULL)) { + r->_errno = ENOENT; + return 1; + } + + strcpy(outName, DirEntry.entryData); + return 1; +} + +int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink) { + r->_errno = ENOTSUP; + return -1; +} + +int _FAT_unlink_r (struct _reent *r, const char *path) { + PARTITION* partition = NULL; + DIR_ENTRY dirEntry; + DIR_ENTRY dirContents; + u32 cluster; + bool nextEntry; + bool errorOccured = false; + + // Get the partition this directory is on + partition = _FAT_partition_getPartitionFromPath (path); + + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Make sure we aren't trying to write to a read-only disc + if (partition->readOnly) { + r->_errno = EROFS; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + // Search for the file on the disc + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) { + r->_errno = ENOENT; + return -1; + } + + cluster = _FAT_directory_entryGetCluster (dirEntry.entryData); + + + // If this is a directory, make sure it is empty + if (_FAT_directory_isDirectory (&dirEntry)) { + nextEntry = _FAT_directory_getFirstEntry (partition, &dirContents, cluster); + + while (nextEntry) { + if (!_FAT_directory_isDot (&dirContents)) { + // The directory had something in it that isn't a reference to itself or it's parent + r->_errno = EPERM; + return -1; + } + nextEntry = _FAT_directory_getNextEntry (partition, &dirContents); + } + } + + if (cluster != CLUSTER_FREE) { + // Remove the cluster chain for this file + if (!_FAT_fat_clearLinks (partition, cluster)) { + r->_errno = EIO; + errorOccured = true; + } + } + + // Remove the directory entry for this file + if (!_FAT_directory_removeEntry (partition, &dirEntry)) { + r->_errno = EIO; + errorOccured = true; + } + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush(partition->cache)) { + r->_errno = EIO; + errorOccured = true; + } + + if (errorOccured) { + return -1; + } else { + return 0; + } +} + +int _FAT_chdir_r (struct _reent *r, const char *path) { + PARTITION* partition = NULL; + + // Get the partition this directory is on + partition = _FAT_partition_getPartitionFromPath (path); + + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + // Set the default device to match this one + if (!_FAT_partition_setDefaultPartition (partition)) { + r->_errno = ENOENT; + return -1; + } + + // Try changing directory + if (_FAT_directory_chdir (partition, path)) { + // Successful + return 0; + } else { + // Failed + r->_errno = ENOTDIR; + return -1; + } +} + +int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { + PARTITION* partition = NULL; + DIR_ENTRY oldDirEntry; + DIR_ENTRY newDirEntry; + const char *pathEnd; + u32 dirCluster; + + // Get the partition this directory is on + partition = _FAT_partition_getPartitionFromPath (oldName); + + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Make sure the same partition is used for the old and new names + if (partition != _FAT_partition_getPartitionFromPath (newName)) { + r->_errno = EXDEV; + return -1; + } + + // Make sure we aren't trying to write to a read-only disc + if (partition->readOnly) { + r->_errno = EROFS; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (oldName, ':') != NULL) { + oldName = strchr (oldName, ':') + 1; + } + if (strchr (oldName, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + if (strchr (newName, ':') != NULL) { + newName = strchr (newName, ':') + 1; + } + if (strchr (newName, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + // Search for the file on the disc + if (!_FAT_directory_entryFromPath (partition, &oldDirEntry, oldName, NULL)) { + r->_errno = ENOENT; + return -1; + } + + // Make sure there is no existing file / directory with the new name + if (_FAT_directory_entryFromPath (partition, &newDirEntry, newName, NULL)) { + r->_errno = EEXIST; + return -1; + } + + // Create the new file entry + // Get the directory it has to go in + pathEnd = strrchr (newName, DIR_SEPARATOR); + if (pathEnd == NULL) { + // No path was specified + dirCluster = partition->cwdCluster; + pathEnd = newName; + } else { + // Path was specified -- get the right dirCluster + // Recycling newDirEntry, since it needs to be recreated anyway + if (!_FAT_directory_entryFromPath (partition, &newDirEntry, newName, pathEnd) || + !_FAT_directory_isDirectory(&newDirEntry)) { + r->_errno = ENOTDIR; + return -1; + } + dirCluster = _FAT_directory_entryGetCluster (newDirEntry.entryData); + // Move the pathEnd past the last DIR_SEPARATOR + pathEnd += 1; + } + + // Copy the entry data + memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY)); + + // Set the new name + strncpy (newDirEntry.d_name, pathEnd, MAX_FILENAME_LENGTH - 1); + + // Write the new entry + if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) { + r->_errno = ENOSPC; + return -1; + } + + // Remove the old entry + if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) { + r->_errno = EIO; + return -1; + } + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush (partition->cache)) { + r->_errno = EIO; + return -1; + } + + return 0; +} + +int _FAT_hideAttrib_r (struct _reent *r, const char *name, u8 hide) { + PARTITION* partition = NULL; + DIR_ENTRY oldDirEntry; + DIR_ENTRY newDirEntry; + u32 dirCluster; + + // Get the partition this directory is on + partition = _FAT_partition_getPartitionFromPath (name); + + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Make sure we aren't trying to write to a read-only disc + if (partition->readOnly) { + r->_errno = EROFS; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (name, ':') != NULL) { + name = strchr (name, ':') + 1; + } + if (strchr (name, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + // Search for the file on the disc + if (!_FAT_directory_entryFromPath (partition, &oldDirEntry, name, NULL)) { + r->_errno = ENOENT; + return -1; + } + + // Create the new file entry + // Get the directory it has to go in + memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY)); + + // No path was specified + dirCluster = partition->cwdCluster; + + // Remove the old entry hopefully doesn't screw things up... + if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) { + r->_errno = EIO; + return -1; + } + + // Set the new attribute + if(hide) + newDirEntry.entryData[DIR_ENTRY_attributes] |= ATTRIB_HID; + else + newDirEntry.entryData[DIR_ENTRY_attributes] &= ~ATTRIB_HID; + + // Write the new entry + if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) { + r->_errno = ENOSPC; + return -1; + } + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush (partition->cache)) { + r->_errno = EIO; + return -1; + } + + return 0; +} + +int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { + PARTITION* partition = NULL; + bool fileExists; + DIR_ENTRY dirEntry; + const char* pathEnd; + u32 parentCluster, dirCluster; + u8 newEntryData[DIR_ENTRY_DATA_SIZE]; + + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + // Search for the file/directory on the disc + fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); + + // Make sure it doesn't exist + if (fileExists) { + r->_errno = EEXIST; + return -1; + } + + if (partition->readOnly) { + // We can't write to a read-only partition + r->_errno = EROFS; + return -1; + } + + // Get the directory it has to go in + pathEnd = strrchr (path, DIR_SEPARATOR); + if (pathEnd == NULL) { + // No path was specified + parentCluster = partition->cwdCluster; + pathEnd = path; + } else { + // Path was specified -- get the right parentCluster + // Recycling dirEntry, since it needs to be recreated anyway + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) || + !_FAT_directory_isDirectory(&dirEntry)) { + r->_errno = ENOTDIR; + return -1; + } + parentCluster = _FAT_directory_entryGetCluster (dirEntry.entryData); + // Move the pathEnd past the last DIR_SEPARATOR + pathEnd += 1; + } + + // Create the entry data + strncpy (dirEntry.d_name, pathEnd, MAX_FILENAME_LENGTH - 1); + memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); + + // Set the creation time and date + dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0; + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC()); + + // Set the directory attribute + dirEntry.entryData[DIR_ENTRY_attributes] = ATTRIB_DIR; + + // Get a cluster for the new directory + dirCluster = _FAT_fat_linkFreeClusterCleared (partition, CLUSTER_FREE); + if (dirCluster == CLUSTER_FREE) { + // No space left on disc for the cluster + r->_errno = ENOSPC; + return -1; + } + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cluster, dirCluster); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_clusterHigh, dirCluster >> 16); + + // Write the new directory's entry to it's parent + if (!_FAT_directory_addEntry (partition, &dirEntry, parentCluster)) { + r->_errno = ENOSPC; + return -1; + } + + // Create the dot entry within the directory + memset (newEntryData, 0, DIR_ENTRY_DATA_SIZE); + memset (newEntryData, ' ', 11); + newEntryData[DIR_ENTRY_name] = '.'; + newEntryData[DIR_ENTRY_attributes] = ATTRIB_DIR; + u16_to_u8array (newEntryData, DIR_ENTRY_cluster, dirCluster); + u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, dirCluster >> 16); + + // Write it to the directory, erasing that sector in the process + _FAT_cache_eraseWritePartialSector ( partition->cache, newEntryData, + _FAT_fat_clusterToSector (partition, dirCluster), 0, DIR_ENTRY_DATA_SIZE); + + + // Create the double dot entry within the directory + newEntryData[DIR_ENTRY_name + 1] = '.'; + u16_to_u8array (newEntryData, DIR_ENTRY_cluster, parentCluster); + u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, parentCluster >> 16); + + // Write it to the directory + _FAT_cache_writePartialSector ( partition->cache, newEntryData, + _FAT_fat_clusterToSector (partition, dirCluster), DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush(partition->cache)) { + r->_errno = EIO; + return -1; + } + + return 0; +} + +DIR_STATE_STRUCT* _FAT_diropen_r(struct _reent *r, DIR_STATE_STRUCT *dirState, const char *path) { + DIR_ENTRY dirEntry; + DIR_STATE_STRUCT* state = dirState; + bool fileExists; + const char* root_path= "/"; + + state->partition = _FAT_partition_getPartitionFromPath (path); + if (state->partition == NULL) { + r->_errno = ENODEV; + return NULL; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return NULL; + } + + if('\0' == path[0]) path = root_path; + + // Get the start cluster of the directory + fileExists = _FAT_directory_entryFromPath (state->partition, &dirEntry, path, NULL); + if (!fileExists) { + r->_errno = ENOENT; + return NULL; + } + + // Make sure it is a directory + if (! _FAT_directory_isDirectory (&dirEntry)) { + r->_errno = ENOTDIR; + return NULL; + } + + // Save the start cluster for use when resetting the directory data + state->startCluster = _FAT_directory_entryGetCluster (dirEntry.entryData); + + //Entry location pointer + state->posEntry = 0; + +// // Get the first entry for use with a call to dirnext +// state->validEntry = +// _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); + state->validEntry = false; + + // We are now using this entry + state->inUse = true; + return state; +} + +int _FAT_dirreset_r (struct _reent *r, DIR_STATE_STRUCT *dirState) { + DIR_STATE_STRUCT* state = dirState; + + // Make sure we are still using this entry + if (!state->inUse) { + r->_errno = EBADF; + return -1; + } + + // Get the first entry for use with a call to dirnext +// state->validEntry = +// _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); + + state->posEntry = 0; + + return 0; +} + +int _FAT_dirnext_r (struct _reent *r, DIR_STATE_STRUCT *dirState, struct stat *filestat) { + DIR_STATE_STRUCT* state = dirState; + + // Make sure we are still using this entry + if (!state->inUse) { + r->_errno = EBADF; + return -1; + } + + // Make sure there is another file to report on +// if (!state->validEntry) { +// r->_errno = ENOENT; +// return -1; +// } + + if(0 == state->posEntry) { + state->validEntry = _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); + } + else + state->validEntry = _FAT_directory_getNextEntry (state->partition, &(state->currentEntry)); + + state->posEntry += 1; + + if(!state->validEntry) + { + r->_errno = ENOENT; + return -1; + } + + if (filestat != NULL) { + _FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat); + } + + return 0; +/* + // Get the filename + strncpy (filename, state->currentEntry.d_name, MAX_FILENAME_LENGTH); + // Get the stats, if requested + if (filestat != NULL) { + _FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat); + } + + // Look for the next entry for use next time + state->validEntry = + _FAT_directory_getNextEntry (state->partition, &(state->currentEntry)); + + return 0; +*/ +} + +int _FAT_dirclose_r (struct _reent *r, DIR_STATE_STRUCT *dirState) { + DIR_STATE_STRUCT* state = dirState; + + // We are no longer using this entry + state->inUse = false; + + return 0; +} diff --git a/sdk-modifications/libsrc/fs/fatdir.h b/sdk-modifications/libsrc/fs/fatdir.h new file mode 100644 index 0000000..7c419ee --- /dev/null +++ b/sdk-modifications/libsrc/fs/fatdir.h @@ -0,0 +1,85 @@ +/* + fatdir.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-08-13 - Chishm + * Moved all externally visible directory related functions to fatdir + * Added _FAT_mkdir_r + + 2006-08-14 - Chishm + * Added directory iterator functions + + 2007-01-10 - Chishm + * Updated directory iterator functions for DevkitPro r20 +*/ + + +#ifndef _FATDIR_H +#define _FATDIR_H + +//#include +#include +//#include +#include "fs_common.h" +#include "directory.h" + +typedef struct { + PARTITION* partition; + DIR_ENTRY currentEntry; + u32 startCluster; + u32 posEntry; + bool inUse; + bool validEntry; +} DIR_STATE_STRUCT; + +extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); + +extern int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); + +extern int _FAT_unlink_r (struct _reent *r, const char *name); + +extern int _FAT_chdir_r (struct _reent *r, const char *name); + +extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); + +extern int _FAT_getshortname_r (struct _reent *r, const char *name, char *outName); + +extern int _FAT_hideAttrib_r (struct _reent *r, const char *name, u8 hide); + +extern int _FAT_mkdir_r (struct _reent *r, const char *path, int mode); + +/* +Directory iterator functions +*/ +extern DIR_STATE_STRUCT* _FAT_diropen_r(struct _reent *r, DIR_STATE_STRUCT *dirState, const char *path); +extern int _FAT_dirreset_r (struct _reent *r, DIR_STATE_STRUCT *dirState); +extern int _FAT_dirnext_r (struct _reent *r, DIR_STATE_STRUCT *dirState, struct stat *filestat); +extern int _FAT_dirclose_r (struct _reent *r, DIR_STATE_STRUCT *dirState); + + +#endif // _FATDIR_H diff --git a/sdk-modifications/libsrc/fs/fatdir_ex.c b/sdk-modifications/libsrc/fs/fatdir_ex.c new file mode 100644 index 0000000..b773255 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fatdir_ex.c @@ -0,0 +1,183 @@ +#include + +#include + +#include + +#include + +#include + + +#include "fatdir.h" + +#include "fatdir_ex.h" + + +#include "cache.h" + +#include "file_allocation_table.h" + +#include "partition.h" + +#include "directory.h" + +#include "bit_ops.h" + +#include "filetime.h" + +#include "unicode/unicode.h" + +int dirnextl (DIR_ITER *dirState, char *filename, char *longFilename, struct stat *filestat) +{ + DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + + + // Make sure we are still using this entry + + if (!state->inUse) { + + errno = EBADF; + return -1; + + } + + + // Make sure there is another file to report on + + if (! state->validEntry) { + errno = ENOENT; + + return -1; + + } + + + // Get the filename + + strncpy (filename, state->currentEntry.d_name, MAX_FILENAME_LENGTH); + + // Get long filename + _FAT_unicode_unicode_to_local( state->currentEntry.unicodeFilename, (u8 *)longFilename ); + + + // Get the stats, if requested + + if (filestat != NULL) { + + _FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat); + + } + + + // Look for the next entry for use next time + + state->validEntry = +_FAT_directory_getNextEntry (state->partition, &(state->currentEntry)); + + + return 0; +} + +int renamex( const char *oldName, const char *newName ) +{ + PARTITION* partition = NULL; + DIR_ENTRY oldDirEntry; + DIR_ENTRY newDirEntry; + const char *pathEnd; + u32 dirCluster; + + // Get the partition this directory is on + partition = _FAT_partition_getPartitionFromPath (oldName); + + if (partition == NULL) { + errno = ENODEV; + return -1; + } + + // Make sure the same partition is used for the old and new names + if (partition != _FAT_partition_getPartitionFromPath (newName)) { + errno = EXDEV; + return -1; + } + + // Make sure we aren't trying to write to a read-only disc + if (partition->readOnly) { + errno = EROFS; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (oldName, ':') != NULL) { + oldName = strchr (oldName, ':') + 1; + } + if (strchr (oldName, ':') != NULL) { + errno = EINVAL; + return -1; + } + if (strchr (newName, ':') != NULL) { + newName = strchr (newName, ':') + 1; + } + if (strchr (newName, ':') != NULL) { + errno = EINVAL; + return -1; + } + + // Search for the file on the disc + if (!_FAT_directory_entryFromPath (partition, &oldDirEntry, oldName, NULL)) { + errno = ENOENT; + return -1; + } + + // Make sure there is no existing file / directory with the new name + if (_FAT_directory_entryFromPath (partition, &newDirEntry, newName, NULL)) { + errno = EEXIST; + return -1; + } + + // Create the new file entry + // Get the directory it has to go in + pathEnd = strrchr (newName, DIR_SEPARATOR); + if (pathEnd == NULL) { + // No path was specified + dirCluster = partition->cwdCluster; + pathEnd = newName; + } else { + // Path was specified -- get the right dirCluster + // Recycling newDirEntry, since it needs to be recreated anyway + if (!_FAT_directory_entryFromPath (partition, &newDirEntry, newName, pathEnd) || + !_FAT_directory_isDirectory(&newDirEntry)) { + errno = ENOTDIR; + return -1; + } + dirCluster = _FAT_directory_entryGetCluster (newDirEntry.entryData); + // Move the pathEnd past the last DIR_SEPARATOR + pathEnd += 1; + } + + // Copy the entry data + memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY)); + + // Set the new name + strncpy (newDirEntry.d_name, pathEnd, MAX_FILENAME_LENGTH - 1); + + // Write the new entry + if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) { + errno = ENOSPC; + return -1; + } + + // Remove the old entry + if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) { + errno = EIO; + return -1; + } + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush (partition->cache)) { + errno = EIO; + return -1; + } + + return 0; +} diff --git a/sdk-modifications/libsrc/fs/fatdir_ex.h b/sdk-modifications/libsrc/fs/fatdir_ex.h new file mode 100644 index 0000000..fbac46f --- /dev/null +++ b/sdk-modifications/libsrc/fs/fatdir_ex.h @@ -0,0 +1,18 @@ +#ifndef _FATDIR_EX_H_ +#define _FATDIR_EX_H_ + +#include "fatdir.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int dirnextl (DIR_ITER *dirState, char *filename, char *longFilename, struct stat *filestat); +int renamex( const char *oldName, const char *newName ); + +#ifdef __cplusplus +} +#endif + + +#endif//_FATDIR_EX_H_ diff --git a/sdk-modifications/libsrc/fs/fatfile.c b/sdk-modifications/libsrc/fs/fatfile.c new file mode 100644 index 0000000..304da34 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fatfile.c @@ -0,0 +1,889 @@ +/* + fatfile.c + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-07-17 - Chishm + * Made all path inputs const char* + * Added _FAT_rename_r + + 2006-08-02 - Chishm + * Fixed _FAT_seek_r + + 2006-08-13 - Chishm + * Moved all externally visible directory related functions to fatdir +*/ +//version 1.12 + +#include "fatfile.h" + +#include +#include +#include +#include +#include + +#include "fs_cache.h" +#include "file_allocation_table.h" +#include "bit_ops.h" +#include "filetime.h" + + +int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags) { + PARTITION* partition = NULL; + bool fileExists; + DIR_ENTRY dirEntry; + const char* pathEnd; + u32 dirCluster; + FILE_STRUCT* file = (FILE_STRUCT*) fileStruct; + + + + partition = _FAT_partition_getPartitionFromPath (path); + + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + // Determine which mode the file is openned for + if ((flags & 0x03) == O_RDONLY) { + // Open the file for read-only access + file->read = true; + file->write = false; + file->append = false; + } else if ((flags & 0x03) == O_WRONLY) { + // Open file for write only access + file->read = false; + file->write = true; + file->append = false; + } else if ((flags & 0x03) == O_RDWR) { + // Open file for read/write access + file->read = true; + file->write = true; + file->append = false; + } else { + r->_errno = EACCES; + return -1; + } + + // Make sure we aren't trying to write to a read-only disc + if (file->write && partition->readOnly) { + r->_errno = EROFS; + return -1; + } + + // Search for the file on the disc + fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); + + // The file shouldn't exist if we are trying to create it + if ((flags & O_CREAT) && (flags & O_EXCL) && fileExists) { + r->_errno = EEXIST; + return -1; + } + + // It should not be a directory if we're openning a file, + if (fileExists && _FAT_directory_isDirectory(&dirEntry)) { + r->_errno = EISDIR; + return -1; + } + // If the file doesn't exist, create it if we're allowed to + if (!fileExists) { + if (flags & O_CREAT) { + if (partition->readOnly) { + // We can't write to a read-only partition + r->_errno = EROFS; + return -1; + } + // Create the file + // Get the directory it has to go in + pathEnd = strrchr (path, DIR_SEPARATOR); + if (pathEnd == NULL) { + // No path was specified + dirCluster = partition->cwdCluster; + pathEnd = path; + } else { + // Path was specified -- get the right dirCluster + // Recycling dirEntry, since it needs to be recreated anyway + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) || + !_FAT_directory_isDirectory(&dirEntry)) { + r->_errno = ENOTDIR; + return -1; + } + dirCluster = _FAT_directory_entryGetCluster (dirEntry.entryData); + // Move the pathEnd past the last DIR_SEPARATOR + pathEnd += 1; + } + // Create the entry data + strncpy (dirEntry.d_name, pathEnd, MAX_FILENAME_LENGTH - 1); + memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); + + // Set the creation time and date + dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0; + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC()); + + if (!_FAT_directory_addEntry (partition, &dirEntry, dirCluster)) { + r->_errno = ENOSPC; + return -1; + } + } else { + // file doesn't exist, and we aren't creating it + r->_errno = ENOENT; + return -1; + } + } + + file->filesize = u8array_to_u32 (dirEntry.entryData, DIR_ENTRY_fileSize); + /* Allow LARGEFILEs with undefined results + // Make sure that the file size can fit in the available space + if (!(flags & O_LARGEFILE) && (file->filesize >= (1<<31))) { + r->_errno = EFBIG; + return -1; + } + */ + + // Make sure we aren't trying to write to a read-only file + if (file->write && !_FAT_directory_isWritable(&dirEntry)) { + r->_errno = EROFS; + return -1; + } + + // Associate this file with a particular partition + file->partition = partition; + file->startCluster = _FAT_directory_entryGetCluster (dirEntry.entryData); + + // Truncate the file if requested + if ((flags & O_TRUNC) && file->write && (file->startCluster != 0)) { + _FAT_fat_clearLinks (partition, file->startCluster); + file->startCluster = 0; + file->filesize = 0; + } + + // Get a new cluster for the file if required + if (file->startCluster == 0) { + file->startCluster = _FAT_fat_linkFreeCluster (partition, CLUSTER_FREE); + } + + // Remember the position of this file's directory entry + file->dirEntryStart = dirEntry.dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + file->dirEntryEnd = dirEntry.dataEnd; + + file->currentPosition = 0; + + file->rwPosition.cluster = file->startCluster; + file->rwPosition.sector = 0; + file->rwPosition.byte = 0; + + + if (flags & O_APPEND) { + file->append = true; + file->appendPosition.cluster = _FAT_fat_lastCluster (partition, file->startCluster); + file->appendPosition.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ; + file->appendPosition.byte = file->filesize % BYTES_PER_READ; + + // Check if the end of the file is on the end of a cluster + if ( (file->filesize > 0) && ((file->filesize % partition->bytesPerCluster)==0) ){ + // Set flag to allocate a new cluster + file->appendPosition.sector = partition->sectorsPerCluster; + file->appendPosition.byte = 0; + } + } else{ + file->append = false; + file->appendPosition = file->rwPosition; + } + + file->inUse = true; + + partition->openFileCount += 1; + + return (int) file; +} + +int _FAT_close_r (struct _reent *r, int fd) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + u8 dirEntryData[DIR_ENTRY_DATA_SIZE]; + + if (!file->inUse) { + r->_errno = EBADF; + return -1; + } + if (file->write) { + // Load the old entry + _FAT_cache_readPartialSector (file->partition->cache, dirEntryData, + _FAT_fat_clusterToSector(file->partition, file->dirEntryEnd.cluster) + file->dirEntryEnd.sector, + file->dirEntryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + // Write new data to the directory entry + // File size + u32_to_u8array (dirEntryData, DIR_ENTRY_fileSize, file->filesize); + + // Start cluster + u16_to_u8array (dirEntryData, DIR_ENTRY_cluster, file->startCluster); + u16_to_u8array (dirEntryData, DIR_ENTRY_clusterHigh, file->startCluster >> 16); + + // Modification time and date + u16_to_u8array (dirEntryData, DIR_ENTRY_mTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntryData, DIR_ENTRY_mDate, _FAT_filetime_getDateFromRTC()); + + // Access date + u16_to_u8array (dirEntryData, DIR_ENTRY_aDate, _FAT_filetime_getDateFromRTC()); + + // Write the new entry + _FAT_cache_writePartialSector (file->partition->cache, dirEntryData, + _FAT_fat_clusterToSector(file->partition, file->dirEntryEnd.cluster) + file->dirEntryEnd.sector, + file->dirEntryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush(file->partition->cache)) { + r->_errno = EIO; + return -1; + } + } + + file->inUse = false; + file->partition->openFileCount -= 1; + + return 0; +} + +int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + CACHE* cache; + + FILE_POSITION position; + u32 tempNextCluster; + + int tempVar; + + u32 remain; + + bool flagNoError = true; + + // Make sure we can actually read from the file + if ((file == NULL) || !file->inUse || !file->read) { + r->_errno = EBADF; + return 0; + } + + // Don't try to read if the read pointer is past the end of file + if (file->currentPosition >= file->filesize) { + return 0; + } + + // Don't read past end of file + if (len + file->currentPosition > file->filesize) { + r->_errno = EOVERFLOW; + len = file->filesize - file->currentPosition; + } + + remain = len; //Assume len > 0 + + position = file->rwPosition; + + partition = file->partition; + cache = file->partition->cache; + + // Move onto next cluster if needed + if (position.sector >= partition->sectorsPerCluster) { + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if (tempNextCluster == CLUSTER_EOF) { + position.sector = partition->sectorsPerCluster; + } else if (tempNextCluster == CLUSTER_FREE) { + r->_errno = EIO; + return 0; + } else { + position.sector = 0; + position.cluster = tempNextCluster; + } + } + + // Align to sector + tempVar = BYTES_PER_READ - position.byte; + if (tempVar > remain) { + tempVar = remain; + } + + if (tempVar < BYTES_PER_READ) + { + _FAT_cache_readPartialSector ( cache, ptr, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, + position.byte, tempVar); + + remain -= tempVar; + ptr += tempVar; + + position.byte += tempVar; + if (position.byte >= BYTES_PER_READ) { + position.byte = 0; + position.sector++; + } + } + + // Align to cluster + //remaining more than 1 sector and read part of cluster + if((remain >= BYTES_PER_READ) && (position.sector < partition->sectorsPerCluster)) + { + // tempVar is number of sectors to write + tempVar = remain / BYTES_PER_READ; + if(tempVar > (partition->sectorsPerCluster - position.sector)) + tempVar = partition->sectorsPerCluster - position.sector; + + // read several sectors from disk + _FAT_disc_readSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, + tempVar, ptr); + + ptr += tempVar * BYTES_PER_READ; + remain -= tempVar * BYTES_PER_READ; + position.sector += tempVar; + } + + // Move onto next cluster + // It should get to here without reading anything if a cluster is due to be allocated + if ((remain>0) && (position.sector >= partition->sectorsPerCluster)) { + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if (tempNextCluster == CLUSTER_EOF) { + position.sector = partition->sectorsPerCluster; + } else if (tempNextCluster == CLUSTER_FREE) { + r->_errno = EIO; + flagNoError = false; + } else { + position.sector = 0; + position.cluster = tempNextCluster; + } + } + + // Read in whole clusters + while ((remain >= partition->bytesPerCluster) && flagNoError) { + _FAT_disc_readSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster), partition->sectorsPerCluster, ptr); + ptr += partition->bytesPerCluster; + remain -= partition->bytesPerCluster; + + // Advance to next cluster + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if ((remain == 0) && (tempNextCluster == CLUSTER_EOF)) { + position.sector = partition->sectorsPerCluster; + } else if (tempNextCluster == CLUSTER_FREE) { + r->_errno = EIO; + flagNoError = false; + } else { + position.sector = 0; + position.cluster = tempNextCluster; + } + } + + // Read remaining sectors + tempVar = remain / BYTES_PER_READ; // Number of sectors left + if ((tempVar > 0) && flagNoError) { + _FAT_disc_readSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster), + tempVar, ptr); + ptr += tempVar * BYTES_PER_READ; + remain -= tempVar * BYTES_PER_READ; + position.sector += tempVar; + } + + // Last remaining sector + // Check if anything is left + if ((remain > 0) && flagNoError) { + _FAT_cache_readPartialSector ( cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + position.byte += remain; + remain = 0; + } + + // Length read is the wanted length minus the stuff not read + len = len - remain; + + // Update file information + file->rwPosition = position; + file->currentPosition += len; + + return len; +} + +/* +Extend a file so that the size is the same as the rwPosition +*/ +static bool file_extend_r (struct _reent *r, FILE_STRUCT* file) { + PARTITION* partition = file->partition; + CACHE* cache = file->partition->cache; + + FILE_POSITION position; + + u32 remain; + + u8 zeroBuffer [BYTES_PER_READ] = {0}; + + u32 tempNextCluster; + + position.byte = file->filesize % BYTES_PER_READ; + + u32 partCluster = file->filesize % partition->bytesPerCluster; + if(0 == partCluster && 0 != file->filesize) //integer cluster + partCluster = partition->bytesPerCluster; + //position.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ; + position.sector = partCluster / BYTES_PER_READ; + + //This function index the last Cluster currently used, when file size equal Cluster size, will cause problem + position.cluster = _FAT_fat_lastCluster (partition, file->startCluster); + + remain = file->currentPosition - file->filesize; + + // Move onto next cluster if needed + if (position.sector >= partition->sectorsPerCluster) { + //Because _FAT_fat_lastCluster point to the last cluster currently used, so + //position.sector == partition->sectorsPerCluster means, the last cluster all used + //move to next cluster + position.sector = 0; + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) { + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + } + if (tempNextCluster == CLUSTER_FREE) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + return false; + } else { + position.cluster = tempNextCluster; + } + } + + // Only need to clear to the end of the sector + if (remain + position.byte < BYTES_PER_READ) { + _FAT_cache_writePartialSector (cache, zeroBuffer, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, remain); + position.byte += remain; + } else { + if (position.byte > 0) { + _FAT_cache_writePartialSector (cache, zeroBuffer, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, + BYTES_PER_READ - position.byte); + remain -= (BYTES_PER_READ - position.byte); + position.byte = 0; + position.sector ++; + } + + while (remain >= BYTES_PER_READ) { + if (position.sector >= partition->sectorsPerCluster) { + position.sector = 0; + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) { + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + } + if (tempNextCluster == CLUSTER_FREE) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + return false; + } else { + position.cluster = tempNextCluster; + } + } + + _FAT_disc_writeSectors (partition->disc, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 1, zeroBuffer); + //cancel the dirty state of cahced sctor, not necessary here, the sector haven't allocated yet + //_FAT_cache_writePartialSector_check(cache, + // _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 1, zeroBuffer); + + remain -= BYTES_PER_READ; + position.sector ++; + } + + if (position.sector >= partition->sectorsPerCluster) { + position.sector = 0; + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) { + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + } + if (tempNextCluster == CLUSTER_FREE) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + return false; + } else { + position.cluster = tempNextCluster; + } + } + + if (remain > 0) { + _FAT_cache_writePartialSector (cache, zeroBuffer, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + position.byte = remain; + } + } + + file->rwPosition = position; + file->filesize = file->currentPosition; + return true; +} + + +int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + + PARTITION* partition; + CACHE* cache; + + FILE_POSITION position; + u32 tempNextCluster; + + int tempVar; + + u32 remain; + + bool flagNoError = true; + bool flagAppending = false; + + // Make sure we can actually write to the file + if ((file == NULL) || !file->inUse || !file->write) { + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + cache = file->partition->cache; + remain = len; + + if (file->append) { + position = file->appendPosition; + flagAppending = true; + } else { + // If the write pointer is past the end of the file, extend the file to that size, + // the extended area set to zero + if (file->currentPosition > file->filesize) { //This may accure when fseek called before + if (!file_extend_r (r, file)) { //the function have done Cluster moving + return 0; + } + } + + // Write at current read pointer + position = file->rwPosition; + + // If it is writing past the current end of file, set appending flag + if (len + file->currentPosition > file->filesize) { + flagAppending = true; + } + } + + // Move onto next cluster if needed + if (position.sector >= partition->sectorsPerCluster) { + position.sector = 0; + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) { + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + } + if (tempNextCluster == CLUSTER_FREE) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + flagNoError = false; + } else { + position.cluster = tempNextCluster; + } + } + + // Align to sector + if(flagNoError && (position.byte > 0)) + { + tempVar = BYTES_PER_READ - position.byte; + if (tempVar > remain) { + tempVar = remain; + } + + // Write partial sector to disk + _FAT_cache_writePartialSector (cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, tempVar); + + remain -= tempVar; + ptr += tempVar; + position.byte += tempVar; + + // Move onto next sector + if (position.byte >= BYTES_PER_READ) { + position.byte = 0; + position.sector ++; //here may be needed move to next cluster + } + } + + // Align to cluster + //remaining more than 1 sector and used part of cluster + if(flagNoError && (remain >= BYTES_PER_READ) && (position.sector < partition->sectorsPerCluster)) + { + // tempVar is number of sectors to write + tempVar = remain / BYTES_PER_READ; + if(tempVar > (partition->sectorsPerCluster - position.sector)) + tempVar = partition->sectorsPerCluster - position.sector; + + // write several sectors to disk + _FAT_disc_writeSectors (partition->disc, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, tempVar, ptr); + //cancel the dirty state of cached sctor + _FAT_cache_writePartialSector_check(cache, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, tempVar, ptr); + + ptr += tempVar * BYTES_PER_READ; + remain -= tempVar * BYTES_PER_READ; + position.sector += tempVar; + } + + // Move onto next cluster if needed + if (flagNoError && (position.sector >= partition->sectorsPerCluster) && (remain > 0)) { + position.sector = 0; + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) { + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + } + if (tempNextCluster == CLUSTER_FREE) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + flagNoError = false; + } else { + position.cluster = tempNextCluster; + } + } + + // Write whole clusters + while ((remain >= partition->bytesPerCluster) && flagNoError) { + _FAT_disc_writeSectors (partition->disc, _FAT_fat_clusterToSector(partition, position.cluster), + partition->sectorsPerCluster, ptr); + //cancel the dirty state of cahced sctor + _FAT_cache_writePartialSector_check(cache, _FAT_fat_clusterToSector(partition, position.cluster), + partition->sectorsPerCluster, ptr); + + ptr += partition->bytesPerCluster; + remain -= partition->bytesPerCluster; + if (remain > 0) { + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) { + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + } + if (tempNextCluster == CLUSTER_FREE) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + flagNoError = false; + } else { + position.cluster = tempNextCluster; + } + } else { + // Allocate a new cluster when next writing the file + position.sector = partition->sectorsPerCluster; + } + } + + // Write remaining sectors + // Number of sectors left + tempVar = remain / BYTES_PER_READ; + if ((tempVar > 0) && flagNoError) { + _FAT_disc_writeSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster), + tempVar, ptr); + //cancel the dirty state of cahced sctor + _FAT_cache_writePartialSector_check(cache, _FAT_fat_clusterToSector (partition, position.cluster), + tempVar, ptr); + + ptr += tempVar * BYTES_PER_READ; + remain -= tempVar * BYTES_PER_READ; + position.sector += tempVar; + } + + // Last remaining partial sector + if ((remain > 0) && flagNoError) { + if (flagAppending) { + //allocated new sector, erasing remaing unused part + //Actually, no necessary. when using fwrite to increase the file size, valid data area end at currentPosition + //when using fseek to increase file size, valid data area end at rwPosition, the increased zero area will valid + //at next fwrite, fread before this can not read out the increased zero area, the file size also not changed + //before next fwrite called + _FAT_cache_eraseWritePartialSector ( cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + } else { + _FAT_cache_writePartialSector ( cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + } + position.byte += remain; + remain = 0; + } + + // Amount read is the originally requested amount minus stuff remaining + len = len - remain; + + // Update file information + if (file->append) { + // Appending doesn't affect the read pointer + file->appendPosition = position; + file->filesize += len; + } else { + // Writing also shifts the read pointer + file->rwPosition = position; + file->currentPosition += len; + if (file->filesize < file->currentPosition) { + file->filesize = file->currentPosition; + } + } + + return len; +} + +#include "ds2io.h" +int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + + PARTITION* partition; + + u32 cluster, nextCluster; + int clusCount; + int position; + + if ((file == NULL) || (file->inUse == false)) { + // invalid file + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + + switch (dir) { + case SEEK_SET: + position = pos; + break; + case SEEK_CUR: + position = file->currentPosition + pos; + break; + case SEEK_END: + position = file->filesize + pos; + break; + default: + r->_errno = EINVAL; + return -1; + } + + if ((pos > 0) && (position < 0)) { + r->_errno = EOVERFLOW; + return -1; + } + + if (position < 0) { + r->_errno = EINVAL; + return -1; + } + + // Only change the read/write position if it is within or at the bounds of the current filesize + if (file->filesize >= position) { + + // Calculate where the correct cluster is + if (position >= file->currentPosition) { + clusCount = (position / partition->bytesPerCluster) - (file->currentPosition / partition->bytesPerCluster); + cluster = file->rwPosition.cluster; + //When last reading, it stop at the cluster boundary, + //file->rwPosition.sector == partition->bytesPerCluster, but + //file->rwPosition.cluster did not move to next cluster + if(file->rwPosition.sector >= partition->sectorsPerCluster) + clusCount += 1; + } else { + clusCount = position / partition->bytesPerCluster; + cluster = file->startCluster; + } + + // Calculate the sector and byte of the current position, and store them + file->rwPosition.sector = (position % partition->bytesPerCluster) / BYTES_PER_READ; + file->rwPosition.byte = position % BYTES_PER_READ; + + nextCluster = _FAT_fat_nextCluster (partition, cluster); + while ((clusCount > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) { + clusCount--; + cluster = nextCluster; + nextCluster = _FAT_fat_nextCluster (partition, cluster); + } + + // Check if ran out of clusters, and the file is being written to + if ((clusCount > 0) && (file->write || file->append)) { + // Set flag to allocate a new cluster + file->rwPosition.sector = partition->sectorsPerCluster; + file->rwPosition.byte = 0; + } + + file->rwPosition.cluster = cluster; + } + + // Save position + file->currentPosition = position; + + return position; +} + + + +int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + + PARTITION* partition; + + DIR_ENTRY fileEntry; + + if ((file == NULL) || (file->inUse == false)) { + // invalid file + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + + // Get the file's entry data + fileEntry.dataStart = file->dirEntryStart; + fileEntry.dataEnd = file->dirEntryEnd; + + if (!_FAT_directory_entryFromPosition (partition, &fileEntry)) { + r->_errno = EIO; + return -1; + } + + // Fill in the stat struct + _FAT_directory_entryStat (partition, &fileEntry, st); + + // Fix stats that have changed since the file was openned + st->st_ino = (ino_t)(file->startCluster); // The file serial number is the start cluster + st->st_size = file->filesize; // File size + + return 0; +} + diff --git a/sdk-modifications/libsrc/fs/fatfile.h b/sdk-modifications/libsrc/fs/fatfile.h new file mode 100644 index 0000000..4869562 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fatfile.h @@ -0,0 +1,89 @@ +/* + fatfile.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-07-17 - Chishm + * Made all path inputs const char* + * Added _FAT_rename_r + + 2006-07-24 - Chishm + * Removed padding workaround from FILE_STRUCT + + 2006-08-13 - Chishm + * Moved all externally visible directory related functions to fatdir +*/ + + +#ifndef _FATFILE_H +#define _FATFILE_H + +//#include +#include + +#include "fs_common.h" +#include "partition.h" +#include "directory.h" + +typedef struct { + u32 cluster; + u32 sector; + s32 byte; +} FILE_POSITION; + +typedef struct { + int fd; + u32 filesize; + u32 startCluster; + u32 currentPosition; + FILE_POSITION rwPosition; + FILE_POSITION appendPosition; + bool read; + bool write; + bool append; + bool inUse; + PARTITION* partition; + DIR_ENTRY_POSITION dirEntryStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + DIR_ENTRY_POSITION dirEntryEnd; // Always points to the file's alias entry +} FILE_STRUCT; + +extern int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags); + +extern int _FAT_close_r (struct _reent *r, int fd); + +extern int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len); + +extern int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len); + +extern int _FAT_seek_r (struct _reent *r, int fd,int pos, int dir); + +extern int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st); + +#endif // _FATFILE_H diff --git a/sdk-modifications/libsrc/fs/fatfile_ex.c b/sdk-modifications/libsrc/fs/fatfile_ex.c new file mode 100644 index 0000000..aa23fb3 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fatfile_ex.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "cache.h" +#include "file_allocation_table.h" +#include "bit_ops.h" +#include "filetime.h" +#include "fatfile.h" + +// origin fread/fwrite do not take advantage of continuous read/write function of SD/NAND, +// it looks like the third parameter to _FAT_read_r()/_FAT_write_r() is a fixed '2' +// so they are much slower than these two.... + +// due to behavior of _FAT_read_r()/_FAT_write_r(), +// FAT should have a at least 8192 cluster size to get better performance, +// 16K or larger cluster size can get the best performance. + + + +int freadex( void * buffer, int _size, int _n, FILE * f ) +{ + if( 0 == _n ) + return 0; + dbg_printf("freadx %d\n", _n ); + struct _reent r; + int ret = _FAT_read_r( &r, (int)f->_file + 8, buffer, _size * _n ); + errno = r._errno; + return ret; +} + + +int fwriteex( const void * buffer, int _size, int _n, FILE * f ) +{ + if( 0 == _n ) + return 0; + dbg_printf("fwritex new %d\n", _n ); + struct _reent r; + int ret = _FAT_write_r( &r, (int)f->_file + 8, buffer, _size * _n ); + errno = r._errno; + return ret; +} + diff --git a/sdk-modifications/libsrc/fs/fatfile_ex.h b/sdk-modifications/libsrc/fs/fatfile_ex.h new file mode 100644 index 0000000..c434b63 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fatfile_ex.h @@ -0,0 +1,19 @@ +#ifndef _FATFILE_EX_H_ +#define _FATFILE_EX_H_ + +#include +#include "fatfile.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int freadex( void * buffer, int _size, int _n, FILE * f ); +int fwritex( const void * buffer, int _size, int _n, FILE * f ); + +#ifdef __cplusplus +} +#endif + + +#endif//_FATFILE_EX_H_ diff --git a/sdk-modifications/libsrc/fs/file_allocation_table.c b/sdk-modifications/libsrc/fs/file_allocation_table.c new file mode 100644 index 0000000..f382b52 --- /dev/null +++ b/sdk-modifications/libsrc/fs/file_allocation_table.c @@ -0,0 +1,330 @@ +/* + file_allocation_table.c + Reading, writing and manipulation of the FAT structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-07-11 - Chishm + * Made several fixes related to free clusters, thanks to Loopy + + 2006-10-01 - Chishm + * Added _FAT_fat_linkFreeClusterCleared to clear a cluster when it is allocated +*/ + + +#include "file_allocation_table.h" +#include "partition.h" +#include + +/* +Gets the cluster linked from input cluster +*/ +u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster) +{ + u32 nextCluster = CLUSTER_FREE; + u32 sector; + int offset; + + switch (partition->filesysType) + { + case FS_UNKNOWN: + nextCluster = CLUSTER_FREE; + break; + + case FS_FAT12: + sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ); + offset = ((cluster * 3) / 2) % BYTES_PER_READ; + + + _FAT_cache_readPartialSector (partition->cache, &nextCluster, sector, offset, sizeof(u8)); + + offset++; + + if (offset >= BYTES_PER_READ) { + offset = 0; + sector++; + } + + _FAT_cache_readPartialSector (partition->cache, ((u8*)&nextCluster) + sizeof(u8), sector, offset, sizeof(u8)); + + if (cluster & 0x01) { + nextCluster = nextCluster >> 4; + } else { + nextCluster &= 0x0FFF; + } + + if (nextCluster >= 0x0FF7) + { + nextCluster = CLUSTER_EOF; + } + + break; + + case FS_FAT16: + sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ); + offset = (cluster % (BYTES_PER_READ >> 1)) << 1; + + _FAT_cache_readPartialSector (partition->cache, &nextCluster, sector, offset, sizeof(u16)); + + if (nextCluster >= 0xFFF7) + { + nextCluster = CLUSTER_EOF; + } + break; + + case FS_FAT32: + sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ); + offset = (cluster % (BYTES_PER_READ >> 2)) << 2; + + _FAT_cache_readPartialSector (partition->cache, &nextCluster, sector, offset, sizeof(u32)); + + if (nextCluster >= 0x0FFFFFF7) + { + nextCluster = CLUSTER_EOF; + } + break; + + default: + nextCluster = CLUSTER_FREE; + break; + } + + return nextCluster; +} + +/* +writes value into the correct offset within a partition's FAT, based +on the cluster number. +*/ +static bool _FAT_fat_writeFatEntry (PARTITION* partition, u32 cluster, u32 value) { + u32 sector; + int offset; + u8 oldValue; + + if ((cluster < 0x0002) || (cluster > partition->fat.lastCluster)) + { + return false; + } + + switch (partition->filesysType) + { + case FS_UNKNOWN: + return false; + break; + + case FS_FAT12: + sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ); + offset = ((cluster * 3) / 2) % BYTES_PER_READ; + + if (cluster & 0x01) { + + _FAT_cache_readPartialSector (partition->cache, &oldValue, sector, offset, sizeof(u8)); + + value = (value << 4) | (oldValue & 0x0F); + + _FAT_cache_writePartialSector (partition->cache, &value, sector, offset, sizeof(u8)); + + offset++; + if (offset >= BYTES_PER_READ) { + offset = 0; + sector++; + } + + _FAT_cache_writePartialSector (partition->cache, ((u8*)&value) + sizeof(u8), sector, offset, sizeof(u8)); + + } else { + + _FAT_cache_writePartialSector (partition->cache, &value, sector, offset, sizeof(u8)); + + offset++; + if (offset >= BYTES_PER_READ) { + offset = 0; + sector++; + } + + _FAT_cache_readPartialSector (partition->cache, &oldValue, sector, offset, sizeof(u8)); + + value = ((value >> 8) & 0x0F) | (oldValue & 0xF0); + + _FAT_cache_writePartialSector (partition->cache, &value, sector, offset, sizeof(u8)); + } + + break; + + case FS_FAT16: + sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ); + offset = (cluster % (BYTES_PER_READ >> 1)) << 1; + + _FAT_cache_writePartialSector (partition->cache, &value, sector, offset, sizeof(u16)); + + break; + + case FS_FAT32: + sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ); + offset = (cluster % (BYTES_PER_READ >> 2)) << 2; + + _FAT_cache_writePartialSector (partition->cache, &value, sector, offset, sizeof(u32)); + + break; + + default: + return false; + break; + } + + return true; +} + +/*----------------------------------------------------------------- +gets the first available free cluster, sets it +to end of file, links the input cluster to it then returns the +cluster number +If an error occurs, return CLUSTER_FREE +-----------------------------------------------------------------*/ +u32 _FAT_fat_linkFreeCluster(PARTITION* partition, u32 cluster) { + u32 firstFree; + u32 curLink; + u32 lastCluster; + bool loopedAroundFAT = false; + + lastCluster = partition->fat.lastCluster; + + if (cluster > lastCluster) { + return CLUSTER_FREE; + } + + // Check if the cluster already has a link, and return it if so + curLink = _FAT_fat_nextCluster(partition, cluster); + if ((curLink >= CLUSTER_FIRST) && (curLink <= lastCluster)) { + return curLink; // Return the current link - don't allocate a new one + } + + // Get a free cluster + firstFree = partition->fat.firstFree; + // Start at first valid cluster + if (firstFree < CLUSTER_FIRST) { + firstFree = CLUSTER_FIRST; + } + + // Search until a free cluster is found + while (_FAT_fat_nextCluster(partition, firstFree) != CLUSTER_FREE) { + firstFree++; + if (firstFree > lastCluster) { + if (loopedAroundFAT) { + // If couldn't get a free cluster then return, saying this fact + partition->fat.firstFree = firstFree; + return CLUSTER_FREE; + } else { + // Try looping back to the beginning of the FAT + // This was suggested by loopy + firstFree = CLUSTER_FIRST; + loopedAroundFAT = true; + } + } + } + partition->fat.firstFree = firstFree; + + if ((cluster >= CLUSTER_FIRST) && (cluster < lastCluster)) + { + // Update the linked from FAT entry + _FAT_fat_writeFatEntry (partition, cluster, firstFree); + } + // Create the linked to FAT entry + _FAT_fat_writeFatEntry (partition, firstFree, CLUSTER_EOF); + + return firstFree; +} + +/*----------------------------------------------------------------- +gets the first available free cluster, sets it +to end of file, links the input cluster to it, clears the new +cluster to 0 valued bytes, then returns the cluster number +If an error occurs, return CLUSTER_FREE +-----------------------------------------------------------------*/ +u32 _FAT_fat_linkFreeClusterCleared (PARTITION* partition, u32 cluster) { + u32 newCluster; + int i; + u8 emptySector[BYTES_PER_READ]; + + // Link the cluster + newCluster = _FAT_fat_linkFreeCluster(partition, cluster); + if (newCluster == CLUSTER_FREE) { + return CLUSTER_FREE; + } + + // Clear all the sectors within the cluster + memset (emptySector, 0, BYTES_PER_READ); + for (i = 0; i < partition->sectorsPerCluster; i++) { + _FAT_disc_writeSectors (partition->disc, + _FAT_fat_clusterToSector (partition, newCluster) + i, + 1, emptySector); + } + + return newCluster; +} + + +/*----------------------------------------------------------------- +_FAT_fat_clearLinks +frees any cluster used by a file +-----------------------------------------------------------------*/ +bool _FAT_fat_clearLinks (PARTITION* partition, u32 cluster) { + u32 nextCluster; + + if ((cluster < 0x0002) || (cluster > partition->fat.lastCluster)) + return false; + + // If this clears up more space in the FAT before the current free pointer, move it backwards + if (cluster < partition->fat.firstFree) { + partition->fat.firstFree = cluster; + } + + while ((cluster != CLUSTER_EOF) && (cluster != CLUSTER_FREE)) { + // Store next cluster before erasing the link + nextCluster = _FAT_fat_nextCluster (partition, cluster); + + // Erase the link + _FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE); + + // Move onto next cluster + cluster = nextCluster; + } + + return true; +} + +/*----------------------------------------------------------------- +_FAT_fat_lastCluster +Trace the cluster links until the last one is found +-----------------------------------------------------------------*/ +u32 _FAT_fat_lastCluster (PARTITION* partition, u32 cluster) { + while ((_FAT_fat_nextCluster(partition, cluster) != CLUSTER_FREE) && (_FAT_fat_nextCluster(partition, cluster) != CLUSTER_EOF)) { + cluster = _FAT_fat_nextCluster(partition, cluster); + } + return cluster; +} diff --git a/sdk-modifications/libsrc/fs/file_allocation_table.h b/sdk-modifications/libsrc/fs/file_allocation_table.h new file mode 100644 index 0000000..4fb4149 --- /dev/null +++ b/sdk-modifications/libsrc/fs/file_allocation_table.h @@ -0,0 +1,64 @@ +/* + file_allocation_table.h + Reading, writing and manipulation of the FAT structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-10-01 - Chishm + * Added _FAT_fat_linkFreeClusterCleared to clear a cluster when it is allocated +*/ + +#ifndef _FAT_H +#define _FAT_H + +#include "fs_common.h" +#include "partition.h" + +#define CLUSTER_EOF_16 0xFFFF +#define CLUSTER_EOF 0x0FFFFFFF +#define CLUSTER_FREE 0x0000 +#define CLUSTER_FIRST 0x0002 + +#define CLUSTERS_PER_FAT12 4085 +#define CLUSTERS_PER_FAT16 65525 + + +u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster); + +u32 _FAT_fat_linkFreeCluster(PARTITION* partition, u32 cluster); +u32 _FAT_fat_linkFreeClusterCleared (PARTITION* partition, u32 cluster); + +bool _FAT_fat_clearLinks (PARTITION* partition, u32 cluster); + +u32 _FAT_fat_lastCluster (PARTITION* partition, u32 cluster); + +static inline u32 _FAT_fat_clusterToSector (PARTITION* partition, u32 cluster) { + return (cluster >= 2) ? ((cluster - 2) * partition->sectorsPerCluster) + partition->dataStart : partition->rootDirStart; +} + +#endif // _FAT_H diff --git a/sdk-modifications/libsrc/fs/filetime.c b/sdk-modifications/libsrc/fs/filetime.c new file mode 100644 index 0000000..f2de6ef --- /dev/null +++ b/sdk-modifications/libsrc/fs/filetime.c @@ -0,0 +1,146 @@ +/* + filetime.c + Conversion of file time and date values to various other types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-09-30 - Chishm + * Validity checks performed on the time supplied by the IPC + * Cleaned up magic numbers + + 2006-10-01 - Chishm + * Fixed incorrect use of bitwise-or instead of logical-or +*/ + + +#include "filetime.h" + +#ifdef NDS +//#include +#include "ds2io.h" +#endif + +#define HOUR_PM_INDICATOR 40 + +#define MAX_HOUR 23 +#define MAX_MINUTE 59 +#define MAX_SECOND 59 + +#define MAX_YEAR 99 +#define MIN_YEAR 6 // The date is invalid if it's before this year +#define MAX_MONTH 12 +#define MIN_MONTH 1 +#define MAX_DAY 31 +#define MIN_DAY 1 + +// Second values are averages, so time value won't be 100% accurate, +// but should be within the correct month. +#define SECONDS_PER_MINUTE 60 +#define SECONDS_PER_HOUR 3600 +#define SECONDS_PER_DAY 86400 +#define SECONDS_PER_MONTH 2629743 +#define SECONDS_PER_YEAR 31556926 + +u16 _FAT_filetime_getTimeFromRTC (void) { +#ifdef NDS + int hour, minute, second; + struct rtc time; + + ds2_getTime(&time); + + hour = (time.hours >= HOUR_PM_INDICATOR ? time.hours - HOUR_PM_INDICATOR : time.hours); + minute = time.minutes; + second = time.seconds; + + // Check that the values are all in range. + // If they are not, return 0 (no timestamp) + if ((hour < 0) || (hour > MAX_HOUR)) return 0; + if ((minute < 0) || (minute > MAX_MINUTE)) return 0; + if ((second < 0) || (second > MAX_SECOND)) return 0; + + return ( + ((hour & 0x1F) << 11) | + ((minute & 0x3F) << 5) | + ((second >> 1) & 0x1F) + ); +#else + return 0; +#endif +} + + +u16 _FAT_filetime_getDateFromRTC (void) { +#ifdef NDS + int year, month, day; + struct rtc time; + + ds2_getTime(&time); + + year = time.year; + month = time.month; + day = time.day; + + if ((year < MIN_YEAR) || (year > MAX_YEAR)) return 0; + if ((month < MIN_MONTH) || (month > MAX_MONTH)) return 0; + if ((day < MIN_DAY) || (day > MAX_DAY)) return 0; + + return ( + (((year + 20) & 0x7F) <<9) | // Adjust for MS-FAT base year (1980 vs 2000 for DS clock) + ((month & 0xF) << 5) | + (day & 0x1F) + ); +#else + return 0; +#endif +} + +time_t _FAT_filetime_to_time_t (u16 time, u16 date) { + int hour, minute, second; + int day, month, year; + + time_t result; + + hour = time >> 11; + minute = (time >> 5) & 0x3F; + second = (time & 0x1F) << 1; + + day = date & 0x1F; + month = (date >> 5) & 0x0F; + year = date >> 9; + + // Second values are averages, so time value won't be 100% accurate, + // but should be within the correct month. + result = second + + minute * SECONDS_PER_MINUTE + + hour * SECONDS_PER_HOUR + + day * SECONDS_PER_DAY + + month * SECONDS_PER_MONTH + + year * SECONDS_PER_YEAR + ; + + return result; +} diff --git a/sdk-modifications/libsrc/fs/filetime.h b/sdk-modifications/libsrc/fs/filetime.h new file mode 100644 index 0000000..fa651a7 --- /dev/null +++ b/sdk-modifications/libsrc/fs/filetime.h @@ -0,0 +1,44 @@ +/* + filetime.h + Conversion of file time and date values to various other types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _FILETIME_H +#define _FILETIME_H + +#include "fs_common.h" +#include + +u16 _FAT_filetime_getTimeFromRTC (void); +u16 _FAT_filetime_getDateFromRTC (void); + +time_t _FAT_filetime_to_time_t (u16 time, u16 date); + + +#endif // _FILETIME_H diff --git a/sdk-modifications/libsrc/fs/fs.mk b/sdk-modifications/libsrc/fs/fs.mk new file mode 100644 index 0000000..9b17c48 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fs.mk @@ -0,0 +1,24 @@ +#fs.mk + +SRC += $(FS_DIR)/cache.c \ + $(FS_DIR)/directory.c \ + $(FS_DIR)/fatdir.c \ + $(FS_DIR)/fatfile.c \ + $(FS_DIR)/file_allocation_table.c \ + $(FS_DIR)/filetime.c \ + $(FS_DIR)/fs_api.c \ + $(FS_DIR)/fs_unicode.c \ + $(FS_DIR)/libfat.c \ + $(FS_DIR)/partition.c \ + $(FS_DIR)/fat_misc.c \ + $(FS_DIR)/disc_io/disc.c \ + $(FS_DIR)/disc_io/io_ds2_mmcf.c \ + $(FS_DIR)/ds2_fcntl.c \ + $(FS_DIR)/ds2_unistd.c \ + +SSRC += + +INC += -I$(FS_DIR) -I$(FS_DIR)/disc_io + +CFLAGS += -DNDS + diff --git a/sdk-modifications/libsrc/fs/fs_api.c b/sdk-modifications/libsrc/fs/fs_api.c new file mode 100644 index 0000000..b23a450 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fs_api.c @@ -0,0 +1,452 @@ +//fs_api.c + +#include +#include +#include +#include +#include +#include +#include "fs_common.h" +#include "fatfile.h" +#include "fatdir.h" + +typedef unsigned int size_t; +typedef unsigned int mode_t; + +typedef struct { + const char* mode; /* mode string */ + unsigned int flag; /* mode flag */ +// unsigned char mode_r; /* READ */ +// unsigned char mode_w; /* WRITE */ +// unsigned char mode_a; /* APPEND */ +// unsigned char mode_c; /* CREATE */ +} _fat_mode_type; + +static const _fat_mode_type _fat_valid_mode[] = { + { "r" , O_RDONLY }, + { "w" , O_WRONLY | O_TRUNC | O_CREAT }, + { "a" , O_WRONLY | O_APPEND | O_CREAT }, + { "rb" , O_RDONLY }, + { "wb" , O_WRONLY | O_TRUNC | O_CREAT }, + { "ab" , O_WRONLY | O_APPEND | O_CREAT }, + { "r+" , O_RDWR }, + { "w+" , O_RDWR | O_TRUNC | O_CREAT }, + { "a+" , O_RDWR | O_APPEND | O_CREAT }, + { "r+b" , O_RDWR }, + { "rb+" , O_RDWR }, + { "w+b" , O_RDWR | O_TRUNC | O_CREAT }, + { "wb+" , O_RDWR | O_TRUNC | O_CREAT }, + { "a+b" , O_RDWR | O_APPEND | O_CREAT }, + { "ab+" , O_RDWR | O_APPEND | O_CREAT } +}; + +#define MAX_OPEN_FILE 16 +#define MAX_OPEN_DIR 32 +#define MAX_PWD_LEN 512 +#define MAX_STDIO_BUF_SIZE 2048 + +#define FAT_VALID_MODE_NUM (sizeof(_fat_valid_mode)/sizeof(_fat_mode_type)) + +static FILE_STRUCT __FILEs[MAX_OPEN_FILE]; +struct _reent __REENT; +static DIR_STATE_STRUCT __DIRs[MAX_OPEN_DIR]; +static char __PWD[MAX_PWD_LEN]; + +int fat_init(void) +{ + int i, flag; + + for(i= 0; i < MAX_OPEN_FILE; i++) + __FILEs[i].inUse = false; + + for(i= 0; i < MAX_OPEN_DIR; i++) + __DIRs[i].inUse = false; + + flag = -1; + if(_FAT_Init() == true) //success + flag = 0; + + return flag; +} + +FILE_STRUCT* fat_fopen(const char *file, const char *mode) +{ + int i, k; + int fd; + FILE_STRUCT* fp; + + for(i= 0; i < MAX_OPEN_FILE; i++) + if(false == __FILEs[i].inUse) break; + + if(i >= MAX_OPEN_FILE) + { + __REENT._errno = EMFILE; /* Too many open files */ + return NULL; + } + + for(k = 0; k < FAT_VALID_MODE_NUM; k++) + if(!strcasecmp(_fat_valid_mode[k].mode, mode)) break; + + if(k >= FAT_VALID_MODE_NUM) + { + __REENT._errno = EINVAL; + return NULL; + } + + fd = _FAT_open_r(&__REENT, (void*)&__FILEs[i], file, _fat_valid_mode[k].flag); + if(-1 == fd) return NULL; + + fp = &__FILEs[i]; + fp -> fd = fd; + + return fp; +} + +size_t fat_fread(void *buf, size_t size, size_t count, FILE_STRUCT *fp) +{ + if(0 == size || 0 == count) + return 0; + + int len = _FAT_read_r(&__REENT, fp->fd, (char*)buf, size*count); + len /= size; + return len; +} + +size_t fat_fwrite(const void *buf, size_t size, size_t count, FILE_STRUCT *fp) +{ + if(0 == size || 0 == count) + return 0; + + int len = _FAT_write_r(&__REENT, fp->fd, (const char*)buf, size*count); + len /= size; + + return len; +} + +int fat_fclose(FILE_STRUCT *fp) +{ + return( _FAT_close_r(&__REENT, fp->fd) ); +} + +int fat_fseek(FILE_STRUCT *fp, long offset, int whence) +{ + int flag; + + //When success, _FAT_seek_r return file position pointer + flag = _FAT_seek_r (&__REENT, fp->fd, (int)offset, whence); + if(flag > 0) flag = 0; + + return flag; +} + +long fat_ftell(FILE_STRUCT *fp) +{ + return( (long)fp->currentPosition ); +} + +int fat_feof(FILE_STRUCT *fp) +{ + int result; + + result = 0; + if((fp->currentPosition +1) >= (fp->filesize)) + result = -1; + + return result; +} + +int fat_ferror(FILE_STRUCT *fp) +{ + return( __REENT._errno ); +} + +void fat_clearerr(FILE_STRUCT *fp) +{ + fp = fp; + + __REENT._errno = 0; +} + +int fat_fflush(FILE_STRUCT *fp) +{ + return(_FAT_cache_flush(fp->partition->cache)); +} + +int fat_fgetc(FILE_STRUCT *fp) +{ + char ch; + int result; + + result = _FAT_read_r(&__REENT, fp->fd, &ch, 1); + if(0 == result) + return EOF; + + return ( (int)ch ); +} + +char* fat_fgets(char* buf, int n, FILE_STRUCT* fp) +{ + int m; + char *s; + + buf[0] = '\0'; + if(n <= 1) return buf; + + n -= 1; + m = _FAT_read_r(&__REENT, fp->fd, buf, n); + if(0 == m) return NULL; + + buf[m] = '\0'; + s = strchr((const char*)buf, 0x0A); + + if(NULL != s) + { + *(++s)= '\0'; + m -= s - buf; + + //fix reading pointer + _FAT_seek_r (&__REENT, fp->fd, -m, SEEK_CUR); + } + else if(m == n) + { + if(0x0D == buf[n-1]) //0x0D,0x0A + { + buf[n-1] = '\0'; + _FAT_seek_r (&__REENT, fp->fd, -1, SEEK_CUR); + } + } + + return buf; +} + +int fat_fputc(int ch, FILE_STRUCT *fp) +{ + return( _FAT_write_r(&__REENT, fp->fd, (const char*)&ch, 1) ); +} + +int fat_fputs(const char *s, FILE_STRUCT *fp) +{ + unsigned int len; + + len = strlen(s); + return( _FAT_write_r(&__REENT, fp->fd, s, len) ); +} + +int fat_remove(const char *filename) +{ + return( _FAT_unlink_r (&__REENT, (const char*)filename) ); +} + +int fat_rename(const char *oldName, const char *newName) +{ + return( _FAT_rename_r(&__REENT, oldName, newName) ); +} + +int fat_setHidden(const char *name, unsigned char hide){ + return(_FAT_hideAttrib_r (&__REENT, name, hide)); +} + +#define S_ISHID(st_mode) ((st_mode & S_IHIDDEN) != 0) +int fat_isHidden(struct stat *st){ + return S_ISHID(st->st_mode); +} + +int fat_getShortName(const char *fullName, char *outName){ + return(_FAT_getshortname_r (&__REENT, fullName, outName)); +} + + +void fat_rewind(FILE_STRUCT *fp) +{ + _FAT_seek_r (&__REENT, fp->fd, 0, SEEK_SET); +} + +int fat_fstat(int fildes, struct stat *buf) +{ + return( _FAT_fstat_r (&__REENT, fildes, buf) ); +} + +//int fat_fprintf(FILE_STRUCT *fp, const char *format, ...) +int fat_fprintf(void* fp, const char *format, ...) +{ + int ret; + va_list ap; + char buf[MAX_STDIO_BUF_SIZE]; + + if(NULL == fp) + { + __REENT._errno = EINVAL; + return -1; + } + + //FIXME: stderr, stdout + if((void*)stderr == fp) return 0; + if((void*)stdout == fp) return 0; + + memset(buf, 0, MAX_STDIO_BUF_SIZE); + + va_start (ap, format); + ret = vsnprintf (buf, MAX_STDIO_BUF_SIZE, format, ap); + va_end (ap); + + //if output string too long, it will not put out to file + if(ret >= MAX_STDIO_BUF_SIZE) + return -1; + + return( _FAT_write_r(&__REENT, ((FILE_STRUCT*)fp)->fd, (const char*)buf, strlen(buf)) ); +} + +int fat_fscanf(FILE_STRUCT *fp, const char *format, ...) +{ + int ret; + va_list ap; + char buf[MAX_STDIO_BUF_SIZE]; + char *pt; + + if(NULL == fp) + { + __REENT._errno = EINVAL; + return -1; + } + + pt = fat_fgets(buf, MAX_STDIO_BUF_SIZE, fp); + if(NULL == pt) + return -1; + + va_start (ap, format); + ret = vsscanf (buf, format, ap); + + return ret; +} + +DIR_STATE_STRUCT* fat_opendir(const char *name) +{ + int i; + + for(i = 0; i < MAX_OPEN_DIR; i++) + { + if(false == __DIRs[i].inUse) break; + } + + if(i>= MAX_OPEN_DIR) + { + __REENT._errno = EMFILE; /* Too many open files */ + return NULL; + } + + return( _FAT_diropen_r(&__REENT, &__DIRs[i], name) ); +} + +DIR_ENTRY* fat_readdir(DIR_STATE_STRUCT *dirp) +{ + int isValid; + + isValid = _FAT_dirnext_r (&__REENT, dirp, NULL); + if(0 != isValid) + return NULL; + + return( &(dirp->currentEntry) ); +} + +long int fat_telldir(DIR_STATE_STRUCT *dirp) +{ + return( dirp->posEntry ); +} + +void fat_seekdir(DIR_STATE_STRUCT *dirp, long int loc) +{ + if (!dirp->inUse) { + __REENT._errno = EBADF; + return; + } + + if(0 == loc) + { + dirp->posEntry = 0; + } + else if(loc > 0) + { + while(dirp->posEntry < loc) + { + dirp->validEntry = _FAT_directory_getNextEntry (dirp->partition, &(dirp->currentEntry)); + dirp->posEntry += 1; + + if(!dirp->validEntry) break; + } + } + + return; +} + +int fat_closedir(DIR_STATE_STRUCT *dirp) +{ + return(_FAT_dirclose_r (&__REENT, dirp)); +} + +int fat_chdir(const char *path) +{ + int ret; + char *pt; + + ret = _FAT_chdir_r (&__REENT, path); + if(0 != ret) return -1; + + pt = strchr(path, ':'); + if(pt == NULL) + strcat(__PWD, path); + else + strcpy(__PWD, path); + + pt = strchr(__PWD, '\0'); + while(pt-- != __PWD) + { + if(pt[0] != DIR_SEPARATOR) break; + } + + pt[1] = DIR_SEPARATOR; + pt[2] = '\0'; + + return 0; +} + +char* fat_getcwd(char *buf, size_t size) +{ + int len; + + len = strlen(__PWD); + if(len >= size) + { + __REENT._errno = ERANGE; + return NULL; + } + + strcpy(buf, __PWD); + return buf; +} + +int fat_mkdir(const char *path, mode_t mode) +{ + return( _FAT_mkdir_r(&__REENT, path, mode) ); +} + +int fat_rmdir(const char *path) +{ + return( _FAT_unlink_r(&__REENT, path) ); +} + +int fat_lstat(const char *path, struct stat *buf) +{ + return( _FAT_stat_r (&__REENT, path, buf) ); +} + +DIR_ENTRY* fat_readdir_ex(DIR_STATE_STRUCT *dirp, struct stat *statbuf) +{ + int isValid; + + isValid = _FAT_dirnext_r (&__REENT, dirp, statbuf); + if(0 != isValid) + return NULL; + + return( &(dirp->currentEntry) ); +} + diff --git a/sdk-modifications/libsrc/fs/fs_api.h b/sdk-modifications/libsrc/fs/fs_api.h new file mode 100644 index 0000000..fa4ae07 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fs_api.h @@ -0,0 +1,130 @@ +#ifndef __FS_API_H__ +#define __FS_API_H__ +//v1.0 + +#include "sys/stat.h" +#include "fatfile.h" +#include "fatdir.h" + +extern struct _reent __REENT; +typedef unsigned int mode_t; + +extern int fat_init(void); + +extern FILE_STRUCT* fat_fopen(const char *file, const char *mode); + +extern size_t fat_fread(void *buf, size_t size, size_t count, FILE_STRUCT *fp); + +extern size_t fat_fwrite(const void *buf, size_t size, size_t count, FILE_STRUCT *fp); + +extern int fat_fclose(FILE_STRUCT *fp); + +extern int fat_fseek(FILE_STRUCT *fp, long offset, int whence); + +extern long fat_ftell(FILE_STRUCT *fp); + +extern int fat_feof(FILE_STRUCT *fp); + +extern int fat_ferror(FILE_STRUCT *fp); + +extern void fat_clearerr(FILE_STRUCT *fp); + +extern int fat_fflush(FILE_STRUCT *fp); + +extern int fat_fgetc(FILE_STRUCT *fp); + +extern char* fat_fgets(char *buf, int n, FILE_STRUCT *fp); + +extern int fat_fputc(int ch, FILE_STRUCT *fp); + +extern int fat_fputs(const char *s, FILE_STRUCT *fp); + +extern int fat_remove(const char *filename); + +extern int fat_rename(const char *oldName, const char *newName); + +extern int fat_setHidden(const char *name, unsigned char hide); + +extern int fat_isHidden(struct stat *st); + +extern int fat_getShortName(const char *fullName, char *outName); + +extern void fat_rewind(FILE_STRUCT *fp); + +extern int fat_fstat(int fildes, struct stat *buf); + +extern int fat_fprintf(void* fp, const char *format, ...); + +extern int fat_fscanf(FILE_STRUCT *fp, const char *format, ...); + +extern DIR_STATE_STRUCT* fat_opendir(const char *name); + +extern DIR_ENTRY* fat_readdir(DIR_STATE_STRUCT *dirp); + +extern long fat_telldir(DIR_STATE_STRUCT *dirp); + +extern void fat_seekdir(DIR_STATE_STRUCT *dirp, long int loc); + +extern int fat_closedir(DIR_STATE_STRUCT *dirp); + +extern int fat_chdir(const char *path); + +extern char* fat_getcwd(char *buf, size_t size); + +extern int fat_mkdir(const char *path, mode_t mode); + +extern int fat_rmdir(const char *path); + +extern int fat_lstat(const char *path, struct stat *buf); + +extern DIR_ENTRY* fat_readdir_ex(DIR_STATE_STRUCT *dirp, struct stat *statbuf); + +//#define S_ISDIR(st) (st.st_mode & S_IFDIR) + +#define FILE FILE_STRUCT +#define fopen fat_fopen +#define fread fat_fread +#define fwrite fat_fwrite +#define fclose fat_fclose +#define fseek fat_fseek +#define ftell fat_ftell +#define feof fat_feof +#define ferror fat_ferror +#define fclearerr fat_clearerr +#define fflush fat_fflush +#define fgetc fat_fgetc +#define fgets fat_fgets +#define fputc fat_fputc +#define fputs fat_fputs +#define fprintf fat_fprintf +#define fscanf fat_fscanf +#define remove fat_remove +#define fhidden fat_isHidden + +#define DIR DIR_STATE_STRUCT +#define dirent DIR_ENTRY +#define opendir fat_opendir +#define readdir fat_readdir +#define telldir fat_telldir +#define seekdir fat_seekdir +#define closedir fat_closedir +#define chdir fat_chdir +#define getcwd fat_getcwd +#define mkdir fat_mkdir +#define rmdir fat_rmdir + +#define lstat fat_lstat +#define fstat fat_fstat + +#define S_ISHID(st_mode) ((st_mode & S_IHIDDEN) != 0) + +//the extended version of readdir_ex +#define readdir_ex fat_readdir_ex + +#define MAX_PATH 512 +#define MAX_FILE 512 + +//Misc function +extern bool fat_getDiskSpaceInfo( char * diskName, unsigned int *total, unsigned int *used, unsigned int *freeSpace ); + +#endif //__FS_API_H__ diff --git a/sdk-modifications/libsrc/fs/fs_cache.h b/sdk-modifications/libsrc/fs/fs_cache.h new file mode 100644 index 0000000..1abae66 --- /dev/null +++ b/sdk-modifications/libsrc/fs/fs_cache.h @@ -0,0 +1,125 @@ +/* + cache.h + The cache is not visible to the user. It should be flushed + when any file is closed or changes are made to the filesystem. + + This cache implements a least-used-page replacement policy. This will + distribute sectors evenly over the pages, so if less than the maximum + pages are used at once, they should all eventually remain in the cache. + This also has the benefit of throwing out old sectors, so as not to keep + too many stale pages around. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _CACHE_H +#define _CACHE_H + +#include "fs_common.h" +#include "disc_io/disc_io.h" + +#define CACHE_PAGE_SIZE BYTES_PER_READ + +typedef struct { + u32 sector; + u32 count; + bool dirty; +} CACHE_ENTRY; + +typedef struct { + const IO_INTERFACE* disc; + u32 numberOfPages; + CACHE_ENTRY* cacheEntries; + u8* pages; +} CACHE; + + +/* +Read data from a sector in the cache +If the sector is not in the cache, it will be swapped in +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, u32 sector, u32 offset, u32 size); + +/* +Write data to a sector in the cache +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); + +/* +some where call _FAT_cache_writePartialSector to cache sector m , but later, another +place(in fwrite function) directly write data to sector m, in this case, need to +cancel the dirty state of sector m +*/ +void _FAT_cache_writePartialSector_check (CACHE* cache, u32 sector, u32 num, const void* buffer); + +/* +Write data to a sector in the cache, zeroing the sector first +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); + +/* +Read a full sector from the cache +*/ +static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, u32 sector) { + return _FAT_cache_readPartialSector (cache, buffer, sector, 0, BYTES_PER_READ); +} + +/* +Write a full sector to the cache +*/ +static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, u32 sector) { + return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ); +} + +/* +Write any dirty sectors back to disc and clear out the contents of the cache +*/ +bool _FAT_cache_flush (CACHE* cache); + +/* +Clear out the contents of the cache without writing any dirty sectors first +*/ +void _FAT_cache_invalidate (CACHE* cache); + +CACHE* _FAT_cache_constructor (u32 numberOfPages, const IO_INTERFACE* discInterface); + +void _FAT_cache_destructor (CACHE* cache); + +#endif // _CACHE_H diff --git a/sdk-modifications/libsrc/fs/fs_common.h b/sdk-modifications/libsrc/fs/fs_common.h new file mode 100644 index 0000000..ce1cfff --- /dev/null +++ b/sdk-modifications/libsrc/fs/fs_common.h @@ -0,0 +1,129 @@ +/* + common.h + Common definitions and included files for the FATlib + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _COMMON_H +#define _COMMON_H + +// When compiling for NDS, make sure NDS is defined +#ifndef NDS + #if defined ARM9 || defined ARM7 + #define NDS + #endif +#endif + +#if 0 +#ifdef NDS + #include +#else + #include "gba_types.h" +#endif +#endif + +#define BYTES_PER_READ 512 + +#ifndef NULL + #define NULL 0 +#endif + +#ifndef bool +#define bool int +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef u32 +#define u32 unsigned long +#endif + +#ifndef s32 +#define s32 long +#endif + +struct _reent +{ + /* FILE is a big struct and may change over time. To try to achieve binary + compatibility with future versions, put stdin,stdout,stderr here. + These are pointers into member __sf defined below. */ +// __FILE *_stdin, *_stdout, *_stderr; /* XXX */ + + int _errno; /* local copy of errno */ + +// int _inc; /* used by tmpnam */ + +// char *_emergency; + +// int __sdidinit; /* 1 means stdio has been init'd */ + +// int _current_category; /* unused */ +// _CONST char *_current_locale; /* unused */ + +// struct _mprec *_mp; + +// void _EXFNPTR(__cleanup, (struct _reent *)); + +// int _gamma_signgam; + + /* used by some fp conversion routines */ +// int _cvtlen; /* should be size_t */ +// char *_cvtbuf; + +// struct _rand48 *_r48; +// struct __tm *_localtime_buf; +// char *_asctime_buf; + + /* signal info */ +// void (**(_sig_func))(int); + + /* atexit stuff */ +// struct _atexit *_atexit; +// struct _atexit _atexit0; + +// struct _glue __sglue; /* root of glue chain */ +// __FILE *__sf; /* file descriptors */ +// struct _misc_reent *_misc; /* strtok, multibyte states */ +// char *_signal_buf; /* strsignal */ +}; + +#endif // _COMMON_H diff --git a/sdk-modifications/libsrc/fs/fs_unicode.c b/sdk-modifications/libsrc/fs/fs_unicode.c new file mode 100644 index 0000000..2f1c1ed --- /dev/null +++ b/sdk-modifications/libsrc/fs/fs_unicode.c @@ -0,0 +1,173 @@ +//fs_unicode.c + +#include +#include "fs_common.h" + +//void _FAT_unicode_init_default() // ANSI CODE PAGE +//{ +// _L2UTable = NULL; +// _U2LTable = NULL; +// _ankTable = NULL; +//} + +static inline const char* _FAT_utf8decode(const char* utf8, u16 *ucs) +{ + unsigned char c = *utf8++; + unsigned long code; + int tail = 0; + + if ((c <= 0x7f) || (c >= 0xc2)) { + /* Start of new character. */ + if (c < 0x80) { /* U-00000000 - U-0000007F, 1 byte */ + code = c; + } else if (c < 0xe0) { /* U-00000080 - U-000007FF, 2 bytes */ + tail = 1; + code = c & 0x1f; + } else if (c < 0xf0) { /* U-00000800 - U-0000FFFF, 3 bytes */ + tail = 2; + code = c & 0x0f; + } else if (c < 0xf5) { /* U-00010000 - U-001FFFFF, 4 bytes */ + tail = 3; + code = c & 0x07; + } else { + /* Invalid size. */ + code = 0; + } + + while (tail-- && ((c = *utf8++) != 0)) { + if ((c & 0xc0) == 0x80) { + /* Valid continuation character. */ + code = (code << 6) | (c & 0x3f); + + } else { + /* Invalid continuation char */ + code = 0xfffd; + utf8--; + break; + } + } + } else { + /* Invalid UTF-8 char */ + code = 0; + } + /* currently we don't support chars above U-FFFF */ + *ucs = (code < 0x10000) ? code : 0; + return utf8; +} + +void _FAT_utf8_to_unicode16( const char* src, unsigned short* dest ) +{ + while('\0' != *src) + { + src = _FAT_utf8decode(src, dest++); + } + + *dest = '\0'; +} + +#if 0 +static inline int _FAT_utf8coding(const u16* ucs, char* dest) +{ + int len= 0; + + if (*ucs < 0x80) //one byte + { + dest[len++] = *ucs; + } + else if (*ucs < 0x800) //two bytes + { + dest[len++] = 0xC0 | (*ucs >> 6 & 0x1F); + dest[len++] = 0x80 | (*ucs & 0x3F); + } + else //if(*ucs < 0x10000) //three bytes + { + dest[len++] = 0xE0 | (*ucs >> 12); + dest[len++] = 0x80 | (*ucs >>6 & 0x3F); + dest[len++] = 0x80 | (*ucs &0x3F); + } + + return len; +} +#endif + +void _FAT_unicode16_to_utf8( const u16* src, char* dest) +{ + int len=0; + while(*src) + { + if (*src < 0x80) //1 byte + { + dest[len++] = *src; + } + else if (*src < 0x800) //2 bytes + { + dest[len++] = 0xC0 | (*src >> 6 & 0x1F); + dest[len++] = 0x80 | (*src & 0x3F); + } + else //if(*src < 0x10000) //3 bytes + { + dest[len++] = 0xE0 | (*src >> 12); + dest[len++] = 0x80 | (*src >>6 & 0x3F); + dest[len++] = 0x80 | (*src &0x3F); + } + src ++; + } + dest[len] = 0; +} + +u32 _unistrnlen( const u16* unistr, u32 maxlen ) +{ + const u16 * pstr = NULL; + u32 len = 0; + if( NULL == unistr ) + return 0; + + if( 0 == maxlen ) + return 0; + + pstr = unistr; + + while( len < maxlen && *pstr != 0x0000 ) + { + ++len; + ++pstr; + } + return len; +} + +int _unistrncmp( const u16* src, const u16* dest, u32 maxlen ) +{ + if( NULL == src || NULL == dest ) + { + if( src == dest ) return 0; + return (NULL == src ) ? -1 : 1; + } + + while( *src == *dest && maxlen && *src != 0x0000 && *dest != 0x0000 ) + { + ++src; + ++dest; + --maxlen; + } + if( 0 == maxlen ) return 0; + + return *src > *dest ? 1 : -1; +} + +const u16 * _unistrchr( const u16 * str, u16 unichar ) +{ + if( NULL == str ) + return NULL; + + while( *str != unichar && *str != 0x0000 ) + { + ++str; + } + return str; +} + +int _uniisalnum( u8 ch ) +{ + return isalnum( ch ); +} + diff --git a/sdk-modifications/libsrc/fs/fs_unicode.h b/sdk-modifications/libsrc/fs/fs_unicode.h new file mode 100644 index 0000000..45e9d0a --- /dev/null +++ b/sdk-modifications/libsrc/fs/fs_unicode.h @@ -0,0 +1,16 @@ +#ifndef __FS_UNICODE_H__ +#define __FS_UNICODE_H__ + +extern void _FAT_utf8_to_unicode16( const char* src, u16* dest ); + +extern void _FAT_unicode16_to_utf8( const u16* src, char* dest); + +extern u32 _unistrnlen( const u16* unistr, u32 maxlen ); + +extern int _unistrncmp( const u16 * src, const u16 * dest, u32 maxlen ); + +extern const u16 * _unistrchr( const u16 * str, u16 unichar ); + +int _uniisalnum( u8 ch ); + +#endif //__FS_UNICODE_H__ diff --git a/sdk-modifications/libsrc/fs/libfat.c b/sdk-modifications/libsrc/fs/libfat.c new file mode 100644 index 0000000..1956d13 --- /dev/null +++ b/sdk-modifications/libsrc/fs/libfat.c @@ -0,0 +1,174 @@ +/* + libfat.c + Simple functionality for startup, mounting and unmounting of FAT-based devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-08-13 - Chishm + * Moved all externally visible directory related functions to fatdir + + 2006-08-14 - Chishm + * Added extended devoptab_t functions + + 2007-01-10 - Chishm + * fatInit now sets the correct path when setAsDefaultDevice + + 2007-01-11 - Chishm + * Added missing #include +*/ + +/* + +*/ + +#include + +#include "fs_common.h" +#include "partition.h" +#include "fatfile.h" +#include "fatdir.h" +#include "fs_unicode.h" +#include "io_ds2_mmcf.h" + +#define GBA_DEFAULT_CACHE_PAGES 2 +#define NDS_DEFAULT_CACHE_PAGES 8 + +#if 0 +const devoptab_t dotab_fat = { + "fat", + sizeof (FILE_STRUCT), + _FAT_open_r, + _FAT_close_r, + _FAT_write_r, + _FAT_read_r, + _FAT_seek_r, + _FAT_fstat_r, + _FAT_stat_r, + _FAT_link_r, + _FAT_unlink_r, + _FAT_chdir_r, + _FAT_rename_r, + _FAT_mkdir_r, + sizeof (DIR_STATE_STRUCT), + _FAT_diropen_r, + _FAT_dirreset_r, + _FAT_dirnext_r, + _FAT_dirclose_r +}; +#endif + +#if 0 +bool fatInit (u32 cacheSize, bool setAsDefaultDevice) +{ +#ifdef NDS + bool slot1Device, slot2Device; + + // add unicode suppport + //file name string coding are set to UTF8, other coding needed conveted to UTF8 by the caller + //_FAT_unicode_init_default(); + + // Try mounting both slots + slot1Device = _FAT_partition_mount (PI_SLOT_1, cacheSize); + slot2Device = _FAT_partition_mount (PI_SLOT_2, cacheSize); + + // Choose the default device + if (slot1Device) { + _FAT_partition_setDefaultInterface (PI_SLOT_1); + } else if (slot2Device) { + _FAT_partition_setDefaultInterface (PI_SLOT_2); + } else { + return false; + } + +#else // not defined NDS + bool cartSlotDevice; + + cartSlotDevice = _FAT_partition_mount (PI_CART_SLOT, cacheSize); + + if (cartSlotDevice) { + _FAT_partition_setDefaultInterface (PI_CART_SLOT); + } else { + return false; + } + +#endif // defined NDS + + AddDevice (&dotab_fat); + + if (setAsDefaultDevice) { + chdir ("fat:/"); + } + + return true; +} +#endif + +#if 0 +bool fatInitDefault (void) { +#ifdef NDS + return fatInit (NDS_DEFAULT_CACHE_PAGES, true); +#else + return fatInit (GBA_DEFAULT_CACHE_PAGES, true); +#endif +} +#endif + +bool _FAT_Init(void) +{ + // Try mounting sd/mmc + bool sdOK = false; + if( _io_ds2_mmcf.fn_startup() == 0) //NO ERROR + sdOK = _FAT_partition_freeMount( PI_DEFAULT, &_io_ds2_mmcf, 8); + else + return false; + + if(sdOK == true) + fat_chdir ("fat:/"); + + return sdOK; +} + +bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize) { + return _FAT_partition_mount (partitionNumber, cacheSize); +} + +bool fatMountCustomInterface (const IO_INTERFACE* device, u32 cacheSize) { + return _FAT_partition_mountCustomInterface (device, cacheSize); +} + +bool fatUnmount (PARTITION_INTERFACE partitionNumber) { + return _FAT_partition_unmount (partitionNumber); +} + + +bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber) { + return _FAT_partition_unsafeUnmount (partitionNumber); +} + +bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber) { + return _FAT_partition_setDefaultInterface (partitionNumber); +} diff --git a/sdk-modifications/libsrc/fs/mem_allocate.h b/sdk-modifications/libsrc/fs/mem_allocate.h new file mode 100644 index 0000000..7bbe8de --- /dev/null +++ b/sdk-modifications/libsrc/fs/mem_allocate.h @@ -0,0 +1,47 @@ +/* + mem_allocate.h + Memory allocation and destruction calls + Replace these calls with custom allocators if + malloc is unavailable + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _MEM_ALLOCATE_H +#define _MEM_ALLOCATE_H + +#include "ds2_malloc.h" + +static inline void* _FAT_mem_allocate (size_t size) { + return ((void*)malloc (size)); +} + +static inline void _FAT_mem_free (void* mem) { + return (free ((void*)mem)); +} + +#endif // _MEM_ALLOCATE_H diff --git a/sdk-modifications/libsrc/fs/partition.c b/sdk-modifications/libsrc/fs/partition.c new file mode 100644 index 0000000..1791b40 --- /dev/null +++ b/sdk-modifications/libsrc/fs/partition.c @@ -0,0 +1,501 @@ +/* + partition.c + Functions for mounting and dismounting partitions + on various block devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-08-10 - Chishm + * Fixed problem when openning files starting with "fat" + + 2006-10-28 - Chishm + * _partitions changed to _FAT_partitions to maintain the same style of naming as the functions +*/ +//version 1.1 +//Note: fix bug in _FAT_partition_setDefaultPartition() function + +#include "partition.h" +#include "bit_ops.h" +#include "file_allocation_table.h" +#include "directory.h" + +#include +#include + +#include "mem_allocate.h" + +/* +This device name, as known by DevKitPro +*/ +const char* DEVICE_NAME = "fat"; + +/* +Data offsets +*/ + +// BIOS Parameter Block offsets +enum BPB { + BPB_jmpBoot = 0x00, + BPB_OEMName = 0x03, + // BIOS Parameter Block + BPB_bytesPerSector = 0x0B, + BPB_sectorsPerCluster = 0x0D, + BPB_reservedSectors = 0x0E, + BPB_numFATs = 0x10, + BPB_rootEntries = 0x11, + BPB_numSectorsSmall = 0x13, + BPB_mediaDesc = 0x15, + BPB_sectorsPerFAT = 0x16, + BPB_sectorsPerTrk = 0x18, + BPB_numHeads = 0x1A, + BPB_numHiddenSectors = 0x1C, + BPB_numSectors = 0x20, + // Ext BIOS Parameter Block for FAT16 + BPB_FAT16_driveNumber = 0x24, + BPB_FAT16_reserved1 = 0x25, + BPB_FAT16_extBootSig = 0x26, + BPB_FAT16_volumeID = 0x27, + BPB_FAT16_volumeLabel = 0x2B, + BPB_FAT16_fileSysType = 0x36, + // Bootcode + BPB_FAT16_bootCode = 0x3E, + // FAT32 extended block + BPB_FAT32_sectorsPerFAT32 = 0x24, + BPB_FAT32_extFlags = 0x28, + BPB_FAT32_fsVer = 0x2A, + BPB_FAT32_rootClus = 0x2C, + BPB_FAT32_fsInfo = 0x30, + BPB_FAT32_bkBootSec = 0x32, + // Ext BIOS Parameter Block for FAT32 + BPB_FAT32_driveNumber = 0x40, + BPB_FAT32_reserved1 = 0x41, + BPB_FAT32_extBootSig = 0x42, + BPB_FAT32_volumeID = 0x43, + BPB_FAT32_volumeLabel = 0x47, + BPB_FAT32_fileSysType = 0x52, + // Bootcode + BPB_FAT32_bootCode = 0x5A, + BPB_bootSig_55 = 0x1FE, + BPB_bootSig_AA = 0x1FF +}; + + +#ifdef NDS +#define MAXIMUM_PARTITIONS 4 +PARTITION* _FAT_partitions[MAXIMUM_PARTITIONS] = {NULL}; +#else // not defined NDS +#define MAXIMUM_PARTITIONS 1 +PARTITION* _FAT_partitions[MAXIMUM_PARTITIONS] = {NULL}; +#endif // defined NDS + +// Use a single static buffer for the partitions + + +static PARTITION* _FAT_partition_constructor ( const IO_INTERFACE* disc, u32 cacheSize) { + PARTITION* partition; + int i; + u32 bootSector; + u8 sectorBuffer[BYTES_PER_READ] = {0}; + + // Read first sector of disc + if ( !_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) { + return NULL; + } + + // Make sure it is a valid MBR or boot sector + if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) { + return NULL; + } + + // Check if there is a FAT string, which indicates this is a boot sector + if ((sectorBuffer[0x36] == 'F') && (sectorBuffer[0x37] == 'A') && (sectorBuffer[0x38] == 'T')) { + bootSector = 0; + } else if ((sectorBuffer[0x52] == 'F') && (sectorBuffer[0x53] == 'A') && (sectorBuffer[0x54] == 'T')) { + // Check for FAT32 + bootSector = 0; + } else { + // This is an MBR + // Find first valid partition from MBR + // First check for an active partition + for (i=0x1BE; (i < 0x1FE) && (sectorBuffer[i] != 0x80); i+= 0x10); + // If it didn't find an active partition, search for any valid partition + if (i == 0x1FE) { + for (i=0x1BE; (i < 0x1FE) && (sectorBuffer[i+0x04] == 0x00); i+= 0x10); + } + + // Go to first valid partition + if ( i != 0x1FE) { + // Make sure it found a partition + bootSector = u8array_to_u32(sectorBuffer, 0x8 + i); + } else { + bootSector = 0; // No partition found, assume this is a MBR free disk + } + } + + // Read in boot sector + if ( !_FAT_disc_readSectors (disc, bootSector, 1, sectorBuffer)) { + return NULL; + } + + partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION)); + if (partition == NULL) { + return NULL; + } + + // Set partition's disc interface + partition->disc = disc; + + // Store required information about the file system + partition->fat.sectorsPerFat = u8array_to_u16(sectorBuffer, BPB_sectorsPerFAT); + if (partition->fat.sectorsPerFat == 0) { + partition->fat.sectorsPerFat = u8array_to_u32( sectorBuffer, BPB_FAT32_sectorsPerFAT32); + } + + partition->numberOfSectors = u8array_to_u16( sectorBuffer, BPB_numSectorsSmall); + if (partition->numberOfSectors == 0) { + partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors); + } + + partition->bytesPerSector = BYTES_PER_READ; // Sector size is redefined to be 512 bytes + partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster] * u8array_to_u16(sectorBuffer, BPB_bytesPerSector) / BYTES_PER_READ; + partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster; + partition->fat.fatStart = bootSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors); + + partition->rootDirStart = partition->fat.fatStart + (sectorBuffer[BPB_numFATs] * partition->fat.sectorsPerFat); + partition->dataStart = partition->rootDirStart + (( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); + + partition->totalSize = (partition->numberOfSectors - partition->dataStart) * partition->bytesPerSector; + + // Store info about FAT + partition->fat.lastCluster = (partition->numberOfSectors - partition->dataStart) / partition->sectorsPerCluster; + partition->fat.firstFree = CLUSTER_FIRST; + + if (partition->fat.lastCluster < CLUSTERS_PER_FAT12) { + partition->filesysType = FS_FAT12; // FAT12 volume + } else if (partition->fat.lastCluster < CLUSTERS_PER_FAT16) { + partition->filesysType = FS_FAT16; // FAT16 volume + } else { + partition->filesysType = FS_FAT32; // FAT32 volume + } + + if (partition->filesysType != FS_FAT32) { + partition->rootDirCluster = FAT16_ROOT_DIR_CLUSTER; + } else { + // Set up for the FAT32 way + partition->rootDirCluster = u8array_to_u32(sectorBuffer, BPB_FAT32_rootClus); + // Check if FAT mirroring is enabled + if (!(sectorBuffer[BPB_FAT32_extFlags] & 0x80)) { + // Use the active FAT + partition->fat.fatStart = partition->fat.fatStart + ( partition->fat.sectorsPerFat * (sectorBuffer[BPB_FAT32_extFlags] & 0x0F)); + } + } + + // Create a cache to use + partition->cache = _FAT_cache_constructor (cacheSize, partition->disc); + + // Set current directory to the root + partition->cwdCluster = partition->rootDirCluster; + + // Check if this disc is writable, and set the readOnly property appropriately + partition->readOnly = !(_FAT_disc_features(disc) & FEATURE_MEDIUM_CANWRITE); + + // There are currently no open files on this partition + partition->openFileCount = 0; + + return partition; +} + +static void _FAT_partition_destructor (PARTITION* partition) { + _FAT_cache_destructor (partition->cache); + _FAT_disc_shutdown (partition->disc); + _FAT_mem_free (partition); +} + +bool _FAT_partition_mount (PARTITION_INTERFACE partitionNumber, u32 cacheSize) +{ +#ifdef NDS + int i; + const IO_INTERFACE* disc = NULL; + + if (_FAT_partitions[partitionNumber] != NULL) { + return false; + } + + switch (partitionNumber) { + case PI_SLOT_1: + // Mount the disc in slot 1 + disc = _FAT_disc_dsSlotFindInterface (); + break; + case PI_SLOT_2: + // Mount the disc in slot 2 + disc = _FAT_disc_gbaSlotFindInterface (); + break; + case PI_DEFAULT: + case PI_CUSTOM: + default: + // Anything else has to be handled specially + return false; + break; + } + + if (disc == NULL) { + return false; + } + + // See if that disc is already in use, if so, then just copy the partition pointer + for (i = 0; i < MAXIMUM_PARTITIONS; i++) { + if ((_FAT_partitions[i] != NULL) && (_FAT_partitions[i]->disc == disc)) { + _FAT_partitions[partitionNumber] = _FAT_partitions[i]; + return true; + } + } + + _FAT_partitions[partitionNumber] = _FAT_partition_constructor (disc, cacheSize); + + if (_FAT_partitions[partitionNumber] == NULL) { + return false; + } + +#else // not defined NDS + const IO_INTERFACE* disc = NULL; + + if (_FAT_partitions[partitionNumber] != NULL) { + return false; + } + + // Only ever one partition on GBA + disc = _FAT_disc_gbaSlotFindInterface (); + _FAT_partitions[partitionNumber] = _FAT_partition_constructor (disc, cacheSize); + +#endif // defined NDS + + return true; +} + +bool _FAT_partition_mountCustomInterface (const IO_INTERFACE* device, u32 cacheSize) { +#ifdef NDS + int i; + + if (_FAT_partitions[PI_CUSTOM] != NULL) { + return false; + } + + if (device == NULL) { + return false; + } + + // See if that disc is already in use, if so, then just copy the partition pointer + for (i = 0; i < MAXIMUM_PARTITIONS; i++) { + if ((_FAT_partitions[i] != NULL) && (_FAT_partitions[i]->disc == device)) { + _FAT_partitions[PI_CUSTOM] = _FAT_partitions[i]; + return true; + } + } + + _FAT_partitions[PI_CUSTOM] = _FAT_partition_constructor (device, cacheSize); + + if (_FAT_partitions[PI_CUSTOM] == NULL) { + return false; + } + +#else // not defined NDS + if (_FAT_partitions[PI_CART_SLOT] != NULL) { + return false; + } + + if (device == NULL) { + return false; + } + + // Only ever one partition on GBA + _FAT_partitions[PI_CART_SLOT] = _FAT_partition_constructor (device, cacheSize); + +#endif // defined NDS + + return true; +} + +bool _FAT_partition_setDefaultInterface (PARTITION_INTERFACE partitionNumber) +{ +#ifdef NDS // Can only set the default partition when there is more than 1, so doesn't apply to GBA + if ((partitionNumber < 1) || (partitionNumber >= MAXIMUM_PARTITIONS)) { + return false; + } + + if (_FAT_partitions[partitionNumber] == NULL) { + return false; + } + + _FAT_partitions[PI_DEFAULT] = _FAT_partitions[partitionNumber]; +#endif + return true; +} + +bool _FAT_partition_setDefaultPartition (PARTITION* partition) { +#ifdef NDS // Can only set the default partition when there is more than 1, so doesn't apply to GBA + int i; + + if (partition == NULL) { + return false; + } + + if(_FAT_partitions[PI_DEFAULT] == partition) //Already is the default partition + return true; + + // Ensure that this device is already in the list + for (i = 1; i < MAXIMUM_PARTITIONS; i++) { + if (_FAT_partitions[i] == partition) { + break; + } + } + + // It wasn't in the list, so fail + if (i == MAXIMUM_PARTITIONS) { + return false; + } + + // Change the default partition / device to this one + _FAT_partitions[PI_DEFAULT] = partition; + +#endif + return true; +} + +bool _FAT_partition_unmount (PARTITION_INTERFACE partitionNumber) { + int i; + PARTITION* partition = _FAT_partitions[partitionNumber]; + + if (partition == NULL) { + return false; + } + + if (partition->openFileCount > 0) { + // There are still open files that need closing + return false; + } + + // Remove all references to this partition + for (i = 0; i < MAXIMUM_PARTITIONS; i++) { + if (_FAT_partitions[i] == partition) { + _FAT_partitions[i] = NULL; + } + } + + _FAT_partition_destructor (partition); + return true; +} + +bool _FAT_partition_unsafeUnmount (PARTITION_INTERFACE partitionNumber) { + int i; + PARTITION* partition = _FAT_partitions[partitionNumber]; + + if (partition == NULL) { + return false; + } + + // Remove all references to this partition + for (i = 0; i < MAXIMUM_PARTITIONS; i++) { + if (_FAT_partitions[i] == partition) { + _FAT_partitions[i] = NULL; + } + } + + _FAT_cache_invalidate (partition->cache); + _FAT_partition_destructor (partition); + return true; +} + +PARTITION* _FAT_partition_getPartitionFromPath (const char* path) { +#ifdef NDS + int namelen; + int partitionNumber; + + // Device name extraction code taken from DevKitPro + namelen = strlen(DEVICE_NAME); + if (strchr (path, ':') == NULL) { + // No device specified + partitionNumber = PI_DEFAULT; + } else if( strncmp(DEVICE_NAME, path, namelen) == 0 ) { + if ( path[namelen] == ':' ) { + // Only the device name is specified + partitionNumber = PI_DEFAULT; + } else if (isdigit(path[namelen]) && path[namelen+1] ==':' ) { + // Device name and number specified + partitionNumber = path[namelen] - '0'; + } else { + // Incorrect device name + return NULL; + } + } else { + // Incorrect device name + return NULL; + } + + if ((partitionNumber < 0) || (partitionNumber >= MAXIMUM_PARTITIONS)) { + return NULL; + } + + return _FAT_partitions[partitionNumber]; +#else // not defined NDS + // Only one possible partition on GBA + return _FAT_partitions[PI_CART_SLOT]; +#endif // defined NDS +} + +bool _FAT_partition_freeMount( int partitionNumber, const IO_INTERFACE* device, u32 cacheSize) { + + if( partitionNumber < 0 || partitionNumber > 3 ) + return false; + int i; + + if (device == NULL) { + return false; + } + + if (_FAT_partitions[partitionNumber] != NULL) { + if(_FAT_partitions[partitionNumber] -> disc == device) + return true; + + return false; + } + + // See if that disc is already in use, if so, then just copy the partition pointer + for (i = 0; i < MAXIMUM_PARTITIONS; i++) { + if ((_FAT_partitions[i] != NULL) && (_FAT_partitions[i]->disc == device)) { + _FAT_partitions[partitionNumber] = _FAT_partitions[i]; + return true; + } + } + + _FAT_partitions[partitionNumber] = _FAT_partition_constructor (device, cacheSize); + + if (_FAT_partitions[partitionNumber] == NULL) { + return false; + } + + return true; +} diff --git a/sdk-modifications/libsrc/fs/partition.h b/sdk-modifications/libsrc/fs/partition.h new file mode 100644 index 0000000..0777b54 --- /dev/null +++ b/sdk-modifications/libsrc/fs/partition.h @@ -0,0 +1,131 @@ +/* + partition.h + Functions for mounting and dismounting partitions + on various block devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _PARTITION_H +#define _PARTITION_H + +#include "fs_common.h" + +#include "disc_io/disc.h" +#include "fs_cache.h" + +// Device name +extern const char* DEVICE_NAME; + +// Filesystem type +typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; + +#ifdef NDS +typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM} PARTITION_INTERFACE; +#else +typedef enum {PI_CART_SLOT} PARTITION_INTERFACE; +#endif + +typedef struct { + u32 fatStart; + u32 sectorsPerFat; + u32 lastCluster; + u32 firstFree; +} FAT; + +typedef struct { + const IO_INTERFACE* disc; + CACHE* cache; + // Info about the partition + bool readOnly; // If this is set, then do not try writing to the disc + FS_TYPE filesysType; + u32 totalSize; + u32 rootDirStart; + u32 rootDirCluster; + u32 numberOfSectors; + u32 dataStart; + u32 bytesPerSector; + u32 sectorsPerCluster; + u32 bytesPerCluster; + FAT fat; + // Values that may change after construction + u32 cwdCluster; // Current working directory cluser + u32 openFileCount; +} PARTITION; + +/* +Mount the device specified by partitionDevice +PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice +PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +*/ +bool _FAT_partition_mount (PARTITION_INTERFACE partitionNumber, u32 cacheSize); + +/* +Mount a partition on a custom device +*/ +bool _FAT_partition_mountCustomInterface (const IO_INTERFACE* device, u32 cacheSize); + + +/* +Free Mount a partition on a custom device +*/ +bool _FAT_partition_freeMount( int partitionNumber, const IO_INTERFACE* device, u32 cacheSize); + + +/* +Unmount the partition specified by partitionNumber +If there are open files, it will fail +*/ +bool _FAT_partition_unmount (PARTITION_INTERFACE partitionNumber); + +/* +Forcibly unmount the partition specified by partitionNumber +Any open files on the partition will become invalid +The cache will be invalidated, and any unflushed writes will be lost +*/ +bool _FAT_partition_unsafeUnmount (PARTITION_INTERFACE partitionNumber); + +/* +Set the default device for access by fat: and fat0:, +based on the device number +*/ +bool _FAT_partition_setDefaultInterface (PARTITION_INTERFACE partitionNumber); + +/* +Set the default device for access by fat: and fat0:, +based on the partition pointer +*/ +bool _FAT_partition_setDefaultPartition (PARTITION* partition); + +/* +Return the partition specified in a path +For instance, "fat0:", "fat:", "/" and "fat:/" will all +return the default partition +*/ +PARTITION* _FAT_partition_getPartitionFromPath (const char* path); + +#endif // _PARTITION_H diff --git a/sdk-modifications/libsrc/key/key.c b/sdk-modifications/libsrc/key/key.c new file mode 100644 index 0000000..8a6ad5f --- /dev/null +++ b/sdk-modifications/libsrc/key/key.c @@ -0,0 +1,145 @@ +#include "ds2_timer.h" +#include "ds2io.h" + +#define KEY_REPEAT_TIME 200 //5 times/second +#define KEY_REPEAT_TIME_N (KEY_REPEAT_TIME*1000000/SYSTIME_UNIT) + +#define INPUT_REPEAT_TIME 100 +#define INPUT_REPEAT_TIME_N (INPUT_REPEAT_TIME*1000000/SYSTIME_UNIT) + +static unsigned int _last_key = 0; +static unsigned int _last_key_timestamp = 0; + +/* +* Function: only detect the key pressed or not +*/ +unsigned int getKey(void) +{ + struct key_buf input; + unsigned int new_key, hold_key, ret_key, timestamp; + int flag; + + ds2_getrawInput(&input); + timestamp = getSysTime(); + flag = ((timestamp - _last_key_timestamp) >= KEY_REPEAT_TIME_N) ? 1 : 0; + + input.key &= 0x3FFF; + new_key = (_last_key ^ input.key) & input.key; + hold_key = _last_key & input.key; + + ret_key = 0; + if(hold_key) { + if(flag) + { + ret_key = hold_key; + _last_key_timestamp = timestamp; + } + } + + if(new_key) + { + ret_key |= new_key; + _last_key_timestamp = timestamp; + + _last_key = input.key; + } + + return ret_key; +} + +/* +* Function: can get the detail information about key pressed, hold, or release +*/ +unsigned int getKey1(void) +{ + struct key_buf input; + unsigned int new_key, hold_key, ret_key, timestamp; + int flag; + + ds2_getrawInput(&input); + timestamp = getSysTime(); + flag = ((timestamp - _last_key_timestamp) >= KEY_REPEAT_TIME_N) ? 1 : 0; + + input.key &= 0x3FFF; + new_key = _last_key ^ input.key; + hold_key = _last_key & input.key; + //ret_key[31:16] = last key; + //ret_key[15:0] = new key; + + ret_key = 0; + if(hold_key) { + if(flag) + { + ret_key = (hold_key << 16) | hold_key; + _last_key_timestamp = timestamp; + } + } + + if(new_key) + { + unsigned int tmp_key; + + //have new key pressed + if(new_key & input.key) + { + ret_key |= new_key & input.key; + _last_key_timestamp = timestamp; + } + else + { + ret_key |= (new_key & ~input.key) << 16; + } + + _last_key = input.key; + } + + return ret_key; +} + +static unsigned int _last_input = 0; +static unsigned int _last_input_timestamp = 0; + +/* +* Function: only detect the key pressed or not and touch position +*/ +unsigned int getInput(struct key_buf *input) { + struct key_buf rawin; + unsigned int timestamp, new, hold; + int flag, ret; + + ds2_getrawInput(&rawin); + timestamp = getSysTime(); + flag = ((timestamp - _last_input_timestamp) >= INPUT_REPEAT_TIME_N) ? 1 : 0; + + rawin.key &= 0x3FFF; + new = (rawin.key ^ _last_input) & rawin.key; + hold = rawin.key & _last_input; + + ret = 0; + if(hold && flag) + { + ret = hold; + input->x = rawin.x; + input->y = rawin.y; + + _last_input_timestamp = timestamp; + } + + if(new) + { + ret |= new; + input->x = rawin.x; + input->y = rawin.y; + + _last_input_timestamp = timestamp; + _last_input = rawin.key; + } + + input->key = ret; + return ret > 0; +} + + + + + diff --git a/sdk-modifications/libsrc/key/key.h b/sdk-modifications/libsrc/key/key.h new file mode 100644 index 0000000..21674ec --- /dev/null +++ b/sdk-modifications/libsrc/key/key.h @@ -0,0 +1,31 @@ +#ifndef __KEY_H__ +#define __KEY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define KEY_PRESS(key, key_id) (!(key & (key_id<<16)) && (key & key_id)) +#define KEY_HOLD(key, key_id) ((key & (key_id<<16)) && (key & key_id)) +#define KEY_RELEASE(key, key_id) ((key & (key_id<<16)) && !(key & key_id)) + +/* +* Function: only detect the key pressed or not +*/ +unsigned int getKey(void); + +/* +* Function: can get the detail information about key pressed, hold, or release +*/ +unsigned int getKey1(void); + +/* +* Function: detect the key pressed or not and touched position +*/ +extern unsigned int getInput(struct key_buf *input); + +#ifdef __cplusplus +} +#endif + +#endif //__KEY_H__ diff --git a/sdk-modifications/libsrc/key/key.mk b/sdk-modifications/libsrc/key/key.mk new file mode 100644 index 0000000..fa08d7c --- /dev/null +++ b/sdk-modifications/libsrc/key/key.mk @@ -0,0 +1,10 @@ +#key.mk + +SRC += $(KEY_DIR)/key.c + +SSRC += + +INC += -I$(KEY_DIR) + +CFLAGS += + diff --git a/sdk-modifications/libsrc/zlib/README b/sdk-modifications/libsrc/zlib/README new file mode 100644 index 0000000..ee06114 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/README @@ -0,0 +1 @@ +This is a modified source release of zlib. zconf.h removes a reference to sys/types.h, which creates type conflicts on the DS2 SDK. For a pristine source release of zlib, please visit . \ No newline at end of file diff --git a/sdk-modifications/libsrc/zlib/adler32.c b/sdk-modifications/libsrc/zlib/adler32.c new file mode 100644 index 0000000..a868f07 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/adler32.c @@ -0,0 +1,179 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); + +#define BASE 65521 /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/sdk-modifications/libsrc/zlib/compress.c b/sdk-modifications/libsrc/zlib/compress.c new file mode 100644 index 0000000..ea4dfbe --- /dev/null +++ b/sdk-modifications/libsrc/zlib/compress.c @@ -0,0 +1,80 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; +} diff --git a/sdk-modifications/libsrc/zlib/crc32.c b/sdk-modifications/libsrc/zlib/crc32.c new file mode 100644 index 0000000..c12471e --- /dev/null +++ b/sdk-modifications/libsrc/zlib/crc32.c @@ -0,0 +1,447 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + + DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR + typedef u4 crc_table_t; +# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else + typedef unsigned long crc_table_t; +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local crc_table_t FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const crc_table_t FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + crc_table_t c; + int n, k; + crc_table_t poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= (crc_table_t)1 << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (crc_table_t)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const crc_table_t FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const crc_table_t FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/sdk-modifications/libsrc/zlib/crc32.h b/sdk-modifications/libsrc/zlib/crc32.h new file mode 100644 index 0000000..c3e7171 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const crc_table_t FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/sdk-modifications/libsrc/zlib/deflate.c b/sdk-modifications/libsrc/zlib/deflate.c new file mode 100644 index 0000000..8bd480e --- /dev/null +++ b/sdk-modifications/libsrc/zlib/deflate.c @@ -0,0 +1,1965 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://tools.ietf.org/html/rfc1951 + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.6 Copyright 1995-2012 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt str, n; + int wrap; + unsigned avail; + unsigned char *next; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) + return Z_STREAM_ERROR; + s = strm->state; + wrap = s->wrap; + if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) + return Z_STREAM_ERROR; + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap == 1) + strm->adler = adler32(strm->adler, dictionary, dictLength); + s->wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s->w_size) { + if (wrap == 0) { /* already empty otherwise */ + CLEAR_HASH(s); + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + dictionary += dictLength - s->w_size; /* use the tail */ + dictLength = s->w_size; + } + + /* insert dictionary into window and hash */ + avail = strm->avail_in; + next = strm->next_in; + strm->avail_in = dictLength; + strm->next_in = (Bytef *)dictionary; + fill_window(s); + while (s->lookahead >= MIN_MATCH) { + str = s->strstart; + n = s->lookahead - (MIN_MATCH-1); + do { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + } while (--n); + s->strstart = str; + s->lookahead = MIN_MATCH-1; + fill_window(s); + } + s->strstart += s->lookahead; + s->block_start = (long)s->strstart; + s->insert = s->lookahead; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + strm->next_in = next; + strm->avail_in = avail; + s->wrap = wrap; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateResetKeep (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + int ret; + + ret = deflateResetKeep(strm); + if (ret == Z_OK) + lm_init(strm->state); + return ret; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePending (strm, pending, bits) + unsigned *pending; + int *bits; + z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (pending != Z_NULL) + *pending = strm->state->pending; + if (bits != Z_NULL) + *bits = strm->state->bi_valid; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + deflate_state *s; + int put; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; + do { + put = Buf_size - s->bi_valid; + if (put > bits) + put = bits; + s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); + s->bi_valid += put; + _tr_flush_bits(s); + value >>= put; + bits -= put; + } while (bits); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_BLOCK); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + Bytef *str; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (strm == Z_NULL || strm->state == Z_NULL) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len; + deflate_state *s = strm->state; + + _tr_flush_bits(s); + len = s->pending; + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, s->pending_out, len); + strm->next_out += len; + s->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + s->pending -= len; + if (s->pending == 0) { + s->pending_out = s->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + (s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush)); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + zmemcpy(buf, strm->next_in, len); + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, buf, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, buf, len); + } +#endif + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->insert = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) break; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if ((long)s->strstart > s->block_start) + FLUSH_BLOCK(s, 0); + return block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s->lookahead <= MAX_MATCH) { + fill_window(s); + if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (int)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} diff --git a/sdk-modifications/libsrc/zlib/deflate.h b/sdk-modifications/libsrc/zlib/deflate.h new file mode 100644 index 0000000..fbac44d --- /dev/null +++ b/sdk-modifications/libsrc/zlib/deflate.h @@ -0,0 +1,346 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2012 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define Buf_size 16 +/* size of bit buffer in bi_buf */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to suppress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + uInt insert; /* bytes at end of window left to insert */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/sdk-modifications/libsrc/zlib/gzclose.c b/sdk-modifications/libsrc/zlib/gzclose.c new file mode 100644 index 0000000..caeb99a --- /dev/null +++ b/sdk-modifications/libsrc/zlib/gzclose.c @@ -0,0 +1,25 @@ +/* gzclose.c -- zlib gzclose() function + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* gzclose() is in a separate file so that it is linked in only if it is used. + That way the other gzclose functions can be used instead to avoid linking in + unneeded compression or decompression routines. */ +int ZEXPORT gzclose(file) + gzFile file; +{ +#ifndef NO_GZCOMPRESS + gz_statep state; + + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); +#else + return gzclose_r(file); +#endif +} diff --git a/sdk-modifications/libsrc/zlib/gzguts.h b/sdk-modifications/libsrc/zlib/gzguts.h new file mode 100644 index 0000000..5405749 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/gzguts.h @@ -0,0 +1,196 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +//#include +#include "zlib.h" + +#include +#include +#include +#include + +#ifdef STDC +//# include +//# include +//# include +#endif +//#include + +#ifdef __TURBOC__ +# include +#endif + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS +/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# include +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +# ifdef VMS +# define NO_vsnprintf +# endif +# ifdef __OS400__ +# define NO_vsnprintf +# endif +# ifdef __MVS__ +# define NO_vsnprintf +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifdef STDC +# // include +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +/* default i/o buffer size -- double this for output when reading */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer */ + unsigned char *out; /* output buffer (double-sized when reading) */ + int direct; /* 0 if processing gzip, 1 if transparent */ + /* just for reading */ + int how; /* 0: get header, 1: copy, 2: decompress */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/sdk-modifications/libsrc/zlib/gzlib.c b/sdk-modifications/libsrc/zlib/gzlib.c new file mode 100644 index 0000000..7aedab8 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/gzlib.c @@ -0,0 +1,564 @@ +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004, 2010, 2011 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +#if defined(_WIN32) && !defined(__BORLANDC__) +# define LSEEK _lseeki64 +#else +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define LSEEK lseek64 +#else +# define LSEEK lseek +#endif +#endif + +/* Local functions */ +local void gz_reset OF((gz_statep)); +local gzFile gz_open OF((const char *, int, const char *)); + +#if defined UNDER_CE + +/* Map the Windows error number in ERROR to a locale-dependent error message + string and return a pointer to it. Typically, the values for ERROR come + from GetLastError. + + The string pointed to shall not be modified by the application, but may be + overwritten by a subsequent call to gz_strwinerror + + The gz_strwinerror function does not change the current setting of + GetLastError. */ +char ZLIB_INTERNAL *gz_strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +#endif /* UNDER_CE */ + +/* Reset gzip file state */ +local void gz_reset(state) + gz_statep state; +{ + state->x.have = 0; /* no output data available */ + if (state->mode == GZ_READ) { /* for reading ... */ + state->eof = 0; /* not at end of file */ + state->past = 0; /* have not read past end yet */ + state->how = LOOK; /* look for gzip header */ + } + state->seek = 0; /* no seek request pending */ + gz_error(state, Z_OK, NULL); /* clear error */ + state->x.pos = 0; /* no uncompressed data yet */ + state->strm.avail_in = 0; /* no input data yet */ +} + +/* Open a gzip file either by name or file descriptor. */ +local gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gz_statep state; + + /* check input */ + if (path == NULL) + return NULL; + + /* allocate gzFile structure to return */ + state = malloc(sizeof(gz_state)); + if (state == NULL) + return NULL; + state->size = 0; /* no buffers allocated yet */ + state->want = GZBUFSIZE; /* requested buffer size */ + state->msg = NULL; /* no error message yet */ + + /* interpret mode */ + state->mode = GZ_NONE; + state->level = Z_DEFAULT_COMPRESSION; + state->strategy = Z_DEFAULT_STRATEGY; + state->direct = 0; + while (*mode) { + if (*mode >= '0' && *mode <= '9') + state->level = *mode - '0'; + else + switch (*mode) { + case 'r': + state->mode = GZ_READ; + break; +#ifndef NO_GZCOMPRESS + case 'w': + state->mode = GZ_WRITE; + break; + case 'a': + state->mode = GZ_APPEND; + break; +#endif + case '+': /* can't read and write at the same time */ + free(state); + return NULL; + case 'b': /* ignore -- will request binary anyway */ + break; + case 'f': + state->strategy = Z_FILTERED; + break; + case 'h': + state->strategy = Z_HUFFMAN_ONLY; + break; + case 'R': + state->strategy = Z_RLE; + break; + case 'F': + state->strategy = Z_FIXED; + case 'T': + state->direct = 1; + default: /* could consider as an error, but just ignore */ + ; + } + mode++; + } + + /* must provide an "r", "w", or "a" */ + if (state->mode == GZ_NONE) { + free(state); + return NULL; + } + + /* can't force transparent read */ + if (state->mode == GZ_READ) { + if (state->direct) { + free(state); + return NULL; + } + state->direct = 1; /* for empty file */ + } + + /* save the path name for error messages */ + state->path = malloc(strlen(path) + 1); + if (state->path == NULL) { + free(state); + return NULL; + } + strcpy(state->path, path); + + /* open the file with the appropriate mode (or just use fd) */ + state->fd = fd != -1 ? fd : + open(path, +#ifdef O_LARGEFILE + O_LARGEFILE | +#endif +#ifdef O_BINARY + O_BINARY | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | ( + state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))), + 0666); + if (state->fd == -1) { + free(state->path); + free(state); + return NULL; + } + if (state->mode == GZ_APPEND) + state->mode = GZ_WRITE; /* simplify later checks */ + + /* save the current position for rewinding (only if reading) */ + if (state->mode == GZ_READ) { + state->start = LSEEK(state->fd, 0, SEEK_CUR); + if (state->start == -1) state->start = 0; + } + + /* initialize stream */ + gz_reset(state); + + /* return stream */ + return (gzFile)state; +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen64(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzdopen(fd, mode) + int fd; + const char *mode; +{ + char *path; /* identifier for error messages */ + gzFile gz; + + if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + return NULL; + sprintf(path, "", fd); /* for debugging */ + gz = gz_open(path, fd, mode); + free(path); + return gz; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzbuffer(file, size) + gzFile file; + unsigned size; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* make sure we haven't already allocated memory */ + if (state->size != 0) + return -1; + + /* check and set requested size */ + if (size < 2) + size = 2; /* need two bytes to check magic header */ + state->want = size; + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzrewind(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* back up and start over */ + if (LSEEK(state->fd, state->start, SEEK_SET) == -1) + return -1; + gz_reset(state); + return 0; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzseek64(file, offset, whence) + gzFile file; + z_off64_t offset; + int whence; +{ + unsigned n; + z_off64_t ret; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* check that there's no error */ + if (state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* can only seek from start or relative to current position */ + if (whence != SEEK_SET && whence != SEEK_CUR) + return -1; + + /* normalize offset to a SEEK_CUR specification */ + if (whence == SEEK_SET) + offset -= state->x.pos; + else if (state->seek) + offset += state->skip; + state->seek = 0; + + /* if within raw area while reading, just go there */ + if (state->mode == GZ_READ && state->how == COPY && + state->x.pos + offset >= 0) { + ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); + if (ret == -1) + return -1; + state->x.have = 0; + state->eof = 0; + state->past = 0; + state->seek = 0; + gz_error(state, Z_OK, NULL); + state->strm.avail_in = 0; + state->x.pos += offset; + return state->x.pos; + } + + /* calculate skip amount, rewinding if needed for back seek when reading */ + if (offset < 0) { + if (state->mode != GZ_READ) /* writing -- can't go backwards */ + return -1; + offset += state->x.pos; + if (offset < 0) /* before start of file! */ + return -1; + if (gzrewind(file) == -1) /* rewind, then skip to offset */ + return -1; + } + + /* if reading, skip what's in output buffer (one less gzgetc() check) */ + if (state->mode == GZ_READ) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? + (unsigned)offset : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + offset -= n; + } + + /* request skip (if not zero) */ + if (offset) { + state->seek = 1; + state->skip = offset; + } + return state->x.pos + offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzseek(file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + z_off64_t ret; + + ret = gzseek64(file, (z_off64_t)offset, whence); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gztell64(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* return position */ + return state->x.pos + (state->seek ? state->skip : 0); +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gztell(file) + gzFile file; +{ + z_off64_t ret; + + ret = gztell64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzoffset64(file) + gzFile file; +{ + z_off64_t offset; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* compute and return effective offset in file */ + offset = LSEEK(state->fd, 0, SEEK_CUR); + if (offset == -1) + return -1; + if (state->mode == GZ_READ) /* reading */ + offset -= state->strm.avail_in; /* don't count buffered input */ + return offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzoffset(file) + gzFile file; +{ + z_off64_t ret; + + ret = gzoffset64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzeof(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return 0; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return 0; + + /* return end-of-file state */ + return state->mode == GZ_READ ? state->past : 0; +} + +/* -- see zlib.h -- */ +const char * ZEXPORT gzerror(file, errnum) + gzFile file; + int *errnum; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return NULL; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return NULL; + + /* return error information */ + if (errnum != NULL) + *errnum = state->err; + return state->msg == NULL ? "" : state->msg; +} + +/* -- see zlib.h -- */ +void ZEXPORT gzclearerr(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return; + + /* clear error and end-of-file */ + if (state->mode == GZ_READ) { + state->eof = 0; + state->past = 0; + } + gz_error(state, Z_OK, NULL); +} + +/* Create an error message in allocated memory and set state->err and + state->msg accordingly. Free any previous error message already there. Do + not try to free or allocate space if the error is Z_MEM_ERROR (out of + memory). Simply save the error message as a static string. If there is an + allocation failure constructing the error message, then convert the error to + out of memory. */ +void ZLIB_INTERNAL gz_error(state, err, msg) + gz_statep state; + int err; + const char *msg; +{ + /* free previously allocated message and clear */ + if (state->msg != NULL) { + if (state->err != Z_MEM_ERROR) + free(state->msg); + state->msg = NULL; + } + + /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ + if (err != Z_OK && err != Z_BUF_ERROR) + state->x.have = 0; + + /* set error code, and if no message, then done */ + state->err = err; + if (msg == NULL) + return; + + /* for an out of memory error, save as static string */ + if (err == Z_MEM_ERROR) { + state->msg = (char *)msg; + return; + } + + /* construct error message with path */ + if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + state->err = Z_MEM_ERROR; + state->msg = (char *)"out of memory"; + return; + } + strcpy(state->msg, state->path); + strcat(state->msg, ": "); + strcat(state->msg, msg); + return; +} + +#ifndef INT_MAX +/* portably return maximum value for an int (when limits.h presumed not + available) -- we need to do this to cover cases where 2's complement not + used, since C standard permits 1's complement and sign-bit representations, + otherwise we could just use ((unsigned)-1) >> 1 */ +unsigned ZLIB_INTERNAL gz_intmax() +{ + unsigned p, q; + + p = 1; + do { + q = p; + p <<= 1; + p++; + } while (p > q); + return q >> 1; +} +#endif diff --git a/sdk-modifications/libsrc/zlib/gzread.c b/sdk-modifications/libsrc/zlib/gzread.c new file mode 100644 index 0000000..4632e8f --- /dev/null +++ b/sdk-modifications/libsrc/zlib/gzread.c @@ -0,0 +1,584 @@ +/* gzread.c -- zlib functions for reading gzip files + * Copyright (C) 2004, 2005, 2010, 2011 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); +local int gz_avail OF((gz_statep)); +local int gz_look OF((gz_statep)); +local int gz_decomp OF((gz_statep)); +local int gz_fetch OF((gz_statep)); +local int gz_skip OF((gz_statep, z_off64_t)); + +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from + state->fd, and update state->eof, state->err, and state->msg as appropriate. + This function needs to loop on read(), since read() is not guaranteed to + read the number of bytes requested, depending on the type of descriptor. */ +local int gz_load(state, buf, len, have) + gz_statep state; + unsigned char *buf; + unsigned len; + unsigned *have; +{ + int ret; + + *have = 0; + do { + ret = read(state->fd, buf + *have, len - *have); + if (ret <= 0) + break; + *have += ret; + } while (*have < len); + if (ret < 0) { + gz_error(state, Z_ERRNO, "Load Error"); + return -1; + } + if (ret == 0) + state->eof = 1; + return 0; +} + +/* Load up input buffer and set eof flag if last data loaded -- return -1 on + error, 0 otherwise. Note that the eof flag is set when the end of the input + file is reached, even though there may be unused data in the buffer. Once + that data has been used, no more attempts will be made to read the file. + If strm->avail_in != 0, then the current data is moved to the beginning of + the input buffer, and then the remainder of the buffer is loaded with the + available data from the input file. */ +local int gz_avail(state) + gz_statep state; +{ + unsigned got; + z_streamp strm = &(state->strm); + + if (state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + if (state->eof == 0) { + if (strm->avail_in) + memmove(state->in, strm->next_in, strm->avail_in); + if (gz_load(state, state->in + strm->avail_in, + state->size - strm->avail_in, &got) == -1) + return -1; + strm->avail_in += got; + strm->next_in = state->in; + } + return 0; +} + +/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. + If this is the first time in, allocate required memory. state->how will be + left unchanged if there is no more input data available, will be set to COPY + if there is no gzip header and direct copying will be performed, or it will + be set to GZIP for decompression. If direct copying, then leftover input + data from the input buffer will be copied to the output buffer. In that + case, all further file reads will be directly to either the output buffer or + a user buffer. If decompressing, the inflate state will be initialized. + gz_look() will return 0 on success or -1 on failure. */ +local int gz_look(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + /* allocate read buffers and inflate memory */ + if (state->size == 0) { + /* allocate buffers */ + state->in = malloc(state->want); + state->out = malloc(state->want << 1); + if (state->in == NULL || state->out == NULL) { + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + state->size = state->want; + + /* allocate inflate memory */ + state->strm.zalloc = Z_NULL; + state->strm.zfree = Z_NULL; + state->strm.opaque = Z_NULL; + state->strm.avail_in = 0; + state->strm.next_in = Z_NULL; + if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ + free(state->out); + free(state->in); + state->size = 0; + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* get at least the magic bytes in the input buffer */ + if (strm->avail_in < 2) { + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) + return 0; + } + + /* look for gzip magic bytes -- if there, do gzip decoding (note: there is + a logical dilemma here when considering the case of a partially written + gzip file, to wit, if a single 31 byte is written, then we cannot tell + whether this is a single-byte file, or just a partially written gzip + file -- for here we assume that if a gzip file is being written, then + the header will be written in a single operation, so that reading a + single byte is sufficient indication that it is not a gzip file) */ + if (strm->avail_in > 1 && + strm->next_in[0] == 31 && strm->next_in[1] == 139) { + inflateReset(strm); + state->how = GZIP; + state->direct = 0; + return 0; + } + + /* no gzip header -- if we were decoding gzip before, then this is trailing + garbage. Ignore the trailing garbage and finish. */ + if (state->direct == 0) { + strm->avail_in = 0; + state->eof = 1; + state->x.have = 0; + return 0; + } + + /* doing raw i/o, copy any leftover input to output -- this assumes that + the output buffer is larger than the input buffer, which also assures + space for gzungetc() */ + state->x.next = state->out; + if (strm->avail_in) { + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; + strm->avail_in = 0; + } + state->how = COPY; + state->direct = 1; + return 0; +} + +/* Decompress from input to the provided next_out and avail_out in the state. + On return, state->x.have and state->x.next point to the just decompressed + data. If the gzip stream completes, state->how is reset to LOOK to look for + the next gzip stream or raw data, once state->x.have is depleted. Returns 0 + on success, -1 on failure. */ +local int gz_decomp(state) + gz_statep state; +{ + int ret = Z_OK; + unsigned had; + z_streamp strm = &(state->strm); + + /* fill output buffer up to end of deflate stream */ + had = strm->avail_out; + do { + /* get more input for inflate() */ + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) { + gz_error(state, Z_BUF_ERROR, "unexpected end of file"); + break; + } + + /* decompress and handle errors */ + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { + gz_error(state, Z_STREAM_ERROR, + "internal error: inflate stream corrupt"); + return -1; + } + if (ret == Z_MEM_ERROR) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + gz_error(state, Z_DATA_ERROR, + strm->msg == NULL ? "compressed data error" : strm->msg); + return -1; + } + } while (strm->avail_out && ret != Z_STREAM_END); + + /* update available output */ + state->x.have = had - strm->avail_out; + state->x.next = strm->next_out - state->x.have; + + /* if the gzip stream completed successfully, look for another */ + if (ret == Z_STREAM_END) + state->how = LOOK; + + /* good decompression */ + return 0; +} + +/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. + Data is either copied from the input file or decompressed from the input + file depending on state->how. If state->how is LOOK, then a gzip header is + looked for to determine whether to copy or decompress. Returns -1 on error, + otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the + end of the input file has been reached and all data has been processed. */ +local int gz_fetch(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + do { + switch(state->how) { + case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ + if (gz_look(state) == -1) + return -1; + if (state->how == LOOK) + return 0; + break; + case COPY: /* -> COPY */ + if (gz_load(state, state->out, state->size << 1, &(state->x.have)) + == -1) + return -1; + state->x.next = state->out; + return 0; + case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + } while (state->x.have == 0 && (!state->eof || strm->avail_in)); + return 0; +} + +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ +local int gz_skip(state, len) + gz_statep state; + z_off64_t len; +{ + unsigned n; + + /* skip over len bytes or reach end-of-file, whichever comes first */ + while (len) + /* skip over whatever is in output buffer */ + if (state->x.have) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? + (unsigned)len : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + len -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) + break; + + /* need more data to skip -- load up output buffer */ + else { + /* get more output, looking for header if required */ + if (gz_fetch(state) == -1) + return -1; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + unsigned got, n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); + return -1; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* get len bytes to buf, or less than len if at the end */ + got = 0; + do { + /* first just try copying data from the output buffer */ + if (state->x.have) { + n = state->x.have > len ? len : state->x.have; + memcpy(buf, state->x.next, n); + state->x.next += n; + state->x.have -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && strm->avail_in == 0) { + state->past = 1; /* tried to read past end */ + break; + } + + /* need output data -- for small len or new stream load up our output + buffer */ + else if (state->how == LOOK || len < (state->size << 1)) { + /* get more output, looking for header if required */ + if (gz_fetch(state) == -1) + return -1; + continue; /* no progress yet -- go back to memcpy() above */ + /* the copy above assures that we will leave with space in the + output buffer, allowing at least one gzungetc() to succeed */ + } + + /* large len -- read directly into user buffer */ + else if (state->how == COPY) { /* read directly */ + if (gz_load(state, buf, len, &n) == -1) + return -1; + } + + /* large len -- decompress directly into user buffer */ + else { /* state->how == GZIP */ + strm->avail_out = len; + strm->next_out = buf; + if (gz_decomp(state) == -1) + return -1; + n = state->x.have; + state->x.have = 0; + } + + /* update progress */ + len -= n; + buf = (char *)buf + n; + got += n; + state->x.pos += n; + } while (len); + + /* return number of bytes read into user buffer (will fit in int) */ + return (int)got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzgetc_(file) + gzFile file; +{ + int ret; + unsigned char buf[1]; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (state->x.have) { + state->x.have--; + state->x.pos++; + return *(state->x.next)++; + } + + /* nothing there -- try gzread() */ + ret = gzread(file, buf, 1); + return ret < 1 ? -1 : buf[0]; +} + +#undef gzgetc +int ZEXPORT gzgetc(file) +gzFile file; +{ + return gzgetc_(file); +} + +/* -- see zlib.h -- */ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* can't push EOF */ + if (c < 0) + return -1; + + /* if output buffer empty, put byte at end (allows more pushing) */ + if (state->x.have == 0) { + state->x.have = 1; + state->x.next = state->out + (state->size << 1) - 1; + state->x.next[0] = c; + state->x.pos--; + state->past = 0; + return c; + } + + /* if no room, give up (must have already done a gzungetc()) */ + if (state->x.have == (state->size << 1)) { + gz_error(state, Z_DATA_ERROR, "out of room to push characters"); + return -1; + } + + /* slide output data if needed and insert byte before existing data */ + if (state->x.next == state->out) { + unsigned char *src = state->out + state->x.have; + unsigned char *dest = state->out + (state->size << 1); + while (src > state->out) + *--dest = *--src; + state->x.next = dest; + } + state->x.have++; + state->x.next--; + state->x.next[0] = c; + state->x.pos--; + state->past = 0; + return c; +} + +/* -- see zlib.h -- */ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + unsigned left, n; + char *str; + unsigned char *eol; + gz_statep state; + + /* check parameters and get internal structure */ + if (file == NULL || buf == NULL || len < 1) + return NULL; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return NULL; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return NULL; + } + + /* copy output bytes up to new line or len - 1, whichever comes first -- + append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) */ + str = buf; + left = (unsigned)len - 1; + if (left) do { + /* assure that something is in the output buffer */ + if (state->x.have == 0 && gz_fetch(state) == -1) + return NULL; /* error */ + if (state->x.have == 0) { /* end of file */ + state->past = 1; /* read past end */ + break; /* return what we have */ + } + + /* look for end-of-line in current output buffer */ + n = state->x.have > left ? left : state->x.have; + eol = (char*)memchr(state->x.next, '\n', n); + if (eol != NULL) + n = (unsigned)(eol - state->x.next) + 1; + + /* copy through end-of-line, or remainder if not found */ + memcpy(buf, state->x.next, n); + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + left -= n; + buf += n; + } while (left && eol == NULL); + + /* return terminated string, or if nothing, end of file */ + if (buf == str) + return NULL; + buf[0] = 0; + return str; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzdirect(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* if the state is not known, but we can find out, then do so (this is + mainly for right after a gzopen() or gzdopen()) */ + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); + + /* return 1 if transparent, 0 if processing a gzip stream */ + return state->direct; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_r(file) + gzFile file; +{ + int ret, err; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return Z_STREAM_ERROR; + + /* free memory and close file */ + if (state->size) { + inflateEnd(&(state->strm)); + free(state->out); + free(state->in); + } + err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; + gz_error(state, Z_OK, NULL); + free(state->path); + ret = close(state->fd); + free(state); + return ret ? Z_ERRNO : err; +} diff --git a/sdk-modifications/libsrc/zlib/gzwrite.c b/sdk-modifications/libsrc/zlib/gzwrite.c new file mode 100644 index 0000000..c346a64 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/gzwrite.c @@ -0,0 +1,593 @@ +/* gzwrite.c -- zlib functions for writing gzip files + * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_init OF((gz_statep)); +local int gz_comp OF((gz_statep, int)); +local int gz_zero OF((gz_statep, z_off64_t)); + +/* Initialize state for writing a gzip file. Mark initialization by setting + state->size to non-zero. Return -1 on failure or 0 on success. */ +local int gz_init(state) + gz_statep state; +{ + int ret; + z_streamp strm = &(state->strm); + + /* allocate input buffer */ + state->in = malloc(state->want); + if (state->in == NULL) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* only need output buffer and deflate state if compressing */ + if (!state->direct) { + /* allocate output buffer */ + state->out = malloc(state->want); + if (state->out == NULL) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); + if (ret != Z_OK) { + free(state->out); + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* mark state as initialized */ + state->size = state->want; + + /* initialize write buffer if compressing */ + if (!state->direct) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = strm->next_out; + } + return 0; +} + +/* Compress whatever is at avail_in and next_in and write to the output file. + Return -1 if there is an error writing to the output file, otherwise 0. + flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, + then the deflate() state is reset to start a new gzip stream. If gz->direct + is true, then simply write to the output file without compressing, and + ignore flush. */ +local int gz_comp(state, flush) + gz_statep state; + int flush; +{ + int ret, got; + unsigned have; + z_streamp strm = &(state->strm); + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return -1; + + /* write directly if requested */ + if (state->direct) { + got = write(state->fd, strm->next_in, strm->avail_in); + if (got < 0 || (unsigned)got != strm->avail_in) { + gz_error(state, Z_ERRNO, "Write Error"); + return -1; + } + strm->avail_in = 0; + return 0; + } + + /* run deflate() on provided input until it produces no more output */ + ret = Z_OK; + do { + /* write out current buffer contents if full, or if flushing, but if + doing Z_FINISH then don't write until we get to Z_STREAM_END */ + if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && + (flush != Z_FINISH || ret == Z_STREAM_END))) { + have = (unsigned)(strm->next_out - state->x.next); + if (have && ((got = write(state->fd, state->x.next, have)) < 0 || + (unsigned)got != have)) { + gz_error(state, Z_ERRNO, "Flush Error"); + return -1; + } + if (strm->avail_out == 0) { + strm->avail_out = state->size; + strm->next_out = state->out; + } + state->x.next = strm->next_out; + } + + /* compress */ + have = strm->avail_out; + ret = deflate(strm, flush); + if (ret == Z_STREAM_ERROR) { + gz_error(state, Z_STREAM_ERROR, + "internal error: deflate stream corrupt"); + return -1; + } + have -= strm->avail_out; + } while (have); + + /* if that completed a deflate stream, allow another to start */ + if (flush == Z_FINISH) + deflateReset(strm); + + /* all done, no errors */ + return 0; +} + +/* Compress len zeros to output. Return -1 on error, 0 on success. */ +local int gz_zero(state, len) + gz_statep state; + z_off64_t len; +{ + int first; + unsigned n; + z_streamp strm = &(state->strm); + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + + /* compress len zeros (len guaranteed > 0) */ + first = 1; + while (len) { + n = GT_OFF(state->size) || (z_off64_t)state->size > len ? + (unsigned)len : state->size; + if (first) { + memset(state->in, 0, n); + first = 0; + } + strm->avail_in = n; + strm->next_in = state->in; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + len -= n; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + unsigned put = len; + unsigned n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); + return 0; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* for small len, copy to input buffer, otherwise compress directly */ + if (len < state->size) { + /* copy to input buffer, compress when full */ + do { + if (strm->avail_in == 0) + strm->next_in = state->in; + n = state->size - strm->avail_in; + if (n > len) + n = len; + memcpy(strm->next_in + strm->avail_in, buf, n); + strm->avail_in += n; + state->x.pos += n; + buf = (char *)buf + n; + len -= n; + if (len && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } while (len); + } + else { + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* directly compress user buffer to file */ + strm->avail_in = len; + strm->next_in = (voidp)buf; + state->x.pos += len; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } + + /* input was all buffered or compressed (put will fit in int) */ + return (int)put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char buf[1]; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* try writing to input buffer for speed (state->size == 0 if buffer not + initialized) */ + if (strm->avail_in < state->size) { + if (strm->avail_in == 0) + strm->next_in = state->in; + strm->next_in[strm->avail_in++] = c; + state->x.pos++; + return c & 0xff; + } + + /* no room in buffer or not initialized, use gz_write() */ + buf[0] = c; + if (gzwrite(file, buf, 1) != 1) + return -1; + return c & 0xff; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputs(file, str) + gzFile file; + const char *str; +{ + int ret; + unsigned len; + + /* write string */ + len = (unsigned)strlen(str); + ret = gzwrite(file, str, len); + return ret == 0 && len != 0 ? -1 : ret; +} + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +#include + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) +{ + int size, len; + gz_statep state; + z_streamp strm; + va_list va; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(state->in, format, va); + va_end(va); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = vsprintf(state->in, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(state->in, size, format, va); + va_end(va); + len = strlen(state->in); +# else + len = vsnprintf((char *)(state->in), size, format, va); + va_end(va); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->x.pos += len; + return len; +} + +#else /* !STDC && !Z_HAVE_STDARG_H */ + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + int size, len; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that can really pass pointer in ints */ + if (sizeof(int) != sizeof(void *)) + return 0; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(state->in); +# else + len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->x.pos += len; + return len; +} + +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzflush(file, flush) + gzFile file; + int flush; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* check flush parameter */ + if (flush < 0 || flush > Z_FINISH) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* compress remaining data with requested flush */ + gz_comp(state, flush); + return state->err; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzsetparams(file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* if no change is requested, then do nothing */ + if (level == state->level && strategy == state->strategy) + return Z_OK; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* change compression parameters for subsequent input */ + if (state->size) { + /* flush previous input with previous parameters before changing */ + if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + return state->err; + deflateParams(strm, level, strategy); + } + state->level = level; + state->strategy = strategy; + return Z_OK; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_w(file) + gzFile file; +{ + int ret = Z_OK; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing */ + if (state->mode != GZ_WRITE) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + ret = state->err; + } + + /* flush, free memory, and close file */ + if (gz_comp(state, Z_FINISH) == -1) + ret = state->err; + if (!state->direct) { + (void)deflateEnd(&(state->strm)); + free(state->out); + } + free(state->in); + gz_error(state, Z_OK, NULL); + free(state->path); + if (close(state->fd) == -1) + ret = Z_ERRNO; + free(state); + return ret; +} + +/* used by zlibVersion() to get the vsnprintf story from the horse's mouth */ +unsigned long ZEXPORT gzflags() +{ + unsigned long flags = 0; +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} diff --git a/sdk-modifications/libsrc/zlib/infback.c b/sdk-modifications/libsrc/zlib/infback.c new file mode 100644 index 0000000..981aff1 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/infback.c @@ -0,0 +1,640 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2011 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->wnext = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + state->length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/sdk-modifications/libsrc/zlib/inffast.c b/sdk-modifications/libsrc/zlib/inffast.c new file mode 100644 index 0000000..2f1d60b --- /dev/null +++ b/sdk-modifications/libsrc/zlib/inffast.c @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/sdk-modifications/libsrc/zlib/inffast.h b/sdk-modifications/libsrc/zlib/inffast.h new file mode 100644 index 0000000..e5c1aa4 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/sdk-modifications/libsrc/zlib/inffixed.h b/sdk-modifications/libsrc/zlib/inffixed.h new file mode 100644 index 0000000..d628327 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/sdk-modifications/libsrc/zlib/inflate.c b/sdk-modifications/libsrc/zlib/inflate.c new file mode 100644 index 0000000..cc89517 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/inflate.c @@ -0,0 +1,1501 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2011 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateResetKeep(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + unsigned char *next; + unsigned avail; + int ret; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + next = strm->next_out; + avail = strm->avail_out; + strm->next_out = (Bytef *)dictionary + dictLength; + strm->avail_out = 0; + ret = updatewindow(strm, dictLength); + strm->avail_out = avail; + strm->next_out = next; + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} diff --git a/sdk-modifications/libsrc/zlib/inflate.h b/sdk-modifications/libsrc/zlib/inflate.h new file mode 100644 index 0000000..95f4986 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/sdk-modifications/libsrc/zlib/inftrees.c b/sdk-modifications/libsrc/zlib/inftrees.c new file mode 100644 index 0000000..60bbd58 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/inftrees.c @@ -0,0 +1,306 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2012 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.6 Copyright 1995-2012 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 69}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/sdk-modifications/libsrc/zlib/inftrees.h b/sdk-modifications/libsrc/zlib/inftrees.h new file mode 100644 index 0000000..baa53a0 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/sdk-modifications/libsrc/zlib/trees.c b/sdk-modifications/libsrc/zlib/trees.c new file mode 100644 index 0000000..8c32b21 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/trees.c @@ -0,0 +1,1224 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2012 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) + */ +void ZLIB_INTERNAL _tr_flush_bits(s) + deflate_state *s; +{ + bi_flush(s); +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/sdk-modifications/libsrc/zlib/trees.h b/sdk-modifications/libsrc/zlib/trees.h new file mode 100644 index 0000000..d35639d --- /dev/null +++ b/sdk-modifications/libsrc/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/sdk-modifications/libsrc/zlib/uncompr.c b/sdk-modifications/libsrc/zlib/uncompr.c new file mode 100644 index 0000000..ad98be3 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/uncompr.c @@ -0,0 +1,59 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/sdk-modifications/libsrc/zlib/zconf.h b/sdk-modifications/libsrc/zlib/zconf.h new file mode 100644 index 0000000..96810e7 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/zconf.h @@ -0,0 +1,468 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2011 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflags z_gzflags +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# endif +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# ifndef Z_SOLO +# define gz_header_s z_gz_header_s +# endif +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +// # include /* for off_t */ +// Does not work with the DS2 SDK. There is a type conflict between sys/types.h +// and fs_api.h. +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define Z_LARGE +#endif + +#if (defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)) && !defined(Z_SOLO) +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && (defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0) +# define z_off64_t off64_t +#else +# if defined(_WIN32) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +#endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/sdk-modifications/libsrc/zlib/zlib.h b/sdk-modifications/libsrc/zlib/zlib.h new file mode 100644 index 0000000..79142d1 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/zlib.h @@ -0,0 +1,1732 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.6, January 29th, 2012 + + Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.6" +#define ZLIB_VERNUM 0x1260 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 6 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). Then deflate is guaranteed to + return Z_STREAM_END. If not enough output space is provided, deflate will + not return Z_STREAM_END, and it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is not required to perform an + inflation in one step. However it may be used to inform inflate that a + faster approach can be used for the single inflate() call. Z_FINISH also + informs inflate to not maintain a sliding window if the stream completes, + which reduces inflate's memory footprint. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + producted so far. The CRC-32 is checked against the gzip trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); +#define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc_(g)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#ifndef Z_SOLO + ZEXTERN unsigned long ZEXPORT gzflags OF((void)); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/sdk-modifications/libsrc/zlib/zlib.mk b/sdk-modifications/libsrc/zlib/zlib.mk new file mode 100644 index 0000000..94ea103 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/zlib.mk @@ -0,0 +1,10 @@ +# zlib.mk + +SRC += $(wildcard $(ZLIB_DIR)/*.c) + +SSRC += + +INC += -I$(ZLIB_DIR) + +CFLAGS += + diff --git a/sdk-modifications/libsrc/zlib/zutil.c b/sdk-modifications/libsrc/zlib/zutil.c new file mode 100644 index 0000000..8a1d242 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/zutil.c @@ -0,0 +1,301 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010, 2011 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef Z_SOLO + return flags; +#else + return flags + gzflags(); +#endif +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifndef Z_SOLO + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/sdk-modifications/libsrc/zlib/zutil.h b/sdk-modifications/libsrc/zlib/zutil.h new file mode 100644 index 0000000..d8575e0 --- /dev/null +++ b/sdk-modifications/libsrc/zlib/zutil.h @@ -0,0 +1,254 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2011 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#include +#include +#include + +# include + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +//# include +# endif +//# include +//# include +#endif + +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(pyr) || defined(Z_SOLO) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ -- cgit v1.2.3 From fd92545013ed91d2867e1e180a9b86611eb19f9c Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 04:20:51 -0500 Subject: Whoops. I forgot to replace an instance of ds2_setCPULevel from the experimental branch cherry-pick. --- source/nds/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index 3942672..7100cf2 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1666,7 +1666,7 @@ void GameFrequencyCPU() u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 396 if(clock_speed_number <= 5) - ds2_setCPULevel(clock_speed_table[clock_speed_number]); + ds2_setCPUclocklevel(clock_speed_table[clock_speed_number]); } void savefast_int(void) -- cgit v1.2.3 From 461f2406555faaee7191871390192d06625f5a81 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 05:59:48 -0500 Subject: Fix a name clash between Snes9x's dma.h and the DS2 dma.h by renaming the DS2 dma.h to ds2_dma.h. Add preliminary support for drawing emulated screens with DS2 DMA. --- Makefile | 5 +- sdk-modifications/include/dma.h | 46 ----------- sdk-modifications/include/ds2_dma.h | 138 ++++++++------------------------- sdk-modifications/libsrc/dma/dma.h | 46 ----------- sdk-modifications/libsrc/dma/dmacopy.c | 2 +- sdk-modifications/libsrc/dma/ds2_dma.h | 54 +++++++++++++ source/nds/entry.cpp | 37 +++++++++ 7 files changed, 129 insertions(+), 199 deletions(-) delete mode 100644 sdk-modifications/include/dma.h delete mode 100644 sdk-modifications/libsrc/dma/dma.h create mode 100644 sdk-modifications/libsrc/dma/ds2_dma.h diff --git a/Makefile b/Makefile index e0732d3..854a285 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ C_SOURCES = source/unzip/explode.c source/unzip/unreduce.c \ source/unzip/unshrink.c source/unzip/unzip.c \ source/nds/bdf_font.c source/nds/bitmap.c \ source/nds/draw.c source/nds/ds2_main.c source/nds/gcheat.c \ - source/nds/gui.c + source/nds/gui.c source/nds/dma_adj.c CPP_SOURCES = source/apu.cpp source/apudebug.cpp source/c4.cpp \ source/c4emu.cpp source/cheats2.cpp source/cheats.cpp \ source/clip.cpp source/cpu.cpp source/cpuexec.cpp \ @@ -70,7 +70,8 @@ DEFS := -DSPC700_C -DEXECUTE_SUPERFX_PER_LINE -DSDD1_DECOMP \ -DVAR_CYCLES -DCPU_SHUTDOWN -DSPC700_SHUTDOWN \ -DNO_INLINE_SET_GET -DNOASM -DHAVE_MKSTEMP '-DACCEPT_SIZE_T=size_t' \ -DUNZIP_SUPPORT -DFOREVER_16_BIT_SOUND -DFOREVER_STEREO \ - -DFOREVER_FORWARD_STEREO -DNO_VOLATILE_SOUND -DSYNC_JOYPAD_AT_HBLANK + -DFOREVER_FORWARD_STEREO -DNO_VOLATILE_SOUND \ + -DSYNC_JOYPAD_AT_HBLANK -DDS2_DMA .PHONY: clean makedirs .SUFFIXES: .elf .dat .plg diff --git a/sdk-modifications/include/dma.h b/sdk-modifications/include/dma.h deleted file mode 100644 index f6ff230..0000000 --- a/sdk-modifications/include/dma.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __DMA_H__ -#define __DMA_H__ - -//register a DMA transfer request -//ch: channel id request, there are 6 channles, -//irq_handler: the DMA interruption handle -//arg: argument to the handle -//mode: DMA mode, such as port width, address increased/fixed, and so on -//type: DMA request type -extern int dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg, - unsigned int mode, unsigned int type); - -//start DMA transfer, must request a DMA first -//ch: channel id -//srcAddr: DMA source address -//dstAddr: DMA destination address -//count: DMA transfer count, the total bytes due the mode in dma_request -extern void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr, - unsigned int count); - -//Stop DMA transfer -extern void dma_stop(int ch); - -//Wait DMA transfer over -extern int dma_wait_finish(int ch); - - -/* - * Copy 'size' bytes from src to dest, in blocks of 32 bytes. - * size is in bytes and must be a multiple of 32. - * Both src and dest must be aligned to 32 bytes. - * Returns 0 on failure, non-zero on success. - */ -extern int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size); -// Blocks of 16 bytes, aligned to 16 bytes -extern int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size); -// Blocks of 4 bytes, aligned to 4 bytes -extern int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size); -// Blocks of 2 bytes, aligned to 2 bytes -extern int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size); -extern int dma_isBusy(int ch); -extern int dma_isFree(int ch); -extern int dma_getFree(void); - -#endif //__DMA_H__ - diff --git a/sdk-modifications/include/ds2_dma.h b/sdk-modifications/include/ds2_dma.h index c7cd267..491df0e 100644 --- a/sdk-modifications/include/ds2_dma.h +++ b/sdk-modifications/include/ds2_dma.h @@ -1,120 +1,50 @@ -#ifndef _DS2_DMA_H__ -#define _DS2_DMA_H__ +#ifndef __DMA_H__ +#define __DMA_H__ #ifdef __cplusplus extern "C" { #endif - -#define MAX_DMA_NUM 6 /* max 6 channels */ - - -// DMA request source register -#define DMAC_DRSR_RS_BIT 0 -#define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) - - -// DMA channel command register -#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ -#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ - -#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ -#define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) -#define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) -#define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) - -#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ -#define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) -#define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) - #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) - -#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ -#define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) -#define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) -#define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) -#define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) -#define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) - -#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ - - -//detect if channel has completed job -#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ -#define DMAC_BASE 0xB3020000 -#define REG32(addr) *((volatile u32 *)(addr)) -#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ -#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) - -#define ds2_DMA_isBusy(n) \ - !( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) - - -/* -Copy modes - -*/ - -#define DMA_MODE32BYTE DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ - DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM - -#define DMA_MODE16BYTE DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ - DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM - -#define DMA_MODE32BIT DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ - DMAC_DCMD_DS_32BIT - -#define DMA_MODE16BIT DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ - DMAC_DCMD_DS_16BIT - -#define DMA_MODE8BIT DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_8 | \ - DMAC_DCMD_DS_8BIT | DMAC_DCMD_TM - -#define DMA_MODECOPY DMAC_DCMD_SAI - - - -extern int _dmaCopy(int ch, void *dest, void *src, unsigned int size, unsigned int flags); - -//copy from 32 bit source to 32 bit dest -//data must be 32 byte aligned -#define ds2_DMAcopy_32Byte(ch, dest, src, size)\ - _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE32BYTE) - -//copy from 16 bit source to 16 bit dest -//data must be 16 byte aligned -#define ds2_DMAcopy_16Byte(ch, dest, src, size)\ - _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE16BYTE); - -//copy from 32 bit source to 32 bit dest -//data must be 32 bit aligned -#define ds2_DMAcopy_32Bit(ch, dest, src, size)\ - _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE32BIT); - -//copy from 16 bit source to 16 bit dest -//data must be 16 bit aligned -#define ds2_DMAcopy_16Bit(ch, dest, src, size)\ - _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE16BIT) - -//copy from 8 bit source to 8 bit dest -//data must be 8 bit aligned -#define ds2_DMAcopy_8Bit(ch, dest, src, size)\ - _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE8BIT) - - +//register a DMA transfer request +//ch: channel id request, there are 6 channles, +//irq_handler: the DMA interruption handle +//arg: argument to the handle +//mode: DMA mode, such as port width, address increased/fixed, and so on +//type: DMA request type +extern int dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg, + unsigned int mode, unsigned int type); + +//start DMA transfer, must request a DMA first +//ch: channel id +//srcAddr: DMA source address +//dstAddr: DMA destination address +//count: DMA transfer count, the total bytes due the mode in dma_request +extern void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr, + unsigned int count); //Stop DMA transfer extern void dma_stop(int ch); -#define ds2_DMA_stop(ch)\ - dma_stop(ch) - //Wait DMA transfer over extern int dma_wait_finish(int ch); -#define ds2_DMA_wait(ch)\ - dma_wait_finish(ch) - +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bytes. + * size is in bytes and must be a multiple of 32. + * Both src and dest must be aligned to 32 bytes. + * Returns 0 on failure, non-zero on success. + */ +extern int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size); +// Blocks of 16 bytes, aligned to 16 bytes +extern int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size); +// Blocks of 4 bytes, aligned to 4 bytes +extern int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size); +// Blocks of 2 bytes, aligned to 2 bytes +extern int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size); +extern int dma_isBusy(int ch); +extern int dma_isFree(int ch); +extern int dma_getFree(void); #ifdef __cplusplus } diff --git a/sdk-modifications/libsrc/dma/dma.h b/sdk-modifications/libsrc/dma/dma.h deleted file mode 100644 index f6ff230..0000000 --- a/sdk-modifications/libsrc/dma/dma.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __DMA_H__ -#define __DMA_H__ - -//register a DMA transfer request -//ch: channel id request, there are 6 channles, -//irq_handler: the DMA interruption handle -//arg: argument to the handle -//mode: DMA mode, such as port width, address increased/fixed, and so on -//type: DMA request type -extern int dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg, - unsigned int mode, unsigned int type); - -//start DMA transfer, must request a DMA first -//ch: channel id -//srcAddr: DMA source address -//dstAddr: DMA destination address -//count: DMA transfer count, the total bytes due the mode in dma_request -extern void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr, - unsigned int count); - -//Stop DMA transfer -extern void dma_stop(int ch); - -//Wait DMA transfer over -extern int dma_wait_finish(int ch); - - -/* - * Copy 'size' bytes from src to dest, in blocks of 32 bytes. - * size is in bytes and must be a multiple of 32. - * Both src and dest must be aligned to 32 bytes. - * Returns 0 on failure, non-zero on success. - */ -extern int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size); -// Blocks of 16 bytes, aligned to 16 bytes -extern int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size); -// Blocks of 4 bytes, aligned to 4 bytes -extern int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size); -// Blocks of 2 bytes, aligned to 2 bytes -extern int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size); -extern int dma_isBusy(int ch); -extern int dma_isFree(int ch); -extern int dma_getFree(void); - -#endif //__DMA_H__ - diff --git a/sdk-modifications/libsrc/dma/dmacopy.c b/sdk-modifications/libsrc/dma/dmacopy.c index 2c5a2b1..83609d3 100644 --- a/sdk-modifications/libsrc/dma/dmacopy.c +++ b/sdk-modifications/libsrc/dma/dmacopy.c @@ -1,5 +1,5 @@ #include -#include "dma.h" +#include "ds2_dma.h" #include "ds2_types.h" #define MAX_DMA_NUM 6 /* max 6 channels */ diff --git a/sdk-modifications/libsrc/dma/ds2_dma.h b/sdk-modifications/libsrc/dma/ds2_dma.h new file mode 100644 index 0000000..491df0e --- /dev/null +++ b/sdk-modifications/libsrc/dma/ds2_dma.h @@ -0,0 +1,54 @@ +#ifndef __DMA_H__ +#define __DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//register a DMA transfer request +//ch: channel id request, there are 6 channles, +//irq_handler: the DMA interruption handle +//arg: argument to the handle +//mode: DMA mode, such as port width, address increased/fixed, and so on +//type: DMA request type +extern int dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg, + unsigned int mode, unsigned int type); + +//start DMA transfer, must request a DMA first +//ch: channel id +//srcAddr: DMA source address +//dstAddr: DMA destination address +//count: DMA transfer count, the total bytes due the mode in dma_request +extern void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr, + unsigned int count); + +//Stop DMA transfer +extern void dma_stop(int ch); + +//Wait DMA transfer over +extern int dma_wait_finish(int ch); + + +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bytes. + * size is in bytes and must be a multiple of 32. + * Both src and dest must be aligned to 32 bytes. + * Returns 0 on failure, non-zero on success. + */ +extern int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size); +// Blocks of 16 bytes, aligned to 16 bytes +extern int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size); +// Blocks of 4 bytes, aligned to 4 bytes +extern int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size); +// Blocks of 2 bytes, aligned to 2 bytes +extern int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size); +extern int dma_isBusy(int ch); +extern int dma_isFree(int ch); +extern int dma_getFree(void); + +#ifdef __cplusplus +} +#endif + +#endif //__DMA_H__ + diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 5d79b64..4aa2977 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -23,6 +23,11 @@ #include "entry.h" #include "ds2sound.h" +#ifdef DS2_DMA +#include "ds2_dma.h" +#include "dma_adj.h" +#endif + void S9xProcessSound (unsigned int); char *rom_filename = NULL; @@ -58,7 +63,11 @@ void S9xExtraUsage () */ void S9xDeinitDisplay (void) { +#ifdef DS2_DMA + if(GFX.Screen) AlignedFree(GFX.Screen, PtrAdj.GFXScreen); +#else if(GFX.Screen) free(GFX.Screen); +#endif if(GFX.SubScreen) free(GFX.SubScreen); if(GFX.ZBuffer) free(GFX.ZBuffer); if(GFX.SubZBuffer) free(GFX.SubZBuffer); @@ -69,7 +78,11 @@ void S9xInitDisplay (int, char **) int h = IMAGE_HEIGHT; GFX.Pitch = IMAGE_WIDTH * 2; +#ifdef DS2_DMA + GFX.Screen = (unsigned char*) AlignedMalloc (GFX.Pitch * h, 32, &PtrAdj.GFXScreen); +#else GFX.Screen = (unsigned char*) malloc (GFX.Pitch * h); +#endif GFX.SubScreen = (unsigned char*) malloc (GFX.Pitch * h); GFX.ZBuffer = (unsigned char*) malloc ((GFX.Pitch >> 1) * h); GFX.SubZBuffer =(unsigned char*) malloc ((GFX.Pitch >> 1) * h); @@ -130,17 +143,35 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) { //Up case 1: +#ifdef DS2_DMA + dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); + dma_wait_finish(5); + dma_stop(5); +#else memcpy(up_screen_addr, GFX.Screen+256*32*2, 256*192*2); +#endif break; //Down case 2: +#ifdef DS2_DMA + dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); + dma_wait_finish(5); + dma_stop(5); +#else memcpy(up_screen_addr, GFX.Screen, 256*192*2); +#endif break; //Both case 3: +#ifdef DS2_DMA + dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); + dma_wait_finish(5); + dma_stop(5); +#else memcpy(up_screen_addr, GFX.Screen+256*16*2, 256*192*2); +#endif break; case 4: @@ -157,7 +188,13 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) dst = (unsigned char*)up_screen_addr; for(m = 0; m < 32; m++) { +#ifdef DS2_DMA + dma_copy32Byte(5 /* channel: graphics */, dst, src, 256 * 6 * 2); + dma_wait_finish(5); + dma_stop(5); +#else memcpy(dst, src, 256*6*2); +#endif dst += 256*6*2; src += 256*7*2; } -- cgit v1.2.3 From 9b75c09a7fd7c78d8c42077478e796672fae5c1b Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 06:25:12 -0500 Subject: Force waiting for a screen to be transferred (update mode 1) because otherwise the next screen can go into DMA. Use channel 1 instead of channel 5, which must be busy for some reason. --- source/nds/entry.cpp | 24 ++++++++++++------------ source/nds/gui.h | 4 ++++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 4aa2977..3fa6517 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -144,9 +144,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Up case 1: #ifdef DS2_DMA - dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); - dma_wait_finish(5); - dma_stop(5); + dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); + dma_wait_finish(1); + dma_stop(1); #else memcpy(up_screen_addr, GFX.Screen+256*32*2, 256*192*2); #endif @@ -155,9 +155,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Down case 2: #ifdef DS2_DMA - dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); - dma_wait_finish(5); - dma_stop(5); + dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); + dma_wait_finish(1); + dma_stop(1); #else memcpy(up_screen_addr, GFX.Screen, 256*192*2); #endif @@ -166,9 +166,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Both case 3: #ifdef DS2_DMA - dma_copy32Byte(5 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); - dma_wait_finish(5); - dma_stop(5); + dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); + dma_wait_finish(1); + dma_stop(1); #else memcpy(up_screen_addr, GFX.Screen+256*16*2, 256*192*2); #endif @@ -189,9 +189,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) for(m = 0; m < 32; m++) { #ifdef DS2_DMA - dma_copy32Byte(5 /* channel: graphics */, dst, src, 256 * 6 * 2); - dma_wait_finish(5); - dma_stop(5); + dma_copy32Byte(1 /* channel: graphics */, dst, src, 256 * 6 * 2); + dma_wait_finish(1); + dma_stop(1); #else memcpy(dst, src, 256*6*2); #endif diff --git a/source/nds/gui.h b/source/nds/gui.h index b2eae62..9df2ad2 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -24,7 +24,11 @@ #include "fs_api.h" #include "gcheat.h" +#ifdef DS2_DMA +#define UP_SCREEN_UPDATE_METHOD 1 +#else #define UP_SCREEN_UPDATE_METHOD 0 +#endif #define DOWN_SCREEN_UPDATE_METHOD 2 #define MAX_GAMEPAD_MAP 16 -- cgit v1.2.3 From 397bf5192a44ea95a82a9792cb7a8a23b112bb3e Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 15:29:05 -0500 Subject: Add some forgotten DMA files. --- source/nds/dma_adj.c | 26 ++++++++++++++++++++++++++ source/nds/dma_adj.h | 25 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 source/nds/dma_adj.c create mode 100644 source/nds/dma_adj.h diff --git a/source/nds/dma_adj.c b/source/nds/dma_adj.c new file mode 100644 index 0000000..8b6f9ad --- /dev/null +++ b/source/nds/dma_adj.c @@ -0,0 +1,26 @@ +#include "ds2_malloc.h" +#include "dma_adj.h" + +#ifdef DS2_DMA + +struct SPointerAdjustments PtrAdj; + +void* AlignedMalloc (unsigned int Size, unsigned int Alignment, unsigned int* Adjustment) +{ + if (Alignment == 0) Alignment = 1; + + unsigned char* result = (unsigned char*) malloc(Size + Alignment); + if (!result) { + return result; + } else { + *Adjustment = Alignment - ((unsigned int) result & (Alignment - 1)); + return (void*) (result + *Adjustment); + } +} + +void AlignedFree (void* Memory, unsigned int Adjustment) +{ + free((void*) ((unsigned char*) Memory - Adjustment)); +} + +#endif // DS2_DMA diff --git a/source/nds/dma_adj.h b/source/nds/dma_adj.h new file mode 100644 index 0000000..62b0098 --- /dev/null +++ b/source/nds/dma_adj.h @@ -0,0 +1,25 @@ +#ifndef _DMA_ADJ_H_ +#define _DMA_ADJ_H_ + +#ifdef DS2_DMA + +#ifdef __cplusplus +extern "C" { +#endif + +struct SPointerAdjustments { + unsigned int GFXScreen; +}; + +extern struct SPointerAdjustments PtrAdj; + +extern void* AlignedMalloc (unsigned int Size, unsigned int Alignment, unsigned int* Adjustment); +extern void AlignedFree (void* Memory, unsigned int Adjustment); + +#ifdef __cplusplus +} +#endif + +#endif // DS2_DMA + +#endif // !_DMA_ADJ_H_ -- cgit v1.2.3 From 538718997fd9c85289669c1b5a8e46a45b6328af Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 15:52:45 -0500 Subject: Write back the data cache before using DMA to draw emulated frames. --- source/nds/entry.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 3fa6517..286722e 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -144,6 +144,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Up case 1: #ifdef DS2_DMA + __dcache_writeback_all(); dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); dma_wait_finish(1); dma_stop(1); @@ -155,6 +156,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Down case 2: #ifdef DS2_DMA + __dcache_writeback_all(); dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); dma_wait_finish(1); dma_stop(1); @@ -166,6 +168,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) //Both case 3: #ifdef DS2_DMA + __dcache_writeback_all(); dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); dma_wait_finish(1); dma_stop(1); @@ -181,8 +184,11 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) default: { - unsigned char *src, *dst; - unsigned int m; +#ifdef DS2_DMA + __dcache_writeback_all(); +#endif + register unsigned char *src, *dst; + register unsigned int m; src = GFX.Screen; dst = (unsigned char*)up_screen_addr; -- cgit v1.2.3 From 1ddc8b53fe92a88578f23ace849168bc19ca0cd0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 16:17:06 -0500 Subject: Faking out the sound synchronisation with a buffer of silence wasn't necessary. --- source/nds/entry.cpp | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 286722e..727986e 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -982,27 +982,8 @@ void S9xProcessSound (unsigned int) if (Now - LastSoundEmissionTime >= 11719 /* 500 milliseconds */) { LastSoundEmissionTime = Now; - // We were probably paused. Restart sending sound with an - // empty buffer. - do { - audiobuff = (unsigned short*)ds2_getAudiobuff(); - } while (audiobuff == NULL); //There are audio queue in sending or wait to send - - memset(audiobuff, 0, DS2_BUFFER_SIZE -#ifndef FOREVER_STEREO - << (so.stereo ? 1 : 0) -#else - << 1 -#endif -#ifndef FOREVER_16_BIT_SOUND - << (so.sixteen_bit ? 1 : 0) -#else - << 1 -#endif - ); - - ds2_updateAudio(); - // And then the real audio. (fall through) + // We were probably paused. Restart sending sound, + // synchronising from now. } else { -- cgit v1.2.3 From b3a7f8f1fceddcd45ec62bcbf75ba128e4f84f5a Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 19:26:34 -0500 Subject: Synchronise the controller status more spread out inside a rendered frame: * before rendering a background; * before rendering sprites; * while rendering more than 128 samples of audio at once ("Prefer fluid video"); * after every 16 scanlines of CPU execution instead of every 1; * while waiting for an audio buffer to become available; * while killing time between frames with fast-forward disabled. Controller presses and releases are now combined in a DS button bitfield using a shorter 32-bit algorithm. See entry.cpp:NDSSFCAccumulateJoypad and #define ACCUMULATE_JOYPAD in the source. This is still not suitable for playing platformers frame-perfectly, but it's much better than half a second of latency to press or release a button, and one still needs to press buttons a bit more than just light taps. I'd say 50 milliseconds is the latency now. Platformers requiring more precision can be played with frameskip 0. DMA does not require double-buffered displaying, so synchronise the controller more often by disabling double-buffered displaying again. --- Makefile | 2 +- source/cpuexec.cpp | 35 +++++------ source/display.h | 3 + source/gfx.cpp | 16 +++++ source/nds/entry.cpp | 162 +++++++++++++++++++++++++++++++++------------------ source/nds/gui.h | 4 -- source/ppu.cpp | 33 ----------- source/ppu.h | 3 - source/soundux.cpp | 9 +++ 9 files changed, 150 insertions(+), 117 deletions(-) diff --git a/Makefile b/Makefile index 854a285..c325437 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ DEFS := -DSPC700_C -DEXECUTE_SUPERFX_PER_LINE -DSDD1_DECOMP \ -DNO_INLINE_SET_GET -DNOASM -DHAVE_MKSTEMP '-DACCEPT_SIZE_T=size_t' \ -DUNZIP_SUPPORT -DFOREVER_16_BIT_SOUND -DFOREVER_STEREO \ -DFOREVER_FORWARD_STEREO -DNO_VOLATILE_SOUND \ - -DSYNC_JOYPAD_AT_HBLANK -DDS2_DMA + -DACCUMULATE_JOYPAD -DDS2_DMA .PHONY: clean makedirs .SUFFIXES: .elf .dat .plg diff --git a/source/cpuexec.cpp b/source/cpuexec.cpp index a0c7ebc..30dff21 100644 --- a/source/cpuexec.cpp +++ b/source/cpuexec.cpp @@ -105,7 +105,7 @@ #include "sa1.h" #include "spc7110.h" -#ifdef SYNC_JOYPAD_AT_HBLANK +#ifdef ACCUMULATE_JOYPAD #include "display.h" #endif @@ -473,15 +473,14 @@ void S9xDoHBlankProcessing_SFX () switch (CPU.WhichEvent) { case HBLANK_START_EVENT: -#ifdef SYNC_JOYPAD_AT_HBLANK - // Re-get the controls every hblank. A resolution algorithm in - // ppu.cpp will determine with greater accuracy whether a key was - // pressed or released during the frame. - uint32 i; - for (i = 0; i < 5; i++) - { - IPPU.JoypadsAtHBlanks [i][CPU.V_Counter] = S9xReadJoypad (i); - } +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + if ((CPU.V_Counter & 0xF) == 0) + NDSSFCAccumulateJoypad (); #endif if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); @@ -663,15 +662,13 @@ void S9xDoHBlankProcessing_NoSFX () switch (CPU.WhichEvent) { case HBLANK_START_EVENT: -#ifdef SYNC_JOYPAD_AT_HBLANK - // Re-get the controls every hblank. A resolution algorithm in - // ppu.cpp will determine with greater accuracy whether a key was - // pressed or released during the frame. - uint32 i; - for (i = 0; i < 5; i++) - { - IPPU.JoypadsAtHBlanks [i][CPU.V_Counter] = S9xReadJoypad (i); - } +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); #endif if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); diff --git a/source/display.h b/source/display.h index 8e65885..d00c5ed 100644 --- a/source/display.h +++ b/source/display.h @@ -97,6 +97,9 @@ void S9xGraphicsMode (); char *S9xParseArgs (char **argv, int argc); void S9xParseArg (char **argv, int &index, int argc); void S9xExtraUsage (); +#ifdef ACCUMULATE_JOYPAD +void NDSSFCAccumulateJoypad (); +#endif uint32 S9xReadJoypad (int which1_0_to_4); bool8 S9xReadMousePosition (int which1_0_to_1, int &x, int &y, uint32 &buttons); bool8 S9xReadSuperScopePosition (int &x, int &y, uint32 &buttons); diff --git a/source/gfx.cpp b/source/gfx.cpp index 1b429c6..9ea0a97 100644 --- a/source/gfx.cpp +++ b/source/gfx.cpp @@ -1169,6 +1169,14 @@ void S9xSetupOBJ () static void DrawOBJS (bool8 OnMain = FALSE, uint8 D = 0) { +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); +#endif #ifdef MK_DEBUG_RTO if(Settings.BGLayering) fprintf(stderr, "Entering DrawOBJS() for %d-%d\n", GFX.StartY, GFX.EndY); #endif @@ -2314,6 +2322,14 @@ static void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 static void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) { +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); +#endif GFX.PixSize = 1; BG.TileSize = BGSizes [PPU.BG[bg].BGSize]; diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 727986e..14c6243 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -734,6 +734,14 @@ void S9xSyncSpeed () { do { S9xProcessSound (0); +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); +#endif syncdif = sync_next - getSysTime(); } while (syncdif > 0); } @@ -767,6 +775,14 @@ void S9xSyncSpeed () { do { S9xProcessSound (0); +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + NDSSFCAccumulateJoypad (); +#endif syncdif = sync_next - getSysTime(); } while (syncdif > 0); // After that little delay, what time is it? @@ -968,17 +984,17 @@ void S9xProcessSound (unsigned int) if (!game_enable_audio) return; - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) - { - LastSoundEmissionTime++; - return; - } - - unsigned short *audiobuff; - unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) + { + LastSoundEmissionTime++; + return; + } + + unsigned short *audiobuff; + if (Now - LastSoundEmissionTime >= 11719 /* 500 milliseconds */) { LastSoundEmissionTime = Now; @@ -1003,9 +1019,14 @@ void S9xProcessSound (unsigned int) } #endif - do { + audiobuff = (unsigned short*)ds2_getAudiobuff(); + while (audiobuff == NULL) //There are audio queue in sending or wait to send + { +#ifdef ACCUMULATE_JOYPAD + NDSSFCAccumulateJoypad (); +#endif audiobuff = (unsigned short*)ds2_getAudiobuff(); - } while (audiobuff == NULL); //There are audio queue in sending or wait to send + } /* If we need more audio samples */ if (so.samples_mixed_so_far < sample_count) @@ -1141,72 +1162,99 @@ const unsigned int keymap[12] = { static bool8 SoundToggleWasHeld = FALSE; -unsigned int S9xReadJoypad (int which1) -{ - struct key_buf inputdata; +#ifdef ACCUMULATE_JOYPAD +// These are kept as DS key bitfields until it's time to send them to Snes9x. +static uint32 PreviousControls = 0x00000000; +static uint32 ControlsPressed = 0x00000000; +static uint32 ControlsReleased = 0x00000000; +void NDSSFCAccumulateJoypad () +{ + struct key_buf inputdata; ds2_getrawInput(&inputdata); - if (inputdata.key & KEY_LID) + ControlsPressed |= inputdata.key & ~PreviousControls; + ControlsReleased |= PreviousControls & ~inputdata.key; +} +#endif // ACCUMULATE_JOYPAD + +uint32 S9xReadJoypad (int which1) +{ + if(which1 < 1) { - LowFrequencyCPU(); - ds2_setSupend(); - do { + uint32 Controls; +#ifdef ACCUMULATE_JOYPAD + Controls = (PreviousControls | ControlsPressed) & ~ControlsReleased; + PreviousControls = Controls; + ControlsPressed = ControlsReleased = 0x00000000; +#else + { + struct key_buf inputdata; ds2_getrawInput(&inputdata); - mdelay(1); - } while (inputdata.key & KEY_LID); - ds2_wakeup(); - // Before starting to emulate again, turn off the lower - // screen's backlight. - mdelay(100); // needed to avoid ds2_setBacklight crashing - ds2_setBacklight(2); - GameFrequencyCPU(); - } - u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu; - u32 HotkeyTemporaryFastForward = game_config.HotkeyTemporaryFastForward != 0 ? game_config.HotkeyTemporaryFastForward : emu_config.HotkeyTemporaryFastForward; - u32 HotkeyToggleSound = game_config.HotkeyToggleSound != 0 ? game_config.HotkeyToggleSound : emu_config.HotkeyToggleSound; + Controls = inputdata.key; + } +#endif - if(inputdata.key & KEY_TOUCH || - (HotkeyReturnToMenu && ((inputdata.key & HotkeyReturnToMenu) == HotkeyReturnToMenu)) - ) //Active menu - Settings.Paused = 1; + if (Controls & KEY_LID) + { + LowFrequencyCPU(); + ds2_setSupend(); + struct key_buf inputdata; + do { + ds2_getrawInput(&inputdata); + mdelay(1); + } while (inputdata.key & KEY_LID); + ds2_wakeup(); + // Before starting to emulate again, turn off the lower + // screen's backlight. + mdelay(100); // needed to avoid ds2_setBacklight crashing + ds2_setBacklight(2); + GameFrequencyCPU(); + } - temporary_fast_forward = - (HotkeyTemporaryFastForward && ((inputdata.key & HotkeyTemporaryFastForward) == HotkeyTemporaryFastForward)) - ; + u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu; + u32 HotkeyTemporaryFastForward = game_config.HotkeyTemporaryFastForward != 0 ? game_config.HotkeyTemporaryFastForward : emu_config.HotkeyTemporaryFastForward; + u32 HotkeyToggleSound = game_config.HotkeyToggleSound != 0 ? game_config.HotkeyToggleSound : emu_config.HotkeyToggleSound; - bool8 SoundToggleIsHeld = - (HotkeyToggleSound && ((inputdata.key & HotkeyToggleSound) == HotkeyToggleSound)) - ; + if(Controls & KEY_TOUCH || + (HotkeyReturnToMenu && ((Controls & HotkeyReturnToMenu) == HotkeyReturnToMenu)) + ) //Active menu + Settings.Paused = 1; - if (SoundToggleIsHeld && !SoundToggleWasHeld) - { - game_enable_audio = !game_enable_audio; - game_disableAudio(); - } + temporary_fast_forward = + (HotkeyTemporaryFastForward && ((Controls & HotkeyTemporaryFastForward) == HotkeyTemporaryFastForward)) + ; - SoundToggleWasHeld = SoundToggleIsHeld; + bool8 SoundToggleIsHeld = + (HotkeyToggleSound && ((Controls & HotkeyToggleSound) == HotkeyToggleSound)) + ; - if(which1 < 1) - { - unsigned int key; + if (SoundToggleIsHeld && !SoundToggleWasHeld) + { + game_enable_audio = !game_enable_audio; + game_disableAudio(); + } + + SoundToggleWasHeld = SoundToggleIsHeld; + + uint32 key = 0x80000000; // Required by Snes9x // DS -> SNES - key = (inputdata.key & KEY_A ) << 7; // 0x0001 -> 0x0080 - key |= (inputdata.key & KEY_B ) << 14; // 0x0002 -> 0x8000 - key |= (inputdata.key & KEY_SELECT) << 11; // 0x0004 -> 0x2000 - key |= (inputdata.key & KEY_START ) << 9; // 0x0008 -> 0x1000 - key |= (inputdata.key & KEY_UP ) << 5; // 0x0040 -> 0x0800 + key |= (Controls & KEY_A ) << 7; // 0x0001 -> 0x0080 + key |= (Controls & KEY_B ) << 14; // 0x0002 -> 0x8000 + key |= (Controls & KEY_SELECT) << 11; // 0x0004 -> 0x2000 + key |= (Controls & KEY_START ) << 9; // 0x0008 -> 0x1000 + key |= (Controls & KEY_UP ) << 5; // 0x0040 -> 0x0800 // 0x0010 -> 0x0100; 0x0020 -> 0x0200 // 0x0030 -> 0x0300 - key |= (inputdata.key & (KEY_RIGHT | KEY_LEFT)) << 4; + key |= (Controls & (KEY_RIGHT | KEY_LEFT)) << 4; // 0x0100 -> 0x0010; 0x0200 -> 0x0020; 0x0400 -> 0x0040 // 0x0700 -> 0x0070 - key |= (inputdata.key & (KEY_R | KEY_L | KEY_X)) >> 4; + key |= (Controls & (KEY_R | KEY_L | KEY_X)) >> 4; // 0x0080 -> 0x0400; 0x0800 -> 0x4000 // 0x0880 -> 0x4400 - key |= (inputdata.key & (KEY_DOWN | KEY_Y)) << 3; + key |= (Controls & (KEY_DOWN | KEY_Y)) << 3; /* for(i= 0; i < 12; i++) //remap key { @@ -1214,7 +1262,7 @@ unsigned int S9xReadJoypad (int which1) } */ - return (key | 0x80000000); + return key; } else return 0; diff --git a/source/nds/gui.h b/source/nds/gui.h index 9df2ad2..b2eae62 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -24,11 +24,7 @@ #include "fs_api.h" #include "gcheat.h" -#ifdef DS2_DMA -#define UP_SCREEN_UPDATE_METHOD 1 -#else #define UP_SCREEN_UPDATE_METHOD 0 -#endif #define DOWN_SCREEN_UPDATE_METHOD 2 #define MAX_GAMEPAD_MAP 16 diff --git a/source/ppu.cpp b/source/ppu.cpp index ad937c4..179838d 100644 --- a/source/ppu.cpp +++ b/source/ppu.cpp @@ -2853,43 +2853,10 @@ void S9xUpdateJoypads () { uint32 i; -#ifdef SYNC_JOYPAD_AT_HBLANK - uint32 j, k, KeyValue; - bool8 StartedPressed; - - // For each joypad - for (i = 0; i < 5; i++) - { - IPPU.Joypads [i] = 0; - // Sync each key - for (k = 1; k != 0; k <<= 1) - { - KeyValue = IPPU.JoypadsAtHBlanks[i][0] & k; - StartedPressed = KeyValue != 0; - // from each line. - // If, initially, the key is NOT pressed, one line of it being - // pressed means that the key MUST be pressed. - // Otherwise, the key MUST be depressed if it starts pressed. - for (j = 1; j < (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER); j++) - { - if ((StartedPressed) && ((IPPU.JoypadsAtHBlanks[i][j] & k) == 0)) { - KeyValue = 0; - break; - } - else if ((!StartedPressed) && ((IPPU.JoypadsAtHBlanks[i][j] & k) != 0)) { - KeyValue = k; - break; - } - } - IPPU.Joypads [i] |= KeyValue; - } - } -#else for (i = 0; i < 5; i++) { IPPU.Joypads [i] = S9xReadJoypad (i); } -#endif // S9xMovieUpdate(); diff --git a/source/ppu.h b/source/ppu.h index 1d3c7b7..8f8b8e7 100644 --- a/source/ppu.h +++ b/source/ppu.h @@ -152,9 +152,6 @@ struct InternalPPU { int CurrentLine; int Controller; uint32 Joypads[5]; -#ifdef SYNC_JOYPAD_AT_HBLANK - uint32 JoypadsAtHBlanks[5][SNES_MAX_PAL_VCOUNTER]; -#endif uint32 SuperScope; uint32 Mouse[2]; int PrevMouseX[2]; diff --git a/source/soundux.cpp b/source/soundux.cpp index dde8a14..c20f366 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -1233,6 +1233,15 @@ static inline void MixMono (int sample_count) for (uint32 I = 0; I < (uint32) sample_count; I++) { +#ifdef ACCUMULATE_JOYPAD +/* + * This call allows NDSSFC to synchronise the DS controller more often. + * If porting a later version of Snes9x into NDSSFC, it is essential to + * preserve it. + */ + if ((I & 0x7F) == 0x7F) + NDSSFCAccumulateJoypad (); +#endif unsigned long freq = freq0; if (mod) -- cgit v1.2.3 From 4096050f400f0a9cafa237ac11766e6b0faa70f0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 3 Feb 2013 20:12:29 -0500 Subject: Release 1.27. --- README.md | 2 +- source/nds/gui.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b67691e..a0b2713 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -CATSFC version 1.26, 2013-02-02 +CATSFC version 1.27, 2013-02-03 A Super Nintendo emulator for the Supercard DSTWO. diff --git a/source/nds/gui.c b/source/nds/gui.c index 7100cf2..e2a469d 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.26" +#define NDSSFC_VERSION "1.27" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From cb610fd0c257a7710fa0212e68b2cba6d6095b9d Mon Sep 17 00:00:00 2001 From: derpking Date: Sun, 3 Feb 2013 21:44:15 -0800 Subject: Update source/dsp1.cpp static const uint16 DSP1ROM[1024] snes9x 1.53 updated the dummy loops--- source/dsp1.cpp | 259 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 130 insertions(+), 129 deletions(-) diff --git a/source/dsp1.cpp b/source/dsp1.cpp index 2628447..244d8b0 100644 --- a/source/dsp1.cpp +++ b/source/dsp1.cpp @@ -941,136 +941,137 @@ uint8 DSP2GetByte(uint16 address) //Disable non-working chips? #ifdef DSP_DUMMY_LOOPS - +//static const uint16 DSP1ROM[1024] from SNES9X v1.53 uint16 Dsp3Rom[1024] = { - 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, - 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001, - 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, - 0x0000, 0x000f, 0x0400, 0x0200, 0x0140, 0x0400, 0x0200, 0x0040, - 0x007d, 0x007e, 0x007e, 0x007b, 0x007c, 0x007d, 0x007b, 0x007c, - 0x0002, 0x0020, 0x0030, 0x0000, 0x000d, 0x0019, 0x0026, 0x0032, - 0x003e, 0x004a, 0x0056, 0x0062, 0x006d, 0x0079, 0x0084, 0x008e, - 0x0098, 0x00a2, 0x00ac, 0x00b5, 0x00be, 0x00c6, 0x00ce, 0x00d5, - 0x00dc, 0x00e2, 0x00e7, 0x00ec, 0x00f1, 0x00f5, 0x00f8, 0x00fb, - 0x00fd, 0x00ff, 0x0100, 0x0100, 0x0100, 0x00ff, 0x00fd, 0x00fb, - 0x00f8, 0x00f5, 0x00f1, 0x00ed, 0x00e7, 0x00e2, 0x00dc, 0x00d5, - 0x00ce, 0x00c6, 0x00be, 0x00b5, 0x00ac, 0x00a2, 0x0099, 0x008e, - 0x0084, 0x0079, 0x006e, 0x0062, 0x0056, 0x004a, 0x003e, 0x0032, - 0x0026, 0x0019, 0x000d, 0x0000, 0xfff3, 0xffe7, 0xffdb, 0xffce, - 0xffc2, 0xffb6, 0xffaa, 0xff9e, 0xff93, 0xff87, 0xff7d, 0xff72, - 0xff68, 0xff5e, 0xff54, 0xff4b, 0xff42, 0xff3a, 0xff32, 0xff2b, - 0xff25, 0xff1e, 0xff19, 0xff14, 0xff0f, 0xff0b, 0xff08, 0xff05, - 0xff03, 0xff01, 0xff00, 0xff00, 0xff00, 0xff01, 0xff03, 0xff05, - 0xff08, 0xff0b, 0xff0f, 0xff13, 0xff18, 0xff1e, 0xff24, 0xff2b, - 0xff32, 0xff3a, 0xff42, 0xff4b, 0xff54, 0xff5d, 0xff67, 0xff72, - 0xff7c, 0xff87, 0xff92, 0xff9e, 0xffa9, 0xffb5, 0xffc2, 0xffce, - 0xffda, 0xffe7, 0xfff3, 0x002b, 0x007f, 0x0020, 0x00ff, 0xff00, - 0xffbe, 0x0000, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0x0045, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffc5, 0x0003, 0x0004, 0x0005, 0x0047, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008, - 0x0009, 0x004a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x004e, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011, - 0x0012, 0x0013, 0x0014, 0x0053, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, - 0x0059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e, - 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0060, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, - 0x002b, 0x002c, 0x0068, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0071, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, - 0x003e, 0x003f, 0x0040, 0x0041, 0x007b, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, - 0x000b, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, - 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0050, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b, - 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0x005d, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, - 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, - 0x006b, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, - 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0044, 0x0000, 0x0000, - 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, - 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, - 0x001f, 0x0020, 0x0054, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, - 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0065, - 0xffbe, 0x0000, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0xfead, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffc5, 0x0003, 0x0004, 0x0005, 0xfeaf, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008, - 0x0009, 0xfeb2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0xfeb6, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011, - 0x0012, 0x0013, 0x0014, 0xfebb, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, - 0xfec1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e, - 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0xfec8, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, - 0x002b, 0x002c, 0xfed0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0xfed9, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, - 0x003e, 0x003f, 0x0040, 0x0041, 0xfee3, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, - 0x000b, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, - 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0xfeb8, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b, - 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0xfec5, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, - 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, - 0xfed3, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, - 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0xfeac, 0x0000, 0x0000, - 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, - 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, - 0x001f, 0x0020, 0xfebc, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, - 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0xfecd, - 0x0154, 0x0218, 0x0110, 0x00b0, 0x00cc, 0x00b0, 0x0088, 0x00b0, - 0x0044, 0x00b0, 0x0000, 0x00b0, 0x00fe, 0xff07, 0x0002, 0x00ff, - 0x00f8, 0x0007, 0x00fe, 0x00ee, 0x07ff, 0x0200, 0x00ef, 0xf800, - 0x0700, 0x00ee, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, - 0xffff, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, - 0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0x0001, 0x0000, 0x0001, - 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, - 0xffff, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, - 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0044, 0x0088, 0x00cc, - 0x0110, 0x0154, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, + 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, + 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, + 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8000, 0xffe5, 0x0100, 0x7fff, 0x7f02, 0x7e08, + 0x7d12, 0x7c1f, 0x7b30, 0x7a45, 0x795d, 0x7878, 0x7797, 0x76ba, + 0x75df, 0x7507, 0x7433, 0x7361, 0x7293, 0x71c7, 0x70fe, 0x7038, + 0x6f75, 0x6eb4, 0x6df6, 0x6d3a, 0x6c81, 0x6bca, 0x6b16, 0x6a64, + 0x69b4, 0x6907, 0x685b, 0x67b2, 0x670b, 0x6666, 0x65c4, 0x6523, + 0x6484, 0x63e7, 0x634c, 0x62b3, 0x621c, 0x6186, 0x60f2, 0x6060, + 0x5fd0, 0x5f41, 0x5eb5, 0x5e29, 0x5d9f, 0x5d17, 0x5c91, 0x5c0c, + 0x5b88, 0x5b06, 0x5a85, 0x5a06, 0x5988, 0x590b, 0x5890, 0x5816, + 0x579d, 0x5726, 0x56b0, 0x563b, 0x55c8, 0x5555, 0x54e4, 0x5474, + 0x5405, 0x5398, 0x532b, 0x52bf, 0x5255, 0x51ec, 0x5183, 0x511c, + 0x50b6, 0x5050, 0x4fec, 0x4f89, 0x4f26, 0x4ec5, 0x4e64, 0x4e05, + 0x4da6, 0x4d48, 0x4cec, 0x4c90, 0x4c34, 0x4bda, 0x4b81, 0x4b28, + 0x4ad0, 0x4a79, 0x4a23, 0x49cd, 0x4979, 0x4925, 0x48d1, 0x487f, + 0x482d, 0x47dc, 0x478c, 0x473c, 0x46ed, 0x469f, 0x4651, 0x4604, + 0x45b8, 0x456c, 0x4521, 0x44d7, 0x448d, 0x4444, 0x43fc, 0x43b4, + 0x436d, 0x4326, 0x42e0, 0x429a, 0x4255, 0x4211, 0x41cd, 0x4189, + 0x4146, 0x4104, 0x40c2, 0x4081, 0x4040, 0x3fff, 0x41f7, 0x43e1, + 0x45bd, 0x478d, 0x4951, 0x4b0b, 0x4cbb, 0x4e61, 0x4fff, 0x5194, + 0x5322, 0x54a9, 0x5628, 0x57a2, 0x5914, 0x5a81, 0x5be9, 0x5d4a, + 0x5ea7, 0x5fff, 0x6152, 0x62a0, 0x63ea, 0x6530, 0x6672, 0x67b0, + 0x68ea, 0x6a20, 0x6b53, 0x6c83, 0x6daf, 0x6ed9, 0x6fff, 0x7122, + 0x7242, 0x735f, 0x747a, 0x7592, 0x76a7, 0x77ba, 0x78cb, 0x79d9, + 0x7ae5, 0x7bee, 0x7cf5, 0x7dfa, 0x7efe, 0x7fff, 0x0000, 0x0324, + 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, 0x18f8, 0x1c0b, + 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, 0x30fb, 0x33de, + 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, 0x471c, 0x49b4, + 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, 0x5a82, 0x5cb4, + 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, 0x6a6d, 0x6c24, + 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, 0x7641, 0x776c, + 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, 0x7d8a, 0x7e1d, + 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x7fff, 0x7ff6, + 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, + 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, + 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, + 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, + 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, + 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, + 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, + 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x0000, 0xfcdc, + 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 0xe708, 0xe3f5, + 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef, 0xcf05, 0xcc22, + 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 0xb8e4, 0xb64c, + 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be, 0xa57e, 0xa34c, + 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 0x9593, 0x93dc, + 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc, 0x89bf, 0x8894, + 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 0x8276, 0x81e3, + 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a, 0x6488, 0x0080, + 0x03ff, 0x0116, 0x0002, 0x0080, 0x4000, 0x3fd7, 0x3faf, 0x3f86, + 0x3f5d, 0x3f34, 0x3f0c, 0x3ee3, 0x3eba, 0x3e91, 0x3e68, 0x3e40, + 0x3e17, 0x3dee, 0x3dc5, 0x3d9c, 0x3d74, 0x3d4b, 0x3d22, 0x3cf9, + 0x3cd0, 0x3ca7, 0x3c7f, 0x3c56, 0x3c2d, 0x3c04, 0x3bdb, 0x3bb2, + 0x3b89, 0x3b60, 0x3b37, 0x3b0e, 0x3ae5, 0x3abc, 0x3a93, 0x3a69, + 0x3a40, 0x3a17, 0x39ee, 0x39c5, 0x399c, 0x3972, 0x3949, 0x3920, + 0x38f6, 0x38cd, 0x38a4, 0x387a, 0x3851, 0x3827, 0x37fe, 0x37d4, + 0x37aa, 0x3781, 0x3757, 0x372d, 0x3704, 0x36da, 0x36b0, 0x3686, + 0x365c, 0x3632, 0x3609, 0x35df, 0x35b4, 0x358a, 0x3560, 0x3536, + 0x350c, 0x34e1, 0x34b7, 0x348d, 0x3462, 0x3438, 0x340d, 0x33e3, + 0x33b8, 0x338d, 0x3363, 0x3338, 0x330d, 0x32e2, 0x32b7, 0x328c, + 0x3261, 0x3236, 0x320b, 0x31df, 0x31b4, 0x3188, 0x315d, 0x3131, + 0x3106, 0x30da, 0x30ae, 0x3083, 0x3057, 0x302b, 0x2fff, 0x2fd2, + 0x2fa6, 0x2f7a, 0x2f4d, 0x2f21, 0x2ef4, 0x2ec8, 0x2e9b, 0x2e6e, + 0x2e41, 0x2e14, 0x2de7, 0x2dba, 0x2d8d, 0x2d60, 0x2d32, 0x2d05, + 0x2cd7, 0x2ca9, 0x2c7b, 0x2c4d, 0x2c1f, 0x2bf1, 0x2bc3, 0x2b94, + 0x2b66, 0x2b37, 0x2b09, 0x2ada, 0x2aab, 0x2a7c, 0x2a4c, 0x2a1d, + 0x29ed, 0x29be, 0x298e, 0x295e, 0x292e, 0x28fe, 0x28ce, 0x289d, + 0x286d, 0x283c, 0x280b, 0x27da, 0x27a9, 0x2777, 0x2746, 0x2714, + 0x26e2, 0x26b0, 0x267e, 0x264c, 0x2619, 0x25e7, 0x25b4, 0x2581, + 0x254d, 0x251a, 0x24e6, 0x24b2, 0x247e, 0x244a, 0x2415, 0x23e1, + 0x23ac, 0x2376, 0x2341, 0x230b, 0x22d6, 0x229f, 0x2269, 0x2232, + 0x21fc, 0x21c4, 0x218d, 0x2155, 0x211d, 0x20e5, 0x20ad, 0x2074, + 0x203b, 0x2001, 0x1fc7, 0x1f8d, 0x1f53, 0x1f18, 0x1edd, 0x1ea1, + 0x1e66, 0x1e29, 0x1ded, 0x1db0, 0x1d72, 0x1d35, 0x1cf6, 0x1cb8, + 0x1c79, 0x1c39, 0x1bf9, 0x1bb8, 0x1b77, 0x1b36, 0x1af4, 0x1ab1, + 0x1a6e, 0x1a2a, 0x19e6, 0x19a1, 0x195c, 0x1915, 0x18ce, 0x1887, + 0x183f, 0x17f5, 0x17ac, 0x1761, 0x1715, 0x16c9, 0x167c, 0x162e, + 0x15df, 0x158e, 0x153d, 0x14eb, 0x1497, 0x1442, 0x13ec, 0x1395, + 0x133c, 0x12e2, 0x1286, 0x1228, 0x11c9, 0x1167, 0x1104, 0x109e, + 0x1036, 0x0fcc, 0x0f5f, 0x0eef, 0x0e7b, 0x0e04, 0x0d89, 0x0d0a, + 0x0c86, 0x0bfd, 0x0b6d, 0x0ad6, 0x0a36, 0x098d, 0x08d7, 0x0811, + 0x0736, 0x063e, 0x0519, 0x039a, 0x0000, 0x7fff, 0x0100, 0x0080, + 0x021d, 0x00c8, 0x00ce, 0x0048, 0x0a26, 0x277a, 0x00ce, 0x6488, + 0x14ac, 0x0001, 0x00f9, 0x00fc, 0x00ff, 0x00fc, 0x00f9, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff + }; void DSP3SetByte(uint8 byte, uint16 address) -- cgit v1.2.3 From 1c9094d99f6cb2f9ca63134cb7a348370b568b7c Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Mon, 4 Feb 2013 05:57:53 -0500 Subject: Release 1.28 after disabling the controller status sync hack. --- Makefile | 2 +- README.md | 2 +- source/nds/gui.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c325437..04b9181 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ DEFS := -DSPC700_C -DEXECUTE_SUPERFX_PER_LINE -DSDD1_DECOMP \ -DNO_INLINE_SET_GET -DNOASM -DHAVE_MKSTEMP '-DACCEPT_SIZE_T=size_t' \ -DUNZIP_SUPPORT -DFOREVER_16_BIT_SOUND -DFOREVER_STEREO \ -DFOREVER_FORWARD_STEREO -DNO_VOLATILE_SOUND \ - -DACCUMULATE_JOYPAD -DDS2_DMA + -DDS2_DMA .PHONY: clean makedirs .SUFFIXES: .elf .dat .plg diff --git a/README.md b/README.md index a0b2713..c7c14db 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -CATSFC version 1.27, 2013-02-03 +CATSFC version 1.28, 2013-02-04 A Super Nintendo emulator for the Supercard DSTWO. diff --git a/source/nds/gui.c b/source/nds/gui.c index e2a469d..3d2ab70 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan ******************************************************************************/ #define SUBMENU_ROW_NUM 6 -#define NDSSFC_VERSION "1.27" +#define NDSSFC_VERSION "1.28" #define SAVE_STATE_SLOT_NUM 16 -- cgit v1.2.3 From d1a7bf5eb558e7db4a1a27e15ebedb02e6b7f804 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Mon, 4 Feb 2013 23:45:44 -0500 Subject: Fully integrate BassAceGold's libraries, finally. The README still states that 1.2 is required to overwrite 0.13's stuff; really, 0.13 is needed only for `gcc`. So the sequence goes 0.13's `gcc` -> 1.2 -> BassAceGold's libraries -> make `libds2a.a`. DMA function names changed to match BassAceGold's. --- Makefile | 4 +- README.md | 8 +- sdk-modifications/include/archdefs.h | 2356 -------------------- sdk-modifications/include/bit_ops.h | 58 - sdk-modifications/include/console.h | 9 - sdk-modifications/include/directory.h | 172 -- sdk-modifications/include/ds2_cpu.h | 57 - sdk-modifications/include/ds2_cpuclock.h | 22 - sdk-modifications/include/ds2_dma.h | 54 - sdk-modifications/include/ds2_excpt.h | 55 - sdk-modifications/include/ds2_fcntl.h | 51 - sdk-modifications/include/ds2_malloc.h | 32 - sdk-modifications/include/ds2_mmc_api.h | 56 - sdk-modifications/include/ds2_timer.h | 50 - sdk-modifications/include/ds2_types.h | 45 - sdk-modifications/include/ds2io.h | 285 --- sdk-modifications/include/fat.h | 118 - sdk-modifications/include/fatdir.h | 81 - sdk-modifications/include/fatdir_ex.h | 18 - sdk-modifications/include/fatfile.h | 89 - sdk-modifications/include/fatfile_ex.h | 19 - sdk-modifications/include/file_allocation_table.h | 64 - sdk-modifications/include/filetime.h | 44 - sdk-modifications/include/fs_api.h | 151 -- sdk-modifications/include/fs_cache.h | 118 - sdk-modifications/include/fs_common.h | 129 -- sdk-modifications/include/fs_unicode.h | 16 - sdk-modifications/include/mem_allocate.h | 47 - sdk-modifications/include/mips.h | 820 ------- sdk-modifications/include/mipsregs.h | 985 -------- sdk-modifications/include/mmc_api.h | 56 - sdk-modifications/include/partition.h | 131 -- sdk-modifications/include/tcm.h | 10 - sdk-modifications/libsrc/.depend | 0 sdk-modifications/libsrc/Makefile | 13 +- sdk-modifications/libsrc/changes_bag.txt | 28 + sdk-modifications/libsrc/console/console.c | 0 sdk-modifications/libsrc/console/console.h | 0 sdk-modifications/libsrc/console/console.mk | 0 sdk-modifications/libsrc/console/font_dot.h | 0 sdk-modifications/libsrc/core/core.mk | 11 + sdk-modifications/libsrc/core/ds2_cpuclock.c | 272 +++ sdk-modifications/libsrc/core/ds2_cpuclock.h | 22 + sdk-modifications/libsrc/core/ds2_dma.c | 34 + sdk-modifications/libsrc/core/ds2_dma.h | 142 ++ sdk-modifications/libsrc/dma/dma.mk | 9 - sdk-modifications/libsrc/dma/dmacopy.c | 167 -- sdk-modifications/libsrc/dma/ds2_dma.h | 54 - sdk-modifications/libsrc/fs/bit_ops.h | 0 sdk-modifications/libsrc/fs/cache.c | 0 sdk-modifications/libsrc/fs/directory.c | 0 sdk-modifications/libsrc/fs/directory.h | 0 sdk-modifications/libsrc/fs/disc_io/disc.c | 0 sdk-modifications/libsrc/fs/disc_io/disc.h | 0 sdk-modifications/libsrc/fs/disc_io/disc_io.h | 0 sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.c | 0 sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.h | 0 sdk-modifications/libsrc/fs/ds2_fcntl.c | 0 sdk-modifications/libsrc/fs/ds2_fcntl.h | 0 sdk-modifications/libsrc/fs/ds2_unistd.c | 0 sdk-modifications/libsrc/fs/ds2_unistd.h | 0 sdk-modifications/libsrc/fs/fat.h | 0 sdk-modifications/libsrc/fs/fat_misc.c | 52 +- sdk-modifications/libsrc/fs/fat_misc.h | 0 sdk-modifications/libsrc/fs/fatdir.h | 0 sdk-modifications/libsrc/fs/fatdir_ex.c | 0 sdk-modifications/libsrc/fs/fatdir_ex.h | 0 sdk-modifications/libsrc/fs/fatfile.c | 0 sdk-modifications/libsrc/fs/fatfile.h | 0 sdk-modifications/libsrc/fs/fatfile_ex.c | 0 sdk-modifications/libsrc/fs/fatfile_ex.h | 0 .../libsrc/fs/file_allocation_table.h | 0 sdk-modifications/libsrc/fs/filetime.c | 0 sdk-modifications/libsrc/fs/filetime.h | 0 sdk-modifications/libsrc/fs/fs.mk | 2 +- sdk-modifications/libsrc/fs/fs_api.c | 0 sdk-modifications/libsrc/fs/fs_api.h | 0 sdk-modifications/libsrc/fs/fs_cache.h | 0 sdk-modifications/libsrc/fs/fs_common.h | 0 sdk-modifications/libsrc/fs/fs_unicode.c | 0 sdk-modifications/libsrc/fs/fs_unicode.h | 0 sdk-modifications/libsrc/fs/libfat.c | 0 sdk-modifications/libsrc/fs/mem_allocate.h | 0 sdk-modifications/libsrc/fs/partition.c | 0 sdk-modifications/libsrc/fs/partition.h | 0 sdk-modifications/libsrc/key/key.c | 0 sdk-modifications/libsrc/key/key.h | 0 sdk-modifications/libsrc/key/key.mk | 0 sdk-modifications/libsrc/zlib/README | 9 +- sdk-modifications/libsrc/zlib/adler32.c | 0 sdk-modifications/libsrc/zlib/compress.c | 0 sdk-modifications/libsrc/zlib/crc32.c | 0 sdk-modifications/libsrc/zlib/crc32.h | 0 sdk-modifications/libsrc/zlib/deflate.c | 0 sdk-modifications/libsrc/zlib/deflate.h | 0 sdk-modifications/libsrc/zlib/gzclose.c | 0 sdk-modifications/libsrc/zlib/gzguts.h | 0 sdk-modifications/libsrc/zlib/gzlib.c | 0 sdk-modifications/libsrc/zlib/gzread.c | 0 sdk-modifications/libsrc/zlib/gzwrite.c | 0 sdk-modifications/libsrc/zlib/infback.c | 0 sdk-modifications/libsrc/zlib/inffast.c | 0 sdk-modifications/libsrc/zlib/inffast.h | 0 sdk-modifications/libsrc/zlib/inffixed.h | 0 sdk-modifications/libsrc/zlib/inflate.c | 0 sdk-modifications/libsrc/zlib/inflate.h | 0 sdk-modifications/libsrc/zlib/inftrees.c | 0 sdk-modifications/libsrc/zlib/inftrees.h | 0 sdk-modifications/libsrc/zlib/trees.c | 0 sdk-modifications/libsrc/zlib/trees.h | 0 sdk-modifications/libsrc/zlib/uncompr.c | 0 sdk-modifications/libsrc/zlib/zconf.h | 4 +- sdk-modifications/libsrc/zlib/zlib.h | 0 sdk-modifications/libsrc/zlib/zlib.mk | 0 sdk-modifications/libsrc/zlib/zutil.c | 0 sdk-modifications/libsrc/zlib/zutil.h | 0 source/nds/entry.cpp | 26 +- 117 files changed, 575 insertions(+), 6480 deletions(-) delete mode 100644 sdk-modifications/include/archdefs.h delete mode 100644 sdk-modifications/include/bit_ops.h delete mode 100644 sdk-modifications/include/console.h delete mode 100644 sdk-modifications/include/directory.h delete mode 100644 sdk-modifications/include/ds2_cpu.h delete mode 100644 sdk-modifications/include/ds2_cpuclock.h delete mode 100644 sdk-modifications/include/ds2_dma.h delete mode 100644 sdk-modifications/include/ds2_excpt.h delete mode 100644 sdk-modifications/include/ds2_fcntl.h delete mode 100644 sdk-modifications/include/ds2_malloc.h delete mode 100644 sdk-modifications/include/ds2_mmc_api.h delete mode 100644 sdk-modifications/include/ds2_timer.h delete mode 100644 sdk-modifications/include/ds2_types.h delete mode 100644 sdk-modifications/include/ds2io.h delete mode 100644 sdk-modifications/include/fat.h delete mode 100644 sdk-modifications/include/fatdir.h delete mode 100644 sdk-modifications/include/fatdir_ex.h delete mode 100644 sdk-modifications/include/fatfile.h delete mode 100644 sdk-modifications/include/fatfile_ex.h delete mode 100644 sdk-modifications/include/file_allocation_table.h delete mode 100644 sdk-modifications/include/filetime.h delete mode 100644 sdk-modifications/include/fs_api.h delete mode 100644 sdk-modifications/include/fs_cache.h delete mode 100644 sdk-modifications/include/fs_common.h delete mode 100644 sdk-modifications/include/fs_unicode.h delete mode 100644 sdk-modifications/include/mem_allocate.h delete mode 100644 sdk-modifications/include/mips.h delete mode 100644 sdk-modifications/include/mipsregs.h delete mode 100644 sdk-modifications/include/mmc_api.h delete mode 100644 sdk-modifications/include/partition.h delete mode 100644 sdk-modifications/include/tcm.h delete mode 100644 sdk-modifications/libsrc/.depend create mode 100644 sdk-modifications/libsrc/changes_bag.txt mode change 100644 => 100755 sdk-modifications/libsrc/console/console.c mode change 100644 => 100755 sdk-modifications/libsrc/console/console.h mode change 100644 => 100755 sdk-modifications/libsrc/console/console.mk mode change 100644 => 100755 sdk-modifications/libsrc/console/font_dot.h create mode 100644 sdk-modifications/libsrc/core/core.mk create mode 100644 sdk-modifications/libsrc/core/ds2_cpuclock.c create mode 100644 sdk-modifications/libsrc/core/ds2_cpuclock.h create mode 100644 sdk-modifications/libsrc/core/ds2_dma.c create mode 100644 sdk-modifications/libsrc/core/ds2_dma.h delete mode 100644 sdk-modifications/libsrc/dma/dma.mk delete mode 100644 sdk-modifications/libsrc/dma/dmacopy.c delete mode 100644 sdk-modifications/libsrc/dma/ds2_dma.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/bit_ops.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/cache.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/directory.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/directory.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/disc_io/disc.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/disc_io/disc.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/disc_io/disc_io.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/ds2_fcntl.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/ds2_fcntl.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/ds2_unistd.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/ds2_unistd.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fat.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fat_misc.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fatdir.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fatdir_ex.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/fatdir_ex.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fatfile.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/fatfile.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fatfile_ex.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/fatfile_ex.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/file_allocation_table.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/filetime.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/filetime.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fs_api.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/fs_api.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fs_cache.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fs_common.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/fs_unicode.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/fs_unicode.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/libfat.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/mem_allocate.h mode change 100644 => 100755 sdk-modifications/libsrc/fs/partition.c mode change 100644 => 100755 sdk-modifications/libsrc/fs/partition.h mode change 100644 => 100755 sdk-modifications/libsrc/key/key.c mode change 100644 => 100755 sdk-modifications/libsrc/key/key.h mode change 100644 => 100755 sdk-modifications/libsrc/key/key.mk mode change 100644 => 100755 sdk-modifications/libsrc/zlib/adler32.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/compress.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/crc32.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/crc32.h mode change 100644 => 100755 sdk-modifications/libsrc/zlib/deflate.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/deflate.h mode change 100644 => 100755 sdk-modifications/libsrc/zlib/gzclose.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/gzguts.h mode change 100644 => 100755 sdk-modifications/libsrc/zlib/gzlib.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/gzread.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/gzwrite.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/infback.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/inffast.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/inffast.h mode change 100644 => 100755 sdk-modifications/libsrc/zlib/inffixed.h mode change 100644 => 100755 sdk-modifications/libsrc/zlib/inflate.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/inflate.h mode change 100644 => 100755 sdk-modifications/libsrc/zlib/inftrees.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/inftrees.h mode change 100644 => 100755 sdk-modifications/libsrc/zlib/trees.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/trees.h mode change 100644 => 100755 sdk-modifications/libsrc/zlib/uncompr.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/zlib.h mode change 100644 => 100755 sdk-modifications/libsrc/zlib/zlib.mk mode change 100644 => 100755 sdk-modifications/libsrc/zlib/zutil.c mode change 100644 => 100755 sdk-modifications/libsrc/zlib/zutil.h diff --git a/Makefile b/Makefile index 04b9181..c5a8d38 100644 --- a/Makefile +++ b/Makefile @@ -7,12 +7,14 @@ FS_DIR = $(DS2SDKPATH)/libsrc/fs CONSOLE_DIR = $(DS2SDKPATH)/libsrc/console KEY_DIR = $(DS2SDKPATH)/libsrc/key ZLIB_DIR = $(DS2SDKPATH)/libsrc/zlib +CORE_DIR = $(DS2SDKPATH)/libsrc/core LIBS := $(DS2SDKPATH)/lib/libds2b.a -lc -lm -lgcc EXTLIBS := $(DS2SDKPATH)/lib/libds2a.a INCLUDE := -Isource -Isource/unzip -Isource/nds -I$(DS2SDKPATH)/include \ - -I$(FS_DIR) -I$(CONSOLE_DIR) -I$(KEY_DIR) -I$(ZLIB_DIR) + -I$(FS_DIR) -I$(CONSOLE_DIR) -I$(KEY_DIR) -I$(ZLIB_DIR) \ + -I$(CORE_DIR) LINK_SPEC := $(DS2SDKPATH)/specs/link.xn START_ASM := $(DS2SDKPATH)/specs/start.S diff --git a/README.md b/README.md index c7c14db..61b52fe 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,10 @@ Additionally, you will need to add the updated `zlib`, DMA (Direct Memory Access) and filesystem access routines provided by BassAceGold and recompile `libds2a.a`. To do this: -> sudo rm -r /opt/ds2sdk/libsrc/{console,dma,fs,key,zlib,Makefile} /opt/ds2sdk/include -> sudo cp -r sdk-modifications/{libsrc,include} /opt/ds2sdk -> sudo chmod -R 600 /opt/ds2sdk/{libsrc,include} -> sudo chmod -R a+rX /opt/ds2sdk/{libsrc,include} +> sudo rm -r /opt/ds2sdk/libsrc/{console,core,fs,key,zlib,Makefile} +> sudo cp -r sdk-modifications/libsrc /opt/ds2sdk +> sudo chmod -R 600 /opt/ds2sdk/libsrc +> sudo chmod -R a+rX /opt/ds2sdk/libsrc > cd /opt/ds2sdk/libsrc > sudo rm libds2a.a ../lib/libds2a.a > sudo make diff --git a/sdk-modifications/include/archdefs.h b/sdk-modifications/include/archdefs.h deleted file mode 100644 index 37c61b8..0000000 --- a/sdk-modifications/include/archdefs.h +++ /dev/null @@ -1,2356 +0,0 @@ -/************************************************************************** -* * -* PROJECT : MIPS port for uC/OS-II * -* * -* MODULE : ARCHDEFS.h * -* * -* AUTHOR : Michael Anburaj * -* URL : http://geocities.com/michaelanburaj/ * -* EMAIL: michaelanburaj@hotmail.com * -* * -* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board * -* * -* TOOL-CHAIN : SDE & Cygnus * -* * -* DESCRIPTION : * -* Architecture definitions. * -* * -**************************************************************************/ - - -#ifndef __ARCHDEFS_H__ -#define __ARCHDEFS_H__ - - -/* ********************************************************************* */ -/* Module configuration */ - - -/* ********************************************************************* */ -/* Interface macro & data definition */ - -/* - * Utility defines for cross platform handling of 64bit constants. - */ - -#if !defined(Append) - #define Append(c,s) (c##s) -#endif - -#if !defined(__assembler) && !defined(MIPSAVPENV) - #if defined(NT) - #if !defined(UNS64Const) - #define UNS64Const(c) Append(c,ui64) - #endif - - #if !defined(INT64Const) - #define INT64Const(c) Append(c,i64) - #endif - #else - #if !defined(UNS64Const) - #define UNS64Const(c) Append(c,ull) - #endif - - #if !defined(INT64Const) - #define INT64Const(c) Append(c,ll) - #endif - #endif -#else /* Not C or C++ */ - #if !defined(UNS64Const) - #define UNS64Const(c) c - #endif - - #if !defined(INT64Const) - #define INT64Const(c) c - #endif -#endif /* C or C++ */ - - -/* - ************************************************************************ - * I N S T R U C T I O N F O R M A T S * - ************************************************************************ - * - * The following definitions describe each field in an instruction. There - * is one diagram for each type of instruction, with field definitions - * following the diagram for that instruction. Note that if a field of - * the same name and position is defined in an earlier diagram, it is - * not defined again in the subsequent diagram. Only new fields are - * defined for each diagram. - * - * R-Type (operate) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | rs | rt | rd | sa | | - * | Opcode | | | Tcode | func | - * | | Bcode | | sel | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnOpcode 26 -#define M_InstnOpcode (0x3f << S_InstnOpcode) -#define S_InstnRS 21 -#define M_InstnRS (0x1f << S_InstnRS) -#define S_InstnRT 16 -#define M_InstnRT (0x1f << S_InstnRT) -#define S_InstnRD 11 -#define M_InstnRD (0x1f << S_InstnRD) -#define S_InstnSA 6 -#define M_InstnSA (0x1f << S_InstnSA) -#define S_InstnTcode 6 -#define M_InstnTcode (0x3ff << S_InstnTcode) -#define S_InstnBcode 6 -#define M_InstnBcode (0xfffff << S_InstnBcode) -#define S_InstnFunc 0 -#define M_InstnFunc (0x3f << S_InstnFunc) -#define S_InstnSel 0 -#define M_InstnSel (0x7 << S_InstnSel) - -/* - * I-Type (load, store, branch, immediate) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | rs | rt | Offset | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnOffset 0 -#define M_InstnOffset (0xffff << S_InstnOffset) - -/* - * I-Type (pref) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | rs | hint | Offset | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnHint S_InstnRT -#define M_InstnHint M_InstnRT - -/* - * J-Type (jump) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | JIndex | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnJIndex 0 -#define M_InstnJIndex (0x03ffffff << S_InstnJIndex) - -/* - * FP R-Type (operate) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | fmt | ft | fs | fd | func | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnFmt S_InstnRS -#define M_InstnFmt M_InstnRS -#define S_InstnFT S_InstnRT -#define M_InstnFT M_InstnRT -#define S_InstnFS S_InstnRD -#define M_InstnFS M_InstnRD -#define S_InstnFD S_InstnSA -#define M_InstnFD M_InstnSA - -/* - * FP R-Type (cpu <-> cpu data movement)) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | sub | rt | fs | 0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnSub S_InstnRS -#define M_InstnSub M_InstnRS - -/* - * FP R-Type (compare) - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | |C| | - * | Opcode | fmt | ft | fs | cc |0|A| func | - * | | | | | | |B| | - * | | | | | | |S| | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnCCcmp 8 -#define M_InstnCCcmp (0x7 << S_InstnCCcmp) -#define S_InstnCABS 6 -#define M_InstnCABS (0x1 << S_InstnCABS) - -/* - * FP R-Type (FPR conditional move on FP cc) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | fmt | cc |n|t| fs | fd | func | - * | | | |d|f| | | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnCC 18 -#define M_InstnCC (0x7 << S_InstnCC) -#define S_InstnND 17 -#define M_InstnND (0x1 << S_InstnND) -#define S_InstnTF 16 -#define M_InstnTF (0x1 << S_InstnTF) - -/* - * FP R-Type (3-operand operate) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | fr | ft | fs | fd | op4 | fmt3| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnFR S_InstnRS -#define M_InstnFR M_InstnRS -#define S_InstnOp4 3 -#define M_InstnOp4 (0x7 << S_InstnOp4) -#define S_InstnFmt3 0 -#define M_InstnFmt3 (0x7 << S_InstnFmt3) - -/* - * FP R-Type (Indexed load, store) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | rs | rt | 0 | fd | func | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ -/* - * FP R-Type (prefx) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | rs | rt | hint | 0 | func | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define S_InstnHintX S_InstnRD -#define M_InstnHintX M_InstnRD - -/* - * FP R-Type (GPR conditional move on FP cc) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | rs | cc |n|t| rd | 0 | func | - * | | | |d|f| | | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * FP I-Type (load, store) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | rs | ft | Offset | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -/* - * FP I-Type (branch) - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Opcode | fmt | cc |n|t| Offset | - * | | | |d|f| | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - -/* - ************************************************************************* - * V I R T U A L A D D R E S S D E F I N I T I O N S * - ************************************************************************* - */ - -#ifdef MIPSADDR64 -#define A_K0BASE UNS64Const(0xffffffff80000000) -#define A_K1BASE UNS64Const(0xffffffffa0000000) -#define A_K2BASE UNS64Const(0xffffffffc0000000) -#define A_K3BASE UNS64Const(0xffffffffe0000000) -#define A_REGION UNS64Const(0xc000000000000000) -#define A_XKPHYS_ATTR UNS64Const(0x3800000000000000) -#else -#define A_K0BASE 0x80000000 -#define A_K1BASE 0xa0000000 -#define A_K2BASE 0xc0000000 -#define A_K3BASE 0xe0000000 -#endif -#define M_KMAPPED 0x40000000 /* KnSEG address is mapped if bit is one */ - - -#ifdef MIPS_Model64 - -#define S_VMAP64 62 -#define M_VMAP64 UNS64Const(0xc000000000000000) - -#define K_VMode11 3 -#define K_VMode10 2 -#define K_VMode01 1 -#define K_VMode00 0 - -#define S_KSEG3 29 -#define M_KSEG3 (0x7 << S_KSEG3) -#define K_KSEG3 7 - -#define S_SSEG 29 -#define M_SSEG (0x7 << S_KSEG3) -#define K_SSEG 6 - -#define S_KSSEG 29 -#define M_KSSEG (0x7 << S_KSEG3) -#define K_KSSEG 6 - -#define S_KSEG1 29 -#define M_KSEG1 (0x7 << S_KSEG3) -#define K_KSEG1 5 - -#define S_KSEG0 29 -#define M_KSEG0 (0x7 << S_KSEG3) -#define K_KSEG0 4 - -#define S_XKSEG 29 -#define M_XKSEG (0x7 << S_KSEG3) -#define K_XKSEG 3 - -#define S_USEG 31 -#define M_USEG (0x1 << S_USEG) -#define K_USEG 0 - -#define S_EjtagProbeMem 20 -#define M_EjtagProbeMem (0x1 << S_EjtagProbeMem) -#define K_EjtagProbeMem 0 - - - -#else - -#define S_KSEG3 29 -#define M_KSEG3 (0x7 << S_KSEG3) -#define K_KSEG3 7 - -#define S_KSSEG 29 -#define M_KSSEG (0x7 << S_KSSEG) -#define K_KSSEG 6 - -#define S_SSEG 29 -#define M_SSEG (0x7 << S_SSEG) -#define K_SSEG 6 - -#define S_KSEG1 29 -#define M_KSEG1 (0x7 << S_KSEG1) -#define K_KSEG1 5 - -#define S_KSEG0 29 -#define M_KSEG0 (0x7 << S_KSEG0) -#define K_KSEG0 4 - -#define S_KUSEG 31 -#define M_KUSEG (0x1 << S_KUSEG) -#define K_KUSEG 0 - -#define S_SUSEG 31 -#define M_SUSEG (0x1 << S_SUSEG) -#define K_SUSEG 0 - -#define S_USEG 31 -#define M_USEG (0x1 << S_USEG) -#define K_USEG 0 - -#define K_EjtagLower 0xff200000 -#define K_EjtagUpper 0xff3fffff - -#define S_EjtagProbeMem 20 -#define M_EjtagProbeMem (0x1 << S_EjtagProbeMem) -#define K_EjtagProbeMem 0 - -#endif - - - -/* - ************************************************************************* - * C A C H E I N S T R U C T I O N O P E R A T I O N C O D E S * - ************************************************************************* - */ - -/* - * Cache encodings - */ -#define K_CachePriI 0 /* Primary Icache */ -#define K_CachePriD 1 /* Primary Dcache */ -#define K_CachePriU 1 /* Unified primary */ -#define K_CacheTerU 2 /* Unified Tertiary */ -#define K_CacheSecU 3 /* Unified secondary */ - - -/* - * Function encodings - */ -#define S_CacheFunc 2 /* Amount to shift function encoding within 5-bit field */ -#define K_CacheIndexInv 0 /* Index invalidate */ -#define K_CacheIndexWBInv 0 /* Index writeback invalidate */ -#define K_CacheIndexLdTag 1 /* Index load tag */ -#define K_CacheIndexStTag 2 /* Index store tag */ -#define K_CacheHitInv 4 /* Hit Invalidate */ -#define K_CacheFill 5 /* Fill (Icache only) */ -#define K_CacheHitWBInv 5 /* Hit writeback invalidate */ -#define K_CacheHitWB 6 /* Hit writeback */ -#define K_CacheFetchLock 7 /* Fetch and lock */ - -#define ICIndexInv ((K_CacheIndexInv << S_CacheFunc) | K_CachePriI) -#define DCIndexWBInv ((K_CacheIndexWBInv << S_CacheFunc) | K_CachePriD) -#define DCIndexInv DCIndexWBInv -#define ICIndexLdTag ((K_CacheIndexLdTag << S_CacheFunc) | K_CachePriI) -#define DCIndexLdTag ((K_CacheIndexLdTag << S_CacheFunc) | K_CachePriD) -#define ICIndexStTag ((K_CacheIndexStTag << S_CacheFunc) | K_CachePriI) -#define DCIndexStTag ((K_CacheIndexStTag << S_CacheFunc) | K_CachePriD) -#define ICHitInv ((K_CacheHitInv << S_CacheFunc) | K_CachePriI) -#define DCHitInv ((K_CacheHitInv << S_CacheFunc) | K_CachePriD) -#define ICFill ((K_CacheFill << S_CacheFunc) | K_CachePriI) -#define DCHitWBInv ((K_CacheHitWBInv << S_CacheFunc) | K_CachePriD) -#define DCHitWB ((K_CacheHitWB << S_CacheFunc) | K_CachePriD) -#define ICFetchLock ((K_CacheFetchLock << S_CacheFunc) | K_CachePriI) -#define DCFetchLock ((K_CacheFetchLock << S_CacheFunc) | K_CachePriD) - - -/* - ************************************************************************* - * P R E F E T C H I N S T R U C T I O N H I N T S * - ************************************************************************* - */ - -#define PrefLoad 0 -#define PrefStore 1 -#define PrefLoadStreamed 4 -#define PrefStoreStreamed 5 -#define PrefLoadRetained 6 -#define PrefStoreRetained 7 -#define PrefWBInval 25 -#define PrefNudge 25 - - -/* - ************************************************************************* - * C P U R E G I S T E R D E F I N I T I O N S * - ************************************************************************* - */ - - -/* - ************************************************************************* - * S O F T W A R E G P R N A M E S * - ************************************************************************* - */ - -#define zero $0 -#define AT $1 -#define v0 $2 -#define v1 $3 -#define a0 $4 -#define a1 $5 -#define a2 $6 -#define a3 $7 -#define t0 $8 -#define t1 $9 -#define t2 $10 -#define t3 $11 -#define t4 $12 -#define t5 $13 -#define t6 $14 -#define t7 $15 -#define s0 $16 -#define s1 $17 -#define s2 $18 -#define s3 $19 -#define s4 $20 -#define s5 $21 -#define s6 $22 -#define s7 $23 -#define t8 $24 -#define t9 $25 -#define k0 $26 -#define k1 $27 -#define gp $28 -#define sp $29 -#define fp $30 -#define ra $31 - -/* - * The following registers are used by the AVP environment and - * are not part of the normal software definitions. - */ - -#ifdef MIPSAVPENV -#define repc $25 /* Expected exception PC */ -#define tid $30 /* Current test case address */ -#endif - - -/* - ************************************************************************* - * H A R D W A R E G P R N A M E S * - ************************************************************************* - * - * In the AVP environment, several of the `r' names are removed from the - * name space because they are used by the kernel for special purposes. - * Removing them causes assembly rather than runtime errors for tests that - * use the `r' names. - * - * - r25 (repc) is used as the expected PC on an exception - * - r26-r27 (k0, k1) are used in the exception handler - * - r30 (tid) is used as the current test address - */ - -#define r0 $0 -#define r1 $1 -#define r2 $2 -#define r3 $3 -#define r4 $4 -#define r5 $5 -#define r6 $6 -#define r7 $7 -#define r8 $8 -#define r9 $9 -#define r10 $10 -#define r11 $11 -#define r12 $12 -#define r13 $13 -#define r14 $14 -#define r15 $15 -#define r16 $16 -#define r17 $17 -#define r18 $18 -#define r19 $19 -#define r20 $20 -#define r21 $21 -#define r22 $22 -#define r23 $23 -#define r24 $24 -#ifdef MIPSAVPENV -#define r25 r25_unknown -#define r26 r26_unknown -#define r27 r27_unknown -#else -#define r25 $25 -#define r26 $26 -#define r27 $27 -#endif -#define r28 $28 -#define r29 $29 -#ifdef MIPSAVPENV -#define r30 r30_unknown -#else -#define r30 $30 -#endif -#define r31 $31 - - -/* - ************************************************************************* - * H A R D W A R E G P R I N D I C E S * - ************************************************************************* - * - * These definitions provide the index (number) of the GPR, as opposed - * to the assembler register name ($n). - */ - -#define R_r0 0 -#define R_r1 1 -#define R_r2 2 -#define R_r3 3 -#define R_r4 4 -#define R_r5 5 -#define R_r6 6 -#define R_r7 7 -#define R_r8 8 -#define R_r9 9 -#define R_r10 10 -#define R_r11 11 -#define R_r12 12 -#define R_r13 13 -#define R_r14 14 -#define R_r15 15 -#define R_r16 16 -#define R_r17 17 -#define R_r18 18 -#define R_r19 19 -#define R_r20 20 -#define R_r21 21 -#define R_r22 22 -#define R_r23 23 -#define R_r24 24 -#define R_r25 25 -#define R_r26 26 -#define R_r27 27 -#define R_r28 28 -#define R_r29 29 -#define R_r30 30 -#define R_r31 31 -#define R_hi 32 /* Hi register */ -#define R_lo 33 /* Lo register */ - - -/* - ************************************************************************* - * S O F T W A R E G P R M A S K S * - ************************************************************************* - * - * These definitions provide the bit mask corresponding to the GPR number - */ - -#define M_AT (1<<1) -#define M_v0 (1<<2) -#define M_v1 (1<<3) -#define M_a0 (1<<4) -#define M_a1 (1<<5) -#define M_a2 (1<<6) -#define M_a3 (1<<7) -#define M_t0 (1<<8) -#define M_t1 (1<<9) -#define M_t2 (1<<10) -#define M_t3 (1<<11) -#define M_t4 (1<<12) -#define M_t5 (1<<13) -#define M_t6 (1<<14) -#define M_t7 (1<<15) -#define M_s0 (1<<16) -#define M_s1 (1<<17) -#define M_s2 (1<<18) -#define M_s3 (1<<19) -#define M_s4 (1<<20) -#define M_s5 (1<<21) -#define M_s6 (1<<22) -#define M_s7 (1<<23) -#define M_t8 (1<<24) -#define M_t9 (1<<25) -#define M_k0 (1<<26) -#define M_k1 (1<<27) -#define M_gp (1<<28) -#define M_sp (1<<29) -#define M_fp (1<<30) -#define M_ra (1<<31) - - -/* - ************************************************************************* - * C P 0 R E G I S T E R D E F I N I T I O N S * - ************************************************************************* - * Each register has the following definitions: - * - * C0_rrr The register number (as a $n value) - * R_C0_rrr The register index (as an integer corresponding - * to the register number) - * - * Each field in a register has the following definitions: - * - * S_rrrfff The shift count required to right-justify - * the field. This corresponds to the bit - * number of the right-most bit in the field. - * M_rrrfff The Mask required to isolate the field. - * - * Register diagrams included below as comments correspond to the - * MIPS32 and MIPS64 architecture specifications. Refer to other - * sources for register diagrams for older architectures. - */ - - -/* - ************************************************************************ - * I N D E X R E G I S T E R ( 0 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |P| 0 | Index | Index - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Index $0 -#define R_C0_Index 0 -#define C0_INX C0_Index /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_IndexP 31 /* Probe failure (R)*/ -#define M_IndexP (0x1 << S_IndexP) - -#define S_IndexIndex 0 /* TLB index (R/W)*/ -#define M_IndexIndex (0x3f << S_IndexIndex) - -#define M_Index0Fields 0x7fffffc0 -#define M_IndexRFields 0x80000000 - - -/* - ************************************************************************ - * R A N D O M R E G I S T E R ( 1 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0 | Index | Random - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Random $1 -#define R_C0_Random 1 -#define C0_RAND $1 /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_RandomIndex 0 /* TLB random index (R)*/ -#define M_RandomIndex (0x3f << S_RandomIndex) - -#define M_Random0Fields 0xffffffc0 -#define M_RandomRFields 0x0000003f - - -/* - ************************************************************************ - * E N T R Y L O 0 R E G I S T E R ( 2 ) * - ************************************************************************ - * - * 6 6 6 6 5 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 2 1 0 9 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Fill (0) //| 0 | PFN | C |D|V|G| EntryLo0 - * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_EntryLo0 $2 -#define R_C0_EntryLo0 2 -#define C0_TLBLO_0 C0_EntryLo0 /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_EntryLoPFN 6 /* PFN (R/W) */ -#define M_EntryLoPFN (0xffffff << S_EntryLoPFN) -#define S_EntryLoC 3 /* Coherency attribute (R/W) */ -#define M_EntryLoC (0x7 << S_EntryLoC) -#define S_EntryLoD 2 /* Dirty (R/W) */ -#define M_EntryLoD (0x1 << S_EntryLoD) -#define S_EntryLoV 1 /* Valid (R/W) */ -#define M_EntryLoV (0x1 << S_EntryLoV) -#define S_EntryLoG 0 /* Global (R/W) */ -#define M_EntryLoG (0x1 << S_EntryLoG) -#define M_EntryLoOddPFN (0x1 << S_EntryLoPFN) /* Odd PFN bit */ -#define S_EntryLo_RS K_PageAlign /* Right-justify PFN */ -#define S_EntryLo_LS S_EntryLoPFN /* Position PFN to appropriate position */ - -#define M_EntryLo0Fields 0x00000000 -#define M_EntryLoRFields 0xc0000000 -#define M_EntryLo0Fields64 UNS64Const(0x0000000000000000) -#define M_EntryLoRFields64 UNS64Const(0xffffffffc0000000) - -/* - * Cache attribute values in the C field of EntryLo and the - * K0 field of Config - */ -#define K_CacheAttrCWTnWA 0 /* Cacheable, write-thru, no write allocate */ -#define K_CacheAttrCWTWA 1 /* Cacheable, write-thru, write allocate */ -#define K_CacheAttrU 2 /* Uncached */ -#define K_CacheAttrC 3 /* Cacheable */ -#define K_CacheAttrCN 3 /* Cacheable, non-coherent */ -#define K_CacheAttrCCE 4 /* Cacheable, coherent, exclusive */ -#define K_CacheAttrCCS 5 /* Cacheable, coherent, shared */ -#define K_CacheAttrCCU 6 /* Cacheable, coherent, update */ -#define K_CacheAttrUA 7 /* Uncached accelerated */ - - -/* - ************************************************************************ - * E N T R Y L O 1 R E G I S T E R ( 3 ) * - ************************************************************************ - * - * 6 6 6 6 5 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 2 1 0 9 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Fill (0) //| 0 | PFN | C |D|V|G| EntryLo1 - * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_EntryLo1 $3 -#define R_C0_EntryLo1 3 -#define C0_TLBLO_1 C0_EntryLo1 /* OBSOLETE - DO NOT USE IN NEW CODE */ - -/* - * Field definitions are as given for EntryLo0 above - */ - - -/* - ************************************************************************ - * C O N T E X T R E G I S T E R ( 4 ) * - ************************************************************************ - * - * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | // PTEBase | BadVPN<31:13> | 0 | Context - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Context $4 -#define R_C0_Context 4 -#define C0_CTXT C0_Context /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_ContextPTEBase 23 /* PTE base (R/W) */ -#define M_ContextPTEBase (0x1ff << S_ContextPTEBase) -#define S_ContextBadVPN 4 /* BadVPN2 (R) */ -#define M_ContextBadVPN (0x7ffff << S_ContextBadVPN) -#define S_ContextBadVPN_LS 9 /* Position BadVPN to bit 31 */ -#define S_ContextBadVPN_RS 13 /* Right-justify shifted BadVPN field */ - -#define M_Context0Fields 0x0000000f -#define M_ContextRFields 0x007ffff0 -#define M_Context0Fields64 UNS64Const(0x000000000000000f) -#define M_ContextRFields64 UNS64Const(0x00000000007ffff0) - - -/* - ************************************************************************ - * P A G E M A S K R E G I S T E R ( 5 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0 | Mask | 0 | PageMask - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_PageMask $5 -#define R_C0_PageMask 5 /* Mask (R/W) */ -#define C0_PGMASK C0_PageMask /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_PageMaskMask 13 -#define M_PageMaskMask (0xfff << S_PageMaskMask) - -#define M_PageMask0Fields 0xfe001fff -#define M_PageMaskRFields 0x00000000 - -/* - * Values in the Mask field - */ -#define K_PageMask4K 0x000 /* K_PageMasknn values are values for use */ -#define K_PageMask16K 0x003 /* with KReqPageAttributes or KReqPageMask macros */ -#define K_PageMask64K 0x00f -#define K_PageMask256K 0x03f -#define K_PageMask1M 0x0ff -#define K_PageMask4M 0x3ff -#define K_PageMask16M 0xfff - -#define M_PageMask4K (K_PageMask4K << S_PageMaskMask) /* M_PageMasknn values are masks */ -#define M_PageMask16K (K_PageMask16K << S_PageMaskMask) /* in position in the PageMask register */ -#define M_PageMask64K (K_PageMask64K << S_PageMaskMask) -#define M_PageMask256K (K_PageMask256K << S_PageMaskMask) -#define M_PageMask1M (K_PageMask1M << S_PageMaskMask) -#define M_PageMask4M (K_PageMask4M << S_PageMaskMask) -#define M_PageMask16M (K_PageMask16M << S_PageMaskMask) - - -/* - ************************************************************************ - * W I R E D R E G I S T E R ( 6 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0 | Index | Wired - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Wired $6 -#define R_C0_Wired 6 -#define C0_TLBWIRED C0_Wired /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_WiredIndex 0 /* TLB wired boundary (R/W) */ -#define M_WiredIndex (0x3f << S_WiredIndex) - -#define M_Wired0Fields 0xffffffc0 -#define M_WiredRFields 0x00000000 - - -/* - ************************************************************************ - * B A D V A D D R R E G I S T E R ( 8 ) * - ************************************************************************ - * - * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | // Bad Virtual Address | BadVAddr - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_BadVAddr $8 -#define R_C0_BadVAddr 8 -#define C0_BADVADDR C0_BadVAddr /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define M_BadVAddrOddPage K_PageSize /* Even/Odd VA bit for pair of PAs */ - -#define M_BadVAddr0Fields 0x00000000 -#define M_BadVAddrRFields 0xffffffff -#define M_BadVAddr0Fields64 UNS64Const(0x0000000000000000) -#define M_BadVAddrRFields64 UNS64Const(0xffffffffffffffff) - -/* - ************************************************************************ - * C O U N T R E G I S T E R ( 9 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Count Value | Count - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Count $9 -#define R_C0_Count 9 -#define C0_COUNT C0_Count /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define M_Count0Fields 0x00000000 -#define M_CountRFields 0x00000000 - - -/* - ************************************************************************ - * E N T R Y H I R E G I S T E R ( 1 0 ) * - ************************************************************************ - * - * 6 6 6 6 5 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 2 1 0 9 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | R | Fill // VPN2 | 0 | ASID | EntryHi - * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_EntryHi $10 -#define R_C0_EntryHi 10 -#define C0_TLBHI C0_EntryHi /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_EntryHiR64 62 /* Region (R/W) */ -#define M_EntryHiR64 UNS64Const(0xc000000000000000) -#define S_EntryHiVPN2 13 /* VPN/2 (R/W) */ -#define M_EntryHiVPN2 (0x7ffff << S_EntryHiVPN2) -#define M_EntryHiVPN264 UNS64Const(0x000000ffffffe000) -#define S_EntryHiASID 0 /* ASID (R/W) */ -#define M_EntryHiASID (0xff << S_EntryHiASID) -#define S_EntryHiVPN_Shf S_EntryHiVPN2 - -#define M_EntryHi0Fields 0x00001f00 -#define M_EntryHiRFields 0x00000000 -#define M_EntryHi0Fields64 UNS64Const(0x0000000000001f00) -#define M_EntryHiRFields64 UNS64Const(0x3fffff0000000000) - - -/* - ************************************************************************ - * C O M P A R E R E G I S T E R ( 1 1 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Compare Value | Compare - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Compare $11 -#define R_C0_Compare 11 -#define C0_COMPARE C0_Compare /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define M_Compare0Fields 0x00000000 -#define M_CompareRFields 0x00000000 - - -/* - ************************************************************************ - * S T A T U S R E G I S T E R ( 1 2 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |C|C|C|C|R|F|R|M|P|B|T|S|M| | R |I|I|I|I|I|I|I|I|K|S|U|U|R|E|E|I| - * |U|U|U|U|P|R|E|X|X|E|S|R|M| | s |M|M|M|M|M|M|M|M|X|X|X|M|s|R|X|E| Status - * |3|2|1|0| | | | | |V| | |I| | v |7|6|5|4|3|2|1|0| | | | |v|L|L| | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Status $12 -#define R_C0_Status 12 -#define C0_SR C0_Status /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_StatusCU 28 /* Coprocessor enable (R/W) */ -#define M_StatusCU (0xf << S_StatusCU) -#define S_StatusCU3 31 -#define M_StatusCU3 (0x1 << S_StatusCU3) -#define S_StatusCU2 30 -#define M_StatusCU2 (0x1 << S_StatusCU2) -#define S_StatusCU1 29 -#define M_StatusCU1 (0x1 << S_StatusCU1) -#define S_StatusCU0 28 -#define M_StatusCU0 (0x1 << S_StatusCU0) -#define S_StatusRP 27 /* Enable reduced power mode (R/W) */ -#define M_StatusRP (0x1 << S_StatusRP) -#define S_StatusFR 26 /* Enable 64-bit FPRs (MIPS64 only) (R/W) */ -#define M_StatusFR (0x1 << S_StatusFR) -#define S_StatusRE 25 /* Enable reverse endian (R/W) */ -#define M_StatusRE (0x1 << S_StatusRE) -#define S_StatusMX 24 /* Enable access to MDMX resources (MIPS64 only) (R/W) */ -#define M_StatusMX (0x1 << S_StatusMX) -#define S_StatusPX 23 /* Enable access to 64-bit instructions/data (MIPS64 only) (R/W) */ -#define M_StatusPX (0x1 << S_StatusPX) -#define S_StatusBEV 22 /* Enable Boot Exception Vectors (R/W) */ -#define M_StatusBEV (0x1 << S_StatusBEV) -#define S_StatusTS 21 /* Denote TLB shutdown (R/W) */ -#define M_StatusTS (0x1 << S_StatusTS) -#define S_StatusSR 20 /* Denote soft reset (R/W) */ -#define M_StatusSR (0x1 << S_StatusSR) -#define S_StatusNMI 19 -#define M_StatusNMI (0x1 << S_StatusNMI) /* Denote NMI (R/W) */ -#define S_StatusIM 8 /* Interrupt mask (R/W) */ -#define M_StatusIM (0xff << S_StatusIM) -#define S_StatusIM7 15 -#define M_StatusIM7 (0x1 << S_StatusIM7) -#define S_StatusIM6 14 -#define M_StatusIM6 (0x1 << S_StatusIM6) -#define S_StatusIM5 13 -#define M_StatusIM5 (0x1 << S_StatusIM5) -#define S_StatusIM4 12 -#define M_StatusIM4 (0x1 << S_StatusIM4) -#define S_StatusIM3 11 -#define M_StatusIM3 (0x1 << S_StatusIM3) -#define S_StatusIM2 10 -#define M_StatusIM2 (0x1 << S_StatusIM2) -#define S_StatusIM1 9 -#define M_StatusIM1 (0x1 << S_StatusIM1) -#define S_StatusIM0 8 -#define M_StatusIM0 (0x1 << S_StatusIM0) -#define S_StatusKX 7 /* Enable access to extended kernel addresses (MIPS64 only) (R/W) */ -#define M_StatusKX (0x1 << S_StatusKX) -#define S_StatusSX 6 /* Enable access to extended supervisor addresses (MIPS64 only) (R/W) */ -#define M_StatusSX (0x1 << S_StatusSX) -#define S_StatusUX 5 /* Enable access to extended user addresses (MIPS64 only) (R/W) */ -#define M_StatusUX (0x1 << S_StatusUX) -#define S_StatusKSU 3 /* Two-bit current mode (R/W) */ -#define M_StatusKSU (0x3 << S_StatusKSU) -#define S_StatusUM 4 /* User mode if supervisor mode not implemented (R/W) */ -#define M_StatusUM (0x1 << S_StatusUM) -#define S_StatusSM 3 /* Supervisor mode (R/W) */ -#define M_StatusSM (0x1 << S_StatusSM) -#define S_StatusERL 2 /* Denotes error level (R/W) */ -#define M_StatusERL (0x1 << S_StatusERL) -#define S_StatusEXL 1 /* Denotes exception level (R/W) */ -#define M_StatusEXL (0x1 << S_StatusEXL) -#define S_StatusIE 0 /* Enables interrupts (R/W) */ -#define M_StatusIE (0x1 << S_StatusIE) - -#define M_Status0Fields 0x00040000 -#define M_StatusRFields 0x058000e0 /* FR, MX, PX, KX, SX, UX unused in MIPS32 */ -#define M_Status0Fields64 0x00040000 -#define M_StatusRFields64 0x00000000 - -/* - * Values in the KSU field - */ -#define K_StatusKSU_U 2 /* User mode in KSU field */ -#define K_StatusKSU_S 1 /* Supervisor mode in KSU field */ -#define K_StatusKSU_K 0 /* Kernel mode in KSU field */ - - -/* - ************************************************************************ - * C A U S E R E G I S T E R ( 1 3 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |B| | C | |I|W| |I|I|I|I|I|I|I|I| | | R | - * |D| | E | Rsvd |V|P| Rsvd |P|P|P|P|P|P|P|P| | ExcCode | s | Cause - * | | | | | | | |7|6|5|4|3|2|1|0| | | v | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Cause $13 -#define R_C0_Cause 13 -#define C0_CAUSE C0_Cause /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_CauseBD 31 -#define M_CauseBD (0x1 << S_CauseBD) -#define S_CauseCE 28 -#define M_CauseCE (0x3<< S_CauseCE) -#define S_CauseIV 23 -#define M_CauseIV (0x1 << S_CauseIV) -#define S_CauseWP 22 -#define M_CauseWP (0x1 << S_CauseWP) -#define S_CauseIP 8 -#define M_CauseIP (0xff << S_CauseIP) -#define S_CauseIPEXT 10 -#define M_CauseIPEXT (0x3f << S_CauseIPEXT) -#define S_CauseIP7 15 -#define M_CauseIP7 (0x1 << S_CauseIP7) -#define S_CauseIP6 14 -#define M_CauseIP6 (0x1 << S_CauseIP6) -#define S_CauseIP5 13 -#define M_CauseIP5 (0x1 << S_CauseIP5) -#define S_CauseIP4 12 -#define M_CauseIP4 (0x1 << S_CauseIP4) -#define S_CauseIP3 11 -#define M_CauseIP3 (0x1 << S_CauseIP3) -#define S_CauseIP2 10 -#define M_CauseIP2 (0x1 << S_CauseIP2) -#define S_CauseIP1 9 -#define M_CauseIP1 (0x1 << S_CauseIP1) -#define S_CauseIP0 8 -#define M_CauseIP0 (0x1 << S_CauseIP0) -#define S_CauseExcCode 2 -#define M_CauseExcCode (0x1f << S_CauseExcCode) - -#define M_Cause0Fields 0x4f3f0083 -#define M_CauseRFields 0xb000fc7c - -/* - * Values in the CE field - */ -#define K_CauseCE0 0 /* Coprocessor 0 in the CE field */ -#define K_CauseCE1 1 /* Coprocessor 1 in the CE field */ -#define K_CauseCE2 2 /* Coprocessor 2 in the CE field */ -#define K_CauseCE3 3 /* Coprocessor 3 in the CE field */ - -/* - * Values in the ExcCode field - */ -#define EX_INT 0 /* Interrupt */ -#define EXC_INT (EX_INT << S_CauseExcCode) -#define EX_MOD 1 /* TLB modified */ -#define EXC_MOD (EX_MOD << S_CauseExcCode) -#define EX_TLBL 2 /* TLB exception (load or ifetch) */ -#define EXC_TLBL (EX_TLBL << S_CauseExcCode) -#define EX_TLBS 3 /* TLB exception (store) */ -#define EXC_TLBS (EX_TLBS << S_CauseExcCode) -#define EX_ADEL 4 /* Address error (load or ifetch) */ -#define EXC_ADEL (EX_ADEL << S_CauseExcCode) -#define EX_ADES 5 /* Address error (store) */ -#define EXC_ADES (EX_ADES << S_CauseExcCode) -#define EX_IBE 6 /* Instruction Bus Error */ -#define EXC_IBE (EX_IBE << S_CauseExcCode) -#define EX_DBE 7 /* Data Bus Error */ -#define EXC_DBE (EX_DBE << S_CauseExcCode) -#define EX_SYS 8 /* Syscall */ -#define EXC_SYS (EX_SYS << S_CauseExcCode) -#define EX_SYSCALL EX_SYS -#define EXC_SYSCALL EXC_SYS -#define EX_BP 9 /* Breakpoint */ -#define EXC_BP (EX_BP << S_CauseExcCode) -#define EX_BREAK EX_BP -#define EXC_BREAK EXC_BP -#define EX_RI 10 /* Reserved instruction */ -#define EXC_RI (EX_RI << S_CauseExcCode) -#define EX_CPU 11 /* CoProcessor Unusable */ -#define EXC_CPU (EX_CPU << S_CauseExcCode) -#define EX_OV 12 /* OVerflow */ -#define EXC_OV (EX_OV << S_CauseExcCode) -#define EX_TR 13 /* Trap instruction */ -#define EXC_TR (EX_TR << S_CauseExcCode) -#define EX_TRAP EX_TR -#define EXC_TRAP EXC_TR -#define EX_FPE 15 /* floating point exception */ -#define EXC_FPE (EX_FPE << S_CauseExcCode) -#define EX_C2E 18 /* COP2 exception */ -#define EXC_C2E (EX_C2E << S_CauseExcCode) -#define EX_MDMX 22 /* MDMX exception */ -#define EXC_MDMX (EX_MDMX << S_CauseExcCode) -#define EX_WATCH 23 /* Watch exception */ -#define EXC_WATCH (EX_WATCH << S_CauseExcCode) -#define EX_MCHECK 24 /* Machine check exception */ -#define EXC_MCHECK (EX_MCHECK << S_CauseExcCode) -#define EX_CacheErr 30 /* Cache error caused re-entry to Debug Mode */ -#define EXC_CacheErr (EX_CacheErr << S_CauseExcCode) - - -/* - ************************************************************************ - * E P C R E G I S T E R ( 1 4 ) * - ************************************************************************ - * - * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | // Exception PC | EPC - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_EPC $14 -#define R_C0_EPC 14 - -#define M_EPC0Fields 0x00000000 -#define M_EPCRFields 0x00000000 -#define M_EPC0Fields64 UNS64Const(0x0000000000000000) -#define M_EPCRFields64 UNS64Const(0x0000000000000000) - -/* - ************************************************************************ - * P R I D R E G I S T E R ( 1 5 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Company Opts | Company ID | Procesor ID | Revision | PRId - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_PRId $15 -#define R_C0_PRId 15 -#define C0_PRID C0_PRID /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_PRIdCoOpt 24 /* Company options (R) */ -#define M_PRIdCoOpt (0xff << S_PRIdCoOpt) -#define S_PRIdCoID 16 /* Company ID (R) */ -#define M_PRIdCoID (0xff << S_PRIdCoID) -#define S_PRIdImp 8 /* Implementation ID (R) */ -#define M_PRIdImp (0xff << S_PRIdImp) -#define S_PRIdRev 0 /* Revision (R) */ -#define M_PRIdRev (0xff << S_PRIdRev) - -#define M_PRId0Fields 0x00000000 -#define M_PRIdRFields 0xffffffff -/* - * Values in the Company ID field - */ -#define K_PRIdCoID_MIPS 1 -#define K_PRIdCoID_Broadcom 2 -#define K_PRIdCoID_Alchemy 3 -#define K_PRIdCoID_SiByte 4 -#define K_PRIdCoID_SandCraft 5 -#define K_PRIdCoID_Philips 6 -#define K_PRIdCoID_NextAvailable 7 /* Next available encoding */ - - -/* - * Values in the implementation number field - */ -#define K_PRIdImp_Jade 0x80 -#define K_PRIdImp_Opal 0x81 -#define K_PRIdImp_Ruby 0x82 -#define K_PRIdImp_JadeLite 0x83 -#define K_PRIdImp_4KEc 0x84 /* Emerald with TLB MMU */ -#define K_PRIdImp_4KEmp 0x85 /* Emerald with FM MMU */ -#define K_PRIdImp_4KSc 0x86 /* Coral */ - -#define K_PRIdImp_R3000 0x01 -#define K_PRIdImp_R4000 0x04 -#define K_PRIdImp_R10000 0x09 -#define K_PRIdImp_R4300 0x0b -#define K_PRIdImp_R5000 0x23 -#define K_PRIdImp_R5200 0x28 -#define K_PRIdImp_R5400 0x54 - -/* - ************************************************************************ - * C O N F I G R E G I S T E R ( 1 6 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |M| |B| A | A | | K | Config - * | | Reserved for Implementations|E| T | R | Reserved | 0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Config $16 -#define R_C0_Config 16 -#define C0_CONFIG C0_Config /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_ConfigMore 31 /* Additional config registers present (R) */ -#define M_ConfigMore (0x1 << S_ConfigMore) -#define S_ConfigImpl 16 /* Implementation-specific fields */ -#define M_ConfigImpl (0x7fff << S_ConfigImpl) -#define S_ConfigBE 15 /* Denotes big-endian operation (R) */ -#define M_ConfigBE (0x1 << S_ConfigBE) -#define S_ConfigAT 13 /* Architecture type (R) */ -#define M_ConfigAT (0x3 << S_ConfigAT) -#define S_ConfigAR 10 /* Architecture revision (R) */ -#define M_ConfigAR (0x7 << S_ConfigAR) -#define S_ConfigMT 7 /* MMU Type (R) */ -#define M_ConfigMT (0x7 << S_ConfigMT) -#define S_ConfigK0 0 /* Kseg0 coherency algorithm (R/W) */ -#define M_ConfigK0 (0x7 << S_ConfigK0) - -/* - * The following definitions are technically part of the "reserved for - * implementations" field, but are the semi-standard definition used in - * fixed-mapping MMUs to control the cacheability of kuseg and kseg2/3 - * references. For that reason, they are included here, but may be - * overridden by true implementation-specific definitions - */ -#define S_ConfigK23 28 /* Kseg2/3 coherency algorithm (FM MMU only) (R/W) */ -#define M_ConfigK23 (0x7 << S_ConfigK23) -#define S_ConfigKU 25 /* Kuseg coherency algorithm (FM MMU only) (R/W) */ -#define M_ConfigKU (0x7 << S_ConfigKU) - -#define M_Config0Fields 0x00000078 -#define M_ConfigRFields 0x8000ff80 - -/* - * Values in the AT field - */ -#define K_ConfigAT_MIPS32 0 /* MIPS32 */ -#define K_ConfigAT_MIPS64S 1 /* MIPS64 with 32-bit addresses */ -#define K_ConfigAT_MIPS64 2 /* MIPS64 with 32/64-bit addresses */ - -/* - * Values in the MT field - */ -#define K_ConfigMT_NoMMU 0 /* No MMU */ -#define K_ConfigMT_TLBMMU 1 /* Standard TLB MMU */ -#define K_ConfigMT_BATMMU 2 /* Standard BAT MMU */ -#define K_ConfigMT_FMMMU 3 /* Standard Fixed Mapping MMU */ - - -/* - ************************************************************************ - * C O N F I G 1 R E G I S T E R ( 1 6, SELECT 1 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |M| MMU Size | IS | IL | IA | DS | DL | DA |C|M|P|W|C|E|F| Config1 - * | | | | | | | | |2|D|C|R|A|P|P| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Config1 $16,1 -#define R_C0_Config1 16 - -#define S_Config1More 31 /* Additional Config registers present (R) */ -#define M_Config1More (0x1 << S_Config1More) -#define S_Config1MMUSize 25 /* Number of MMU entries - 1 (R) */ -#define M_Config1MMUSize (0x3f << S_Config1MMUSize) -#define S_Config1IS 22 /* Icache sets per way (R) */ -#define M_Config1IS (0x7 << S_Config1IS) -#define S_Config1IL 19 /* Icache line size (R) */ -#define M_Config1IL (0x7 << S_Config1IL) -#define S_Config1IA 16 /* Icache associativity - 1 (R) */ -#define M_Config1IA (0x7 << S_Config1IA) -#define S_Config1DS 13 /* Dcache sets per way (R) */ -#define M_Config1DS (0x7 << S_Config1DS) -#define S_Config1DL 10 /* Dcache line size (R) */ -#define M_Config1DL (0x7 << S_Config1DL) -#define S_Config1DA 7 /* Dcache associativity (R) */ -#define M_Config1DA (0x7 << S_Config1DA) -#define S_Config1C2 6 /* Coprocessor 2 present (R) */ -#define M_Config1C2 (0x1 << S_Config1C2) -#define S_Config1MD 5 /* Denotes MDMX present (R) */ -#define M_Config1MD (0x1 << S_Config1MD) -#define S_Config1PC 4 /* Denotes performance counters present (R) */ -#define M_Config1PC (0x1 << S_Config1PC) -#define S_Config1WR 3 /* Denotes watch registers present (R) */ -#define M_Config1WR (0x1 << S_Config1WR) -#define S_Config1CA 2 /* Denotes MIPS-16 present (R) */ -#define M_Config1CA (0x1 << S_Config1CA) -#define S_Config1EP 1 /* Denotes EJTAG present (R) */ -#define M_Config1EP (0x1 << S_Config1EP) -#define S_Config1FP 0 /* Denotes floating point present (R) */ -#define M_Config1FP (0x1 << S_Config1FP) - -#define M_Config10Fields 0x00000060 -#define M_Config1RFields 0x7fffff9f - -/* - * The following macro generates a table that is indexed - * by the Icache or Dcache sets field in Config1 and - * contains the decoded value of sets per way - */ -#define Config1CacheSets() \ - HALF(64); \ - HALF(128); \ - HALF(256); \ - HALF(512); \ - HALF(1024); \ - HALF(2048); \ - HALF(4096); \ - HALF(8192); - -/* - * The following macro generates a table that is indexed - * by the Icache or Dcache line size field in Config1 and - * contains the decoded value of the cache line size, in bytes - */ -#define Config1CacheLineSize() \ - HALF(0); \ - HALF(4); \ - HALF(8); \ - HALF(16); \ - HALF(32); \ - HALF(64); \ - HALF(128); \ - HALF(256); - - -/* - ************************************************************************ - * C O N F I G 2 R E G I S T E R ( 1 6, SELECT 2 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |M| | | | | | | | | | | | |S|T| Config1 - * | | | | | | | | | | | | | |M|L| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Config2 $16,2 -#define R_C0_Config2 16 - -#define S_Config2More 31 /* Additional Config registers present (R) */ -#define M_Config2More (0x1 << S_Config2More) -#define S_Config2SM 1 /* Denotes SmartMIPS ASE present (R) */ -#define M_Config2SM (0x1 << S_Config2SM) -#define S_Config2TL 0 /* Denotes Tracing Logic present (R) */ -#define M_Config2TL (0x1 << S_Config2TL) - -#define M_Config20Fields 0xfffffffc -#define M_Config2RFields 0x00000003 - -/* - ************************************************************************ - * L L A D D R R E G I S T E R ( 1 7 ) * - ************************************************************************ - * - * 6 6 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | // LL Physical Address | LLAddr - * +-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_LLAddr $17 -#define R_C0_LLAddr 17 -#define C0_LLADDR C0_LLAddr /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define M_LLAddr0Fields 0x00000000 -#define M_LLAddrRFields 0x00000000 -#define M_LLAddr0Fields64 UNS64Const(0x0000000000000000) -#define M_LLAddrRFields64 UNS64Const(0x0000000000000000) - - -/* - ************************************************************************ - * W A T C H L O R E G I S T E R ( 1 8 ) * - ************************************************************************ - * - * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | // Watch Virtual Address |I|R|W| WatchLo - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_WatchLo $18 -#define R_C0_WatchLo 18 -#define C0_WATCHLO C0_WatchLo /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_WatchLoVAddr 3 /* Watch virtual address (R/W) */ -#define M_WatchLoVAddr (0x1fffffff << S_WatchLoVAddr) -#define S_WatchLoI 2 /* Enable Istream watch (R/W) */ -#define M_WatchLoI (0x1 << S_WatchLoI) -#define S_WatchLoR 1 /* Enable data read watch (R/W) */ -#define M_WatchLoR (0x1 << S_WatchLoR) -#define S_WatchLoW 0 /* Enable data write watch (R/W) */ -#define M_WatchLoW (0x1 << S_WatchLoW) - -#define M_WatchLo0Fields 0x00000000 -#define M_WatchLoRFields 0x00000000 -#define M_WatchLo0Fields64 UNS64Const(0x0000000000000000) -#define M_WatchLoRFields64 UNS64Const(0x0000000000000000) - -#define M_WatchLoEnables (M_WatchLoI | M_WatchLoR | M_WatchLoW) - - -/* - ************************************************************************ - * W A T C H H I R E G I S T E R ( 1 9 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |M|G| Rsvd | ASID | Rsvd | Mask | 0 | WatchHi - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_WatchHi $19 -#define R_C0_WatchHi 19 -#define C0_WATCHHI C0_WatchHi /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_WatchHiM 31 /* Denotes additional Watch registers present (R) */ -#define M_WatchHiM (0x1 << S_WatchHiM) -#define S_WatchHiG 30 /* Enable ASID-independent Watch match (R/W) */ -#define M_WatchHiG (0x1 << S_WatchHiG) -#define S_WatchHiASID 16 /* ASID value to match (R/W) */ -#define M_WatchHiASID (0xff << S_WatchHiASID) -#define S_WatchHiMask 3 /* Address inhibit mask (R/W) */ -#define M_WatchHiMask (0x1ff << S_WatchHiMask) - -#define M_WatchHi0Fields 0x3f00f007 -#define M_WatchHiRFields 0x80000000 - - -/* - ************************************************************************ - * X C O N T E X T R E G I S T E R ( 2 0 ) * - ************************************************************************ - * - * 6 // 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 // 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | // PTEBase | R | BadVPN2<39:13> | 0 | XContext - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_XContext $20 -#define R_C0_XContext 20 -#define C0_EXTCTXT C0_XContext /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_XContextBadVPN2 4 /* BadVPN2 (R) */ -#define S_XContextBadVPN S_XContextBadVPN2 - -#define M_XContext0Fields 0x0000000f - - -/* - ************************************************************************ - * D E B U G R E G I S T E R ( 2 3 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |D|D|N|L|D|H|C|I|M|C|D|I|D|D| | |N|S| |D|D|D|D|D|D| - * |B|M|o|S|o|a|o|B|C|a|B|E|D|D|EJTAG|DExcCode |o|S| |I|I|D|D|B|S| - * |D| |D|N|z|l|u|u|h|c|u|X|B|B| ver | |S|t| |N|B|B|B|p|S| - * | | |C|M|e|t|n|s|e|h|s|I|S|L| | |S| | 0 |T| |S|L| | | Debug - * | | |R| | | |t|E|c|e|E| |I|I| | |t| | | | | | | | | - * | | | | | | |D|P|k|E|P| |m|m| | | | | | | | | | | | - * | | | | | | |M| |P|P| | |p|p| | | | | | | | | | | | - * | | | | | | | | | | | | |r|r| | | | | | | | | | | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_Debug $23 /* EJTAG */ -#define R_C0_Debug 23 - -#define S_DebugDBD 31 /* Debug branch delay (R) */ -#define M_DebugDBD (0x1 << S_DebugDBD) -#define S_DebugDM 30 /* Debug mode (R) */ -#define M_DebugDM (0x1 << S_DebugDM) -#define S_DebugNoDCR 29 /* No debug control register present (R) */ -#define M_DebugNoDCR (0x1 << S_DebugNoDCR) -#define S_DebugLSNM 28 /* Load/Store Normal Memory (R/W) */ -#define M_DebugLSNM (0x1 << S_DebugLSNM) -#define S_DebugDoze 27 /* Doze (R) */ -#define M_DebugDoze (0x1 << S_DebugDoze) -#define S_DebugHalt 26 /* Halt (R) */ -#define M_DebugHalt (0x1 << S_DebugHalt) -#define S_DebugCountDM 25 /* Count register behavior in debug mode (R/W) */ -#define M_DebugCountDM (0x1 << S_DebugCountDM) -#define S_DebugIBusEP 24 /* Imprecise Instn Bus Error Pending (R/W) */ -#define M_DebugIBusEP (0x1 << S_DebugIBusEP) -#define S_DebugMCheckP 23 /* Imprecise Machine Check Pending (R/W) */ -#define M_DebugMCheckP (0x1 << S_DebugMCheckP) -#define S_DebugCacheEP 22 /* Imprecise Cache Error Pending (R/W) */ -#define M_DebugCacheEP (0x1 << S_DebugCacheEP) -#define S_DebugDBusEP 21 /* Imprecise Data Bus Error Pending (R/W) */ -#define M_DebugDBusEP (0x1 << S_DebugDBusEP) -#define S_DebugIEXI 20 /* Imprecise Exception Inhibit (R/W) */ -#define M_DebugIEXI (0x1 << S_DebugIEXI) -#define S_DebugDDBSImpr 19 /* Debug data break store imprecise (R) */ -#define M_DebugDDBSImpr (0x1 << S_DebugDDBSImpr) -#define S_DebugDDBLImpr 18 /* Debug data break load imprecise (R) */ -#define M_DebugDDBLImpr (0x1 << S_DebugDDBLImpr) -#define S_DebugEJTAGver 15 /* EJTAG version number (R) */ -#define M_DebugEJTAGver (0x7 << S_DebugEJTAGver) -#define S_DebugDExcCode 10 /* Debug exception code (R) */ -#define M_DebugDExcCode (0x1f << S_DebugDExcCode) -#define S_DebugNoSSt 9 /* No single step implemented (R) */ -#define M_DebugNoSSt (0x1 << S_DebugNoSSt) -#define S_DebugSSt 8 /* Single step enable (R/W) */ -#define M_DebugSSt (0x1 << S_DebugSSt) -#define S_DebugDINT 5 /* Debug interrupt (R) */ -#define M_DebugDINT (0x1 << S_DebugDINT) -#define S_DebugDIB 4 /* Debug instruction break (R) */ -#define M_DebugDIB (0x1 << S_DebugDIB) -#define S_DebugDDBS 3 /* Debug data break store (R) */ -#define M_DebugDDBS (0x1 << S_DebugDDBS) -#define S_DebugDDBL 2 /* Debug data break load (R) */ -#define M_DebugDDBL (0x1 << S_DebugDDBL) -#define S_DebugDBp 1 /* Debug breakpoint (R) */ -#define M_DebugDBp (0x1 << S_DebugDBp) -#define S_DebugDSS 0 /* Debug single step (R) */ -#define M_DebugDSS (0x1 << S_DebugDSS) - -#define M_Debug0Fields 0x01f000c0 -#define M_DebugRFields 0xec0ffe3f - - -/* - ************************************************************************ - * D E P C R E G I S T E R ( 2 4 ) * - ************************************************************************ - * - * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | // EJTAG Debug Exception PC | DEPC - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - -#define C0_DEPC $24 -#define R_C0_DEPC 24 - -#define M_DEEPC0Fields 0x00000000 -#define M_DEEPCRFields 0x00000000 -#define M_DEEPC0Fields64 UNS64Const(0x0000000000000000) -#define M_DEEPCRFields64 UNS64Const(0x0000000000000000) - - -/* - ************************************************************************ - * P E R F C N T R E G I S T E R ( 2 5 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | |I| | | |E| - * |M| 0 | Event |E|U|S|K|X| PerfCnt - * | | | | | | | |L| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Event Count | PerfCnt - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_PerfCnt $25 -#define R_C0_PerfCnt 25 -#define C0_PRFCNT0 C0_PerfCnt /* OBSOLETE - DO NOT USE IN NEW CODE */ -#define C0_PRFCNT1 C0_PerfCnt /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define S_PerfCntM 31 /* More performance counters exist (R) */ -#define M_PerfCntM (1 << S_PerfCntM) -#define S_PerfCntEvent 5 /* Enabled event (R/W) */ -#define M_PerfCntEvent (0x3f << S_PerfCntEvent) -#define S_PerfCntIE 4 /* Interrupt Enable (R/W) */ -#define M_PerfCntIE (1 << S_PerfCntIE) -#define S_PerfCntU 3 /* Enable counting in User Mode (R/W) */ -#define M_PerfCntU (1 << S_PerfCntU) -#define S_PerfCntS 2 /* Enable counting in Supervisor Mode (R/W) */ -#define M_PerfCntS (1 << S_PerfCntS) -#define S_PerfCntK 1 /* Enable counting in Kernel Mode (R/W) */ -#define M_PerfCntK (1 << S_PerfCntK) -#define S_PerfCntEXL 0 /* Enable counting while EXL==1 (R/W) */ -#define M_PerfCntEXL (1 << S_PerfCntEXL) - -#define M_PerfCnt0Fields 0x7ffff800 -#define M_PerfCntRFields 0x80000000 - - -/* - ************************************************************************ - * E R R C T L R E G I S T E R ( 2 6 ) * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Error Control | ErrCtl - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_ErrCtl $26 -#define R_C0_ErrCtl 26 -#define C0_ECC $26 /* OBSOLETE - DO NOT USE IN NEW CODE */ -#define R_C0_ECC 26 /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define M_ErrCtl0Fields 0x00000000 -#define M_ErrCtlRFields 0x00000000 - - -/* - ************************************************************************ - * C A C H E E R R R E G I S T E R ( 2 7 ) * CacheErr - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Cache Error Control | CacheErr - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_CacheErr $27 -#define R_C0_CacheErr 27 -#define C0_CACHE_ERR C0_CacheErr /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define M_CacheErr0Fields 0x00000000 -#define M_CachErrRFields 0x00000000 - - -/* - ************************************************************************ - * T A G L O R E G I S T E R ( 2 8 ) * TagLo - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TagLo | TagLo - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_TagLo $28 -#define R_C0_TagLo 28 -#define C0_TAGLO C0_TagLo /* OBSOLETE - DO NOT USE IN NEW CODE */ - -/* - * Some implementations use separate TagLo registers for the - * instruction and data caches. In those cases, the following - * definitions can be used in relevant code - */ - -#define C0_ITagLo $28,0 -#define C0_DTagLo $28,2 - -#define M_TagLo0Fields 0x00000000 -#define M_TagLoRFields 0x00000000 - - -/* - ************************************************************************ - * D A T A L O R E G I S T E R ( 2 8, SELECT 1 ) * DataLo - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | DataLo | DataLo - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_DataLo $28,1 -#define R_C0_DataLo 28 - -/* - * Some implementations use separate DataLo registers for the - * instruction and data caches. In those cases, the following - * definitions can be used in relevant code - */ - -#define C0_IDataLo $28,1 -#define C0_DDataLo $28,3 - -#define M_DataLo0Fields 0x00000000 -#define M_DataLoRFields 0xffffffff - - -/* - ************************************************************************ - * T A G H I R E G I S T E R ( 2 9 ) * TagHi - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TagHi | TagHi - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_TagHi $29 -#define R_C0_TagHi 29 -#define C0_TAGHI C0_TagHi /* OBSOLETE - DO NOT USE IN NEW CODE */ - -/* - * Some implementations use separate TagHi registers for the - * instruction and data caches. In those cases, the following - * definitions can be used in relevant code - */ - -#define C0_ITagHi $29,0 -#define C0_DTagHi $29,2 - -#define M_TagHi0Fields 0x00000000 -#define M_TagHiRFields 0x00000000 - - -/* - ************************************************************************ - * D A T A H I R E G I S T E R ( 2 9, SELECT 1 ) * DataHi - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | DataHi | DataHi - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_DataHi $29,1 -#define R_C0_DataHi 29 - -/* - * Some implementations use separate DataHi registers for the - * instruction and data caches. In those cases, the following - * definitions can be used in relevant code - */ - -#define C0_IDataHi $29,1 -#define C0_DDataHi $29,3 - -#define M_DataHi0Fields 0x00000000 -#define M_DataHiRFields 0xffffffff - - -/* - ************************************************************************ - * E R R O R E P C R E G I S T E R ( 3 0 ) * - ************************************************************************ - * - * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | // Error PC | ErrorEPC - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_ErrorEPC $30 -#define R_C0_ErrorEPC 30 -#define C0_ERROR_EPC C0_ErrorEPC /* OBSOLETE - DO NOT USE IN NEW CODE */ - -#define M_ErrorEPC0Fields 0x00000000 -#define M_ErrorEPCRFields 0x00000000 -#define M_ErrorEPC0Fields64 UNS64Const(0x0000000000000000) -#define M_ErrorEPCRFields64 UNS64Const(0x0000000000000000) - - -/* - ************************************************************************ - * D E S A V E R E G I S T E R ( 3 1 ) * - ************************************************************************ - * - * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | // EJTAG Register Save Value | DESAVE - * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C0_DESAVE $31 -#define R_C0_DESAVE 31 - -#define M_DESAVE0Fields 0x00000000 -#define M_DESAVERFields 0x00000000 -#define M_DESAVE0Fields64 UNS64Const(0x0000000000000000) -#define M_DESAVERFields64 UNS64Const(0x0000000000000000) - - -/* - ************************************************************************* - * C P 1 R E G I S T E R D E F I N I T I O N S * - ************************************************************************* - */ - - -/* - ************************************************************************* - * H A R D W A R E F P R N A M E S * - ************************************************************************* - */ - -#define fp0 $f0 -#define fp1 $f1 -#define fp2 $f2 -#define fp3 $f3 -#define fp4 $f4 -#define fp5 $f5 -#define fp6 $f6 -#define fp7 $f7 -#define fp8 $f8 -#define fp9 $f9 -#define fp10 $f10 -#define fp11 $f11 -#define fp12 $f12 -#define fp13 $f13 -#define fp14 $f14 -#define fp15 $f15 -#define fp16 $f16 -#define fp17 $f17 -#define fp18 $f18 -#define fp19 $f19 -#define fp20 $f20 -#define fp21 $f21 -#define fp22 $f22 -#define fp23 $f23 -#define fp24 $f24 -#define fp25 $f25 -#define fp26 $f26 -#define fp27 $f27 -#define fp28 $f28 -#define fp29 $f29 -#define fp30 $f30 -#define fp31 $f31 - -/* - * The following definitions are used to convert an FPR name - * into the corresponding even or odd name, respectively. - * This is used in macro substitution in the AVPs. - */ - -#define fp1_even $f0 -#define fp3_even $f2 -#define fp5_even $f4 -#define fp7_even $f6 -#define fp9_even $f8 -#define fp11_even $f10 -#define fp13_even $f12 -#define fp15_even $f14 -#define fp17_even $f16 -#define fp19_even $f18 -#define fp21_even $f20 -#define fp23_even $f22 -#define fp25_even $f24 -#define fp27_even $f26 -#define fp29_even $f28 -#define fp31_even $f30 - -#define fp0_odd $f1 -#define fp2_odd $f3 -#define fp4_odd $f5 -#define fp6_odd $f7 -#define fp8_odd $f9 -#define fp10_odd $f11 -#define fp12_odd $f13 -#define fp14_odd $f15 -#define fp16_odd $f17 -#define fp18_odd $f19 -#define fp20_odd $f21 -#define fp22_odd $f23 -#define fp24_odd $f25 -#define fp26_odd $f27 -#define fp28_odd $f29 -#define fp30_odd $f31 - - -/* - ************************************************************************* - * H A R D W A R E F P R I N D I C E S * - ************************************************************************* - * - * These definitions provide the index (number) of the FPR, as opposed - * to the assembler register name ($n). - */ - -#define R_fp0 0 -#define R_fp1 1 -#define R_fp2 2 -#define R_fp3 3 -#define R_fp4 4 -#define R_fp5 5 -#define R_fp6 6 -#define R_fp7 7 -#define R_fp8 8 -#define R_fp9 9 -#define R_fp10 10 -#define R_fp11 11 -#define R_fp12 12 -#define R_fp13 13 -#define R_fp14 14 -#define R_fp15 15 -#define R_fp16 16 -#define R_fp17 17 -#define R_fp18 18 -#define R_fp19 19 -#define R_fp20 20 -#define R_fp21 21 -#define R_fp22 22 -#define R_fp23 23 -#define R_fp24 24 -#define R_fp25 25 -#define R_fp26 26 -#define R_fp27 27 -#define R_fp28 28 -#define R_fp29 29 -#define R_fp30 30 -#define R_fp31 31 - - -/* - ************************************************************************* - * H A R D W A R E F C R N A M E S * - ************************************************************************* - */ - -#define fc0 $0 -#define fc25 $25 -#define fc26 $26 -#define fc28 $28 -#define fc31 $31 - - -/* - ************************************************************************* - * H A R D W A R E F C R I N D I C E S * - ************************************************************************* - * - * These definitions provide the index (number) of the FCR, as opposed - * to the assembler register name ($n). - */ - -#define R_fc0 0 -#define R_fc25 25 -#define R_fc26 26 -#define R_fc28 28 -#define R_fc31 31 - - -/* - ************************************************************************* - * H A R D W A R E F C C N A M E S * - ************************************************************************* - */ - -#define cc0 $fcc0 -#define cc1 $fcc1 -#define cc2 $fcc2 -#define cc3 $fcc3 -#define cc4 $fcc4 -#define cc5 $fcc5 -#define cc6 $fcc6 -#define cc7 $fcc7 - - -/* - ************************************************************************* - * H A R D W A R E F C C I N D I C E S * - ************************************************************************* - * - * These definitions provide the index (number) of the CC, as opposed - * to the assembler register name ($n). - */ - -#define R_cc0 0 -#define R_cc1 1 -#define R_cc2 2 -#define R_cc3 3 -#define R_cc4 4 -#define R_cc5 5 -#define R_cc6 6 -#define R_cc7 7 - - -/* - ************************************************************************ - * I M P L E M E N T A T I O N R E G I S T E R * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |Reserved for Additional|3|P|D|S| Implementation| Revision | FIR - * | Configuration Bits |D|S| | | | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C1_FIR $0 -#define R_C1_FIR 0 - -#define S_FIRConfigS 16 -#define M_FIRConfigS (0x1 << S_FIRConfigS) -#define S_FIRConfigD 17 -#define M_FIRConfigD (0x1 << S_FIRConfigD) -#define S_FIRConfigPS 18 -#define M_FIRConfigPS (0x1 << S_FIRConfigPS) -#define S_FIRConfig3D 19 -#define M_FIRConfig3D (0x1 << S_FIRConfig3D) -#define M_FIRConfigAll (M_FIRConfigS|M_FIRConfigD|M_FIRConfigPS|M_FIRConfig3D) - -#define S_FIRImp 8 -#define M_FIRImp (0xff << S_FIRImp) - -#define S_FIRRev 0 -#define M_FIRRev (0xff << S_FIRRev) - -#define M_FIR0Fields 0xfff00000 -#define M_FIRRFields 0x000fffff - -/* - ************************************************************************ - * C O N D I T I O N C O D E S R E G I S T E R * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0 | CC | FCCR - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C1_FCCR $25 -#define R_C1_FCCR 25 - -#define S_FCCRCC 0 -#define M_FCCRCC (0xff << S_FCCRCC) -#define S_FCCRCC7 7 -#define M_FCCRCC7 (0x1 << S_FCCRCC7) -#define S_FCCRCC6 6 -#define M_FCCRCC6 (0x1 << S_FCCRCC6) -#define S_FCCRCC5 5 -#define M_FCCRCC5 (0x1 << S_FCCRCC5) -#define S_FCCRCC4 4 -#define M_FCCRCC4 (0x1 << S_FCCRCC4) -#define S_FCCRCC3 3 -#define M_FCCRCC3 (0x1 << S_FCCRCC3) -#define S_FCCRCC2 2 -#define M_FCCRCC2 (0x1 << S_FCCRCC2) -#define S_FCCRCC1 1 -#define M_FCCRCC1 (0x1 << S_FCCRCC1) -#define S_FCCRCC0 0 -#define M_FCCRCC0 (0x1 << S_FCCRCC0) - -#define M_FCCR0Fields 0xffffff00 -#define M_FCCRRFields 0x000000ff - - -/* - ************************************************************************ - * E X C E P T I O N S R E G I S T E R * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0 | Cause | 0 | Flags | 0 | FEXR - * | |E|V|Z|O|U|I| |V|Z|O|U|I| | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C1_FEXR $26 -#define R_C1_FEXR 26 - -#define S_FEXRExc 12 -#define M_FEXRExc (0x3f << S_FEXRExc) -#define S_FEXRExcE 17 -#define M_FEXRExcE (0x1 << S_FEXRExcE) -#define S_FEXRExcV 16 -#define M_FEXRExcV (0x1 << S_FEXRExcV) -#define S_FEXRExcZ 15 -#define M_FEXRExcZ (0x1 << S_FEXRExcZ) -#define S_FEXRExcO 14 -#define M_FEXRExcO (0x1 << S_FEXRExcO) -#define S_FEXRExcU 13 -#define M_FEXRExcU (0x1 << S_FEXRExcU) -#define S_FEXRExcI 12 -#define M_FEXRExcI (0x1 << S_FEXRExcI) - -#define S_FEXRFlg 2 -#define M_FEXRFlg (0x1f << S_FEXRFlg) -#define S_FEXRFlgV 6 -#define M_FEXRFlgV (0x1 << S_FEXRFlgV) -#define S_FEXRFlgZ 5 -#define M_FEXRFlgZ (0x1 << S_FEXRFlgZ) -#define S_FEXRFlgO 4 -#define M_FEXRFlgO (0x1 << S_FEXRFlgO) -#define S_FEXRFlgU 3 -#define M_FEXRFlgU (0x1 << S_FEXRFlgU) -#define S_FEXRFlgI 2 -#define M_FEXRFlgI (0x1 << S_FEXRFlgI) - -#define M_FEXR0Fields 0xfffc0f83 -#define M_FEXRRFields 0x00000000 - - -/* - ************************************************************************ - * E N A B L E S R E G I S T E R * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0 | Enables | 0 |F|RM | FENR - * | |V|Z|O|U|I| |S| | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C1_FENR $28 -#define R_C1_FENR 28 - -#define S_FENREna 7 -#define M_FENREna (0x1f << S_FENREna) -#define S_FENREnaV 11 -#define M_FENREnaV (0x1 << S_FENREnaV) -#define S_FENREnaZ 10 -#define M_FENREnaZ (0x1 << S_FENREnaZ) -#define S_FENREnaO 9 -#define M_FENREnaO (0x1 << S_FENREnaO) -#define S_FENREnaU 8 -#define M_FENREnaU (0x1 << S_FENREnaU) -#define S_FENREnaI 7 -#define M_FENREnaI (0x1 << S_FENREnaI) - -#define S_FENRFS 2 -#define M_FENRFS (0x1 << S_FENRFS) - -#define S_FENRRM 0 -#define M_FENRRM (0x3 << S_FENRRM) - -#define M_FENR0Fields 0xfffff078 -#define M_FENRRFields 0x00000000 - - -/* - ************************************************************************ - * C O N T R O L / S T A T U S R E G I S T E R * - ************************************************************************ - * - * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | FCC |F|C|Imp| 0 | Cause | Enables | Flags | RM| FCSR - * |7|6|5|4|3|2|1|S|C| | |E|V|Z|O|U|I|V|Z|O|U|I|V|Z|O|U|I| | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - -#define C1_FCSR $31 -#define R_C1_FCSR 31 - -#define S_FCSRFCC7_1 25 /* Floating point condition codes 7..1 (R/W) */ -#define M_FCSRFCC7_1 (0x7f << S_FCSRFCC7_1) -#define S_FCSRCC7 31 -#define M_FCSRCC7 (0x1 << S_FCSRCC7) -#define S_FCSRCC6 30 -#define M_FCSRCC6 (0x1 << S_FCSRCC6) -#define S_FCSRCC5 29 -#define M_FCSRCC5 (0x1 << S_FCSRCC5) -#define S_FCSRCC4 28 -#define M_FCSRCC4 (0x1 << S_FCSRCC4) -#define S_FCSRCC3 27 -#define M_FCSRCC3 (0x1 << S_FCSRCC3) -#define S_FCSRCC2 26 -#define M_FCSRCC2 (0x1 << S_FCSRCC2) -#define S_FCSRCC1 25 -#define M_FCSRCC1 (0x1 << S_FCSRCC1) - -#define S_FCSRFS 24 /* Flush denorms to zero (R/W) */ -#define M_FCSRFS (0x1 << S_FCSRFS) - -#define S_FCSRCC0 23 /* Floating point condition code 0 (R/W) */ -#define M_FCSRCC0 (0x1 << S_FCSRCC0) -#define S_FCSRCC S_FCSRCC0 -#define M_FCSRCC M_FCSRCC0 - -#define S_FCSRImpl 21 /* Implementation-specific control bits (R/W) */ -#define M_FCSRImpl (0x3 << S_FCSRImpl) - -#define S_FCSRExc 12 /* Exception cause (R/W) */ -#define M_FCSRExc (0x3f << S_FCSRExc) -#define S_FCSRExcE 17 -#define M_FCSRExcE (0x1 << S_FCSRExcE) -#define S_FCSRExcV 16 -#define M_FCSRExcV (0x1 << S_FCSRExcV) -#define S_FCSRExcZ 15 -#define M_FCSRExcZ (0x1 << S_FCSRExcZ) -#define S_FCSRExcO 14 -#define M_FCSRExcO (0x1 << S_FCSRExcO) -#define S_FCSRExcU 13 -#define M_FCSRExcU (0x1 << S_FCSRExcU) -#define S_FCSRExcI 12 -#define M_FCSRExcI (0x1 << S_FCSRExcI) - -#define S_FCSREna 7 /* Exception enable (R/W) */ -#define M_FCSREna (0x1f << S_FCSREna) -#define S_FCSREnaV 11 -#define M_FCSREnaV (0x1 << S_FCSREnaV) -#define S_FCSREnaZ 10 -#define M_FCSREnaZ (0x1 << S_FCSREnaZ) -#define S_FCSREnaO 9 -#define M_FCSREnaO (0x1 << S_FCSREnaO) -#define S_FCSREnaU 8 -#define M_FCSREnaU (0x1 << S_FCSREnaU) -#define S_FCSREnaI 7 -#define M_FCSREnaI (0x1 << S_FCSREnaI) - -#define S_FCSRFlg 2 /* Exception flags (R/W) */ -#define M_FCSRFlg (0x1f << S_FCSRFlg) -#define S_FCSRFlgV 6 -#define M_FCSRFlgV (0x1 << S_FCSRFlgV) -#define S_FCSRFlgZ 5 -#define M_FCSRFlgZ (0x1 << S_FCSRFlgZ) -#define S_FCSRFlgO 4 -#define M_FCSRFlgO (0x1 << S_FCSRFlgO) -#define S_FCSRFlgU 3 -#define M_FCSRFlgU (0x1 << S_FCSRFlgU) -#define S_FCSRFlgI 2 -#define M_FCSRFlgI (0x1 << S_FCSRFlgI) - -#define S_FCSRRM 0 /* Rounding mode (R/W) */ -#define M_FCSRRM (0x3 << S_FCSRRM) - -#define M_FCSR0Fields 0x001c0000 -#define M_FCSRRFields 0x00000000 - -/* - * Values in the rounding mode field (of both FCSR and FCCR) - */ -#define K_FCSRRM_RN 0 -#define K_FCSRRM_RZ 1 -#define K_FCSRRM_RP 2 -#define K_FCSRRM_RM 3 - - -/* ********************************************************************* */ -/* Interface function definition */ - - -/* ********************************************************************* */ - -#endif /* __ARCHDEFS_H__ */ diff --git a/sdk-modifications/include/bit_ops.h b/sdk-modifications/include/bit_ops.h deleted file mode 100644 index f823db7..0000000 --- a/sdk-modifications/include/bit_ops.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - bit_ops.h - Functions for dealing with conversion of data between types - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef _BIT_OPS_H -#define _BIT_OPS_H - -/*----------------------------------------------------------------- -Functions to deal with little endian values stored in u8 arrays ------------------------------------------------------------------*/ -static inline u16 u8array_to_u16 (const u8* item, int offset) { - return ( item[offset] | (item[offset + 1] << 8)); -} - -static inline u32 u8array_to_u32 (const u8* item, int offset) { - return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); -} - -static inline void u16_to_u8array (u8* item, int offset, u16 value) { - item[offset] = (u8)value; - item[offset + 1] = (u8)(value >> 8); -} - -static inline void u32_to_u8array (u8* item, int offset, u32 value) { - item[offset] = (u8)value; - item[offset + 1] = (u8)(value >> 8); - item[offset + 2] = (u8)(value >> 16); - item[offset + 3] = (u8)(value >> 24); -} - -#endif // _BIT_OPS_H diff --git a/sdk-modifications/include/console.h b/sdk-modifications/include/console.h deleted file mode 100644 index f6d74a4..0000000 --- a/sdk-modifications/include/console.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __CONSOLE_H__ -#define __CONSOLE_H__ -#include "ds2io.h" - -extern int ConsoleInit(unsigned short front_color, unsigned short background_color, enum SCREEN_ID screen, unsigned int buf_size); - -extern int cprintf(const char *format, ...); - -#endif //__CONSOLE_H__ diff --git a/sdk-modifications/include/directory.h b/sdk-modifications/include/directory.h deleted file mode 100644 index 00046a9..0000000 --- a/sdk-modifications/include/directory.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - directory.h - Reading, writing and manipulation of the directory structure on - a FAT partition - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef _DIRECTORY_H -#define _DIRECTORY_H - -#include - -#include "fs_common.h" -#include "partition.h" - -#define DIR_ENTRY_DATA_SIZE 0x20 -#define MAX_FILENAME_LENGTH 256 -#define MAX_ALIAS_LENGTH 13 -#define LFN_ENTRY_LENGTH 13 -#define FAT16_ROOT_DIR_CLUSTER 0 - -#define DIR_SEPARATOR '/' - -// File attributes -#define ATTRIB_ARCH 0x20 // Archive -#define ATTRIB_DIR 0x10 // Directory -#define ATTRIB_LFN 0x0F // Long file name -#define ATTRIB_VOL 0x08 // Volume -#define ATTRIB_SYS 0x04 // System -#define ATTRIB_HID 0x02 // Hidden -#define ATTRIB_RO 0x01 // Read only - -typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE; - -typedef struct { - u32 cluster; - u32 sector; - s32 offset; -} DIR_ENTRY_POSITION; - -typedef struct { - u8 entryData[DIR_ENTRY_DATA_SIZE]; - DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN - DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry - char d_name[MAX_FILENAME_LENGTH + MAX_FILENAME_LENGTH*2]; //Store name string using UTF8 coding - //u16 unicodeFilename[MAX_FILENAME_LENGTH]; -} DIR_ENTRY; - -// Directory entry offsets -enum DIR_ENTRY_offset { - DIR_ENTRY_name = 0x00, - DIR_ENTRY_extension = 0x08, - DIR_ENTRY_attributes = 0x0B, - DIR_ENTRY_reserved = 0x0C, - DIR_ENTRY_cTime_ms = 0x0D, - DIR_ENTRY_cTime = 0x0E, - DIR_ENTRY_cDate = 0x10, - DIR_ENTRY_aDate = 0x12, - DIR_ENTRY_clusterHigh = 0x14, - DIR_ENTRY_mTime = 0x16, - DIR_ENTRY_mDate = 0x18, - DIR_ENTRY_cluster = 0x1A, - DIR_ENTRY_fileSize = 0x1C -}; - -/* -Returns true if the file specified by entry is a directory -*/ -static inline bool _FAT_directory_isDirectory (DIR_ENTRY* entry) { - return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) != 0); -} - -static inline bool _FAT_directory_isWritable (DIR_ENTRY* entry) { - return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO) == 0); -} - -static inline bool _FAT_directory_isDot (DIR_ENTRY* entry) { - return ((entry->d_name[0] == '.') && ((entry->d_name[1] == '\0') || - ((entry->d_name[1] == '.') && entry->d_name[2] == '\0'))); -} - -/* -Reads the first directory entry from the directory starting at dirCluster -Places result in entry -entry will be destroyed even if no directory entry is found -Returns true on success, false on failure -*/ -bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); - -/* -Reads the next directory entry after the one already pointed to by entry -Places result in entry -entry will be destroyed even if no directory entry is found -Returns true on success, false on failure -*/ -bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry); - -/* -Gets the directory entry corrsponding to the supplied path -entry will be destroyed even if no directory entry is found -pathEnd specifies the end of the path string, for cutting strings short if needed - specify NULL to use the full length of path - pathEnd is only a suggestion, and the path string will be searched up until the next PATH_SEPARATOR - after pathEND. -Returns true on success, false on failure -*/ -bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd); - -/* -Changes the current directory to the one specified by path -Returns true on success, false on failure -*/ -bool _FAT_directory_chdir (PARTITION* partition, const char* path); - -/* -Removes the directory entry specified by entry -Assumes that entry is valid -Returns true on success, false on failure -*/ -bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry); - -/* -Add a directory entry to the directory specified by dirCluster -The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are -updated with the new directory entry position and alias. -Returns true on success, false on failure -*/ -bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); - -/* -Get the start cluster of a file from it's entry data -*/ -u32 _FAT_directory_entryGetCluster (const u8* entryData); - -/* -Fill in the file name and entry data of DIR_ENTRY* entry. -Assumes that the entry's dataStart and dataEnd are correct -Returns true on success, false on failure -*/ -bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry); - -/* -Fill in a stat struct based on a file entry -*/ -void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st); - -#endif // _DIRECTORY_H diff --git a/sdk-modifications/include/ds2_cpu.h b/sdk-modifications/include/ds2_cpu.h deleted file mode 100644 index d4b7144..0000000 --- a/sdk-modifications/include/ds2_cpu.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __DS2_CPU_H__ -#define __DS2_CPU_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//exception handle - - -//cache operationr -//invalidate instruction cache -extern void __icache_invalidate_all(void); - -//invalidate data cache -extern void __dcache_invalidate_all(void); - -//data cache writeback -extern void __dcache_writeback_all(void); - -//data cache writeback and invalidate -extern void _dcache_wback_inv(unsigned long addr, unsigned long size); - - -//interruption operation -//clear CPU's interrupt state and enable global interrupt -extern void sti(void); - -//disable global interrupt -extern void cli(void); - -//disable global interrupt and store the global interrupt state -//return: interrupt state -extern unsigned int spin_lock_irqsave(void); - -//restore global interrupt state -extern void spin_unlock_irqrestore(unsigned int val); - - -//CPU frequence -//There are 14 levels, 0 to 13, 13 level have the highest clock frequence -extern int ds2_setCPUclocklevel(unsigned int num); - -//print colock frequence CPU -extern void printf_clock(void); - -//delay n us -extern void udelay(unsigned int usec); - -//delay n ms -extern void mdelay(unsigned int msec); - -#ifdef __cplusplus -} -#endif - -#endif //__DS2_CPU_H__ diff --git a/sdk-modifications/include/ds2_cpuclock.h b/sdk-modifications/include/ds2_cpuclock.h deleted file mode 100644 index 058ba99..0000000 --- a/sdk-modifications/include/ds2_cpuclock.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _DS2_CPUCLOCK_H__ -#define _DS2_CPUCLOCK_H__ - - -#define CPU_MAX_LEVEL_EX 18 - -#ifdef __cplusplus -extern "C" { -#endif - -extern int ds2_getCPUClock(void); -extern int ds2_setCPULevel(unsigned int level); -extern void ds2_udelay(unsigned int usec); -extern void ds2_mdelay(unsigned int msec); - -//#define ds2_setCPUclocklevel ds2_setCPULevel - -#ifdef __cplusplus -} -#endif - -#endif //__DS2_CPUCLOCK_H__ diff --git a/sdk-modifications/include/ds2_dma.h b/sdk-modifications/include/ds2_dma.h deleted file mode 100644 index 491df0e..0000000 --- a/sdk-modifications/include/ds2_dma.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __DMA_H__ -#define __DMA_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//register a DMA transfer request -//ch: channel id request, there are 6 channles, -//irq_handler: the DMA interruption handle -//arg: argument to the handle -//mode: DMA mode, such as port width, address increased/fixed, and so on -//type: DMA request type -extern int dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg, - unsigned int mode, unsigned int type); - -//start DMA transfer, must request a DMA first -//ch: channel id -//srcAddr: DMA source address -//dstAddr: DMA destination address -//count: DMA transfer count, the total bytes due the mode in dma_request -extern void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr, - unsigned int count); - -//Stop DMA transfer -extern void dma_stop(int ch); - -//Wait DMA transfer over -extern int dma_wait_finish(int ch); - - -/* - * Copy 'size' bytes from src to dest, in blocks of 32 bytes. - * size is in bytes and must be a multiple of 32. - * Both src and dest must be aligned to 32 bytes. - * Returns 0 on failure, non-zero on success. - */ -extern int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size); -// Blocks of 16 bytes, aligned to 16 bytes -extern int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size); -// Blocks of 4 bytes, aligned to 4 bytes -extern int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size); -// Blocks of 2 bytes, aligned to 2 bytes -extern int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size); -extern int dma_isBusy(int ch); -extern int dma_isFree(int ch); -extern int dma_getFree(void); - -#ifdef __cplusplus -} -#endif - -#endif //__DMA_H__ - diff --git a/sdk-modifications/include/ds2_excpt.h b/sdk-modifications/include/ds2_excpt.h deleted file mode 100644 index 08fe77e..0000000 --- a/sdk-modifications/include/ds2_excpt.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __DS2_EXCPT_H__ -#define __DS2_EXCPT_H__ - -#include -extern unsigned int Process_RA; -extern unsigned int Process_SP; - -#define SAVE_PROCESS_REGISTER() \ - do{ unsigned int sr ; \ - sr = read_c0_status(); \ - write_c0_status((sr&(~1))); \ - __asm__ __volatile__( \ - "sw $31,0x00(%0)\n\t" \ - "sw $29,0x00(%1)\n\t" \ - : \ - : "r" (&Process_RA),"r" (&Process_SP)); \ - write_c0_status(sr); \ - }while(0) - -#define RESTORE_PROCESS_REGISTER() \ - __asm__ __volatile__( \ - "lw $31,0x00(%0)\n\t" \ - "lw $29,0x00(%1)\n\t" \ - : \ - : "r" (&Process_RA),"r" (&Process_SP)) - -inline static void excpt_exit(x) \ -{ - unsigned int sr; - sr = read_c0_status(); - write_c0_status(sr & (~1)); - __asm__ __volatile__("lw $2,0x00(%0)\n\t" :: "r" (&x)); - RESTORE_PROCESS_REGISTER(); - write_c0_status(sr); - __asm__ __volatile__( - "jr $31\n\t" - "nop\n\t" - ); -} - -typedef void (*PFun_Exception_Handler)(unsigned int); - -//Setup handle to process the exception -//except_index: exception number -//except_handle: handle to process the exception -//arg: argument to the handle -extern int Setup_except_handle(unsigned int except_index, PFun_Exception_Handler except_handle, unsigned int arg); - -//Add a write watched exception, if the CPU write the addr, a exception will -// generated, the watch exception's number is 23 -//addr: address to be watched -extern void add_watch_point(unsigned int addr); - -#endif //__DS2_EXCPT_H__ - diff --git a/sdk-modifications/include/ds2_fcntl.h b/sdk-modifications/include/ds2_fcntl.h deleted file mode 100644 index 2c69221..0000000 --- a/sdk-modifications/include/ds2_fcntl.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __libc_fcntl_h__ -#define __libc_fcntl_h__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define O_RDONLY (1 << 0) -#define O_WRONLY (2 << 0) -#define O_RDWR (3 << 0) -#define O_APPEND (1 << 2) -#define O_CREAT (1 << 3) -#define O_DSYNC (1 << 4) -#define O_EXCL (1 << 5) -#define O_NOCTTY (1 << 6) -#define O_NONBLOCK (1 << 7) -#define O_RSYNC (1 << 8) -#define O_SYNC (1 << 9) -#define O_TRUNC (1 << 10) -#define O_CREATE O_CREAT - -#define O_ACCMODE 0x3 - -#define F_CLOEXEC (1 << 11) - -#define F_DUPFD 1 -#define F_GETFD 2 -#define F_SETFD 3 -#define F_GETFL 4 -#define F_SETFL 5 -#define F_GETLK 6 -#define F_SETLK 7 -#define F_SETLKW 8 -#define F_GETOWN 9 -#define F_SETOWN 10 -#define _F_LAST F_SETOWN - -#define _F_FILE_DESC (F_CLOEXEC) -#define _O_FILE_CREATE (O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC) -#define _O_FILE_STATUS (O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC) -#define _O_UNSUPPORTED (0) - -extern int open(const char* path, int oflag, ...); -extern int fcntl(int fildes, int cmd, ...); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/sdk-modifications/include/ds2_malloc.h b/sdk-modifications/include/ds2_malloc.h deleted file mode 100644 index 5f158f7..0000000 --- a/sdk-modifications/include/ds2_malloc.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __DS2_MALLOC_H__ -#define __DS2_MALLOC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -extern void heapInit(unsigned int start, unsigned int end); - -extern void* Drv_alloc(unsigned int nbytes); -extern void Drv_deAlloc(void* address); -extern void* Drv_realloc(void* address, unsigned int nbytes); -extern void* Drv_calloc(unsigned int nmem, unsigned int size); - -#ifdef __cplusplus -} -#endif - -#define malloc Drv_alloc -#define calloc Drv_calloc -#define realloc Drv_realloc -#define free Drv_deAlloc - -#ifdef __cplusplus -#include -inline void* operator new ( size_t s ) { return malloc( s ); } -inline void* operator new[] ( size_t s ) { return malloc( s ); } -inline void operator delete ( void* p ) { free( p ); } -inline void operator delete[] ( void* p ) { free( p ); } -#endif - -#endif //__DS2_MALLOC_H__ diff --git a/sdk-modifications/include/ds2_mmc_api.h b/sdk-modifications/include/ds2_mmc_api.h deleted file mode 100644 index 28e75ef..0000000 --- a/sdk-modifications/include/ds2_mmc_api.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __MMC_API_H__ -#define __MMC_API_H__ - -/* Error codes */ -enum mmc_result_t { - MMC_NO_RESPONSE = -1, - MMC_NO_ERROR = 0, - MMC_ERROR_OUT_OF_RANGE, - MMC_ERROR_ADDRESS, - MMC_ERROR_BLOCK_LEN, - MMC_ERROR_ERASE_SEQ, - MMC_ERROR_ERASE_PARAM, - MMC_ERROR_WP_VIOLATION, - MMC_ERROR_CARD_IS_LOCKED, - MMC_ERROR_LOCK_UNLOCK_FAILED, - MMC_ERROR_COM_CRC, - MMC_ERROR_ILLEGAL_COMMAND, - MMC_ERROR_CARD_ECC_FAILED, - MMC_ERROR_CC, - MMC_ERROR_GENERAL, - MMC_ERROR_UNDERRUN, - MMC_ERROR_OVERRUN, - MMC_ERROR_CID_CSD_OVERWRITE, - MMC_ERROR_STATE_MISMATCH, - MMC_ERROR_HEADER_MISMATCH, - MMC_ERROR_TIMEOUT, - MMC_ERROR_CRC, - MMC_ERROR_DRIVER_FAILURE, -}; - - -/* Get card's sectors*/ - -extern unsigned int MMC_GetSize(void); - - -/* initialize MMC/SD card */ -extern int MMC_Initialize(void); - -/* read a single block from MMC/SD card */ -extern int MMC_ReadBlock(unsigned int blockaddr, unsigned char *recbuf); - -/* read multi blocks from MMC/SD card */ -extern int MMC_ReadMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); - -/* write a block to MMC/SD card */ -extern int MMC_WriteBlock(unsigned int blockaddr, unsigned char *recbuf); - -/* write multi blocks to MMC/SD card */ -extern int MMC_WriteMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); - -/* detect MMC/SD card */ -extern int MMC_DetectStatus(void); - -#endif /* __MMC_API_H__ */ - diff --git a/sdk-modifications/include/ds2_timer.h b/sdk-modifications/include/ds2_timer.h deleted file mode 100644 index 3e5c3bc..0000000 --- a/sdk-modifications/include/ds2_timer.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __DS2_TIMER_H__ -#define __DS2_TIMER_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* -* Function: register a timer interruptting periodly -* channel: timer id, from 0 to 1 -* period: interrupt period, unit is us, period < 2.5s -* handle: interrupt handle, if handle = NULL, the timer will not generate interrupt -* arg: argument to the interrupt handle -*/ -extern int initTimer(unsigned int channel, unsigned int period, void (*handle)(unsigned int), int arg); - -/* -* Function: set the timer run -*/ -extern void runTimer(unsigned int channel); - -/* -* Function: stop timer -*/ -extern void stopTimer(unsigned int channel); - -/* -* Function: reset timer -*/ -extern void resetTimer(unsigned int channel); - -/* -* Function: read value of timer -*/ -extern unsigned int readTimer(unsigned int channel); - - -#define SYSTIME_UNIT 42667 -/* -* Function: get the elapsed time since DS2 started -* it's uint is 42.667us, it will overflow after 50.9 horus since DS2 started -*/ -extern unsigned int getSysTime(void); - -#ifdef __cplusplus -} -#endif - -#endif //__DS2_TIMER_H__ - diff --git a/sdk-modifications/include/ds2_types.h b/sdk-modifications/include/ds2_types.h deleted file mode 100644 index 3ec59bf..0000000 --- a/sdk-modifications/include/ds2_types.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __DS2_TYPES_H__ -#define __DS2_TYPES_H__ - -#ifndef u8 -#define u8 unsigned char -#endif - -#ifndef s8 -#define s8 char -#endif - -#ifndef u16 -#define u16 unsigned short -#endif - -#ifndef s16 -#define s16 short -#endif - -#ifndef u32 -#define u32 unsigned int -#endif - -#ifndef s32 -#define s32 int -#endif - -#ifndef u64 -#define u64 unsigned long long -#endif - -#ifndef s64 -#define s64 long long -#endif - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#endif //__DS2_TYPES_H__ diff --git a/sdk-modifications/include/ds2io.h b/sdk-modifications/include/ds2io.h deleted file mode 100644 index 1d3be5b..0000000 --- a/sdk-modifications/include/ds2io.h +++ /dev/null @@ -1,285 +0,0 @@ -#ifndef __DS2IO_H__ -#define __DS2IO_H__ - -#ifndef BIT -#define BIT(a) (1< -#include "partition.h" -#include "directory.h" -#include "file_allocation_table.h" -//#include "unicode/unicode.h" -#include "fatdir_ex.h" -#include "fatfile_ex.h" - -//typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM} PARTITION_INTERFACE; - -struct IO_INTERFACE_STRUCT ; - -/* -Initialise any inserted block-devices. -Add the fat device driver to the devoptab, making it available for standard file functions. -cacheSize: The number of pages to allocate for each inserted block-device -setAsDefaultDevice: if true, make this the default device driver for file operations -*/ -bool fatInit (u32 cacheSize, bool setAsDefaultDevice); - -/* -Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. -*/ -bool fatInitDefault (void); - -/* -Special initialize for RPG card -*/ -bool fatInitRPG (void); - -/* -Mount the device specified by partitionNumber -PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice -PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice -*/ -bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize); - -/* -Mount a partition on a custom device -*/ -bool fatMountCustomInterface (struct IO_INTERFACE_STRUCT* device, u32 cacheSize); - -/* -Unmount the partition specified by partitionNumber -If there are open files, it will fail -*/ -bool fatUnmount (PARTITION_INTERFACE partitionNumber); - - -/* -Forcibly unmount the partition specified by partitionNumber -Any open files on the partition will become invalid -The cache will be invalidated, and any unflushed writes will be lost -*/ -bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber); - -/* -Set the default device for access by fat: and fat0: -PD_DEFAULT is unallowed. -Doesn't do anything useful on GBA, since there is only one device -*/ -bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber); - -#ifdef __cplusplus -} -#endif - -#endif // _LIBFAT_H diff --git a/sdk-modifications/include/fatdir.h b/sdk-modifications/include/fatdir.h deleted file mode 100644 index 529e401..0000000 --- a/sdk-modifications/include/fatdir.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - fatdir.h - - Functions used by the newlib disc stubs to interface with - this library - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-08-13 - Chishm - * Moved all externally visible directory related functions to fatdir - * Added _FAT_mkdir_r - - 2006-08-14 - Chishm - * Added directory iterator functions - - 2007-01-10 - Chishm - * Updated directory iterator functions for DevkitPro r20 -*/ - - -#ifndef _FATDIR_H -#define _FATDIR_H - -//#include -#include -//#include -#include "fs_common.h" -#include "directory.h" - -typedef struct { - PARTITION* partition; - DIR_ENTRY currentEntry; - u32 startCluster; - u32 posEntry; - bool inUse; - bool validEntry; -} DIR_STATE_STRUCT; - -extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); - -extern int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); - -extern int _FAT_unlink_r (struct _reent *r, const char *name); - -extern int _FAT_chdir_r (struct _reent *r, const char *name); - -extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); - -extern int _FAT_mkdir_r (struct _reent *r, const char *path, int mode); - -/* -Directory iterator functions -*/ -extern DIR_STATE_STRUCT* _FAT_diropen_r(struct _reent *r, DIR_STATE_STRUCT *dirState, const char *path); -extern int _FAT_dirreset_r (struct _reent *r, DIR_STATE_STRUCT *dirState); -extern int _FAT_dirnext_r (struct _reent *r, DIR_STATE_STRUCT *dirState, struct stat *filestat); -extern int _FAT_dirclose_r (struct _reent *r, DIR_STATE_STRUCT *dirState); - - -#endif // _FATDIR_H diff --git a/sdk-modifications/include/fatdir_ex.h b/sdk-modifications/include/fatdir_ex.h deleted file mode 100644 index fbac46f..0000000 --- a/sdk-modifications/include/fatdir_ex.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _FATDIR_EX_H_ -#define _FATDIR_EX_H_ - -#include "fatdir.h" - -#ifdef __cplusplus -extern "C" { -#endif - -int dirnextl (DIR_ITER *dirState, char *filename, char *longFilename, struct stat *filestat); -int renamex( const char *oldName, const char *newName ); - -#ifdef __cplusplus -} -#endif - - -#endif//_FATDIR_EX_H_ diff --git a/sdk-modifications/include/fatfile.h b/sdk-modifications/include/fatfile.h deleted file mode 100644 index 4869562..0000000 --- a/sdk-modifications/include/fatfile.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - fatfile.h - - Functions used by the newlib disc stubs to interface with - this library - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-07-17 - Chishm - * Made all path inputs const char* - * Added _FAT_rename_r - - 2006-07-24 - Chishm - * Removed padding workaround from FILE_STRUCT - - 2006-08-13 - Chishm - * Moved all externally visible directory related functions to fatdir -*/ - - -#ifndef _FATFILE_H -#define _FATFILE_H - -//#include -#include - -#include "fs_common.h" -#include "partition.h" -#include "directory.h" - -typedef struct { - u32 cluster; - u32 sector; - s32 byte; -} FILE_POSITION; - -typedef struct { - int fd; - u32 filesize; - u32 startCluster; - u32 currentPosition; - FILE_POSITION rwPosition; - FILE_POSITION appendPosition; - bool read; - bool write; - bool append; - bool inUse; - PARTITION* partition; - DIR_ENTRY_POSITION dirEntryStart; // Points to the start of the LFN entries of a file, or the alias for no LFN - DIR_ENTRY_POSITION dirEntryEnd; // Always points to the file's alias entry -} FILE_STRUCT; - -extern int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags); - -extern int _FAT_close_r (struct _reent *r, int fd); - -extern int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len); - -extern int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len); - -extern int _FAT_seek_r (struct _reent *r, int fd,int pos, int dir); - -extern int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st); - -#endif // _FATFILE_H diff --git a/sdk-modifications/include/fatfile_ex.h b/sdk-modifications/include/fatfile_ex.h deleted file mode 100644 index c434b63..0000000 --- a/sdk-modifications/include/fatfile_ex.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _FATFILE_EX_H_ -#define _FATFILE_EX_H_ - -#include -#include "fatfile.h" - -#ifdef __cplusplus -extern "C" { -#endif - -int freadex( void * buffer, int _size, int _n, FILE * f ); -int fwritex( const void * buffer, int _size, int _n, FILE * f ); - -#ifdef __cplusplus -} -#endif - - -#endif//_FATFILE_EX_H_ diff --git a/sdk-modifications/include/file_allocation_table.h b/sdk-modifications/include/file_allocation_table.h deleted file mode 100644 index 4fb4149..0000000 --- a/sdk-modifications/include/file_allocation_table.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - file_allocation_table.h - Reading, writing and manipulation of the FAT structure on - a FAT partition - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release - - 2006-10-01 - Chishm - * Added _FAT_fat_linkFreeClusterCleared to clear a cluster when it is allocated -*/ - -#ifndef _FAT_H -#define _FAT_H - -#include "fs_common.h" -#include "partition.h" - -#define CLUSTER_EOF_16 0xFFFF -#define CLUSTER_EOF 0x0FFFFFFF -#define CLUSTER_FREE 0x0000 -#define CLUSTER_FIRST 0x0002 - -#define CLUSTERS_PER_FAT12 4085 -#define CLUSTERS_PER_FAT16 65525 - - -u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster); - -u32 _FAT_fat_linkFreeCluster(PARTITION* partition, u32 cluster); -u32 _FAT_fat_linkFreeClusterCleared (PARTITION* partition, u32 cluster); - -bool _FAT_fat_clearLinks (PARTITION* partition, u32 cluster); - -u32 _FAT_fat_lastCluster (PARTITION* partition, u32 cluster); - -static inline u32 _FAT_fat_clusterToSector (PARTITION* partition, u32 cluster) { - return (cluster >= 2) ? ((cluster - 2) * partition->sectorsPerCluster) + partition->dataStart : partition->rootDirStart; -} - -#endif // _FAT_H diff --git a/sdk-modifications/include/filetime.h b/sdk-modifications/include/filetime.h deleted file mode 100644 index fa651a7..0000000 --- a/sdk-modifications/include/filetime.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - filetime.h - Conversion of file time and date values to various other types - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef _FILETIME_H -#define _FILETIME_H - -#include "fs_common.h" -#include - -u16 _FAT_filetime_getTimeFromRTC (void); -u16 _FAT_filetime_getDateFromRTC (void); - -time_t _FAT_filetime_to_time_t (u16 time, u16 date); - - -#endif // _FILETIME_H diff --git a/sdk-modifications/include/fs_api.h b/sdk-modifications/include/fs_api.h deleted file mode 100644 index b3431b6..0000000 --- a/sdk-modifications/include/fs_api.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef __FS_API_H__ -#define __FS_API_H__ -//v1.0 - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sys/stat.h" -#include "fatfile.h" -#include "fatdir.h" - - -#define mode_t unsigned int -#define size_t unsigned int - -extern int fat_init(void); - -extern FILE_STRUCT* fat_fopen(const char *file, const char *mode); - -extern size_t fat_fread(void *buf, size_t size, size_t count, FILE_STRUCT *fp); - -extern size_t fat_fwrite(const void *buf, size_t size, size_t count, FILE_STRUCT *fp); - -extern int fat_fclose(FILE_STRUCT *fp); - -extern int fat_fseek(FILE_STRUCT *fp, long offset, int whence); - -extern long fat_ftell(FILE_STRUCT *fp); - -extern int fat_feof(FILE_STRUCT *fp); - -extern int fat_ferror(FILE_STRUCT *fp); - -extern void fat_clearerr(FILE_STRUCT *fp); - -extern int fat_fflush(FILE_STRUCT *fp); - -extern int fat_fgetc(FILE_STRUCT *fp); - -extern char* fat_fgets(char *buf, int n, FILE_STRUCT *fp); - -extern int fat_fputc(int ch, FILE_STRUCT *fp); - -extern int fat_fputs(const char *s, FILE_STRUCT *fp); - -extern int fat_remove(const char *filename); - -extern int fat_rename(const char *oldName, const char *newName); - -extern int fat_setHidden(const char *name, unsigned char hide); - -extern int fat_isHidden(struct stat *st); - -extern int fat_getShortName(const char *fullName, char *outName); - -extern void fat_rewind(FILE_STRUCT *fp); - -extern int fat_fstat(int fildes, struct stat *buf); - -extern int fat_fprintf(void* fp, const char *format, ...); - -extern int fat_fscanf(FILE_STRUCT *fp, const char *format, ...); - -extern DIR_STATE_STRUCT* fat_opendir(const char *name); - -extern DIR_ENTRY* fat_readdir(DIR_STATE_STRUCT *dirp); - -extern long fat_telldir(DIR_STATE_STRUCT *dirp); - -extern void fat_seekdir(DIR_STATE_STRUCT *dirp, long int loc); - -extern int fat_closedir(DIR_STATE_STRUCT *dirp); - -extern int fat_chdir(const char *path); - -extern char* fat_getcwd(char *buf, size_t size); - -extern int fat_mkdir(const char *path, mode_t mode); - -extern int fat_rmdir(const char *path); - -extern int fat_lstat(const char *path, struct stat *buf); - -extern DIR_ENTRY* fat_readdir_ex(DIR_STATE_STRUCT *dirp, struct stat *statbuf); - -#ifndef SEEK_SET -#define SEEK_SET 0 /* Seek from beginning of file. */ -#endif - -#ifndef SEEK_CUR -#define SEEK_CUR 1 /* Seek from current position. */ -#endif - -#ifndef SEEK_END -#define SEEK_END 2 /* Seek from end of file. */ -#endif - -//#define S_ISDIR(st) (st.st_mode & S_IFDIR) - -#define FILE FILE_STRUCT -#define fopen fat_fopen -#define fread fat_fread -#define fwrite fat_fwrite -#define fclose fat_fclose -#define fgets fat_fgets -#define fseek fat_fseek -#define ftell fat_ftell -#define feof fat_feof -#define ferror fat_ferror -#define fclearerr fat_clearerr -#define fflush fat_fflush -#define fgetc fat_fgetc -#define fgets fat_fgets -#define fputc fat_fputc -#define fputs fat_fputs -#define fprintf fat_fprintf -#define fscanf fat_fscanf -#define remove fat_remove - -#define DIR DIR_STATE_STRUCT -#define dirent DIR_ENTRY -#define opendir fat_opendir -#define readdir fat_readdir -#define telldir fat_telldir -#define seekdir fat_seekdir -#define closedir fat_closedir -#define chdir fat_chdir -#define getcwd fat_getcwd -#define mkdir fat_mkdir -#define rmdir fat_rmdir - -#define lstat fat_lstat -#define fstat fat_fstat - -#define S_ISHID(st_mode) ((st_mode & S_IHIDDEN) != 0) - -//the extended version of readdir_ex -#define readdir_ex fat_readdir_ex - -#define MAX_PATH 512 -#define MAX_FILE 512 - -//Misc function -extern bool fat_getDiskSpaceInfo( char * diskName, unsigned int *total, unsigned int *used, unsigned int *freeSpace ); - -#ifdef __cplusplus -} -#endif - -#endif //__FS_API_H__ diff --git a/sdk-modifications/include/fs_cache.h b/sdk-modifications/include/fs_cache.h deleted file mode 100644 index b0ab9be..0000000 --- a/sdk-modifications/include/fs_cache.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - cache.h - The cache is not visible to the user. It should be flushed - when any file is closed or changes are made to the filesystem. - - This cache implements a least-used-page replacement policy. This will - distribute sectors evenly over the pages, so if less than the maximum - pages are used at once, they should all eventually remain in the cache. - This also has the benefit of throwing out old sectors, so as not to keep - too many stale pages around. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef _CACHE_H -#define _CACHE_H - -#include "fs_common.h" -#include "disc_io/disc_io.h" - -#define CACHE_PAGE_SIZE BYTES_PER_READ - -typedef struct { - u32 sector; - u32 count; - bool dirty; -} CACHE_ENTRY; - -typedef struct { - const IO_INTERFACE* disc; - u32 numberOfPages; - CACHE_ENTRY* cacheEntries; - u8* pages; -} CACHE; - - -/* -Read data from a sector in the cache -If the sector is not in the cache, it will be swapped in -offset is the position to start reading from -size is the amount of data to read -Precondition: offset + size <= BYTES_PER_READ -*/ -bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, u32 sector, u32 offset, u32 size); - -/* -Write data to a sector in the cache -If the sector is not in the cache, it will be swapped in. -When the sector is swapped out, the data will be written to the disc -offset is the position to start reading from -size is the amount of data to read -Precondition: offset + size <= BYTES_PER_READ -*/ -bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); - -/* -Write data to a sector in the cache, zeroing the sector first -If the sector is not in the cache, it will be swapped in. -When the sector is swapped out, the data will be written to the disc -offset is the position to start reading from -size is the amount of data to read -Precondition: offset + size <= BYTES_PER_READ -*/ -bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); - -/* -Read a full sector from the cache -*/ -static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, u32 sector) { - return _FAT_cache_readPartialSector (cache, buffer, sector, 0, BYTES_PER_READ); -} - -/* -Write a full sector to the cache -*/ -static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, u32 sector) { - return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ); -} - -/* -Write any dirty sectors back to disc and clear out the contents of the cache -*/ -bool _FAT_cache_flush (CACHE* cache); - -/* -Clear out the contents of the cache without writing any dirty sectors first -*/ -void _FAT_cache_invalidate (CACHE* cache); - -CACHE* _FAT_cache_constructor (u32 numberOfPages, const IO_INTERFACE* discInterface); - -void _FAT_cache_destructor (CACHE* cache); - -#endif // _CACHE_H diff --git a/sdk-modifications/include/fs_common.h b/sdk-modifications/include/fs_common.h deleted file mode 100644 index c482775..0000000 --- a/sdk-modifications/include/fs_common.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - common.h - Common definitions and included files for the FATlib - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef _COMMON_H -#define _COMMON_H - -// When compiling for NDS, make sure NDS is defined -#ifndef NDS - #if defined ARM9 || defined ARM7 - #define NDS - #endif -#endif - -#if 0 -#ifdef NDS - #include -#else - #include "gba_types.h" -#endif -#endif - -#define BYTES_PER_READ 512 - -#ifndef NULL - #define NULL 0 -#endif - -#ifndef bool -#define bool int -#endif - -#ifndef false -#define false 0 -#endif - -#ifndef true -#define true 1 -#endif - -#ifndef u8 -#define u8 unsigned char -#endif - -#ifndef u16 -#define u16 unsigned short -#endif - -#ifndef u32 -#define u32 unsigned long -#endif - -#ifndef s32 -#define s32 long -#endif - -struct _reent -{ - /* FILE is a big struct and may change over time. To try to achieve binary - compatibility with future versions, put stdin,stdout,stderr here. - These are pointers into member __sf defined below. */ -// __FILE *_stdin, *_stdout, *_stderr; /* XXX */ - - int _errno; /* local copy of errno */ - -// int _inc; /* used by tmpnam */ - -// char *_emergency; - -// int __sdidinit; /* 1 means stdio has been init'd */ - -// int _current_category; /* unused */ -// _CONST char *_current_locale; /* unused */ - -// struct _mprec *_mp; - -// void _EXFNPTR(__cleanup, (struct _reent *)); - -// int _gamma_signgam; - - /* used by some fp conversion routines */ -// int _cvtlen; /* should be size_t */ -// char *_cvtbuf; - -// struct _rand48 *_r48; -// struct __tm *_localtime_buf; -// char *_asctime_buf; - - /* signal info */ -// void (**(_sig_func))(int); - - /* atexit stuff */ -// struct _atexit *_atexit; -// struct _atexit _atexit0; - -// struct _glue __sglue; /* root of glue chain */ -// __FILE *__sf; /* file descriptors */ -// struct _misc_reent *_misc; /* strtok, multibyte states */ -// char *_signal_buf; /* strsignal */ -}; - -#endif // _COMMON_H diff --git a/sdk-modifications/include/fs_unicode.h b/sdk-modifications/include/fs_unicode.h deleted file mode 100644 index 45e9d0a..0000000 --- a/sdk-modifications/include/fs_unicode.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __FS_UNICODE_H__ -#define __FS_UNICODE_H__ - -extern void _FAT_utf8_to_unicode16( const char* src, u16* dest ); - -extern void _FAT_unicode16_to_utf8( const u16* src, char* dest); - -extern u32 _unistrnlen( const u16* unistr, u32 maxlen ); - -extern int _unistrncmp( const u16 * src, const u16 * dest, u32 maxlen ); - -extern const u16 * _unistrchr( const u16 * str, u16 unichar ); - -int _uniisalnum( u8 ch ); - -#endif //__FS_UNICODE_H__ diff --git a/sdk-modifications/include/mem_allocate.h b/sdk-modifications/include/mem_allocate.h deleted file mode 100644 index 844f6df..0000000 --- a/sdk-modifications/include/mem_allocate.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - mem_allocate.h - Memory allocation and destruction calls - Replace these calls with custom allocators if - malloc is unavailable - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef _MEM_ALLOCATE_H -#define _MEM_ALLOCATE_H - -#include "ds2_malloc.h" - -static inline void* _FAT_mem_allocate (size_t size) { - return ((void*)malloc (size)); -} - -static inline void _FAT_mem_free (void* mem) { - return (free ((void*)mem)); -} - -#endif // _MEM_ALLOCATE_H diff --git a/sdk-modifications/include/mips.h b/sdk-modifications/include/mips.h deleted file mode 100644 index 3792565..0000000 --- a/sdk-modifications/include/mips.h +++ /dev/null @@ -1,820 +0,0 @@ -/************************************************************************** -* * -* PROJECT : MIPS port for uC/OS-II * -* * -* MODULE : MIPS.h * -* * -* AUTHOR : Michael Anburaj * -* URL : http://geocities.com/michaelanburaj/ * -* EMAIL: michaelanburaj@hotmail.com * -* * -* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board * -* * -* TOOL-CHAIN : SDE & Cygnus * -* * -* DESCRIPTION : * -* MIPS processor definitions. * -* The basic CPU definitions are found in the file archdefs.h, which * -* is included by mips.h. * -* * -* mips.h implements aliases for some of the definitions in archdefs.h * -* and adds various definitions. * -* * -**************************************************************************/ - - -#ifndef __MIPS_H__ -#define __MIPS_H__ - -#include "archdefs.h" - - -/* ********************************************************************* */ -/* Module configuration */ - - -/* ********************************************************************* */ -/* Interface macro & data definition */ - -#ifndef MSK -#define MSK(n) ((1 << (n)) - 1) -#endif - -/* CPU registers */ -#define SYS_CPUREG_ZERO 0 -#define SYS_CPUREG_AT 1 -#define SYS_CPUREG_V0 2 -#define SYS_CPUREG_V1 3 -#define SYS_CPUREG_A0 4 -#define SYS_CPUREG_A1 5 -#define SYS_CPUREG_A2 6 -#define SYS_CPUREG_A3 7 -#define SYS_CPUREG_T0 8 -#define SYS_CPUREG_T1 9 -#define SYS_CPUREG_T2 10 -#define SYS_CPUREG_T3 11 -#define SYS_CPUREG_T4 12 -#define SYS_CPUREG_T5 13 -#define SYS_CPUREG_T6 14 -#define SYS_CPUREG_T7 15 -#define SYS_CPUREG_S0 16 -#define SYS_CPUREG_S1 17 -#define SYS_CPUREG_S2 18 -#define SYS_CPUREG_S3 19 -#define SYS_CPUREG_S4 20 -#define SYS_CPUREG_S5 21 -#define SYS_CPUREG_S6 22 -#define SYS_CPUREG_S7 23 -#define SYS_CPUREG_T8 24 -#define SYS_CPUREG_T9 25 -#define SYS_CPUREG_K0 26 -#define SYS_CPUREG_K1 27 -#define SYS_CPUREG_GP 28 -#define SYS_CPUREG_SP 29 -#define SYS_CPUREG_S8 30 -#define SYS_CPUREG_FP SYS_CPUREG_S8 -#define SYS_CPUREG_RA 31 - - -/* CPU register fp ($30) has an alias s8 */ -#define s8 fp - - -/* Aliases for System Control Coprocessor (CP0) registers */ -#define C0_INDEX C0_Index -#define C0_RANDOM C0_Random -#define C0_ENTRYLO0 C0_EntryLo0 -#define C0_ENTRYLO1 C0_EntryLo1 -#define C0_CONTEXT C0_Context -#define C0_PAGEMASK C0_PageMask -#define C0_WIRED C0_Wired -#define C0_BADVADDR C0_BadVAddr -#define C0_COUNT C0_Count -#define C0_ENTRYHI C0_EntryHi -#define C0_COMPARE C0_Compare -#define C0_STATUS C0_Status -#define C0_CAUSE C0_Cause - -#ifdef C0_PRID /* ArchDefs has an obsolete def. of C0_PRID */ -#undef C0_PRID -#endif -#define C0_PRID C0_PRId - -#define C0_CONFIG C0_Config -#define C0_CONFIG1 C0_Config1 -#define C0_LLADDR C0_LLAddr -#define C0_WATCHLO C0_WatchLo -#define C0_WATCHHI C0_WatchHi -#define C0_DEBUG C0_Debug -#define C0_PERFCNT C0_PerfCnt -#define C0_ERRCTL C0_ErrCtl -#define C0_CACHEERR C0_CacheErr -#define C0_TAGLO C0_TagLo -#define C0_DATALO C0_DataLo -#define C0_TAGHI C0_TagHi -#define C0_DATAHI C0_DataHi -#define C0_ERROREPC C0_ErrorEPC -#if 0 -#define C0_DESAVE C0_DESAVE -#define C0_EPC C0_EPC -#define C0_DEPC C0_DEPC -#endif - -/* System Control Coprocessor (CP0) registers select fields */ -#define C0_INDEX_SEL 0 /* TLB Index */ -#define C0_RANDOM_SEL 0 /* TLB Random */ -#define C0_TLBLO0_SEL 0 /* TLB EntryLo0 */ -#define C0_TLBLO1_SEL 0 /* TLB EntryLo1 */ -#define C0_CONTEXT_SEL 0 /* Context */ -#define C0_PAGEMASK_SEL 0 /* TLB PageMask */ -#define C0_WIRED_SEL 0 /* TLB Wired */ -#define C0_BADVADDR_SEL 0 /* Bad Virtual Address */ -#define C0_COUNT_SEL 0 /* Count */ -#define C0_ENTRYHI_SEL 0 /* TLB EntryHi */ -#define C0_COMPARE_SEL 0 /* Compare */ -#define C0_STATUS_SEL 0 /* Processor Status */ -#define C0_CAUSE_SEL 0 /* Exception Cause */ -#define C0_EPC_SEL 0 /* Exception PC */ -#define C0_PRID_SEL 0 /* Processor Revision Indentifier */ -#define C0_CONFIG_SEL 0 /* Config */ -#define C0_CONFIG1_SEL 1 /* Config1 */ -#define C0_LLADDR_SEL 0 /* LLAddr */ -#define C0_WATCHLO_SEL 0 /* WatchpointLo */ -#define C0_WATCHHI_SEL 0 /* WatchpointHi */ -#define C0_DEBUG_SEL 0 /* EJTAG Debug Register */ -#define C0_DEPC_SEL 0 /* Program counter at last EJTAG debug exception */ -#define C0_PERFCNT_SEL 0 /* Performance counter interface */ -#define C0_ERRCTL_SEL 0 /* ERRCTL */ -#define C0_CACHEERR_SEL 0 /* CacheErr */ -#define C0_TAGLO_SEL 0 /* TagLo */ -#define C0_DATALO_SEL 1 /* DataLo */ -#define C0_DTAGLO_SEL 2 /* DTagLo */ -#define C0_TAGHI_SEL 0 /* TagHi */ -#define C0_DATAHI_SEL 1 /* DataHi */ -#define C0_DTAGHI_SEL 2 /* DTagHi */ -#define C0_ERROREPC_SEL 0 /* ErrorEPC */ -#define C0_DESAVE_SEL 0 /* EJTAG dbg exc. save register */ - - -/* C0_CONFIG register encoding */ - -#define C0_CONFIG_M_SHF S_ConfigMore -#define C0_CONFIG_M_MSK M_ConfigMore -#define C0_CONFIG_M_BIT C0_CONFIG_M_MSK - -#define C0_CONFIG_BE_SHF S_ConfigBE -#define C0_CONFIG_BE_MSK M_ConfigBE -#define C0_CONFIG_BE_BIT C0_CONFIG_BE_MSK - -#define C0_CONFIG_AT_SHF S_ConfigAT -#define C0_CONFIG_AT_MSK M_ConfigAT -#define C0_CONFIG_AT_MIPS32 K_ConfigAT_MIPS32 -#define C0_CONFIG_AT_MIPS64_32ADDR K_ConfigAT_MIPS64S -#define C0_CONFIG_AT_MIPS64 K_ConfigAT_MIPS64 - -#define C0_CONFIG_AR_SHF S_ConfigAR -#define C0_CONFIG_AR_MSK M_ConfigAR - -#define C0_CONFIG_MT_SHF S_ConfigMT -#define C0_CONFIG_MT_MSK M_ConfigMT -#define C0_CONFIG_MT_NONE K_ConfigMT_NoMMU -#define C0_CONFIG_MT_TLB K_ConfigMT_TLBMMU -#define C0_CONFIG_MT_BAT K_ConfigMT_BATMMU -#define C0_CONFIG_MT_NON_STD K_ConfigMT_FMMMU - -#define C0_CONFIG_K0_SHF S_ConfigK0 -#define C0_CONFIG_K0_MSK M_ConfigK0 -#define C0_CONFIG_K0_WTHRU_NOALLOC K_CacheAttrCWTnWA -#define C0_CONFIG_K0_WTHRU_ALLOC K_CacheAttrCWTWA -#define C0_CONFIG_K0_UNCACHED K_CacheAttrU -#define C0_CONFIG_K0_NONCOHERENT K_CacheAttrCN -#define C0_CONFIG_K0_COHERENTXCL K_CacheAttrCCE -#define C0_CONFIG_K0_COHERENTXCLW K_CacheAttrCCS -#define C0_CONFIG_K0_COHERENTUPD K_CacheAttrCCU -#define C0_CONFIG_K0_UNCACHED_ACCEL K_CacheAttrUA - - -/* WC field. - * - * This feature is present specifically to support configuration - * testing of the core in a lead vehicle, and is not supported - * in any other environment. Attempting to use this feature - * outside of the scope of a lead vehicle is a violation of the - * MIPS Architecture, and may cause unpredictable operation of - * the processor. - */ -#define C0_CONFIG_WC_SHF 19 -#define C0_CONFIG_WC_MSK (MSK(1) << C0_CONFIG_WC_SHF) -#define C0_CONFIG_WC_BIT C0_CONFIG_WC_MSK - - -/* C0_CONFIG1 register encoding */ - -#define C0_CONFIG1_MMUSIZE_SHF S_Config1MMUSize -#define C0_CONFIG1_MMUSIZE_MSK M_Config1MMUSize - -#define C0_CONFIG1_IS_SHF S_Config1IS -#define C0_CONFIG1_IS_MSK M_Config1IS - -#define C0_CONFIG1_IL_SHF S_Config1IL -#define C0_CONFIG1_IL_MSK M_Config1IL - -#define C0_CONFIG1_IA_SHF S_Config1IA -#define C0_CONFIG1_IA_MSK M_Config1IA - -#define C0_CONFIG1_DS_SHF S_Config1DS -#define C0_CONFIG1_DS_MSK M_Config1DS - -#define C0_CONFIG1_DL_SHF S_Config1DL -#define C0_CONFIG1_DL_MSK M_Config1DL - -#define C0_CONFIG1_DA_SHF S_Config1DA -#define C0_CONFIG1_DA_MSK M_Config1DA - -#define C0_CONFIG1_WR_SHF S_Config1WR -#define C0_CONFIG1_WR_MSK M_Config1WR -#define C0_CONFIG1_WR_BIT C0_CONFIG1_WR_MSK - -#define C0_CONFIG1_CA_SHF S_Config1CA -#define C0_CONFIG1_CA_MSK M_Config1CA -#define C0_CONFIG1_CA_BIT C0_CONFIG1_CA_MSK - -#define C0_CONFIG1_EP_SHF S_Config1EP -#define C0_CONFIG1_EP_MSK M_Config1EP -#define C0_CONFIG1_EP_BIT C0_CONFIG1_EP_MSK - -#define C0_CONFIG1_FP_SHF S_Config1FP -#define C0_CONFIG1_FP_MSK M_Config1FP -#define C0_CONFIG1_FP_BIT C0_CONFIG1_FP_MSK - - -/* C0_STATUS register encoding */ - -#define C0_STATUS_CU3_SHF S_StatusCU3 -#define C0_STATUS_CU3_MSK M_StatusCU3 -#define C0_STATUS_CU3_BIT C0_STATUS_CU3_MSK - -#define C0_STATUS_CU2_SHF S_StatusCU2 -#define C0_STATUS_CU2_MSK M_StatusCU2 -#define C0_STATUS_CU2_BIT C0_STATUS_CU2_MSK - -#define C0_STATUS_CU1_SHF S_StatusCU1 -#define C0_STATUS_CU1_MSK M_StatusCU1 -#define C0_STATUS_CU1_BIT C0_STATUS_CU1_MSK - -#define C0_STATUS_CU0_SHF S_StatusCU1 -#define C0_STATUS_CU0_MSK M_StatusCU1 -#define C0_STATUS_CU0_BIT C0_STATUS_CU0_MSK - -#define C0_STATUS_RP_SHF S_StatusRP -#define C0_STATUS_RP_MSK M_StatusRP -#define C0_STATUS_RP_BIT C0_STATUS_RP_MSK - -#define C0_STATUS_FR_SHF S_StatusFR -#define C0_STATUS_FR_MSK M_StatusFR -#define C0_STATUS_FR_BIT C0_STATUS_FR_MSK - -#define C0_STATUS_RE_SHF S_StatusRE -#define C0_STATUS_RE_MSK M_StatusRE -#define C0_STATUS_RE_BIT C0_STATUS_RE_MSK - -#define C0_STATUS_BEV_SHF S_StatusBEV -#define C0_STATUS_BEV_MSK M_StatusBEV -#define C0_STATUS_BEV_BIT C0_STATUS_BEV_MSK - -#define C0_STATUS_TS_SHF S_StatusTS -#define C0_STATUS_TS_MSK M_StatusTS -#define C0_STATUS_TS_BIT C0_STATUS_TS_MSK - -#define C0_STATUS_SR_SHF S_StatusSR -#define C0_STATUS_SR_MSK M_StatusSR -#define C0_STATUS_SR_BIT C0_STATUS_SR_MSK - -#define C0_STATUS_NMI_SHF S_StatusNMI -#define C0_STATUS_NMI_MSK M_StatusNMI -#define C0_STATUS_NMI_BIT C0_STATUS_NMI_MSK - -#define C0_STATUS_IM_SHF S_StatusIM -#define C0_STATUS_IM_MSK M_StatusIM -/* Note that the the definitions below indicate the interrupt number - * rather than the mask. - * (0..1 for SW interrupts and 2...7 for HW interrupts) - */ -#define C0_STATUS_IM_SW0 (S_StatusIM0 - S_StatusIM) -#define C0_STATUS_IM_SW1 (S_StatusIM1 - S_StatusIM) -#define C0_STATUS_IM_HW0 (S_StatusIM2 - S_StatusIM) -#define C0_STATUS_IM_HW1 (S_StatusIM3 - S_StatusIM) -#define C0_STATUS_IM_HW2 (S_StatusIM4 - S_StatusIM) -#define C0_STATUS_IM_HW3 (S_StatusIM5 - S_StatusIM) -#define C0_STATUS_IM_HW4 (S_StatusIM6 - S_StatusIM) -#define C0_STATUS_IM_HW5 (S_StatusIM7 - S_StatusIM) - -/* Max interrupt code */ -#define C0_STATUS_IM_MAX C0_STATUS_IM_HW5 - -#define C0_STATUS_KSU_SHF S_StatusKSU -#define C0_STATUS_KSU_MSK M_StatusKSU - -#define C0_STATUS_UM_SHF S_StatusUM -#define C0_STATUS_UM_MSK M_StatusUM -#define C0_STATUS_UM_BIT C0_STATUS_UM_MSK - -#define C0_STATUS_ERL_SHF S_StatusERL -#define C0_STATUS_ERL_MSK M_StatusERL -#define C0_STATUS_ERL_BIT C0_STATUS_ERL_MSK - -#define C0_STATUS_EXL_SHF S_StatusEXL -#define C0_STATUS_EXL_MSK M_StatusEXL -#define C0_STATUS_EXL_BIT C0_STATUS_EXL_MSK - -#define C0_STATUS_IE_SHF S_StatusIE -#define C0_STATUS_IE_MSK M_StatusIE -#define C0_STATUS_IE_BIT C0_STATUS_IE_MSK - - -/* C0_PRID register encoding */ - -#define C0_PRID_OPT_SHF S_PRIdCoOpt -#define C0_PRID_OPT_MSK M_PRIdCoOpt - -#define C0_PRID_COMP_SHF S_PRIdCoID -#define C0_PRID_COMP_MSK M_PRIdCoID -#define C0_PRID_COMP_MIPS K_PRIdCoID_MIPS -#define C0_PRID_COMP_NOT_MIPS32_64 0 - -#define C0_PRID_PRID_SHF S_PRIdImp -#define C0_PRID_PRID_MSK M_PRIdImp - -/* Jade */ -#define C0_PRID_PRID_4Kc K_PRIdImp_Jade -#define C0_PRID_PRID_4Kmp K_PRIdImp_JadeLite /* 4Km/4Kp */ -/* Emerald */ -#define C0_PRID_PRID_4KEc K_PRIdImp_4KEc -#define C0_PRID_PRID_4KEmp K_PRIdImp_4KEmp -/* Coral */ -#define C0_PRID_PRID_4KSc K_PRIdImp_4KSc -/* Opal */ -#define C0_PRID_PRID_5K K_PRIdImp_Opal -/* Ruby */ -#define C0_PRID_PRID_20Kc K_PRIdImp_Ruby -/* Other CPUs */ -#define C0_PRID_PRID_R4000 K_PRIdImp_R4000 -#define C0_PRID_PRID_RM52XX K_PRIdImp_R5200 -#define C0_PRID_PRID_RM70XX 0x27 - -#define C0_PRID_REV_SHF S_PRIdRev -#define C0_PRID_REV_MSK M_PRIdRev - - -#define MIPS_4Kc ( (C0_PRID_COMP_MIPS << \ - C0_PRID_COMP_SHF) | \ - (C0_PRID_PRID_4Kc << \ - C0_PRID_PRID_SHF) \ - ) - -#define MIPS_4Kmp ( (C0_PRID_COMP_MIPS << \ - C0_PRID_COMP_SHF) | \ - (C0_PRID_PRID_4Kmp << \ - C0_PRID_PRID_SHF) \ - ) - -#define MIPS_4KEc ( (C0_PRID_COMP_MIPS << \ - C0_PRID_COMP_SHF) | \ - (C0_PRID_PRID_4KEc << \ - C0_PRID_PRID_SHF) \ - ) - -#define MIPS_4KEmp ( (C0_PRID_COMP_MIPS << \ - C0_PRID_COMP_SHF) | \ - (C0_PRID_PRID_4KEmp << \ - C0_PRID_PRID_SHF) \ - ) - -#define MIPS_4KSc ( (C0_PRID_COMP_MIPS << \ - C0_PRID_COMP_SHF) | \ - (C0_PRID_PRID_4KSc << \ - C0_PRID_PRID_SHF) \ - ) - -#define MIPS_5K ( (C0_PRID_COMP_MIPS << \ - C0_PRID_COMP_SHF) | \ - (C0_PRID_PRID_5K << \ - C0_PRID_PRID_SHF) \ - ) - -#define MIPS_20Kc ( (C0_PRID_COMP_MIPS << \ - C0_PRID_COMP_SHF) | \ - (C0_PRID_PRID_20Kc << \ - C0_PRID_PRID_SHF) \ - ) - -#define QED_RM52XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \ - C0_PRID_COMP_SHF) | \ - (C0_PRID_PRID_RM52XX << \ - C0_PRID_PRID_SHF) \ - ) - -#define QED_RM70XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \ - C0_PRID_COMP_SHF) | \ - (C0_PRID_PRID_RM70XX << \ - C0_PRID_PRID_SHF) \ - ) - -/* C0_ENTRYHI register encoding */ - -#define C0_ENTRYHI_VPN2_SHF S_EntryHiVPN2 -#define C0_ENTRYHI_VPN2_MSK M_EntryHiVPN2 - -#define C0_ENTRYHI_ASID_SHF S_EntryHiASID -#define C0_ENTRYHI_ASID_MSK M_EntryHiASID - - -/* C0_CAUSE register encoding */ - -#define C0_CAUSE_BD_SHF S_CauseBD -#define C0_CAUSE_BD_MSK M_CauseBD -#define C0_CAUSE_BD_BIT C0_CAUSE_BD_MSK - -#define C0_CAUSE_CE_SHF S_CauseCE -#define C0_CAUSE_CE_MSK M_CauseCE - -#define C0_CAUSE_IV_SHF S_CauseIV -#define C0_CAUSE_IV_MSK M_CauseIV -#define C0_CAUSE_IV_BIT C0_CAUSE_IV_MSK - -#define C0_CAUSE_WP_SHF S_CauseWP -#define C0_CAUSE_WP_MSK M_CauseWP -#define C0_CAUSE_WP_BIT C0_CAUSE_WP_MSK - -#define C0_CAUSE_IP_SHF S_CauseIP -#define C0_CAUSE_IP_MSK M_CauseIP - -#define C0_CAUSE_CODE_SHF S_CauseExcCode -#define C0_CAUSE_CODE_MSK M_CauseExcCode - -#define C0_CAUSE_CODE_INT EX_INT -#define C0_CAUSE_CODE_MOD EX_MOD -#define C0_CAUSE_CODE_TLBL EX_TLBL -#define C0_CAUSE_CODE_TLBS EX_TLBS -#define C0_CAUSE_CODE_ADEL EX_ADEL -#define C0_CAUSE_CODE_ADES EX_ADES -#define C0_CAUSE_CODE_IBE EX_IBE -#define C0_CAUSE_CODE_DBE EX_DBE -#define C0_CAUSE_CODE_SYS EX_SYS -#define C0_CAUSE_CODE_BP EX_BP -#define C0_CAUSE_CODE_RI EX_RI -#define C0_CAUSE_CODE_CPU EX_CPU -#define C0_CAUSE_CODE_OV EX_OV -#define C0_CAUSE_CODE_TR EV_TR -#define C0_CAUSE_CODE_FPE EX_FPE -#define C0_CAUSE_CODE_WATCH EX_WATCH -#define C0_CAUSE_CODE_MCHECK EX_MCHECK - -/* Max cause code */ -#define C0_CAUSE_CODE_MAX EX_MCHECK - - -/* C0_PAGEMASK register encoding */ -#define C0_PAGEMASK_MASK_SHF S_PageMaskMask -#define C0_PAGEMASK_MASK_MSK M_PageMaskMask -#define C0_PAGEMASK_MASK_4K K_PageMask4K -#define C0_PAGEMASK_MASK_16K K_PageMask16K -#define C0_PAGEMASK_MASK_64K K_PageMask64K -#define C0_PAGEMASK_MASK_256K K_PageMask256K -#define C0_PAGEMASK_MASK_1M K_PageMask1M -#define C0_PAGEMASK_MASK_4M K_PageMask4M -#define C0_PAGEMASK_MASK_16M K_PageMask16M - - -/* C0_ENTRYLO0 register encoding (equiv. to C0_ENTRYLO1) */ -#define C0_ENTRYLO0_PFN_SHF S_EntryLoPFN -#define C0_ENTRYLO0_PFN_MSK M_EntryLoPFN - -#define C0_ENTRYLO0_C_SHF S_EntryLoC -#define C0_ENTRYLO0_C_MSK M_EntryLoC - -#define C0_ENTRYLO0_D_SHF S_EntryLoD -#define C0_ENTRYLO0_D_MSK M_EntryLoD - -#define C0_ENTRYLO0_V_SHF S_EntryLoV -#define C0_ENTRYLO0_V_MSK M_EntryLoV - -#define C0_ENTRYLO0_G_SHF S_EntryLoG -#define C0_ENTRYLO0_G_MSK M_EntryLoG - - -/* FPU (CP1) FIR register encoding */ -#define C1_FIR_3D_SHF S_FIRConfig3D -#define C1_FIR_3D_MSK M_FIRConfig3D - -#define C1_FIR_PS_SHF S_FIRConfigPS -#define C1_FIR_PS_MSK M_FIRConfigPS - -#define C1_FIR_D_SHF S_FIRConfigD -#define C1_FIR_D_MSK M_FIRConfigD - -#define C1_FIR_S_SHF S_FIRConfigS -#define C1_FIR_S_MSK M_FIRConfigS - -#define C1_FIR_PRID_SHF S_FIRImp -#define C1_FIR_PRID_MSK M_FIRImp - -#define C1_FIR_REV_SHF S_FIRRev -#define C1_FIR_REV_MSK M_FIRRev - - -/* FPU (CP1) FCSR control/status register */ -#define C1_FCSR_FCC_SHF S_FCSRFCC7_1 -#define C1_FCSR_FCC_MSK M_FCSRFCC7_1 - -#define C1_FCSR_FS_SHF S_FCSRFS -#define C1_FCSR_FS_MSK M_FCSRFS -#define C1_FCSR_FS_BIT C1_FCSR_FS_MSK - -#define C1_FCSR_CC_SHF S_FCSRCC -#define C1_FCSR_CC_MSK M_FCSRCC - -#define C1_FCSR_IMPL_SHF S_FCSRImpl -#define C1_FCSR_IMPL_MSK M_FCSRImpl - -#define C1_FCSR_EXC_SHF S_FCSRExc -#define C1_FCSR_EXC_MSK M_FCSRExc - -#define C1_FCSR_ENA_SHF S_FCSREna -#define C1_FCSR_ENA_MSK M_FCSREna - -#define C1_FCSR_FLG_SHF S_FCSRFlg -#define C1_FCSR_FLG_MSK M_FCSRFlg - -#define C1_FCSR_RM_SHF S_FCSRRM -#define C1_FCSR_RM_MSK M_FCSRRM -#define C1_FCSR_RM_RN K_FCSRRM_RN -#define C1_FCSR_RM_RZ K_FCSRRM_RZ -#define C1_FCSR_RM_RP K_FCSRRM_RP -#define C1_FCSR_RM_RM K_FCSRRM_RM - - - -/* cache operations */ - -#define CACHE_OP( code, type ) ( ((code) << 2) | (type) ) - -#define ICACHE_INDEX_INVALIDATE CACHE_OP(0x0, 0) -#define ICACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 0) -#define ICACHE_INDEX_STORE_TAG CACHE_OP(0x2, 0) -#define DCACHE_INDEX_WRITEBACK_INVALIDATE CACHE_OP(0x0, 1) -#define DCACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 1) -#define DCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 1) -#define SCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 3) - -#define ICACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 0) -#define ICACHE_ADDR_FILL CACHE_OP(0x5, 0) -#define ICACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 0) -#define DCACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 1) -#define DCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 1) -#define DCACHE_ADDR_HIT_WRITEBACK CACHE_OP(0x6, 1) -#define DCACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 1) - -#define SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 3) - -/* Workaround for bug in early revisions of MIPS 4K family of - * processors. Only relevant in early engineering samples of test - * chips (RTL revision <= 3.0). - * - * The bug is described in : - * - * MIPS32 4K(tm) Processor Core Family RTL Errata Sheet - * MIPS Document No: MD00003 - * - * The bug is identified as : C16 - */ -#ifndef SET_MIPS0 -#define SET_MIPS0() -#define SET_PUSH() -#define SET_POP() -#endif -#define ICACHE_INVALIDATE_WORKAROUND(reg) \ -SET_PUSH(); \ -SET_MIPS0(); \ - la reg, 999f; \ -SET_POP(); \ - cache ICACHE_ADDR_FILL, 0(reg); \ - sync; \ - nop; nop; nop; nop; \ -999: - -/* EMPTY_PIPELINE is used for the below cache invalidation operations. - * When $I is invalidated, there will still be operations in the - * pipeline. We make sure these are 'nop' operations. - */ -#define EMPTY_PIPELINE nop; nop; nop; nop - -#define ICACHE_INDEX_INVALIDATE_OP(index,scratch) \ - ICACHE_INVALIDATE_WORKAROUND(scratch); \ - cache ICACHE_INDEX_INVALIDATE, 0(index); \ - EMPTY_PIPELINE - -#define ICACHE_ADDR_INVALIDATE_OP(addr,scratch) \ - ICACHE_INVALIDATE_WORKAROUND(scratch); \ - cache ICACHE_ADDR_HIT_INVALIDATE, 0(addr); \ - EMPTY_PIPELINE - -/* The sync used in the below macro is there in case we are installing - * a new instruction (flush $D, sync, invalidate $I sequence). - */ -#define SCACHE_ADDR_HIT_WB_INVALIDATE_OP(reg) \ - cache SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE, 0(reg); \ - sync; \ - EMPTY_PIPELINE - -/* Config1 cache field decoding */ -#define CACHE_CALC_SPW(s) ( 64 << (s) ) -#define CACHE_CALC_LS(l) ( (l) ? 2 << (l) : 0 ) -#define CACHE_CALC_BPW(l,s) ( CACHE_CALC_LS(l) * CACHE_CALC_SPW(s) ) -#define CACHE_CALC_ASSOC(a) ( (a) + 1 ) - - -/**** Move from/to Coprocessor operations ****/ - -/* We use ssnop instead of nop operations in order to handle - * superscalar CPUs. - * The "sll zero,zero,1" notation is compiler backwards compatible. - */ -#define SSNOP sll zero,zero,1 -#define NOPS SSNOP; SSNOP; SSNOP; SSNOP - -#define MFLO(dst) \ - mflo dst;\ - NOPS - -/* Workaround for bug in early revisions of MIPS 4K family of - * processors. - * - * This concerns the nop instruction before mtc0 in the - * MTC0 macro below. - * - * The bug is described in : - * - * MIPS32 4K(tm) Processor Core Family RTL Errata Sheet - * MIPS Document No: MD00003 - * - * The bug is identified as : C27 - */ - -#define MTC0(src, dst) \ - nop; \ - mtc0 src,dst;\ - NOPS - -#define DMTC0(src, dst) \ - nop; \ - dmtc0 src,dst;\ - NOPS - -#define MFC0(dst, src) \ - mfc0 dst,src;\ - NOPS - -#define DMFC0(dst, src) \ - dmfc0 dst,src;\ - NOPS - -#define MFC0_SEL_OPCODE(dst, src, sel)\ - .##word (0x40000000 | ((dst)<<16) | ((src)<<11) | (sel));\ - NOPS - -#define MTC0_SEL_OPCODE(dst, src, sel)\ - .##word (0x40800000 | ((dst)<<16) | ((src)<<11) | (sel));\ - NOPS - -#define LDC1(dst, src, offs)\ - .##word (0xd4000000 | ((src)<<21) | ((dst)<<16) | (offs)) - -#define SDC1(src, dst, offs)\ - .##word (0xf4000000 | ((dst)<<21) | ((src)<<16) | (offs)) - - -/* Instruction opcode fields */ -#define OPC_SPECIAL 0x0 -#define OPC_REGIM 0x1 -#define OPC_J 0x2 -#define OPC_JAL 0x3 -#define OPC_BEQ 0x4 -#define OPC_BNE 0x5 -#define OPC_BLEZ 0x6 -#define OPC_BGTZ 0x7 -#define OPC_COP1 0x11 -#define OPC_JALX 0x1D -#define OPC_BEQL 0x14 -#define OPC_BNEL 0x15 -#define OPC_BLEZL 0x16 -#define OPC_BGTZL 0x17 - -/* Instruction function fields */ -#define FUNC_JR 0x8 -#define FUNC_JALR 0x9 - -/* Instruction rt fields */ -#define RT_BLTZ 0x0 -#define RT_BGEZ 0x1 -#define RT_BLTZL 0x2 -#define RT_BGEZL 0x3 -#define RT_BLTZAL 0x10 -#define RT_BGEZAL 0x11 -#define RT_BLTZALL 0x12 -#define RT_BGEZALL 0x13 - -/* Instruction rs fields */ -#define RS_BC1 0x08 - -/* Access macros for instruction fields */ -#define MIPS_OPCODE( instr) ((instr) >> 26) -#define MIPS_FUNCTION(instr) ((instr) & MSK(6)) -#define MIPS_RT(instr) (((instr) >> 16) & MSK(5)) -#define MIPS_RS(instr) (((instr) >> 21) & MSK(5)) -#define MIPS_OFFSET(instr) ((instr) & 0xFFFF) -#define MIPS_TARGET(instr) ((instr) & MSK(26)) - -/* Instructions */ -#define OPCODE_DERET 0x4200001f -#define OPCODE_BREAK 0x0005000d -#define OPCODE_NOP 0 -#define OPCODE_JUMP(addr) ( (OPC_J << 26) | (((addr) >> 2) & 0x3FFFFFF) ) - -#define DERET .##word OPCODE_DERET - -/* MIPS16e opcodes and instruction field access macros */ - -#define MIPS16E_OPCODE(inst) (((inst) >> 11) & 0x1f) -#define MIPS16E_I8_FUNCTION(inst) (((inst) >> 8) & 0x7) -#define MIPS16E_X(inst) (((inst) >> 26) & 0x1) -#define MIPS16E_RR_FUNCTION(inst) (((inst) >> 0) & 0x1f) -#define MIPS16E_RY(inst) (((inst) >> 5) & 0x3) -#define MIPS16E_OPC_EXTEND 0x1e -#define MIPS16E_OPC_JAL_X 0x03 -#define MIPS16E_OPC_B 0x02 -#define MIPS16E_OPC_BEQZ 0x04 -#define MIPS16E_OPC_BNEZ 0x05 -#define MIPS16E_OPC_I8 0x0c -#define MIPS16E_I8_FUNC_BTEQZ 0x00 -#define MIPS16E_I8_FUNC_BTNEZ 0x01 -#define MIPS16E_X_JALX 0x01 -#define MIPS16E_OPC_RR 0x1d -#define MIPS16E_RR_FUNC_JALRC 0x00 -#define MIPS16E_RR_RY_JRRX 0x00 -#define MIPS16E_RR_RY_JRRA 0x01 -#define MIPS16E_RR_RY_JALR 0x02 -#define MIPS16E_RR_RY_JRCRX 0x04 -#define MIPS16E_RR_RY_JRCRA 0x05 -#define MIPS16E_RR_RY_JALRC 0x06 - -#define MIPS16E_OPCODE_BREAK 0xE805 -#define MIPS16E_OPCODE_NOP 0x6500 - -/* MIPS reset vector */ -#define MIPS_RESET_VECTOR 0x1fc00000 - -/* Clock periods per count register increment */ -#define MIPS4K_COUNT_CLK_PER_CYCLE 2 -#define MIPS5K_COUNT_CLK_PER_CYCLE 2 -#define MIPS20Kc_COUNT_CLK_PER_CYCLE 1 - - -/**** MIPS 4K/5K families specific fields of CONFIG register ****/ - -#define C0_CONFIG_MIPS4K5K_K23_SHF S_ConfigK23 -#define C0_CONFIG_MIPS4K5K_K23_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_K23_SHF) - -#define C0_CONFIG_MIPS4K5K_KU_SHF S_ConfigKU -#define C0_CONFIG_MIPS4K5K_KU_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_KU_SHF) - - -/**** MIPS 20Kc specific fields of CONFIG register ****/ - -#define C0_CONFIG_MIPS20KC_EC_SHF 28 -#define C0_CONFIG_MIPS20KC_EC_MSK (MSK(3) << C0_CONFIG_MIPS20KC_EC_SHF) - -#define C0_CONFIG_MIPS20KC_DD_SHF 27 -#define C0_CONFIG_MIPS20KC_DD_MSK (MSK(1) << C0_CONFIG_MIPS20KC_DD_SHF) -#define C0_CONFIG_MIPS20KC_DD_BIT C0_CONFIG_MIPS20KC_DD_MSK - -#define C0_CONFIG_MIPS20KC_LP_SHF 26 -#define C0_CONFIG_MIPS20KC_LP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_LP_SHF) -#define C0_CONFIG_MIPS20KC_LP_BIT C0_CONFIG_MIPS20KC_LP_MSK - -#define C0_CONFIG_MIPS20KC_SP_SHF 25 -#define C0_CONFIG_MIPS20KC_SP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_SP_SHF) -#define C0_CONFIG_MIPS20KC_SP_BIT C0_CONFIG_MIPS20KC_SP_MSK - -#define C0_CONFIG_MIPS20KC_TI_SHF 24 -#define C0_CONFIG_MIPS20KC_TI_MSK (MSK(1) << C0_CONFIG_MIPS20KC_TI_SHF) -#define C0_CONFIG_MIPS20KC_TI_BIT C0_CONFIG_MIPS20KC_TI_MSK - - -/* ********************************************************************* */ -/* Interface function definition */ - - -/* ********************************************************************* */ - -#endif /* #ifndef __MIPS_H__ */ diff --git a/sdk-modifications/include/mipsregs.h b/sdk-modifications/include/mipsregs.h deleted file mode 100644 index 5eaac44..0000000 --- a/sdk-modifications/include/mipsregs.h +++ /dev/null @@ -1,985 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle - * Copyright (C) 2000 Silicon Graphics, Inc. - * Modified for further R[236]000 support by Paul M. Antoine, 1996. - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * Copyright (C) 2003 Maciej W. Rozycki - */ -#ifndef _ASM_MIPSREGS_H -#define _ASM_MIPSREGS_H - -#include -#include - -/* - * The following macros are especially useful for __asm__ - * inline assembler. - */ -#ifndef __STR -#define __STR(x) #x -#endif -#ifndef STR -#define STR(x) __STR(x) -#endif - -/* - * Configure language - */ -#ifdef __ASSEMBLY__ -#define _ULCAST_ -#else -#define _ULCAST_ (unsigned long) -#endif - -/* - * Coprocessor 0 register names - */ -#define CP0_INDEX $0 -#define CP0_RANDOM $1 -#define CP0_ENTRYLO0 $2 -#define CP0_ENTRYLO1 $3 -#define CP0_CONF $3 -#define CP0_CONTEXT $4 -#define CP0_PAGEMASK $5 -#define CP0_WIRED $6 -#define CP0_INFO $7 -#define CP0_BADVADDR $8 -#define CP0_COUNT $9 -#define CP0_ENTRYHI $10 -#define CP0_COMPARE $11 -#define CP0_STATUS $12 -#define CP0_CAUSE $13 -#define CP0_EPC $14 -#define CP0_PRID $15 -#define CP0_CONFIG $16 -#define CP0_LLADDR $17 -#define CP0_WATCHLO $18 -#define CP0_WATCHHI $19 -#define CP0_XCONTEXT $20 -#define CP0_FRAMEMASK $21 -#define CP0_DIAGNOSTIC $22 -#define CP0_DEBUG $23 -#define CP0_DEPC $24 -#define CP0_PERFORMANCE $25 -#define CP0_ECC $26 -#define CP0_CACHEERR $27 -#define CP0_TAGLO $28 -#define CP0_TAGHI $29 -#define CP0_ERROREPC $30 -#define CP0_DESAVE $31 - -/* - * R4640/R4650 cp0 register names. These registers are listed - * here only for completeness; without MMU these CPUs are not useable - * by Linux. A future ELKS port might take make Linux run on them - * though ... - */ -#define CP0_IBASE $0 -#define CP0_IBOUND $1 -#define CP0_DBASE $2 -#define CP0_DBOUND $3 -#define CP0_CALG $17 -#define CP0_IWATCH $18 -#define CP0_DWATCH $19 - -/* - * Coprocessor 0 Set 1 register names - */ -#define CP0_S1_DERRADDR0 $26 -#define CP0_S1_DERRADDR1 $27 -#define CP0_S1_INTCONTROL $20 - -/* - * TX39 Series - */ -#define CP0_TX39_CACHE $7 - -/* - * Coprocessor 1 (FPU) register names - */ -#define CP1_REVISION $0 -#define CP1_STATUS $31 - -/* - * FPU Status Register Values - */ -/* - * Status Register Values - */ - -#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */ -#define FPU_CSR_COND 0x00800000 /* $fcc0 */ -#define FPU_CSR_COND0 0x00800000 /* $fcc0 */ -#define FPU_CSR_COND1 0x02000000 /* $fcc1 */ -#define FPU_CSR_COND2 0x04000000 /* $fcc2 */ -#define FPU_CSR_COND3 0x08000000 /* $fcc3 */ -#define FPU_CSR_COND4 0x10000000 /* $fcc4 */ -#define FPU_CSR_COND5 0x20000000 /* $fcc5 */ -#define FPU_CSR_COND6 0x40000000 /* $fcc6 */ -#define FPU_CSR_COND7 0x80000000 /* $fcc7 */ - -/* - * X the exception cause indicator - * E the exception enable - * S the sticky/flag bit -*/ -#define FPU_CSR_ALL_X 0x0003f000 -#define FPU_CSR_UNI_X 0x00020000 -#define FPU_CSR_INV_X 0x00010000 -#define FPU_CSR_DIV_X 0x00008000 -#define FPU_CSR_OVF_X 0x00004000 -#define FPU_CSR_UDF_X 0x00002000 -#define FPU_CSR_INE_X 0x00001000 - -#define FPU_CSR_ALL_E 0x00000f80 -#define FPU_CSR_INV_E 0x00000800 -#define FPU_CSR_DIV_E 0x00000400 -#define FPU_CSR_OVF_E 0x00000200 -#define FPU_CSR_UDF_E 0x00000100 -#define FPU_CSR_INE_E 0x00000080 - -#define FPU_CSR_ALL_S 0x0000007c -#define FPU_CSR_INV_S 0x00000040 -#define FPU_CSR_DIV_S 0x00000020 -#define FPU_CSR_OVF_S 0x00000010 -#define FPU_CSR_UDF_S 0x00000008 -#define FPU_CSR_INE_S 0x00000004 - -/* rounding mode */ -#define FPU_CSR_RN 0x0 /* nearest */ -#define FPU_CSR_RZ 0x1 /* towards zero */ -#define FPU_CSR_RU 0x2 /* towards +Infinity */ -#define FPU_CSR_RD 0x3 /* towards -Infinity */ - - -/* - * Values for PageMask register - */ -#ifdef CONFIG_CPU_VR41XX - -/* Why doesn't stupidity hurt ... */ - -#define PM_1K 0x00000000 -#define PM_4K 0x00001800 -#define PM_16K 0x00007800 -#define PM_64K 0x0001f800 -#define PM_256K 0x0007f800 - -#else - -#define PM_4K 0x00000000 -#define PM_16K 0x00006000 -#define PM_64K 0x0001e000 -#define PM_256K 0x0007e000 -#define PM_1M 0x001fe000 -#define PM_4M 0x007fe000 -#define PM_16M 0x01ffe000 -#define PM_64M 0x07ffe000 -#define PM_256M 0x1fffe000 - -#endif - -/* - * Values used for computation of new tlb entries - */ -#define PL_4K 12 -#define PL_16K 14 -#define PL_64K 16 -#define PL_256K 18 -#define PL_1M 20 -#define PL_4M 22 -#define PL_16M 24 -#define PL_64M 26 -#define PL_256M 28 - -/* - * R4x00 interrupt enable / cause bits - */ -#define IE_SW0 (_ULCAST_(1) << 8) -#define IE_SW1 (_ULCAST_(1) << 9) -#define IE_IRQ0 (_ULCAST_(1) << 10) -#define IE_IRQ1 (_ULCAST_(1) << 11) -#define IE_IRQ2 (_ULCAST_(1) << 12) -#define IE_IRQ3 (_ULCAST_(1) << 13) -#define IE_IRQ4 (_ULCAST_(1) << 14) -#define IE_IRQ5 (_ULCAST_(1) << 15) - -/* - * R4x00 interrupt cause bits - */ -#define C_SW0 (_ULCAST_(1) << 8) -#define C_SW1 (_ULCAST_(1) << 9) -#define C_IRQ0 (_ULCAST_(1) << 10) -#define C_IRQ1 (_ULCAST_(1) << 11) -#define C_IRQ2 (_ULCAST_(1) << 12) -#define C_IRQ3 (_ULCAST_(1) << 13) -#define C_IRQ4 (_ULCAST_(1) << 14) -#define C_IRQ5 (_ULCAST_(1) << 15) - -/* - * Bitfields in the R4xx0 cp0 status register - */ -#define ST0_IE 0x00000001 -#define ST0_EXL 0x00000002 -#define ST0_ERL 0x00000004 -#define ST0_KSU 0x00000018 -# define KSU_USER 0x00000010 -# define KSU_SUPERVISOR 0x00000008 -# define KSU_KERNEL 0x00000000 -#define ST0_UX 0x00000020 -#define ST0_SX 0x00000040 -#define ST0_KX 0x00000080 -#define ST0_DE 0x00010000 -#define ST0_CE 0x00020000 - -/* - * Bitfields in the R[23]000 cp0 status register. - */ -#define ST0_IEC 0x00000001 -#define ST0_KUC 0x00000002 -#define ST0_IEP 0x00000004 -#define ST0_KUP 0x00000008 -#define ST0_IEO 0x00000010 -#define ST0_KUO 0x00000020 -/* bits 6 & 7 are reserved on R[23]000 */ -#define ST0_ISC 0x00010000 -#define ST0_SWC 0x00020000 -#define ST0_CM 0x00080000 - -/* - * Bits specific to the R4640/R4650 - */ -#define ST0_UM (_ULCAST_(1) << 4) -#define ST0_IL (_ULCAST_(1) << 23) -#define ST0_DL (_ULCAST_(1) << 24) - -/* - * Bitfields in the TX39 family CP0 Configuration Register 3 - */ -#define TX39_CONF_ICS_SHIFT 19 -#define TX39_CONF_ICS_MASK 0x00380000 -#define TX39_CONF_ICS_1KB 0x00000000 -#define TX39_CONF_ICS_2KB 0x00080000 -#define TX39_CONF_ICS_4KB 0x00100000 -#define TX39_CONF_ICS_8KB 0x00180000 -#define TX39_CONF_ICS_16KB 0x00200000 - -#define TX39_CONF_DCS_SHIFT 16 -#define TX39_CONF_DCS_MASK 0x00070000 -#define TX39_CONF_DCS_1KB 0x00000000 -#define TX39_CONF_DCS_2KB 0x00010000 -#define TX39_CONF_DCS_4KB 0x00020000 -#define TX39_CONF_DCS_8KB 0x00030000 -#define TX39_CONF_DCS_16KB 0x00040000 - -#define TX39_CONF_CWFON 0x00004000 -#define TX39_CONF_WBON 0x00002000 -#define TX39_CONF_RF_SHIFT 10 -#define TX39_CONF_RF_MASK 0x00000c00 -#define TX39_CONF_DOZE 0x00000200 -#define TX39_CONF_HALT 0x00000100 -#define TX39_CONF_LOCK 0x00000080 -#define TX39_CONF_ICE 0x00000020 -#define TX39_CONF_DCE 0x00000010 -#define TX39_CONF_IRSIZE_SHIFT 2 -#define TX39_CONF_IRSIZE_MASK 0x0000000c -#define TX39_CONF_DRSIZE_SHIFT 0 -#define TX39_CONF_DRSIZE_MASK 0x00000003 - -/* - * Status register bits available in all MIPS CPUs. - */ -#define ST0_IM 0x0000ff00 -#define STATUSB_IP0 8 -#define STATUSF_IP0 (_ULCAST_(1) << 8) -#define STATUSB_IP1 9 -#define STATUSF_IP1 (_ULCAST_(1) << 9) -#define STATUSB_IP2 10 -#define STATUSF_IP2 (_ULCAST_(1) << 10) -#define STATUSB_IP3 11 -#define STATUSF_IP3 (_ULCAST_(1) << 11) -#define STATUSB_IP4 12 -#define STATUSF_IP4 (_ULCAST_(1) << 12) -#define STATUSB_IP5 13 -#define STATUSF_IP5 (_ULCAST_(1) << 13) -#define STATUSB_IP6 14 -#define STATUSF_IP6 (_ULCAST_(1) << 14) -#define STATUSB_IP7 15 -#define STATUSF_IP7 (_ULCAST_(1) << 15) -#define STATUSB_IP8 0 -#define STATUSF_IP8 (_ULCAST_(1) << 0) -#define STATUSB_IP9 1 -#define STATUSF_IP9 (_ULCAST_(1) << 1) -#define STATUSB_IP10 2 -#define STATUSF_IP10 (_ULCAST_(1) << 2) -#define STATUSB_IP11 3 -#define STATUSF_IP11 (_ULCAST_(1) << 3) -#define STATUSB_IP12 4 -#define STATUSF_IP12 (_ULCAST_(1) << 4) -#define STATUSB_IP13 5 -#define STATUSF_IP13 (_ULCAST_(1) << 5) -#define STATUSB_IP14 6 -#define STATUSF_IP14 (_ULCAST_(1) << 6) -#define STATUSB_IP15 7 -#define STATUSF_IP15 (_ULCAST_(1) << 7) -#define ST0_CH 0x00040000 -#define ST0_SR 0x00100000 -#define ST0_TS 0x00200000 -#define ST0_BEV 0x00400000 -#define ST0_RE 0x02000000 -#define ST0_FR 0x04000000 -#define ST0_CU 0xf0000000 -#define ST0_CU0 0x10000000 -#define ST0_CU1 0x20000000 -#define ST0_CU2 0x40000000 -#define ST0_CU3 0x80000000 -#define ST0_XX 0x80000000 /* MIPS IV naming */ - -/* - * Bitfields and bit numbers in the coprocessor 0 cause register. - * - * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. - */ -#define CAUSEB_EXCCODE 2 -#define CAUSEF_EXCCODE (_ULCAST_(31) << 2) -#define CAUSEB_IP 8 -#define CAUSEF_IP (_ULCAST_(255) << 8) -#define CAUSEB_IP0 8 -#define CAUSEF_IP0 (_ULCAST_(1) << 8) -#define CAUSEB_IP1 9 -#define CAUSEF_IP1 (_ULCAST_(1) << 9) -#define CAUSEB_IP2 10 -#define CAUSEF_IP2 (_ULCAST_(1) << 10) -#define CAUSEB_IP3 11 -#define CAUSEF_IP3 (_ULCAST_(1) << 11) -#define CAUSEB_IP4 12 -#define CAUSEF_IP4 (_ULCAST_(1) << 12) -#define CAUSEB_IP5 13 -#define CAUSEF_IP5 (_ULCAST_(1) << 13) -#define CAUSEB_IP6 14 -#define CAUSEF_IP6 (_ULCAST_(1) << 14) -#define CAUSEB_IP7 15 -#define CAUSEF_IP7 (_ULCAST_(1) << 15) -#define CAUSEB_IV 23 -#define CAUSEF_IV (_ULCAST_(1) << 23) -#define CAUSEB_CE 28 -#define CAUSEF_CE (_ULCAST_(3) << 28) -#define CAUSEB_BD 31 -#define CAUSEF_BD (_ULCAST_(1) << 31) - -/* - * Bits in the coprocessor 0 config register. - */ -/* Generic bits. */ -#define CONF_CM_CACHABLE_NO_WA 0 -#define CONF_CM_CACHABLE_WA 1 -#define CONF_CM_UNCACHED 2 -#define CONF_CM_CACHABLE_NONCOHERENT 3 -#define CONF_CM_CACHABLE_CE 4 -#define CONF_CM_CACHABLE_COW 5 -#define CONF_CM_CACHABLE_CUW 6 -#define CONF_CM_CACHABLE_ACCELERATED 7 -#define CONF_CM_CMASK 7 -#define CONF_BE (_ULCAST_(1) << 15) - -/* Bits common to various processors. */ -#define CONF_CU (_ULCAST_(1) << 3) -#define CONF_DB (_ULCAST_(1) << 4) -#define CONF_IB (_ULCAST_(1) << 5) -#define CONF_DC (_ULCAST_(7) << 6) -#define CONF_IC (_ULCAST_(7) << 9) -#define CONF_EB (_ULCAST_(1) << 13) -#define CONF_EM (_ULCAST_(1) << 14) -#define CONF_SM (_ULCAST_(1) << 16) -#define CONF_SC (_ULCAST_(1) << 17) -#define CONF_EW (_ULCAST_(3) << 18) -#define CONF_EP (_ULCAST_(15)<< 24) -#define CONF_EC (_ULCAST_(7) << 28) -#define CONF_CM (_ULCAST_(1) << 31) - -/* Bits specific to the R4xx0. */ -#define R4K_CONF_SW (_ULCAST_(1) << 20) -#define R4K_CONF_SS (_ULCAST_(1) << 21) -#define R4K_CONF_SB (_ULCAST_(3) << 22) - -/* Bits specific to the R5000. */ -#define R5K_CONF_SE (_ULCAST_(1) << 12) -#define R5K_CONF_SS (_ULCAST_(3) << 20) - -/* Bits specific to the R10000. */ -#define R10K_CONF_DN (_ULCAST_(3) << 3) -#define R10K_CONF_CT (_ULCAST_(1) << 5) -#define R10K_CONF_PE (_ULCAST_(1) << 6) -#define R10K_CONF_PM (_ULCAST_(3) << 7) -#define R10K_CONF_EC (_ULCAST_(15)<< 9) -#define R10K_CONF_SB (_ULCAST_(1) << 13) -#define R10K_CONF_SK (_ULCAST_(1) << 14) -#define R10K_CONF_SS (_ULCAST_(7) << 16) -#define R10K_CONF_SC (_ULCAST_(7) << 19) -#define R10K_CONF_DC (_ULCAST_(7) << 26) -#define R10K_CONF_IC (_ULCAST_(7) << 29) - -/* Bits specific to the VR41xx. */ -#define VR41_CONF_CS (_ULCAST_(1) << 12) -#define VR41_CONF_M16 (_ULCAST_(1) << 20) -#define VR41_CONF_AD (_ULCAST_(1) << 23) - -/* Bits specific to the R30xx. */ -#define R30XX_CONF_FDM (_ULCAST_(1) << 19) -#define R30XX_CONF_REV (_ULCAST_(1) << 22) -#define R30XX_CONF_AC (_ULCAST_(1) << 23) -#define R30XX_CONF_RF (_ULCAST_(1) << 24) -#define R30XX_CONF_HALT (_ULCAST_(1) << 25) -#define R30XX_CONF_FPINT (_ULCAST_(7) << 26) -#define R30XX_CONF_DBR (_ULCAST_(1) << 29) -#define R30XX_CONF_SB (_ULCAST_(1) << 30) -#define R30XX_CONF_LOCK (_ULCAST_(1) << 31) - -/* Bits specific to the TX49. */ -#define TX49_CONF_DC (_ULCAST_(1) << 16) -#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */ -#define TX49_CONF_HALT (_ULCAST_(1) << 18) -#define TX49_CONF_CWFON (_ULCAST_(1) << 27) - -/* Bits specific to the MIPS32/64 PRA. */ -#define MIPS_CONF_MT (_ULCAST_(7) << 7) -#define MIPS_CONF_AR (_ULCAST_(7) << 10) -#define MIPS_CONF_AT (_ULCAST_(3) << 13) -#define MIPS_CONF_M (_ULCAST_(1) << 31) - -/* - * R10000 performance counter definitions. - * - * FIXME: The R10000 performance counter opens a nice way to implement CPU - * time accounting with a precission of one cycle. I don't have - * R10000 silicon but just a manual, so ... - */ - -/* - * Events counted by counter #0 - */ -#define CE0_CYCLES 0 -#define CE0_INSN_ISSUED 1 -#define CE0_LPSC_ISSUED 2 -#define CE0_S_ISSUED 3 -#define CE0_SC_ISSUED 4 -#define CE0_SC_FAILED 5 -#define CE0_BRANCH_DECODED 6 -#define CE0_QW_WB_SECONDARY 7 -#define CE0_CORRECTED_ECC_ERRORS 8 -#define CE0_ICACHE_MISSES 9 -#define CE0_SCACHE_I_MISSES 10 -#define CE0_SCACHE_I_WAY_MISSPREDICTED 11 -#define CE0_EXT_INTERVENTIONS_REQ 12 -#define CE0_EXT_INVALIDATE_REQ 13 -#define CE0_VIRTUAL_COHERENCY_COND 14 -#define CE0_INSN_GRADUATED 15 - -/* - * Events counted by counter #1 - */ -#define CE1_CYCLES 0 -#define CE1_INSN_GRADUATED 1 -#define CE1_LPSC_GRADUATED 2 -#define CE1_S_GRADUATED 3 -#define CE1_SC_GRADUATED 4 -#define CE1_FP_INSN_GRADUATED 5 -#define CE1_QW_WB_PRIMARY 6 -#define CE1_TLB_REFILL 7 -#define CE1_BRANCH_MISSPREDICTED 8 -#define CE1_DCACHE_MISS 9 -#define CE1_SCACHE_D_MISSES 10 -#define CE1_SCACHE_D_WAY_MISSPREDICTED 11 -#define CE1_EXT_INTERVENTION_HITS 12 -#define CE1_EXT_INVALIDATE_REQ 13 -#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14 -#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15 - -/* - * These flags define in which priviledge mode the counters count events - */ -#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */ -#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */ -#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */ -#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */ - -#ifndef __ASSEMBLY__ - -#define CAUSE_EXCCODE(x) ((CAUSEF_EXCCODE & (x->cp0_cause)) >> CAUSEB_EXCCODE) -#define CAUSE_EPC(x) (x->cp0_epc + (((x->cp0_cause & CAUSEF_BD) >> CAUSEB_BD) << 2)) - -/* - * Functions to access the r10k performance counter and control registers - */ -#define read_r10k_perf_cntr(counter) \ -({ unsigned int __res; \ - __asm__ __volatile__( \ - "mfpc\t%0, "STR(counter) \ - : "=r" (__res)); \ - __res;}) - -#define write_r10k_perf_cntr(counter,val) \ - __asm__ __volatile__( \ - "mtpc\t%0, "STR(counter) \ - : : "r" (val)); - -#define read_r10k_perf_cntl(counter) \ -({ unsigned int __res; \ - __asm__ __volatile__( \ - "mfps\t%0, "STR(counter) \ - : "=r" (__res)); \ - __res;}) - -#define write_r10k_perf_cntl(counter,val) \ - __asm__ __volatile__( \ - "mtps\t%0, "STR(counter) \ - : : "r" (val)); - -/* - * Macros to access the system control coprocessor - */ - -#define __read_32bit_c0_register(source, sel) \ -({ int __res; \ - if (sel == 0) \ - __asm__ __volatile__( \ - "mfc0\t%0, " #source "\n\t" \ - : "=r" (__res)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips32\n\t" \ - "mfc0\t%0, " #source ", " #sel "\n\t" \ - ".set\tmips0\n\t" \ - : "=r" (__res)); \ - __res; \ -}) - -#define __read_64bit_c0_register(source, sel) \ -({ unsigned long __res; \ - if (sel == 0) \ - __asm__ __volatile__( \ - ".set\tmips3\n\t" \ - "dmfc0\t%0, " #source "\n\t" \ - ".set\tmips0" \ - : "=r" (__res)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dmfc0\t%0, " #source ", " #sel "\n\t" \ - ".set\tmips0" \ - : "=r" (__res)); \ - __res; \ -}) - -#define __write_32bit_c0_register(register, sel, value) \ -do { \ - if (sel == 0) \ - __asm__ __volatile__( \ - "mtc0\t%z0, " #register "\n\t" \ - : : "Jr" (value)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips32\n\t" \ - "mtc0\t%z0, " #register ", " #sel "\n\t" \ - ".set\tmips0" \ - : : "Jr" (value)); \ -} while (0) - -#define __write_64bit_c0_register(register, sel, value) \ -do { \ - if (sel == 0) \ - __asm__ __volatile__( \ - ".set\tmips3\n\t" \ - "dmtc0\t%z0, " #register "\n\t" \ - ".set\tmips0" \ - : : "Jr" (value)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dmtc0\t%z0, " #register ", " #sel "\n\t" \ - ".set\tmips0" \ - : : "Jr" (value)); \ -} while (0) - -#define __read_ulong_c0_register(reg, sel) \ - ((sizeof(unsigned long) == 4) ? \ - __read_32bit_c0_register(reg, sel) : \ - __read_64bit_c0_register(reg, sel)) - -#define __write_ulong_c0_register(reg, sel, val) \ -do { \ - if (sizeof(unsigned long) == 4) \ - __write_32bit_c0_register(reg, sel, val); \ - else \ - __write_64bit_c0_register(reg, sel, val); \ -} while (0) - -/* - * These versions are only needed for systems with more than 38 bits of - * physical address space running the 32-bit kernel. That's none atm :-) - */ -#define __read_64bit_c0_split(source, sel) \ -({ \ - unsigned long long val; \ - unsigned long flags; \ - \ - local_irq_save(flags); \ - if (sel == 0) \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dmfc0\t%M0, " #source "\n\t" \ - "dsll\t%L0, %M0, 32\n\t" \ - "dsrl\t%M0, %M0, 32\n\t" \ - "dsrl\t%L0, %L0, 32\n\t" \ - ".set\tmips0" \ - : "=r" (val)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dmfc0\t%M0, " #source ", " #sel "\n\t" \ - "dsll\t%L0, %M0, 32\n\t" \ - "dsrl\t%M0, %M0, 32\n\t" \ - "dsrl\t%L0, %L0, 32\n\t" \ - ".set\tmips0" \ - : "=r" (val)); \ - local_irq_restore(flags); \ - \ - val; \ -}) - -#define __write_64bit_c0_split(source, sel, val) \ -do { \ - unsigned long flags; \ - \ - local_irq_save(flags); \ - if (sel == 0) \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dsll\t%L0, %L0, 32\n\t" \ - "dsrl\t%L0, %L0, 32\n\t" \ - "dsll\t%M0, %M0, 32\n\t" \ - "or\t%L0, %L0, %M0\n\t" \ - "dmtc0\t%L0, " #source "\n\t" \ - ".set\tmips0" \ - : : "r" (val)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dsll\t%L0, %L0, 32\n\t" \ - "dsrl\t%L0, %L0, 32\n\t" \ - "dsll\t%M0, %M0, 32\n\t" \ - "or\t%L0, %L0, %M0\n\t" \ - "dmtc0\t%L0, " #source ", " #sel "\n\t" \ - ".set\tmips0" \ - : : "r" (val)); \ - local_irq_restore(flags); \ -} while (0) - -#define read_c0_index() __read_32bit_c0_register($0, 0) -#define write_c0_index(val) __write_32bit_c0_register($0, 0, val) - -#define read_c0_entrylo0() __read_ulong_c0_register($2, 0) -#define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val) - -#define read_c0_entrylo1() __read_ulong_c0_register($3, 0) -#define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val) - -#define read_c0_conf() __read_32bit_c0_register($3, 0) -#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) - -#define read_c0_context() __read_ulong_c0_register($4, 0) -#define write_c0_context(val) __write_ulong_c0_register($4, 0, val) - -#define read_c0_pagemask() __read_32bit_c0_register($5, 0) -#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) - -#define read_c0_wired() __read_32bit_c0_register($6, 0) -#define write_c0_wired(val) __write_32bit_c0_register($6, 0, val) - -#define read_c0_info() __read_32bit_c0_register($7, 0) - -#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */ -#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val) - -#define read_c0_count() __read_32bit_c0_register($9, 0) -#define write_c0_count(val) __write_32bit_c0_register($9, 0, val) - -#define read_c0_entryhi() __read_ulong_c0_register($10, 0) -#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val) - -#define read_c0_compare() __read_32bit_c0_register($11, 0) -#define write_c0_compare(val) __write_32bit_c0_register($11, 0, val) - -#define read_c0_status() __read_32bit_c0_register($12, 0) -#define write_c0_status(val) __write_32bit_c0_register($12, 0, val) - -#define read_c0_cause() __read_32bit_c0_register($13, 0) -#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) - -#define read_c0_prid() __read_32bit_c0_register($15, 0) - -#define read_c0_config() __read_32bit_c0_register($16, 0) -#define read_c0_config1() __read_32bit_c0_register($16, 1) -#define read_c0_config2() __read_32bit_c0_register($16, 2) -#define read_c0_config3() __read_32bit_c0_register($16, 3) -#define write_c0_config(val) __write_32bit_c0_register($16, 0, val) -#define write_c0_config1(val) __write_32bit_c0_register($16, 1, val) -#define write_c0_config2(val) __write_32bit_c0_register($16, 2, val) -#define write_c0_config3(val) __write_32bit_c0_register($16, 3, val) - -/* - * The WatchLo register. There may be upto 8 of them. - */ -#define read_c0_watchlo0() __read_ulong_c0_register($18, 0) -#define read_c0_watchlo1() __read_ulong_c0_register($18, 1) -#define read_c0_watchlo2() __read_ulong_c0_register($18, 2) -#define read_c0_watchlo3() __read_ulong_c0_register($18, 3) -#define read_c0_watchlo4() __read_ulong_c0_register($18, 4) -#define read_c0_watchlo5() __read_ulong_c0_register($18, 5) -#define read_c0_watchlo6() __read_ulong_c0_register($18, 6) -#define read_c0_watchlo7() __read_ulong_c0_register($18, 7) -#define write_c0_watchlo0(val) __write_ulong_c0_register($18, 0, val) -#define write_c0_watchlo1(val) __write_ulong_c0_register($18, 1, val) -#define write_c0_watchlo2(val) __write_ulong_c0_register($18, 2, val) -#define write_c0_watchlo3(val) __write_ulong_c0_register($18, 3, val) -#define write_c0_watchlo4(val) __write_ulong_c0_register($18, 4, val) -#define write_c0_watchlo5(val) __write_ulong_c0_register($18, 5, val) -#define write_c0_watchlo6(val) __write_ulong_c0_register($18, 6, val) -#define write_c0_watchlo7(val) __write_ulong_c0_register($18, 7, val) - -/* - * The WatchHi register. There may be upto 8 of them. - */ -#define read_c0_watchhi0() __read_32bit_c0_register($19, 0) -#define read_c0_watchhi1() __read_32bit_c0_register($19, 1) -#define read_c0_watchhi2() __read_32bit_c0_register($19, 2) -#define read_c0_watchhi3() __read_32bit_c0_register($19, 3) -#define read_c0_watchhi4() __read_32bit_c0_register($19, 4) -#define read_c0_watchhi5() __read_32bit_c0_register($19, 5) -#define read_c0_watchhi6() __read_32bit_c0_register($19, 6) -#define read_c0_watchhi7() __read_32bit_c0_register($19, 7) - -#define write_c0_watchhi0(val) __write_32bit_c0_register($19, 0, val) -#define write_c0_watchhi1(val) __write_32bit_c0_register($19, 1, val) -#define write_c0_watchhi2(val) __write_32bit_c0_register($19, 2, val) -#define write_c0_watchhi3(val) __write_32bit_c0_register($19, 3, val) -#define write_c0_watchhi4(val) __write_32bit_c0_register($19, 4, val) -#define write_c0_watchhi5(val) __write_32bit_c0_register($19, 5, val) -#define write_c0_watchhi6(val) __write_32bit_c0_register($19, 6, val) -#define write_c0_watchhi7(val) __write_32bit_c0_register($19, 7, val) - -#define read_c0_xcontext() __read_ulong_c0_register($20, 0) -#define write_c0_xcontext(val) __write_ulong_c0_register($20, 0, val) - -#define read_c0_intcontrol() __read_32bit_c0_register($20, 1) -#define write_c0_intcontrol(val) __write_32bit_c0_register($20, 1, val) - -#define read_c0_framemask() __read_32bit_c0_register($21, 0) -#define write_c0_framemask(val) __write_32bit_c0_register($21, 0, val) - -#define read_c0_debug() __read_32bit_c0_register($23, 0) -#define write_c0_debug(val) __write_32bit_c0_register($23, 0, val) - -#define read_c0_depc() __read_ulong_c0_register($24, 0) -#define write_c0_depc(val) __write_ulong_c0_register($24, 0, val) - -#define read_c0_ecc() __read_32bit_c0_register($26, 0) -#define write_c0_ecc(val) __write_32bit_c0_register($26, 0, val) - -#define read_c0_derraddr0() __read_ulong_c0_register($26, 1) -#define write_c0_derraddr0(val) __write_ulong_c0_register($26, 1, val) - -#define read_c0_cacheerr() __read_32bit_c0_register($27, 0) - -#define read_c0_derraddr1() __read_ulong_c0_register($27, 1) -#define write_c0_derraddr1(val) __write_ulong_c0_register($27, 1, val) - -#define read_c0_taglo() __read_32bit_c0_register($28, 0) -#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val) - -#define read_c0_taghi() __read_32bit_c0_register($29, 0) -#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val) - -#define read_c0_errorepc() __read_ulong_c0_register($30, 0) -#define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val) - -#define read_c0_epc() __read_ulong_c0_register($14, 0) -#define write_c0_epc(val) __write_ulong_c0_register($14, 0, val) - -#if 1 -/* - * Macros to access the system control coprocessor - */ -#define read_32bit_cp0_register(source) \ -({ int __res; \ - __asm__ __volatile__( \ - ".set\tpush\n\t" \ - ".set\treorder\n\t" \ - "mfc0\t%0,"STR(source)"\n\t" \ - ".set\tpop" \ - : "=r" (__res)); \ - __res;}) - -#define read_32bit_cp0_set1_register(source) \ -({ int __res; \ - __asm__ __volatile__( \ - ".set\tpush\n\t" \ - ".set\treorder\n\t" \ - "cfc0\t%0,"STR(source)"\n\t" \ - ".set\tpop" \ - : "=r" (__res)); \ - __res;}) - -/* - * For now use this only with interrupts disabled! - */ -#define read_64bit_cp0_register(source) \ -({ int __res; \ - __asm__ __volatile__( \ - ".set\tmips3\n\t" \ - "dmfc0\t%0,"STR(source)"\n\t" \ - ".set\tmips0" \ - : "=r" (__res)); \ - __res;}) - -#define write_32bit_cp0_register(register,value) \ - __asm__ __volatile__( \ - "mtc0\t%0,"STR(register)"\n\t" \ - "nop" \ - : : "r" (value)); - -#define write_32bit_cp0_set1_register(register,value) \ - __asm__ __volatile__( \ - "ctc0\t%0,"STR(register)"\n\t" \ - "nop" \ - : : "r" (value)); - -#define write_64bit_cp0_register(register,value) \ - __asm__ __volatile__( \ - ".set\tmips3\n\t" \ - "dmtc0\t%0,"STR(register)"\n\t" \ - ".set\tmips0" \ - : : "r" (value)) - -/* - * This should be changed when we get a compiler that support the MIPS32 ISA. - */ -#define read_mips32_cp0_config1() \ -({ int __res; \ - __asm__ __volatile__( \ - ".set\tnoreorder\n\t" \ - ".set\tnoat\n\t" \ - "#.set\tmips64\n\t" \ - "#mfc0\t$1, $16, 1\n\t" \ - "#.set\tmips0\n\t" \ - ".word\t0x40018001\n\t" \ - "move\t%0,$1\n\t" \ - ".set\tat\n\t" \ - ".set\treorder" \ - :"=r" (__res)); \ - __res;}) - -#endif -/* - * Macros to access the floating point coprocessor control registers - */ -#define read_32bit_cp1_register(source) \ -({ int __res; \ - __asm__ __volatile__( \ - ".set\tpush\n\t" \ - ".set\treorder\n\t" \ - "cfc1\t%0,"STR(source)"\n\t" \ - ".set\tpop" \ - : "=r" (__res)); \ - __res;}) - -/* TLB operations. */ -static inline void tlb_probe(void) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - "tlbp\n\t" - ".set reorder"); -} - -static inline void tlb_read(void) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - "tlbr\n\t" - ".set reorder"); -} - -static inline void tlb_write_indexed(void) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - "tlbwi\n\t" - ".set reorder"); -} - -static inline void tlb_write_random(void) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - "tlbwr\n\t" - ".set reorder"); -} - -/* - * Manipulate bits in a c0 register. - */ -#define __BUILD_SET_C0(name,register) \ -static inline unsigned int \ -set_c0_##name(unsigned int set) \ -{ \ - unsigned int res; \ - \ - res = read_c0_##name(); \ - res |= set; \ - write_c0_##name(res); \ - \ - return res; \ -} \ - \ -static inline unsigned int \ -clear_c0_##name(unsigned int clear) \ -{ \ - unsigned int res; \ - \ - res = read_c0_##name(); \ - res &= ~clear; \ - write_c0_##name(res); \ - \ - return res; \ -} \ - \ -static inline unsigned int \ -change_c0_##name(unsigned int change, unsigned int new) \ -{ \ - unsigned int res; \ - \ - res = read_c0_##name(); \ - res &= ~change; \ - res |= (new & change); \ - write_c0_##name(res); \ - \ - return res; \ -} - -__BUILD_SET_C0(status,CP0_STATUS) -__BUILD_SET_C0(cause,CP0_CAUSE) -__BUILD_SET_C0(config,CP0_CONFIG) - -#define set_cp0_status(x) set_c0_status(x) -#define set_cp0_cause(x) set_c0_cause(x) -#define set_cp0_config(x) set_c0_config(x) - -#endif /* !__ASSEMBLY__ */ - -#endif /* _ASM_MIPSREGS_H */ diff --git a/sdk-modifications/include/mmc_api.h b/sdk-modifications/include/mmc_api.h deleted file mode 100644 index 28e75ef..0000000 --- a/sdk-modifications/include/mmc_api.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __MMC_API_H__ -#define __MMC_API_H__ - -/* Error codes */ -enum mmc_result_t { - MMC_NO_RESPONSE = -1, - MMC_NO_ERROR = 0, - MMC_ERROR_OUT_OF_RANGE, - MMC_ERROR_ADDRESS, - MMC_ERROR_BLOCK_LEN, - MMC_ERROR_ERASE_SEQ, - MMC_ERROR_ERASE_PARAM, - MMC_ERROR_WP_VIOLATION, - MMC_ERROR_CARD_IS_LOCKED, - MMC_ERROR_LOCK_UNLOCK_FAILED, - MMC_ERROR_COM_CRC, - MMC_ERROR_ILLEGAL_COMMAND, - MMC_ERROR_CARD_ECC_FAILED, - MMC_ERROR_CC, - MMC_ERROR_GENERAL, - MMC_ERROR_UNDERRUN, - MMC_ERROR_OVERRUN, - MMC_ERROR_CID_CSD_OVERWRITE, - MMC_ERROR_STATE_MISMATCH, - MMC_ERROR_HEADER_MISMATCH, - MMC_ERROR_TIMEOUT, - MMC_ERROR_CRC, - MMC_ERROR_DRIVER_FAILURE, -}; - - -/* Get card's sectors*/ - -extern unsigned int MMC_GetSize(void); - - -/* initialize MMC/SD card */ -extern int MMC_Initialize(void); - -/* read a single block from MMC/SD card */ -extern int MMC_ReadBlock(unsigned int blockaddr, unsigned char *recbuf); - -/* read multi blocks from MMC/SD card */ -extern int MMC_ReadMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); - -/* write a block to MMC/SD card */ -extern int MMC_WriteBlock(unsigned int blockaddr, unsigned char *recbuf); - -/* write multi blocks to MMC/SD card */ -extern int MMC_WriteMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); - -/* detect MMC/SD card */ -extern int MMC_DetectStatus(void); - -#endif /* __MMC_API_H__ */ - diff --git a/sdk-modifications/include/partition.h b/sdk-modifications/include/partition.h deleted file mode 100644 index 0777b54..0000000 --- a/sdk-modifications/include/partition.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - partition.h - Functions for mounting and dismounting partitions - on various block devices. - - Copyright (c) 2006 Michael "Chishm" Chisholm - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 2006-07-11 - Chishm - * Original release -*/ - -#ifndef _PARTITION_H -#define _PARTITION_H - -#include "fs_common.h" - -#include "disc_io/disc.h" -#include "fs_cache.h" - -// Device name -extern const char* DEVICE_NAME; - -// Filesystem type -typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; - -#ifdef NDS -typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM} PARTITION_INTERFACE; -#else -typedef enum {PI_CART_SLOT} PARTITION_INTERFACE; -#endif - -typedef struct { - u32 fatStart; - u32 sectorsPerFat; - u32 lastCluster; - u32 firstFree; -} FAT; - -typedef struct { - const IO_INTERFACE* disc; - CACHE* cache; - // Info about the partition - bool readOnly; // If this is set, then do not try writing to the disc - FS_TYPE filesysType; - u32 totalSize; - u32 rootDirStart; - u32 rootDirCluster; - u32 numberOfSectors; - u32 dataStart; - u32 bytesPerSector; - u32 sectorsPerCluster; - u32 bytesPerCluster; - FAT fat; - // Values that may change after construction - u32 cwdCluster; // Current working directory cluser - u32 openFileCount; -} PARTITION; - -/* -Mount the device specified by partitionDevice -PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice -PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice -*/ -bool _FAT_partition_mount (PARTITION_INTERFACE partitionNumber, u32 cacheSize); - -/* -Mount a partition on a custom device -*/ -bool _FAT_partition_mountCustomInterface (const IO_INTERFACE* device, u32 cacheSize); - - -/* -Free Mount a partition on a custom device -*/ -bool _FAT_partition_freeMount( int partitionNumber, const IO_INTERFACE* device, u32 cacheSize); - - -/* -Unmount the partition specified by partitionNumber -If there are open files, it will fail -*/ -bool _FAT_partition_unmount (PARTITION_INTERFACE partitionNumber); - -/* -Forcibly unmount the partition specified by partitionNumber -Any open files on the partition will become invalid -The cache will be invalidated, and any unflushed writes will be lost -*/ -bool _FAT_partition_unsafeUnmount (PARTITION_INTERFACE partitionNumber); - -/* -Set the default device for access by fat: and fat0:, -based on the device number -*/ -bool _FAT_partition_setDefaultInterface (PARTITION_INTERFACE partitionNumber); - -/* -Set the default device for access by fat: and fat0:, -based on the partition pointer -*/ -bool _FAT_partition_setDefaultPartition (PARTITION* partition); - -/* -Return the partition specified in a path -For instance, "fat0:", "fat:", "/" and "fat:/" will all -return the default partition -*/ -PARTITION* _FAT_partition_getPartitionFromPath (const char* path); - -#endif // _PARTITION_H diff --git a/sdk-modifications/include/tcm.h b/sdk-modifications/include/tcm.h deleted file mode 100644 index 4de3333..0000000 --- a/sdk-modifications/include/tcm.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __TCM_H -#define __TCM_H - -/* -* Function: makes cpu to idle state. It will be waken up by RTC in the next second. -* Of course, it can be waken up by keys at any time. -*/ -int enable_enter_idle(void); - -#endif diff --git a/sdk-modifications/libsrc/.depend b/sdk-modifications/libsrc/.depend deleted file mode 100644 index e69de29..0000000 diff --git a/sdk-modifications/libsrc/Makefile b/sdk-modifications/libsrc/Makefile index 6e2b4ab..3d63b76 100644 --- a/sdk-modifications/libsrc/Makefile +++ b/sdk-modifications/libsrc/Makefile @@ -13,7 +13,7 @@ CONSOLE_DIR = $(TOPDIR)/console FS_DIR = $(TOPDIR)/fs KEY_DIR = $(TOPDIR)/key ZLIB_DIR = $(TOPDIR)/zlib -DMA_DIR = $(TOPDIR)/dma +CORE_DIR = $(TOPDIR)/core SRC := @@ -24,14 +24,17 @@ INCLUDES := -I../include INC := $(INCLUDES) CFLAGS := -mips32 -O3 -mno-abicalls -fno-pic -fno-builtin \ - -fno-exceptions -ffunction-sections -mlong-calls\ - -fomit-frame-pointer -msoft-float -G 4 - + -fno-exceptions -ffunction-sections -mno-long-calls\ + -fomit-frame-pointer -msoft-float -G 4 \ + -fgcse-sm -fgcse-las -fgcse-after-reload \ + -fweb -fpeel-loops + + include $(CONSOLE_DIR)/console.mk include $(FS_DIR)/fs.mk include $(KEY_DIR)/key.mk include $(ZLIB_DIR)/zlib.mk -include $(DMA_DIR)/dma.mk +include $(CORE_DIR)/core.mk #OBJS := $(addsuffix .o , $(basename $(notdir $(SRC)))) #SOBJS := $(addsuffix .o , $(basename $(notdir $(SSRC)))) diff --git a/sdk-modifications/libsrc/changes_bag.txt b/sdk-modifications/libsrc/changes_bag.txt new file mode 100644 index 0000000..63b82a9 --- /dev/null +++ b/sdk-modifications/libsrc/changes_bag.txt @@ -0,0 +1,28 @@ +Unofficial libds2a by BassAceGold + Based on 0.13 beta Supercard SDK release, contains full lib with changes + + + +release 1: + -inclusion of ds2_unistd.h and ds2_fcntl.h + -updated zlib to 1.5.2 + +release 2: + -mkdir no longer freezes + -faster fopen times for file reading + (no longer searches for the next cluster to write to with read only mode) + -makes DS2's DMA (direct memory access hardware) features publically available + -adds extra cpu clock speeds (may be unstable) + ds2_setCPULevel(level) + -can now get the current CPU clock speed as an integer value + ds2_getCPUClock() + +release 2 fix 1: + -added ds2_udelay and ds2_mdelay variant functions. + must be used with ds2_setCPULevel for accurate timings, + old functions, udelay and mdelay, should not be used with the new + cpu clock functions + -added further optimizations to makefile + +release 2 fix 2: + -fat_getDiskSpaceInfo no longer freezes diff --git a/sdk-modifications/libsrc/console/console.c b/sdk-modifications/libsrc/console/console.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/console/console.h b/sdk-modifications/libsrc/console/console.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/console/console.mk b/sdk-modifications/libsrc/console/console.mk old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/console/font_dot.h b/sdk-modifications/libsrc/console/font_dot.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/core/core.mk b/sdk-modifications/libsrc/core/core.mk new file mode 100644 index 0000000..4ed3ca8 --- /dev/null +++ b/sdk-modifications/libsrc/core/core.mk @@ -0,0 +1,11 @@ +#fs.mk + +SRC += $(CORE_DIR)/ds2_dma.c \ + $(CORE_DIR)/ds2_cpuclock.c + +SSRC += + +INC += -I$(CORE_DIR) + +CFLAGS += + diff --git a/sdk-modifications/libsrc/core/ds2_cpuclock.c b/sdk-modifications/libsrc/core/ds2_cpuclock.c new file mode 100644 index 0000000..57f2143 --- /dev/null +++ b/sdk-modifications/libsrc/core/ds2_cpuclock.c @@ -0,0 +1,272 @@ +#include + +#include "ds2_cpuclock.h" + +#define REG8(addr) *((volatile u8 *)(addr)) +#define REG16(addr) *((volatile u16 *)(addr)) +#define REG32(addr) *((volatile u32 *)(addr)) + +#define SDRAM_TRAS 50 /* RAS# Active Time */ +#define SDRAM_RCD 23 /* RAS# to CAS# Delay */ +#define SDRAM_TPC 23 /* RAS# Precharge Time */ +#define SDRAM_TRWL 7 /* Write Latency Time */ +#define SDRAM_TREF 7813 /* Refresh period: 8192 refresh cycles/64ms */ + +#define EMC_BASE 0xB3010000 +#define EMC_DMCR (EMC_BASE + 0x80) /* DRAM Control Register */ +#define REG_EMC_DMCR REG32(EMC_DMCR) +#define EMC_RTCSR (EMC_BASE + 0x84) /* Refresh Time Control/Status Register */ +#define REG_EMC_RTCSR REG16(EMC_RTCSR) +#define EMC_RTCOR (EMC_BASE + 0x8c) /* Refresh Time Constant Register */ +#define REG_EMC_RTCOR REG16(EMC_RTCOR) +#define EMC_RTCNT (EMC_BASE + 0x88) /* Refresh Timer Counter */ +#define REG_EMC_RTCNT REG16(EMC_RTCNT) + + + +#define CPM_BASE 0xB0000000 +#define CPM_CPCCR (CPM_BASE+0x00) +#define CPM_CPPCR (CPM_BASE+0x10) +//#define CPM_RSR (CPM_BASE+0x08) +#define REG_CPM_CPCCR REG32(CPM_CPCCR) +#define REG_CPM_CPPCR REG32(CPM_CPPCR) +#define CPM_CPCCR_CE (1 << 22) + + + + + + +#define EMC_DMCR_TRAS_BIT 13 +#define EMC_DMCR_TRAS_MASK (0x07 << EMC_DMCR_TRAS_BIT) +#define EMC_DMCR_RCD_BIT 11 +#define EMC_DMCR_RCD_MASK (0x03 << EMC_DMCR_RCD_BIT) +#define EMC_DMCR_TPC_BIT 8 +#define EMC_DMCR_TPC_MASK (0x07 << EMC_DMCR_TPC_BIT) +#define EMC_DMCR_TRWL_BIT 5 +#define EMC_DMCR_TRWL_MASK (0x03 << EMC_DMCR_TRWL_BIT) +#define EMC_DMCR_TRC_BIT 2 +#define EMC_DMCR_TRC_MASK (0x07 << EMC_DMCR_TRC_BIT) + +#define EMC_RTCSR_CKS_BIT 0 +#define EMC_RTCSR_CKS_MASK (0x07 << EMC_RTCSR_CKS_BIT) + + +#define CPM_CPCCR_LDIV_BIT 16 +#define CPM_CPCCR_LDIV_MASK (0x1f << CPM_CPCCR_LDIV_BIT) +#define CPM_CPCCR_MDIV_BIT 12 +#define CPM_CPCCR_MDIV_MASK (0x0f << CPM_CPCCR_MDIV_BIT) +#define CPM_CPCCR_PDIV_BIT 8 +#define CPM_CPCCR_PDIV_MASK (0x0f << CPM_CPCCR_PDIV_BIT) +#define CPM_CPCCR_HDIV_BIT 4 +#define CPM_CPCCR_HDIV_MASK (0x0f << CPM_CPCCR_HDIV_BIT) +#define CPM_CPCCR_CDIV_BIT 0 +#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT) + + +#define CPM_CPPCR_PLLM_BIT 23 +#define CPM_CPPCR_PLLM_MASK (0x1ff << CPM_CPPCR_PLLM_BIT) +#define CPM_CPPCR_PLLN_BIT 18 +#define CPM_CPPCR_PLLN_MASK (0x1f << CPM_CPPCR_PLLN_BIT) +#define CPM_CPPCR_PLLOD_BIT 16 +#define CPM_CPPCR_PLLOD_MASK (0x03 << CPM_CPPCR_PLLOD_BIT) +#define CPM_CPPCR_PLLS (1 << 10) +#define CPM_CPPCR_PLLBP (1 << 9) +#define CPM_CPPCR_PLLEN (1 << 8) +#define CPM_CPPCR_PLLST_BIT 0 +#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT) + + +#define PLL_M 0 +#define PLL_N 1 +#define PLL_CCLK 2 +#define PLL_HCLK 3 +#define PLL_MCLK 4 +#define PLL_PCLK 5 + +#define CFG_EXTAL 24000000 +#define EXTAL_CLK CFG_EXTAL + + +#define __cpm_get_pllm() \ + ((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT) + +#define __cpm_get_plln() \ + ((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT) + +#define __cpm_get_cdiv() \ + ((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT) + + +static unsigned char pll_m_n[CPU_MAX_LEVEL_EX + 1][6] = { + //M, N, CCLK, HCLK, MCLK, PCLK, EXT_CLK=24MHz + {10-2, 2-2, 1, 1, 1, 1}, //0 60, 60, 1/1 + {10-2, 2-2, 0, 1, 1, 1}, //1 120, 60, 1/2 + {10-2, 2-2, 0, 0, 0, 0}, //2 120, 120, 1/1 + {12-2, 2-2, 0, 1, 1, 1}, //3 144, 72, 1/2 + {16-2, 2-2, 0, 1, 1, 1}, //4 192, 96, 1/2 + {17-2, 2-2, 0, 0, 1, 1}, //5 204, 102, 1/2 + {20-2, 2-2, 0, 1, 1, 1}, //6 240, 120, 1/2 + {22-2, 2-2, 0, 2, 2, 2}, //7 264, 88, 1/3 + {24-2, 2-2, 0, 2, 2, 2}, //8 288, 96, 1/3 + {25-2, 2-2, 0, 2, 2, 2}, //9 300, 100, 1/3 + {28-2, 2-2, 0, 2, 2, 2}, //10 336, 112, 1/3 + {30-2, 2-2, 0, 2, 2, 2}, //11 360, 120, 1/3 + {32-2, 2-2, 0, 2, 2, 2}, //12 384, 128, 1/3 + {33-2, 2-2, 0, 2, 2, 2}, //13 396, 132, 1/3 + + {34-2, 2-2, 0, 2, 2, 2}, //14 404, 132, 1/3 + {35-2, 2-2, 0, 2, 2, 2}, //15 420, 132, 1/3 + {36-2, 2-2, 0, 2, 2, 2}, //16 438, 132, 1/3 + {37-2, 2-2, 0, 2, 2, 2}, //17 444, 132, 1/3 + {38-2, 2-2, 0, 2, 2, 2}, //18 456, 132, 1/3 + //{39-2, 2-2, 0, 2, 2, 2}, //468, instant crash! + }; + +static int _sdram_convert(unsigned int pllin,unsigned int *sdram_dmcr, unsigned int *sdram_div, unsigned int *sdram_tref) +{ + register unsigned int ns, dmcr,tmp; + + dmcr = ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | + EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK) & REG_EMC_DMCR; + + /* Set sdram operation parameter */ + //pllin unit is KHz + ns = 1000000*1024 / pllin; + tmp = SDRAM_TRAS*1024/ns; + if (tmp < 4) tmp = 4; + if (tmp > 11) tmp = 11; + dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT); + + tmp = SDRAM_RCD*1024/ns; + if (tmp > 3) tmp = 3; + dmcr |= (tmp << EMC_DMCR_RCD_BIT); + + tmp = SDRAM_TPC*1024/ns; + if (tmp > 7) tmp = 7; + dmcr |= (tmp << EMC_DMCR_TPC_BIT); + + tmp = SDRAM_TRWL*1024/ns; + if (tmp > 3) tmp = 3; + dmcr |= (tmp << EMC_DMCR_TRWL_BIT); + + tmp = (SDRAM_TRAS + SDRAM_TPC)*1024/ns; + if (tmp > 14) tmp = 14; + dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT); + + *sdram_dmcr = dmcr; + + /* Set refresh registers */ + unsigned int div; + tmp = SDRAM_TREF*1024/ns; + div = (tmp + 254)/255; + if(div <= 4) div = 1; // 1/4 + else if(div <= 16) div = 2; // 1/16 + else div = 3; // 1/64 + + *sdram_div = ~EMC_RTCSR_CKS_MASK & REG_EMC_RTCSR | div; + + unsigned int divm= 4; + while(--div) divm *= 4; + + tmp = tmp/divm + 1; + *sdram_tref = tmp; + + return 0; +} + + +const static int FR2n[] = { + 1, 2, 3, 4, 6, 8, 12, 16, 24, 32 +}; + +static unsigned int _pllout; +static unsigned int _iclk; + +static void detect_clockNew(void){ + _pllout = (__cpm_get_pllm() + 2)* EXTAL_CLK / (__cpm_get_plln() + 2); + _iclk = _pllout / FR2n[__cpm_get_cdiv()]; +} + + +//udelay overclock +void ds2_udelay(unsigned int usec) +{ + /*unsigned int i = usec * (_iclk / 2000000); + + __asm__ __volatile__ ( + "\t.set noreorder\n" + "1:\n\t" + "bne\t%0, $0, 1b\n\t" + "addi\t%0, %0, -1\n\t" + ".set reorder\n" + : "=r" (i) + : "0" (i) + );*/ +} + +//mdelay overclock +void ds2_mdelay(unsigned int msec) +{ + /*int i; + for(i=0;i CPU_MAX_LEVEL_EX) return -1; + + freq_b = (pll_m_n[level][PLL_M]+2)*(EXTAL_CLK/1000)/(pll_m_n[level][PLL_N]+2); + + //freq_b unit is KHz + _sdram_convert(freq_b/pll_m_n[level][PLL_MCLK], &dmcr, &rtcsr, &tref); + + cpccr = REG_CPM_CPCCR; + cppcr = REG_CPM_CPPCR; + + REG_CPM_CPCCR = ~CPM_CPCCR_CE & cpccr; + + cppcr &= ~(CPM_CPPCR_PLLM_MASK | CPM_CPPCR_PLLN_MASK); + cppcr |= (pll_m_n[level][PLL_M] << CPM_CPPCR_PLLM_BIT) | (pll_m_n[level][PLL_N] << CPM_CPPCR_PLLN_BIT); + + cpccr &= ~(CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | + CPM_CPCCR_MDIV_MASK | CPM_CPCCR_LDIV_MASK); + cpccr |= (pll_m_n[level][PLL_CCLK] << CPM_CPCCR_CDIV_BIT) | (pll_m_n[level][PLL_HCLK] << CPM_CPCCR_HDIV_BIT) | + (pll_m_n[level][PLL_MCLK] << CPM_CPCCR_MDIV_BIT) | (pll_m_n[level][PLL_PCLK] << CPM_CPCCR_PDIV_BIT) | + (31 << CPM_CPCCR_LDIV_BIT); + + REG_CPM_CPCCR = cpccr; + REG_CPM_CPPCR = cppcr; + + REG_CPM_CPCCR |= CPM_CPCCR_CE; + //Wait PLL stable + while(!(CPM_CPPCR_PLLS & REG_CPM_CPPCR)); + + //REG_EMC_DMCR = dmcr; + REG_EMC_RTCOR = tref; + REG_EMC_RTCNT = tref; + + detect_clockNew(); + return 0; +} + + diff --git a/sdk-modifications/libsrc/core/ds2_cpuclock.h b/sdk-modifications/libsrc/core/ds2_cpuclock.h new file mode 100644 index 0000000..c28635b --- /dev/null +++ b/sdk-modifications/libsrc/core/ds2_cpuclock.h @@ -0,0 +1,22 @@ +#ifndef _DS2_CPUCLOCK_H__ +#define _DS2_CPUCLOCK_H__ + + +#define CPU_MAX_LEVEL_EX 18 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int ds2_getCPUClock(void); +extern int ds2_setCPULevel(unsigned int level); +extern void udelayOC(unsigned int usec); +extern void mdelayOC(unsigned int msec); + +//#define ds2_setCPUclocklevel ds2_setCPULevel + +#ifdef __cplusplus +} +#endif + +#endif //__DS2_CPUCLOCK_H__ diff --git a/sdk-modifications/libsrc/core/ds2_dma.c b/sdk-modifications/libsrc/core/ds2_dma.c new file mode 100644 index 0000000..0b0eca1 --- /dev/null +++ b/sdk-modifications/libsrc/core/ds2_dma.c @@ -0,0 +1,34 @@ +#include "ds2_dma.h" + + + +//register a DMA transfer request +//ch: channel id request, there are 6 channles, +//irq_handler: the DMA interruption handle +//arg: argument to the handle +//mode: DMA mode, such as port width, address increased/fixed, and so on +//type: DMA request type +extern int dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg, + unsigned int mode, unsigned int type); + +//start DMA transfer, must request a DMA first +//ch: channel id +//srcAddr: DMA source address +//dstAddr: DMA destination address +//count: DMA transfer count, the total bytes due the mode in dma_request +extern void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr, + unsigned int count); + + +int _dmaCopy(int ch, void *dest, void *src, unsigned int size, unsigned int flags){ + int test = 0; + if(!(test = dma_request(ch, 0, 0, + //increment dest addr + DMAC_DCMD_DAI | flags, + //auto request type + DMAC_DRSR_RS_AUTO))) + { + dma_start(ch, (unsigned int)src, (unsigned int)dest, size); + } + return test; +} diff --git a/sdk-modifications/libsrc/core/ds2_dma.h b/sdk-modifications/libsrc/core/ds2_dma.h new file mode 100644 index 0000000..a66588a --- /dev/null +++ b/sdk-modifications/libsrc/core/ds2_dma.h @@ -0,0 +1,142 @@ +#ifndef _DS2_DMA_H__ +#define _DS2_DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define MAX_DMA_NUM 6 /* max 6 channels */ + + +// DMA request source register +#define DMAC_DRSR_RS_BIT 0 +#define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) + + +// DMA channel command register +#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ +#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ + +#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ +#define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) +#define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) +#define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) + +#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ +#define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) +#define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) + +#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ +#define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) + +#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ + + +//detect if channel has completed job +#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ +#define DMAC_BASE 0xB3020000 +#define REG32(addr) *((volatile u32 *)(addr)) +#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ +#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) + +#define ds2_DMA_isBusy(n) \ + !( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) + + +/* +Copy modes + +*/ + +#define DMA_MODE32BYTE DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM + +#define DMA_MODE16BYTE DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM + +#define DMA_MODE32BIT DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_32BIT + +#define DMA_MODE16BIT DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BIT + +#define DMA_MODE8BIT DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_8 | \ + DMAC_DCMD_DS_8BIT | DMAC_DCMD_TM + +#define DMA_MODECOPY DMAC_DCMD_SAI + + + +extern int _dmaCopy(int ch, void *dest, void *src, unsigned int size, unsigned int flags); + +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bytes. + * size is in bytes and must be a multiple of 32. + * Both src and dest must be aligned to 32 bytes. + * Returns 0 on failure, non-zero on success. + */ +#define ds2_DMAcopy_32Byte(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE32BYTE) + +/* + * Copy 'size' bytes from src to dest, in blocks of 16 bytes. + * size is in bytes and must be a multiple of 16. + * Both src and dest must be aligned to 16 bytes. + * Returns 0 on failure, non-zero on success. + */ +#define ds2_DMAcopy_16Byte(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE16BYTE); + +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bits (4 bytes). + * size is in bytes and must be a multiple of 4. + * Both src and dest must be aligned to 32 bits (4 bytes). + * Returns 0 on failure, non-zero on success. + */ +#define ds2_DMAcopy_32Bit(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE32BIT); + +/* +- * Copy 'size' bytes from src to dest, in blocks of 16 bits (2 bytes). +- * size is in bytes and must be a multiple of 2. +- * Both src and dest must be aligned to 16 bits (2 bytes). +- * Returns 0 on failure, non-zero on success. +- */ +#define ds2_DMAcopy_16Bit(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE16BIT) + +/* +- * Copy 'size' individual bytes (8 bits at a time) from src to dest. +- * Returns 0 on failure, non-zero on success. +- */ +#define ds2_DMAcopy_8Bit(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE8BIT) + + + +//Stop DMA transfer +extern void dma_stop(int ch); + +#define ds2_DMA_stop(ch)\ + dma_stop(ch) + +//Wait DMA transfer over +extern int dma_wait_finish(int ch); + +#define ds2_DMA_wait(ch)\ + dma_wait_finish(ch) + + + +#ifdef __cplusplus +} +#endif + +#endif //__DMA_H__ + diff --git a/sdk-modifications/libsrc/dma/dma.mk b/sdk-modifications/libsrc/dma/dma.mk deleted file mode 100644 index 0edf343..0000000 --- a/sdk-modifications/libsrc/dma/dma.mk +++ /dev/null @@ -1,9 +0,0 @@ -#dma.mk - -SRC += $(DMA_DIR)/dmacopy.c - -SSRC += - -INC += -I$(DMA_DIR) - -CFLAGS += \ No newline at end of file diff --git a/sdk-modifications/libsrc/dma/dmacopy.c b/sdk-modifications/libsrc/dma/dmacopy.c deleted file mode 100644 index 83609d3..0000000 --- a/sdk-modifications/libsrc/dma/dmacopy.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include "ds2_dma.h" -#include "ds2_types.h" - -#define MAX_DMA_NUM 6 /* max 6 channels */ - - -// DMA request source register -#define DMAC_DRSR_RS_BIT 0 -#define DMAC_DRSR_RS_MASK (0x2f << DMAC_DRSR_RS_BIT) - #define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) - #define DMAC_DRSR_RS_UART0OUT (20 << DMAC_DRSR_RS_BIT) - #define DMAC_DRSR_RS_UART0IN (21 << DMAC_DRSR_RS_BIT) - #define DMAC_DRSR_RS_SSIOUT (22 << DMAC_DRSR_RS_BIT) - #define DMAC_DRSR_RS_SSIIN (23 << DMAC_DRSR_RS_BIT) - #define DMAC_DRSR_RS_AICOUT (24 << DMAC_DRSR_RS_BIT) - #define DMAC_DRSR_RS_AICIN (25 << DMAC_DRSR_RS_BIT) - #define DMAC_DRSR_RS_MSCOUT (26 << DMAC_DRSR_RS_BIT) //SD0 - #define DMAC_DRSR_RS_MSCIN (27 << DMAC_DRSR_RS_BIT) - - -// DMA channel command register -#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ -#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ -#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ -#define DMAC_DCMD_SWDH_MASK (0x03 << DMAC_DCMD_SWDH_BIT) - #define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) - #define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) - #define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) -#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ -#define DMAC_DCMD_DWDH_MASK (0x03 << DMAC_DCMD_DWDH_BIT) - #define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) - #define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) - #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) -#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ -#define DMAC_DCMD_DS_MASK (0x07 << DMAC_DCMD_DS_BIT) - #define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) - #define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) - #define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) - #define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) - #define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) -#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ -#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ - -#define DMAC_BASE 0xB3020000 -#define REG32(addr) *((volatile u32 *)(addr)) -#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ -#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) - -#define __dmac_channel_transmit_end_detected(n) \ - ( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) - -/* - * Copy 'size' bytes from src to dest, in blocks of 32 bytes. - * size is in bytes and must be a multiple of 32. - * Both src and dest must be aligned to 32 bytes. - * Returns 0 on failure, non-zero on success. - */ -int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size){ - int test = 0; - if(!(test = dma_request(ch, NULL, 0, - //increment dest addr, increment source addr - DMAC_DCMD_DAI | DMAC_DCMD_SAI | - //set src width 32 bytes, set dest width 32 bytes - DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | - //set copy mode to 32 bytes, copy in blocks - DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM, - //auto request type - DMAC_DRSR_RS_AUTO))) - { - dma_start(ch, (unsigned int)src, (unsigned int)dest, size); - } - return test; -} - -/* - -int sampleUsage(in ch, void *dest, void *src, unsigned int size){ - //channel 0 is used for mmc stuff, so its best to avoid using it - - //initialize and start copy - if(dma_copy32Byte(ch, dest, src, size)){ - dma_wait_finish(ch);//wait for copy to finish - dma_stop(ch);//must stop after transfer is done to reset channel - return 0; - } - return -1; -} - -*/ - -/* - * Copy 'size' bytes from src to dest, in blocks of 16 bytes. - * size is in bytes and must be a multiple of 16. - * Both src and dest must be aligned to 16 bytes. - * Returns 0 on failure, non-zero on success. - */ -int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size){ - int test = 0; - if(!(test = dma_request(ch, NULL, 0, - DMAC_DCMD_DAI | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_16 | - DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM, - DMAC_DRSR_RS_AUTO))) - { - dma_start(ch, (unsigned int)src, (unsigned int)dest, size); - } - - return test; -} - -/* - * Copy 'size' bytes from src to dest, in blocks of 32 bits (4 bytes). - * size is in bytes and must be a multiple of 4. - * Both src and dest must be aligned to 32 bits (4 bytes). - * Returns 0 on failure, non-zero on success. - */ -int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size){ - int test = 0; - if(!(test = dma_request(ch, NULL, 0, - DMAC_DCMD_DAI | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | - DMAC_DCMD_DS_32BIT | DMAC_DCMD_TM, - DMAC_DRSR_RS_AUTO))) - { - dma_start(ch, (unsigned int)src, (unsigned int)dest, size); - } - - return test; -} - -/* - * Copy 'size' bytes from src to dest, in blocks of 16 bits (2 bytes). - * size is in bytes and must be a multiple of 2. - * Both src and dest must be aligned to 16 bits (2 bytes). - * Returns 0 on failure, non-zero on success. - */ -int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size){ - int test = 0; - - if(!(test = dma_request(ch, NULL, 0, - DMAC_DCMD_DAI | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | - DMAC_DCMD_DS_16BIT, - DMAC_DRSR_RS_AUTO))) - { - dma_start(ch, (unsigned int)src, (unsigned int)dest, size); - } - - return test; -} - - -//returns if a channel is still copying -int dma_isBusy(int ch){ - if(ch < 1 || ch >= MAX_DMA_NUM) - return 0; - - return !__dmac_channel_transmit_end_detected(ch); -} - -//returns the first non busy channel -int dma_getFree(void){ - int i; - for(i = 1; i < MAX_DMA_NUM; i++){ - if(!dma_isBusy(i)) - return i; - } - return -1; -} diff --git a/sdk-modifications/libsrc/dma/ds2_dma.h b/sdk-modifications/libsrc/dma/ds2_dma.h deleted file mode 100644 index 491df0e..0000000 --- a/sdk-modifications/libsrc/dma/ds2_dma.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __DMA_H__ -#define __DMA_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//register a DMA transfer request -//ch: channel id request, there are 6 channles, -//irq_handler: the DMA interruption handle -//arg: argument to the handle -//mode: DMA mode, such as port width, address increased/fixed, and so on -//type: DMA request type -extern int dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg, - unsigned int mode, unsigned int type); - -//start DMA transfer, must request a DMA first -//ch: channel id -//srcAddr: DMA source address -//dstAddr: DMA destination address -//count: DMA transfer count, the total bytes due the mode in dma_request -extern void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr, - unsigned int count); - -//Stop DMA transfer -extern void dma_stop(int ch); - -//Wait DMA transfer over -extern int dma_wait_finish(int ch); - - -/* - * Copy 'size' bytes from src to dest, in blocks of 32 bytes. - * size is in bytes and must be a multiple of 32. - * Both src and dest must be aligned to 32 bytes. - * Returns 0 on failure, non-zero on success. - */ -extern int dma_copy32Byte(int ch, void *dest, void *src, unsigned int size); -// Blocks of 16 bytes, aligned to 16 bytes -extern int dma_copy16Byte(int ch, void *dest, void *src, unsigned int size); -// Blocks of 4 bytes, aligned to 4 bytes -extern int dma_copy32Bit(int ch, void *dest, void *src, unsigned int size); -// Blocks of 2 bytes, aligned to 2 bytes -extern int dma_copy16Bit(int ch, void *dest, void *src, unsigned int size); -extern int dma_isBusy(int ch); -extern int dma_isFree(int ch); -extern int dma_getFree(void); - -#ifdef __cplusplus -} -#endif - -#endif //__DMA_H__ - diff --git a/sdk-modifications/libsrc/fs/bit_ops.h b/sdk-modifications/libsrc/fs/bit_ops.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/cache.c b/sdk-modifications/libsrc/fs/cache.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/directory.c b/sdk-modifications/libsrc/fs/directory.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/directory.h b/sdk-modifications/libsrc/fs/directory.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/disc_io/disc.c b/sdk-modifications/libsrc/fs/disc_io/disc.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/disc_io/disc.h b/sdk-modifications/libsrc/fs/disc_io/disc.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/disc_io/disc_io.h b/sdk-modifications/libsrc/fs/disc_io/disc_io.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.c b/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.h b/sdk-modifications/libsrc/fs/disc_io/io_ds2_mmcf.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/ds2_fcntl.c b/sdk-modifications/libsrc/fs/ds2_fcntl.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/ds2_fcntl.h b/sdk-modifications/libsrc/fs/ds2_fcntl.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/ds2_unistd.c b/sdk-modifications/libsrc/fs/ds2_unistd.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/ds2_unistd.h b/sdk-modifications/libsrc/fs/ds2_unistd.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fat.h b/sdk-modifications/libsrc/fs/fat.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fat_misc.c b/sdk-modifications/libsrc/fs/fat_misc.c index c0f62ac..335ab59 100644 --- a/sdk-modifications/libsrc/fs/fat_misc.c +++ b/sdk-modifications/libsrc/fs/fat_misc.c @@ -1,9 +1,9 @@ -//fat_misc.c -//v1.0 - +//fat_misc.c +//v1.0 + #include "fat_misc.h" -#include "fs_api.h" - +#include "fs_api.h" + static unsigned int _usedSecNums; static int strFindFromEnd( char *str,char strValue ) @@ -40,11 +40,11 @@ static int strFindFromEnd( char *str,char strValue ) int getDirSize( const char * path, int includeSubdirs, unsigned int * dirSize ) { - char dirPath[MAX_FILENAME_LENGTH]; + char dirPath[MAX_FILENAME_LENGTH]; unsigned int size = 0; if( "" == path ){ return false; - } + } memset( dirPath,0,MAX_FILENAME_LENGTH ); strcpy( dirPath,path ); @@ -54,29 +54,31 @@ int getDirSize( const char * path, int includeSubdirs, unsigned int * dirSize ) if( strlen(dirPath) > MAX_FILENAME_LENGTH ) return false; - DIR_STATE_STRUCT *dir; dir = fat_opendir((const char*)dirPath); + DIR_STATE_STRUCT *dir; + dir = fat_opendir((const char*)dirPath); if (dir == NULL) - return false; - struct stat stat_buf; - DIR_ENTRY *currentEntry; - char* filename; - - while(fat_readdir_ex(dir, &stat_buf) != NULL) + return false; + + struct stat stat_buf; + DIR_ENTRY *currentEntry; + char* filename; + + while((currentEntry = fat_readdir_ex(dir, &stat_buf)) != NULL) { - filename = currentEntry->d_name; - + filename = currentEntry->d_name; + if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; if (!(stat_buf.st_mode & S_IFDIR)) { size += (stat_buf.st_size+511)/512; _usedSecNums +=(stat_buf.st_size+511)/512; - } - else if (includeSubdirs) + } + else if (includeSubdirs) { // calculate the size recursively - unsigned int subDirSize = 0; - char dirPathBuffer[MAX_FILENAME_LENGTH]; + unsigned int subDirSize = 0; + char dirPathBuffer[MAX_FILENAME_LENGTH]; memset( dirPathBuffer,0,MAX_FILENAME_LENGTH ); strcpy( dirPathBuffer,dirPath ); @@ -90,8 +92,8 @@ int getDirSize( const char * path, int includeSubdirs, unsigned int * dirSize ) memset( dirPath,0,MAX_FILENAME_LENGTH ); strcpy( dirPath,dirPathBuffer ); } - } - + } + fat_closedir(dir); *dirSize = size; @@ -102,7 +104,7 @@ int fat_getDiskTotalSpace( char * diskName, unsigned int * diskSpace ) { if( !strcmp("",diskName) ) return false; - + unsigned int len = strlen(diskName); if( *(diskName+len-1) != '/' ){ *(diskName+len) = '/'; @@ -116,10 +118,10 @@ int fat_getDiskTotalSpace( char * diskName, unsigned int * diskSpace ) return true; } -int fat_getDiskSpaceInfo( char * diskName, unsigned int * total, unsigned int * used, unsigned int * freeSpace ) +int fat_getDiskSpaceInfo( char * diskName, unsigned int * total, unsigned int * used, unsigned int * freeSpace ) { _usedSecNums = 0; - + if( !strcmp("",diskName) ) return -1; if( !fat_getDiskTotalSpace(diskName, total) ) diff --git a/sdk-modifications/libsrc/fs/fat_misc.h b/sdk-modifications/libsrc/fs/fat_misc.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fatdir.h b/sdk-modifications/libsrc/fs/fatdir.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fatdir_ex.c b/sdk-modifications/libsrc/fs/fatdir_ex.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fatdir_ex.h b/sdk-modifications/libsrc/fs/fatdir_ex.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fatfile.c b/sdk-modifications/libsrc/fs/fatfile.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fatfile.h b/sdk-modifications/libsrc/fs/fatfile.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fatfile_ex.c b/sdk-modifications/libsrc/fs/fatfile_ex.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fatfile_ex.h b/sdk-modifications/libsrc/fs/fatfile_ex.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/file_allocation_table.h b/sdk-modifications/libsrc/fs/file_allocation_table.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/filetime.c b/sdk-modifications/libsrc/fs/filetime.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/filetime.h b/sdk-modifications/libsrc/fs/filetime.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fs.mk b/sdk-modifications/libsrc/fs/fs.mk index 9b17c48..3fee249 100644 --- a/sdk-modifications/libsrc/fs/fs.mk +++ b/sdk-modifications/libsrc/fs/fs.mk @@ -14,7 +14,7 @@ SRC += $(FS_DIR)/cache.c \ $(FS_DIR)/disc_io/disc.c \ $(FS_DIR)/disc_io/io_ds2_mmcf.c \ $(FS_DIR)/ds2_fcntl.c \ - $(FS_DIR)/ds2_unistd.c \ + $(FS_DIR)/ds2_unistd.c SSRC += diff --git a/sdk-modifications/libsrc/fs/fs_api.c b/sdk-modifications/libsrc/fs/fs_api.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fs_api.h b/sdk-modifications/libsrc/fs/fs_api.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fs_cache.h b/sdk-modifications/libsrc/fs/fs_cache.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fs_common.h b/sdk-modifications/libsrc/fs/fs_common.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fs_unicode.c b/sdk-modifications/libsrc/fs/fs_unicode.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/fs_unicode.h b/sdk-modifications/libsrc/fs/fs_unicode.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/libfat.c b/sdk-modifications/libsrc/fs/libfat.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/mem_allocate.h b/sdk-modifications/libsrc/fs/mem_allocate.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/partition.c b/sdk-modifications/libsrc/fs/partition.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/fs/partition.h b/sdk-modifications/libsrc/fs/partition.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/key/key.c b/sdk-modifications/libsrc/key/key.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/key/key.h b/sdk-modifications/libsrc/key/key.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/key/key.mk b/sdk-modifications/libsrc/key/key.mk old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/README b/sdk-modifications/libsrc/zlib/README index ee06114..90f3327 100644 --- a/sdk-modifications/libsrc/zlib/README +++ b/sdk-modifications/libsrc/zlib/README @@ -1 +1,8 @@ -This is a modified source release of zlib. zconf.h removes a reference to sys/types.h, which creates type conflicts on the DS2 SDK. For a pristine source release of zlib, please visit . \ No newline at end of file +This is a modified source release of zlib. + +Changes: + zconf.h removes a reference to sys/types.h, which creates type conflicts on the DS2 SDK. + gzguts.h removes standard c library includes for DS2 SDK equivalents + + +For a pristine source release of zlib, please visit . \ No newline at end of file diff --git a/sdk-modifications/libsrc/zlib/adler32.c b/sdk-modifications/libsrc/zlib/adler32.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/compress.c b/sdk-modifications/libsrc/zlib/compress.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/crc32.c b/sdk-modifications/libsrc/zlib/crc32.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/crc32.h b/sdk-modifications/libsrc/zlib/crc32.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/deflate.c b/sdk-modifications/libsrc/zlib/deflate.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/deflate.h b/sdk-modifications/libsrc/zlib/deflate.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/gzclose.c b/sdk-modifications/libsrc/zlib/gzclose.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/gzguts.h b/sdk-modifications/libsrc/zlib/gzguts.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/gzlib.c b/sdk-modifications/libsrc/zlib/gzlib.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/gzread.c b/sdk-modifications/libsrc/zlib/gzread.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/gzwrite.c b/sdk-modifications/libsrc/zlib/gzwrite.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/infback.c b/sdk-modifications/libsrc/zlib/infback.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/inffast.c b/sdk-modifications/libsrc/zlib/inffast.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/inffast.h b/sdk-modifications/libsrc/zlib/inffast.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/inffixed.h b/sdk-modifications/libsrc/zlib/inffixed.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/inflate.c b/sdk-modifications/libsrc/zlib/inflate.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/inflate.h b/sdk-modifications/libsrc/zlib/inflate.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/inftrees.c b/sdk-modifications/libsrc/zlib/inftrees.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/inftrees.h b/sdk-modifications/libsrc/zlib/inftrees.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/trees.c b/sdk-modifications/libsrc/zlib/trees.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/trees.h b/sdk-modifications/libsrc/zlib/trees.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/uncompr.c b/sdk-modifications/libsrc/zlib/uncompr.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/zconf.h b/sdk-modifications/libsrc/zlib/zconf.h index 96810e7..587a87c 100644 --- a/sdk-modifications/libsrc/zlib/zconf.h +++ b/sdk-modifications/libsrc/zlib/zconf.h @@ -399,8 +399,8 @@ typedef uLong FAR uLongf; #ifdef STDC # ifndef Z_SOLO // # include /* for off_t */ -// Does not work with the DS2 SDK. There is a type conflict between sys/types.h -// and fs_api.h. +// Doesn't work on the DS2 SDK, because there are type conflicts between +// sys/types.h and the filesystem API.//# include /* for off_t */ # endif #endif diff --git a/sdk-modifications/libsrc/zlib/zlib.h b/sdk-modifications/libsrc/zlib/zlib.h old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/zlib.mk b/sdk-modifications/libsrc/zlib/zlib.mk old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/zutil.c b/sdk-modifications/libsrc/zlib/zutil.c old mode 100644 new mode 100755 diff --git a/sdk-modifications/libsrc/zlib/zutil.h b/sdk-modifications/libsrc/zlib/zutil.h old mode 100644 new mode 100755 diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 14c6243..de30332 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -145,9 +145,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) case 1: #ifdef DS2_DMA __dcache_writeback_all(); - dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); - dma_wait_finish(1); - dma_stop(1); + ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); + ds2_DMA_wait(1); + ds2_DMA_stop(1); #else memcpy(up_screen_addr, GFX.Screen+256*32*2, 256*192*2); #endif @@ -157,9 +157,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) case 2: #ifdef DS2_DMA __dcache_writeback_all(); - dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); - dma_wait_finish(1); - dma_stop(1); + ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2); + ds2_DMA_wait(1); + ds2_DMA_stop(1); #else memcpy(up_screen_addr, GFX.Screen, 256*192*2); #endif @@ -169,9 +169,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) case 3: #ifdef DS2_DMA __dcache_writeback_all(); - dma_copy32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); - dma_wait_finish(1); - dma_stop(1); + ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); + ds2_DMA_wait(1); + ds2_DMA_stop(1); #else memcpy(up_screen_addr, GFX.Screen+256*16*2, 256*192*2); #endif @@ -195,9 +195,9 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) for(m = 0; m < 32; m++) { #ifdef DS2_DMA - dma_copy32Byte(1 /* channel: graphics */, dst, src, 256 * 6 * 2); - dma_wait_finish(1); - dma_stop(1); + ds2_DMAcopy_32Byte(1 /* channel: graphics */, dst, src, 256 * 6 * 2); + ds2_DMA_wait(1); + ds2_DMA_stop(1); #else memcpy(dst, src, 256*6*2); #endif @@ -987,7 +987,7 @@ void S9xProcessSound (unsigned int) unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT * 3/4) + if(ds2_checkAudiobuff() > 4) { LastSoundEmissionTime++; return; -- cgit v1.2.3 From dfa2d3cc68616ddc7e5c5fd1bb9f250fa44cd2fd Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Tue, 5 Feb 2013 01:33:39 -0500 Subject: Add include files from BassAceGold's library, release 2 fix 2.2. --- README.md | 8 +- sdk-modifications/include/archdefs.h | 2356 +++++++++++++++++++++ sdk-modifications/include/bit_ops.h | 58 + sdk-modifications/include/console.h | 9 + sdk-modifications/include/directory.h | 172 ++ sdk-modifications/include/ds2_cpu.h | 57 + sdk-modifications/include/ds2_cpuclock.h | 21 + sdk-modifications/include/ds2_dma.h | 142 ++ sdk-modifications/include/ds2_excpt.h | 55 + sdk-modifications/include/ds2_fcntl.h | 51 + sdk-modifications/include/ds2_malloc.h | 32 + sdk-modifications/include/ds2_mmc_api.h | 56 + sdk-modifications/include/ds2_timer.h | 50 + sdk-modifications/include/ds2_types.h | 45 + sdk-modifications/include/ds2io.h | 285 +++ sdk-modifications/include/fat.h | 118 ++ sdk-modifications/include/fatdir.h | 81 + sdk-modifications/include/fatdir_ex.h | 18 + sdk-modifications/include/fatfile.h | 89 + sdk-modifications/include/fatfile_ex.h | 19 + sdk-modifications/include/file_allocation_table.h | 64 + sdk-modifications/include/filetime.h | 44 + sdk-modifications/include/fs_api.h | 151 ++ sdk-modifications/include/fs_cache.h | 118 ++ sdk-modifications/include/fs_common.h | 129 ++ sdk-modifications/include/fs_unicode.h | 16 + sdk-modifications/include/mem_allocate.h | 47 + sdk-modifications/include/mips.h | 820 +++++++ sdk-modifications/include/mipsregs.h | 985 +++++++++ sdk-modifications/include/mmc_api.h | 56 + sdk-modifications/include/partition.h | 131 ++ sdk-modifications/include/tcm.h | 10 + sdk-modifications/libsrc/core/ds2_cpuclock.c | 8 +- sdk-modifications/libsrc/core/ds2_dma.h | 16 +- 34 files changed, 6301 insertions(+), 16 deletions(-) create mode 100755 sdk-modifications/include/archdefs.h create mode 100755 sdk-modifications/include/bit_ops.h create mode 100755 sdk-modifications/include/console.h create mode 100755 sdk-modifications/include/directory.h create mode 100755 sdk-modifications/include/ds2_cpu.h create mode 100644 sdk-modifications/include/ds2_cpuclock.h create mode 100644 sdk-modifications/include/ds2_dma.h create mode 100755 sdk-modifications/include/ds2_excpt.h create mode 100755 sdk-modifications/include/ds2_fcntl.h create mode 100755 sdk-modifications/include/ds2_malloc.h create mode 100755 sdk-modifications/include/ds2_mmc_api.h create mode 100755 sdk-modifications/include/ds2_timer.h create mode 100755 sdk-modifications/include/ds2_types.h create mode 100755 sdk-modifications/include/ds2io.h create mode 100755 sdk-modifications/include/fat.h create mode 100755 sdk-modifications/include/fatdir.h create mode 100755 sdk-modifications/include/fatdir_ex.h create mode 100755 sdk-modifications/include/fatfile.h create mode 100755 sdk-modifications/include/fatfile_ex.h create mode 100755 sdk-modifications/include/file_allocation_table.h create mode 100755 sdk-modifications/include/filetime.h create mode 100755 sdk-modifications/include/fs_api.h create mode 100755 sdk-modifications/include/fs_cache.h create mode 100755 sdk-modifications/include/fs_common.h create mode 100755 sdk-modifications/include/fs_unicode.h create mode 100755 sdk-modifications/include/mem_allocate.h create mode 100755 sdk-modifications/include/mips.h create mode 100755 sdk-modifications/include/mipsregs.h create mode 100755 sdk-modifications/include/mmc_api.h create mode 100755 sdk-modifications/include/partition.h create mode 100755 sdk-modifications/include/tcm.h diff --git a/README.md b/README.md index 61b52fe..5fb7351 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,10 @@ Additionally, you will need to add the updated `zlib`, DMA (Direct Memory Access) and filesystem access routines provided by BassAceGold and recompile `libds2a.a`. To do this: -> sudo rm -r /opt/ds2sdk/libsrc/{console,core,fs,key,zlib,Makefile} -> sudo cp -r sdk-modifications/libsrc /opt/ds2sdk -> sudo chmod -R 600 /opt/ds2sdk/libsrc -> sudo chmod -R a+rX /opt/ds2sdk/libsrc +> sudo rm -r /opt/ds2sdk/libsrc/{console,core,fs,key,zlib,Makefile} /opt/ds2sdk/include +> sudo cp -r sdk-modifications/{libsrc,include} /opt/ds2sdk +> sudo chmod -R 600 /opt/ds2sdk/{libsrc,include} +> sudo chmod -R a+rX /opt/ds2sdk/{libsrc,include} > cd /opt/ds2sdk/libsrc > sudo rm libds2a.a ../lib/libds2a.a > sudo make diff --git a/sdk-modifications/include/archdefs.h b/sdk-modifications/include/archdefs.h new file mode 100755 index 0000000..37c61b8 --- /dev/null +++ b/sdk-modifications/include/archdefs.h @@ -0,0 +1,2356 @@ +/************************************************************************** +* * +* PROJECT : MIPS port for uC/OS-II * +* * +* MODULE : ARCHDEFS.h * +* * +* AUTHOR : Michael Anburaj * +* URL : http://geocities.com/michaelanburaj/ * +* EMAIL: michaelanburaj@hotmail.com * +* * +* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board * +* * +* TOOL-CHAIN : SDE & Cygnus * +* * +* DESCRIPTION : * +* Architecture definitions. * +* * +**************************************************************************/ + + +#ifndef __ARCHDEFS_H__ +#define __ARCHDEFS_H__ + + +/* ********************************************************************* */ +/* Module configuration */ + + +/* ********************************************************************* */ +/* Interface macro & data definition */ + +/* + * Utility defines for cross platform handling of 64bit constants. + */ + +#if !defined(Append) + #define Append(c,s) (c##s) +#endif + +#if !defined(__assembler) && !defined(MIPSAVPENV) + #if defined(NT) + #if !defined(UNS64Const) + #define UNS64Const(c) Append(c,ui64) + #endif + + #if !defined(INT64Const) + #define INT64Const(c) Append(c,i64) + #endif + #else + #if !defined(UNS64Const) + #define UNS64Const(c) Append(c,ull) + #endif + + #if !defined(INT64Const) + #define INT64Const(c) Append(c,ll) + #endif + #endif +#else /* Not C or C++ */ + #if !defined(UNS64Const) + #define UNS64Const(c) c + #endif + + #if !defined(INT64Const) + #define INT64Const(c) c + #endif +#endif /* C or C++ */ + + +/* + ************************************************************************ + * I N S T R U C T I O N F O R M A T S * + ************************************************************************ + * + * The following definitions describe each field in an instruction. There + * is one diagram for each type of instruction, with field definitions + * following the diagram for that instruction. Note that if a field of + * the same name and position is defined in an earlier diagram, it is + * not defined again in the subsequent diagram. Only new fields are + * defined for each diagram. + * + * R-Type (operate) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | rs | rt | rd | sa | | + * | Opcode | | | Tcode | func | + * | | Bcode | | sel | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnOpcode 26 +#define M_InstnOpcode (0x3f << S_InstnOpcode) +#define S_InstnRS 21 +#define M_InstnRS (0x1f << S_InstnRS) +#define S_InstnRT 16 +#define M_InstnRT (0x1f << S_InstnRT) +#define S_InstnRD 11 +#define M_InstnRD (0x1f << S_InstnRD) +#define S_InstnSA 6 +#define M_InstnSA (0x1f << S_InstnSA) +#define S_InstnTcode 6 +#define M_InstnTcode (0x3ff << S_InstnTcode) +#define S_InstnBcode 6 +#define M_InstnBcode (0xfffff << S_InstnBcode) +#define S_InstnFunc 0 +#define M_InstnFunc (0x3f << S_InstnFunc) +#define S_InstnSel 0 +#define M_InstnSel (0x7 << S_InstnSel) + +/* + * I-Type (load, store, branch, immediate) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | rt | Offset | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnOffset 0 +#define M_InstnOffset (0xffff << S_InstnOffset) + +/* + * I-Type (pref) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | hint | Offset | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnHint S_InstnRT +#define M_InstnHint M_InstnRT + +/* + * J-Type (jump) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | JIndex | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnJIndex 0 +#define M_InstnJIndex (0x03ffffff << S_InstnJIndex) + +/* + * FP R-Type (operate) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | fmt | ft | fs | fd | func | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnFmt S_InstnRS +#define M_InstnFmt M_InstnRS +#define S_InstnFT S_InstnRT +#define M_InstnFT M_InstnRT +#define S_InstnFS S_InstnRD +#define M_InstnFS M_InstnRD +#define S_InstnFD S_InstnSA +#define M_InstnFD M_InstnSA + +/* + * FP R-Type (cpu <-> cpu data movement)) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | sub | rt | fs | 0 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnSub S_InstnRS +#define M_InstnSub M_InstnRS + +/* + * FP R-Type (compare) + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | |C| | + * | Opcode | fmt | ft | fs | cc |0|A| func | + * | | | | | | |B| | + * | | | | | | |S| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnCCcmp 8 +#define M_InstnCCcmp (0x7 << S_InstnCCcmp) +#define S_InstnCABS 6 +#define M_InstnCABS (0x1 << S_InstnCABS) + +/* + * FP R-Type (FPR conditional move on FP cc) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | fmt | cc |n|t| fs | fd | func | + * | | | |d|f| | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnCC 18 +#define M_InstnCC (0x7 << S_InstnCC) +#define S_InstnND 17 +#define M_InstnND (0x1 << S_InstnND) +#define S_InstnTF 16 +#define M_InstnTF (0x1 << S_InstnTF) + +/* + * FP R-Type (3-operand operate) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | fr | ft | fs | fd | op4 | fmt3| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnFR S_InstnRS +#define M_InstnFR M_InstnRS +#define S_InstnOp4 3 +#define M_InstnOp4 (0x7 << S_InstnOp4) +#define S_InstnFmt3 0 +#define M_InstnFmt3 (0x7 << S_InstnFmt3) + +/* + * FP R-Type (Indexed load, store) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | rt | 0 | fd | func | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +/* + * FP R-Type (prefx) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | rt | hint | 0 | func | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define S_InstnHintX S_InstnRD +#define M_InstnHintX M_InstnRD + +/* + * FP R-Type (GPR conditional move on FP cc) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | cc |n|t| rd | 0 | func | + * | | | |d|f| | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/* + * FP I-Type (load, store) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | rs | ft | Offset | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/* + * FP I-Type (branch) + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | fmt | cc |n|t| Offset | + * | | | |d|f| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + +/* + ************************************************************************* + * V I R T U A L A D D R E S S D E F I N I T I O N S * + ************************************************************************* + */ + +#ifdef MIPSADDR64 +#define A_K0BASE UNS64Const(0xffffffff80000000) +#define A_K1BASE UNS64Const(0xffffffffa0000000) +#define A_K2BASE UNS64Const(0xffffffffc0000000) +#define A_K3BASE UNS64Const(0xffffffffe0000000) +#define A_REGION UNS64Const(0xc000000000000000) +#define A_XKPHYS_ATTR UNS64Const(0x3800000000000000) +#else +#define A_K0BASE 0x80000000 +#define A_K1BASE 0xa0000000 +#define A_K2BASE 0xc0000000 +#define A_K3BASE 0xe0000000 +#endif +#define M_KMAPPED 0x40000000 /* KnSEG address is mapped if bit is one */ + + +#ifdef MIPS_Model64 + +#define S_VMAP64 62 +#define M_VMAP64 UNS64Const(0xc000000000000000) + +#define K_VMode11 3 +#define K_VMode10 2 +#define K_VMode01 1 +#define K_VMode00 0 + +#define S_KSEG3 29 +#define M_KSEG3 (0x7 << S_KSEG3) +#define K_KSEG3 7 + +#define S_SSEG 29 +#define M_SSEG (0x7 << S_KSEG3) +#define K_SSEG 6 + +#define S_KSSEG 29 +#define M_KSSEG (0x7 << S_KSEG3) +#define K_KSSEG 6 + +#define S_KSEG1 29 +#define M_KSEG1 (0x7 << S_KSEG3) +#define K_KSEG1 5 + +#define S_KSEG0 29 +#define M_KSEG0 (0x7 << S_KSEG3) +#define K_KSEG0 4 + +#define S_XKSEG 29 +#define M_XKSEG (0x7 << S_KSEG3) +#define K_XKSEG 3 + +#define S_USEG 31 +#define M_USEG (0x1 << S_USEG) +#define K_USEG 0 + +#define S_EjtagProbeMem 20 +#define M_EjtagProbeMem (0x1 << S_EjtagProbeMem) +#define K_EjtagProbeMem 0 + + + +#else + +#define S_KSEG3 29 +#define M_KSEG3 (0x7 << S_KSEG3) +#define K_KSEG3 7 + +#define S_KSSEG 29 +#define M_KSSEG (0x7 << S_KSSEG) +#define K_KSSEG 6 + +#define S_SSEG 29 +#define M_SSEG (0x7 << S_SSEG) +#define K_SSEG 6 + +#define S_KSEG1 29 +#define M_KSEG1 (0x7 << S_KSEG1) +#define K_KSEG1 5 + +#define S_KSEG0 29 +#define M_KSEG0 (0x7 << S_KSEG0) +#define K_KSEG0 4 + +#define S_KUSEG 31 +#define M_KUSEG (0x1 << S_KUSEG) +#define K_KUSEG 0 + +#define S_SUSEG 31 +#define M_SUSEG (0x1 << S_SUSEG) +#define K_SUSEG 0 + +#define S_USEG 31 +#define M_USEG (0x1 << S_USEG) +#define K_USEG 0 + +#define K_EjtagLower 0xff200000 +#define K_EjtagUpper 0xff3fffff + +#define S_EjtagProbeMem 20 +#define M_EjtagProbeMem (0x1 << S_EjtagProbeMem) +#define K_EjtagProbeMem 0 + +#endif + + + +/* + ************************************************************************* + * C A C H E I N S T R U C T I O N O P E R A T I O N C O D E S * + ************************************************************************* + */ + +/* + * Cache encodings + */ +#define K_CachePriI 0 /* Primary Icache */ +#define K_CachePriD 1 /* Primary Dcache */ +#define K_CachePriU 1 /* Unified primary */ +#define K_CacheTerU 2 /* Unified Tertiary */ +#define K_CacheSecU 3 /* Unified secondary */ + + +/* + * Function encodings + */ +#define S_CacheFunc 2 /* Amount to shift function encoding within 5-bit field */ +#define K_CacheIndexInv 0 /* Index invalidate */ +#define K_CacheIndexWBInv 0 /* Index writeback invalidate */ +#define K_CacheIndexLdTag 1 /* Index load tag */ +#define K_CacheIndexStTag 2 /* Index store tag */ +#define K_CacheHitInv 4 /* Hit Invalidate */ +#define K_CacheFill 5 /* Fill (Icache only) */ +#define K_CacheHitWBInv 5 /* Hit writeback invalidate */ +#define K_CacheHitWB 6 /* Hit writeback */ +#define K_CacheFetchLock 7 /* Fetch and lock */ + +#define ICIndexInv ((K_CacheIndexInv << S_CacheFunc) | K_CachePriI) +#define DCIndexWBInv ((K_CacheIndexWBInv << S_CacheFunc) | K_CachePriD) +#define DCIndexInv DCIndexWBInv +#define ICIndexLdTag ((K_CacheIndexLdTag << S_CacheFunc) | K_CachePriI) +#define DCIndexLdTag ((K_CacheIndexLdTag << S_CacheFunc) | K_CachePriD) +#define ICIndexStTag ((K_CacheIndexStTag << S_CacheFunc) | K_CachePriI) +#define DCIndexStTag ((K_CacheIndexStTag << S_CacheFunc) | K_CachePriD) +#define ICHitInv ((K_CacheHitInv << S_CacheFunc) | K_CachePriI) +#define DCHitInv ((K_CacheHitInv << S_CacheFunc) | K_CachePriD) +#define ICFill ((K_CacheFill << S_CacheFunc) | K_CachePriI) +#define DCHitWBInv ((K_CacheHitWBInv << S_CacheFunc) | K_CachePriD) +#define DCHitWB ((K_CacheHitWB << S_CacheFunc) | K_CachePriD) +#define ICFetchLock ((K_CacheFetchLock << S_CacheFunc) | K_CachePriI) +#define DCFetchLock ((K_CacheFetchLock << S_CacheFunc) | K_CachePriD) + + +/* + ************************************************************************* + * P R E F E T C H I N S T R U C T I O N H I N T S * + ************************************************************************* + */ + +#define PrefLoad 0 +#define PrefStore 1 +#define PrefLoadStreamed 4 +#define PrefStoreStreamed 5 +#define PrefLoadRetained 6 +#define PrefStoreRetained 7 +#define PrefWBInval 25 +#define PrefNudge 25 + + +/* + ************************************************************************* + * C P U R E G I S T E R D E F I N I T I O N S * + ************************************************************************* + */ + + +/* + ************************************************************************* + * S O F T W A R E G P R N A M E S * + ************************************************************************* + */ + +#define zero $0 +#define AT $1 +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define ra $31 + +/* + * The following registers are used by the AVP environment and + * are not part of the normal software definitions. + */ + +#ifdef MIPSAVPENV +#define repc $25 /* Expected exception PC */ +#define tid $30 /* Current test case address */ +#endif + + +/* + ************************************************************************* + * H A R D W A R E G P R N A M E S * + ************************************************************************* + * + * In the AVP environment, several of the `r' names are removed from the + * name space because they are used by the kernel for special purposes. + * Removing them causes assembly rather than runtime errors for tests that + * use the `r' names. + * + * - r25 (repc) is used as the expected PC on an exception + * - r26-r27 (k0, k1) are used in the exception handler + * - r30 (tid) is used as the current test address + */ + +#define r0 $0 +#define r1 $1 +#define r2 $2 +#define r3 $3 +#define r4 $4 +#define r5 $5 +#define r6 $6 +#define r7 $7 +#define r8 $8 +#define r9 $9 +#define r10 $10 +#define r11 $11 +#define r12 $12 +#define r13 $13 +#define r14 $14 +#define r15 $15 +#define r16 $16 +#define r17 $17 +#define r18 $18 +#define r19 $19 +#define r20 $20 +#define r21 $21 +#define r22 $22 +#define r23 $23 +#define r24 $24 +#ifdef MIPSAVPENV +#define r25 r25_unknown +#define r26 r26_unknown +#define r27 r27_unknown +#else +#define r25 $25 +#define r26 $26 +#define r27 $27 +#endif +#define r28 $28 +#define r29 $29 +#ifdef MIPSAVPENV +#define r30 r30_unknown +#else +#define r30 $30 +#endif +#define r31 $31 + + +/* + ************************************************************************* + * H A R D W A R E G P R I N D I C E S * + ************************************************************************* + * + * These definitions provide the index (number) of the GPR, as opposed + * to the assembler register name ($n). + */ + +#define R_r0 0 +#define R_r1 1 +#define R_r2 2 +#define R_r3 3 +#define R_r4 4 +#define R_r5 5 +#define R_r6 6 +#define R_r7 7 +#define R_r8 8 +#define R_r9 9 +#define R_r10 10 +#define R_r11 11 +#define R_r12 12 +#define R_r13 13 +#define R_r14 14 +#define R_r15 15 +#define R_r16 16 +#define R_r17 17 +#define R_r18 18 +#define R_r19 19 +#define R_r20 20 +#define R_r21 21 +#define R_r22 22 +#define R_r23 23 +#define R_r24 24 +#define R_r25 25 +#define R_r26 26 +#define R_r27 27 +#define R_r28 28 +#define R_r29 29 +#define R_r30 30 +#define R_r31 31 +#define R_hi 32 /* Hi register */ +#define R_lo 33 /* Lo register */ + + +/* + ************************************************************************* + * S O F T W A R E G P R M A S K S * + ************************************************************************* + * + * These definitions provide the bit mask corresponding to the GPR number + */ + +#define M_AT (1<<1) +#define M_v0 (1<<2) +#define M_v1 (1<<3) +#define M_a0 (1<<4) +#define M_a1 (1<<5) +#define M_a2 (1<<6) +#define M_a3 (1<<7) +#define M_t0 (1<<8) +#define M_t1 (1<<9) +#define M_t2 (1<<10) +#define M_t3 (1<<11) +#define M_t4 (1<<12) +#define M_t5 (1<<13) +#define M_t6 (1<<14) +#define M_t7 (1<<15) +#define M_s0 (1<<16) +#define M_s1 (1<<17) +#define M_s2 (1<<18) +#define M_s3 (1<<19) +#define M_s4 (1<<20) +#define M_s5 (1<<21) +#define M_s6 (1<<22) +#define M_s7 (1<<23) +#define M_t8 (1<<24) +#define M_t9 (1<<25) +#define M_k0 (1<<26) +#define M_k1 (1<<27) +#define M_gp (1<<28) +#define M_sp (1<<29) +#define M_fp (1<<30) +#define M_ra (1<<31) + + +/* + ************************************************************************* + * C P 0 R E G I S T E R D E F I N I T I O N S * + ************************************************************************* + * Each register has the following definitions: + * + * C0_rrr The register number (as a $n value) + * R_C0_rrr The register index (as an integer corresponding + * to the register number) + * + * Each field in a register has the following definitions: + * + * S_rrrfff The shift count required to right-justify + * the field. This corresponds to the bit + * number of the right-most bit in the field. + * M_rrrfff The Mask required to isolate the field. + * + * Register diagrams included below as comments correspond to the + * MIPS32 and MIPS64 architecture specifications. Refer to other + * sources for register diagrams for older architectures. + */ + + +/* + ************************************************************************ + * I N D E X R E G I S T E R ( 0 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |P| 0 | Index | Index + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Index $0 +#define R_C0_Index 0 +#define C0_INX C0_Index /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_IndexP 31 /* Probe failure (R)*/ +#define M_IndexP (0x1 << S_IndexP) + +#define S_IndexIndex 0 /* TLB index (R/W)*/ +#define M_IndexIndex (0x3f << S_IndexIndex) + +#define M_Index0Fields 0x7fffffc0 +#define M_IndexRFields 0x80000000 + + +/* + ************************************************************************ + * R A N D O M R E G I S T E R ( 1 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Index | Random + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Random $1 +#define R_C0_Random 1 +#define C0_RAND $1 /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_RandomIndex 0 /* TLB random index (R)*/ +#define M_RandomIndex (0x3f << S_RandomIndex) + +#define M_Random0Fields 0xffffffc0 +#define M_RandomRFields 0x0000003f + + +/* + ************************************************************************ + * E N T R Y L O 0 R E G I S T E R ( 2 ) * + ************************************************************************ + * + * 6 6 6 6 5 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 2 1 0 9 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Fill (0) //| 0 | PFN | C |D|V|G| EntryLo0 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_EntryLo0 $2 +#define R_C0_EntryLo0 2 +#define C0_TLBLO_0 C0_EntryLo0 /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_EntryLoPFN 6 /* PFN (R/W) */ +#define M_EntryLoPFN (0xffffff << S_EntryLoPFN) +#define S_EntryLoC 3 /* Coherency attribute (R/W) */ +#define M_EntryLoC (0x7 << S_EntryLoC) +#define S_EntryLoD 2 /* Dirty (R/W) */ +#define M_EntryLoD (0x1 << S_EntryLoD) +#define S_EntryLoV 1 /* Valid (R/W) */ +#define M_EntryLoV (0x1 << S_EntryLoV) +#define S_EntryLoG 0 /* Global (R/W) */ +#define M_EntryLoG (0x1 << S_EntryLoG) +#define M_EntryLoOddPFN (0x1 << S_EntryLoPFN) /* Odd PFN bit */ +#define S_EntryLo_RS K_PageAlign /* Right-justify PFN */ +#define S_EntryLo_LS S_EntryLoPFN /* Position PFN to appropriate position */ + +#define M_EntryLo0Fields 0x00000000 +#define M_EntryLoRFields 0xc0000000 +#define M_EntryLo0Fields64 UNS64Const(0x0000000000000000) +#define M_EntryLoRFields64 UNS64Const(0xffffffffc0000000) + +/* + * Cache attribute values in the C field of EntryLo and the + * K0 field of Config + */ +#define K_CacheAttrCWTnWA 0 /* Cacheable, write-thru, no write allocate */ +#define K_CacheAttrCWTWA 1 /* Cacheable, write-thru, write allocate */ +#define K_CacheAttrU 2 /* Uncached */ +#define K_CacheAttrC 3 /* Cacheable */ +#define K_CacheAttrCN 3 /* Cacheable, non-coherent */ +#define K_CacheAttrCCE 4 /* Cacheable, coherent, exclusive */ +#define K_CacheAttrCCS 5 /* Cacheable, coherent, shared */ +#define K_CacheAttrCCU 6 /* Cacheable, coherent, update */ +#define K_CacheAttrUA 7 /* Uncached accelerated */ + + +/* + ************************************************************************ + * E N T R Y L O 1 R E G I S T E R ( 3 ) * + ************************************************************************ + * + * 6 6 6 6 5 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 2 1 0 9 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Fill (0) //| 0 | PFN | C |D|V|G| EntryLo1 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_EntryLo1 $3 +#define R_C0_EntryLo1 3 +#define C0_TLBLO_1 C0_EntryLo1 /* OBSOLETE - DO NOT USE IN NEW CODE */ + +/* + * Field definitions are as given for EntryLo0 above + */ + + +/* + ************************************************************************ + * C O N T E X T R E G I S T E R ( 4 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // PTEBase | BadVPN<31:13> | 0 | Context + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Context $4 +#define R_C0_Context 4 +#define C0_CTXT C0_Context /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_ContextPTEBase 23 /* PTE base (R/W) */ +#define M_ContextPTEBase (0x1ff << S_ContextPTEBase) +#define S_ContextBadVPN 4 /* BadVPN2 (R) */ +#define M_ContextBadVPN (0x7ffff << S_ContextBadVPN) +#define S_ContextBadVPN_LS 9 /* Position BadVPN to bit 31 */ +#define S_ContextBadVPN_RS 13 /* Right-justify shifted BadVPN field */ + +#define M_Context0Fields 0x0000000f +#define M_ContextRFields 0x007ffff0 +#define M_Context0Fields64 UNS64Const(0x000000000000000f) +#define M_ContextRFields64 UNS64Const(0x00000000007ffff0) + + +/* + ************************************************************************ + * P A G E M A S K R E G I S T E R ( 5 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Mask | 0 | PageMask + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_PageMask $5 +#define R_C0_PageMask 5 /* Mask (R/W) */ +#define C0_PGMASK C0_PageMask /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_PageMaskMask 13 +#define M_PageMaskMask (0xfff << S_PageMaskMask) + +#define M_PageMask0Fields 0xfe001fff +#define M_PageMaskRFields 0x00000000 + +/* + * Values in the Mask field + */ +#define K_PageMask4K 0x000 /* K_PageMasknn values are values for use */ +#define K_PageMask16K 0x003 /* with KReqPageAttributes or KReqPageMask macros */ +#define K_PageMask64K 0x00f +#define K_PageMask256K 0x03f +#define K_PageMask1M 0x0ff +#define K_PageMask4M 0x3ff +#define K_PageMask16M 0xfff + +#define M_PageMask4K (K_PageMask4K << S_PageMaskMask) /* M_PageMasknn values are masks */ +#define M_PageMask16K (K_PageMask16K << S_PageMaskMask) /* in position in the PageMask register */ +#define M_PageMask64K (K_PageMask64K << S_PageMaskMask) +#define M_PageMask256K (K_PageMask256K << S_PageMaskMask) +#define M_PageMask1M (K_PageMask1M << S_PageMaskMask) +#define M_PageMask4M (K_PageMask4M << S_PageMaskMask) +#define M_PageMask16M (K_PageMask16M << S_PageMaskMask) + + +/* + ************************************************************************ + * W I R E D R E G I S T E R ( 6 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Index | Wired + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Wired $6 +#define R_C0_Wired 6 +#define C0_TLBWIRED C0_Wired /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_WiredIndex 0 /* TLB wired boundary (R/W) */ +#define M_WiredIndex (0x3f << S_WiredIndex) + +#define M_Wired0Fields 0xffffffc0 +#define M_WiredRFields 0x00000000 + + +/* + ************************************************************************ + * B A D V A D D R R E G I S T E R ( 8 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // Bad Virtual Address | BadVAddr + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_BadVAddr $8 +#define R_C0_BadVAddr 8 +#define C0_BADVADDR C0_BadVAddr /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_BadVAddrOddPage K_PageSize /* Even/Odd VA bit for pair of PAs */ + +#define M_BadVAddr0Fields 0x00000000 +#define M_BadVAddrRFields 0xffffffff +#define M_BadVAddr0Fields64 UNS64Const(0x0000000000000000) +#define M_BadVAddrRFields64 UNS64Const(0xffffffffffffffff) + +/* + ************************************************************************ + * C O U N T R E G I S T E R ( 9 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Count Value | Count + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Count $9 +#define R_C0_Count 9 +#define C0_COUNT C0_Count /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_Count0Fields 0x00000000 +#define M_CountRFields 0x00000000 + + +/* + ************************************************************************ + * E N T R Y H I R E G I S T E R ( 1 0 ) * + ************************************************************************ + * + * 6 6 6 6 5 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 2 1 0 9 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | R | Fill // VPN2 | 0 | ASID | EntryHi + * +-+-+-+-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_EntryHi $10 +#define R_C0_EntryHi 10 +#define C0_TLBHI C0_EntryHi /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_EntryHiR64 62 /* Region (R/W) */ +#define M_EntryHiR64 UNS64Const(0xc000000000000000) +#define S_EntryHiVPN2 13 /* VPN/2 (R/W) */ +#define M_EntryHiVPN2 (0x7ffff << S_EntryHiVPN2) +#define M_EntryHiVPN264 UNS64Const(0x000000ffffffe000) +#define S_EntryHiASID 0 /* ASID (R/W) */ +#define M_EntryHiASID (0xff << S_EntryHiASID) +#define S_EntryHiVPN_Shf S_EntryHiVPN2 + +#define M_EntryHi0Fields 0x00001f00 +#define M_EntryHiRFields 0x00000000 +#define M_EntryHi0Fields64 UNS64Const(0x0000000000001f00) +#define M_EntryHiRFields64 UNS64Const(0x3fffff0000000000) + + +/* + ************************************************************************ + * C O M P A R E R E G I S T E R ( 1 1 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Compare Value | Compare + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Compare $11 +#define R_C0_Compare 11 +#define C0_COMPARE C0_Compare /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_Compare0Fields 0x00000000 +#define M_CompareRFields 0x00000000 + + +/* + ************************************************************************ + * S T A T U S R E G I S T E R ( 1 2 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |C|C|C|C|R|F|R|M|P|B|T|S|M| | R |I|I|I|I|I|I|I|I|K|S|U|U|R|E|E|I| + * |U|U|U|U|P|R|E|X|X|E|S|R|M| | s |M|M|M|M|M|M|M|M|X|X|X|M|s|R|X|E| Status + * |3|2|1|0| | | | | |V| | |I| | v |7|6|5|4|3|2|1|0| | | | |v|L|L| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Status $12 +#define R_C0_Status 12 +#define C0_SR C0_Status /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_StatusCU 28 /* Coprocessor enable (R/W) */ +#define M_StatusCU (0xf << S_StatusCU) +#define S_StatusCU3 31 +#define M_StatusCU3 (0x1 << S_StatusCU3) +#define S_StatusCU2 30 +#define M_StatusCU2 (0x1 << S_StatusCU2) +#define S_StatusCU1 29 +#define M_StatusCU1 (0x1 << S_StatusCU1) +#define S_StatusCU0 28 +#define M_StatusCU0 (0x1 << S_StatusCU0) +#define S_StatusRP 27 /* Enable reduced power mode (R/W) */ +#define M_StatusRP (0x1 << S_StatusRP) +#define S_StatusFR 26 /* Enable 64-bit FPRs (MIPS64 only) (R/W) */ +#define M_StatusFR (0x1 << S_StatusFR) +#define S_StatusRE 25 /* Enable reverse endian (R/W) */ +#define M_StatusRE (0x1 << S_StatusRE) +#define S_StatusMX 24 /* Enable access to MDMX resources (MIPS64 only) (R/W) */ +#define M_StatusMX (0x1 << S_StatusMX) +#define S_StatusPX 23 /* Enable access to 64-bit instructions/data (MIPS64 only) (R/W) */ +#define M_StatusPX (0x1 << S_StatusPX) +#define S_StatusBEV 22 /* Enable Boot Exception Vectors (R/W) */ +#define M_StatusBEV (0x1 << S_StatusBEV) +#define S_StatusTS 21 /* Denote TLB shutdown (R/W) */ +#define M_StatusTS (0x1 << S_StatusTS) +#define S_StatusSR 20 /* Denote soft reset (R/W) */ +#define M_StatusSR (0x1 << S_StatusSR) +#define S_StatusNMI 19 +#define M_StatusNMI (0x1 << S_StatusNMI) /* Denote NMI (R/W) */ +#define S_StatusIM 8 /* Interrupt mask (R/W) */ +#define M_StatusIM (0xff << S_StatusIM) +#define S_StatusIM7 15 +#define M_StatusIM7 (0x1 << S_StatusIM7) +#define S_StatusIM6 14 +#define M_StatusIM6 (0x1 << S_StatusIM6) +#define S_StatusIM5 13 +#define M_StatusIM5 (0x1 << S_StatusIM5) +#define S_StatusIM4 12 +#define M_StatusIM4 (0x1 << S_StatusIM4) +#define S_StatusIM3 11 +#define M_StatusIM3 (0x1 << S_StatusIM3) +#define S_StatusIM2 10 +#define M_StatusIM2 (0x1 << S_StatusIM2) +#define S_StatusIM1 9 +#define M_StatusIM1 (0x1 << S_StatusIM1) +#define S_StatusIM0 8 +#define M_StatusIM0 (0x1 << S_StatusIM0) +#define S_StatusKX 7 /* Enable access to extended kernel addresses (MIPS64 only) (R/W) */ +#define M_StatusKX (0x1 << S_StatusKX) +#define S_StatusSX 6 /* Enable access to extended supervisor addresses (MIPS64 only) (R/W) */ +#define M_StatusSX (0x1 << S_StatusSX) +#define S_StatusUX 5 /* Enable access to extended user addresses (MIPS64 only) (R/W) */ +#define M_StatusUX (0x1 << S_StatusUX) +#define S_StatusKSU 3 /* Two-bit current mode (R/W) */ +#define M_StatusKSU (0x3 << S_StatusKSU) +#define S_StatusUM 4 /* User mode if supervisor mode not implemented (R/W) */ +#define M_StatusUM (0x1 << S_StatusUM) +#define S_StatusSM 3 /* Supervisor mode (R/W) */ +#define M_StatusSM (0x1 << S_StatusSM) +#define S_StatusERL 2 /* Denotes error level (R/W) */ +#define M_StatusERL (0x1 << S_StatusERL) +#define S_StatusEXL 1 /* Denotes exception level (R/W) */ +#define M_StatusEXL (0x1 << S_StatusEXL) +#define S_StatusIE 0 /* Enables interrupts (R/W) */ +#define M_StatusIE (0x1 << S_StatusIE) + +#define M_Status0Fields 0x00040000 +#define M_StatusRFields 0x058000e0 /* FR, MX, PX, KX, SX, UX unused in MIPS32 */ +#define M_Status0Fields64 0x00040000 +#define M_StatusRFields64 0x00000000 + +/* + * Values in the KSU field + */ +#define K_StatusKSU_U 2 /* User mode in KSU field */ +#define K_StatusKSU_S 1 /* Supervisor mode in KSU field */ +#define K_StatusKSU_K 0 /* Kernel mode in KSU field */ + + +/* + ************************************************************************ + * C A U S E R E G I S T E R ( 1 3 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |B| | C | |I|W| |I|I|I|I|I|I|I|I| | | R | + * |D| | E | Rsvd |V|P| Rsvd |P|P|P|P|P|P|P|P| | ExcCode | s | Cause + * | | | | | | | |7|6|5|4|3|2|1|0| | | v | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Cause $13 +#define R_C0_Cause 13 +#define C0_CAUSE C0_Cause /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_CauseBD 31 +#define M_CauseBD (0x1 << S_CauseBD) +#define S_CauseCE 28 +#define M_CauseCE (0x3<< S_CauseCE) +#define S_CauseIV 23 +#define M_CauseIV (0x1 << S_CauseIV) +#define S_CauseWP 22 +#define M_CauseWP (0x1 << S_CauseWP) +#define S_CauseIP 8 +#define M_CauseIP (0xff << S_CauseIP) +#define S_CauseIPEXT 10 +#define M_CauseIPEXT (0x3f << S_CauseIPEXT) +#define S_CauseIP7 15 +#define M_CauseIP7 (0x1 << S_CauseIP7) +#define S_CauseIP6 14 +#define M_CauseIP6 (0x1 << S_CauseIP6) +#define S_CauseIP5 13 +#define M_CauseIP5 (0x1 << S_CauseIP5) +#define S_CauseIP4 12 +#define M_CauseIP4 (0x1 << S_CauseIP4) +#define S_CauseIP3 11 +#define M_CauseIP3 (0x1 << S_CauseIP3) +#define S_CauseIP2 10 +#define M_CauseIP2 (0x1 << S_CauseIP2) +#define S_CauseIP1 9 +#define M_CauseIP1 (0x1 << S_CauseIP1) +#define S_CauseIP0 8 +#define M_CauseIP0 (0x1 << S_CauseIP0) +#define S_CauseExcCode 2 +#define M_CauseExcCode (0x1f << S_CauseExcCode) + +#define M_Cause0Fields 0x4f3f0083 +#define M_CauseRFields 0xb000fc7c + +/* + * Values in the CE field + */ +#define K_CauseCE0 0 /* Coprocessor 0 in the CE field */ +#define K_CauseCE1 1 /* Coprocessor 1 in the CE field */ +#define K_CauseCE2 2 /* Coprocessor 2 in the CE field */ +#define K_CauseCE3 3 /* Coprocessor 3 in the CE field */ + +/* + * Values in the ExcCode field + */ +#define EX_INT 0 /* Interrupt */ +#define EXC_INT (EX_INT << S_CauseExcCode) +#define EX_MOD 1 /* TLB modified */ +#define EXC_MOD (EX_MOD << S_CauseExcCode) +#define EX_TLBL 2 /* TLB exception (load or ifetch) */ +#define EXC_TLBL (EX_TLBL << S_CauseExcCode) +#define EX_TLBS 3 /* TLB exception (store) */ +#define EXC_TLBS (EX_TLBS << S_CauseExcCode) +#define EX_ADEL 4 /* Address error (load or ifetch) */ +#define EXC_ADEL (EX_ADEL << S_CauseExcCode) +#define EX_ADES 5 /* Address error (store) */ +#define EXC_ADES (EX_ADES << S_CauseExcCode) +#define EX_IBE 6 /* Instruction Bus Error */ +#define EXC_IBE (EX_IBE << S_CauseExcCode) +#define EX_DBE 7 /* Data Bus Error */ +#define EXC_DBE (EX_DBE << S_CauseExcCode) +#define EX_SYS 8 /* Syscall */ +#define EXC_SYS (EX_SYS << S_CauseExcCode) +#define EX_SYSCALL EX_SYS +#define EXC_SYSCALL EXC_SYS +#define EX_BP 9 /* Breakpoint */ +#define EXC_BP (EX_BP << S_CauseExcCode) +#define EX_BREAK EX_BP +#define EXC_BREAK EXC_BP +#define EX_RI 10 /* Reserved instruction */ +#define EXC_RI (EX_RI << S_CauseExcCode) +#define EX_CPU 11 /* CoProcessor Unusable */ +#define EXC_CPU (EX_CPU << S_CauseExcCode) +#define EX_OV 12 /* OVerflow */ +#define EXC_OV (EX_OV << S_CauseExcCode) +#define EX_TR 13 /* Trap instruction */ +#define EXC_TR (EX_TR << S_CauseExcCode) +#define EX_TRAP EX_TR +#define EXC_TRAP EXC_TR +#define EX_FPE 15 /* floating point exception */ +#define EXC_FPE (EX_FPE << S_CauseExcCode) +#define EX_C2E 18 /* COP2 exception */ +#define EXC_C2E (EX_C2E << S_CauseExcCode) +#define EX_MDMX 22 /* MDMX exception */ +#define EXC_MDMX (EX_MDMX << S_CauseExcCode) +#define EX_WATCH 23 /* Watch exception */ +#define EXC_WATCH (EX_WATCH << S_CauseExcCode) +#define EX_MCHECK 24 /* Machine check exception */ +#define EXC_MCHECK (EX_MCHECK << S_CauseExcCode) +#define EX_CacheErr 30 /* Cache error caused re-entry to Debug Mode */ +#define EXC_CacheErr (EX_CacheErr << S_CauseExcCode) + + +/* + ************************************************************************ + * E P C R E G I S T E R ( 1 4 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // Exception PC | EPC + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_EPC $14 +#define R_C0_EPC 14 + +#define M_EPC0Fields 0x00000000 +#define M_EPCRFields 0x00000000 +#define M_EPC0Fields64 UNS64Const(0x0000000000000000) +#define M_EPCRFields64 UNS64Const(0x0000000000000000) + +/* + ************************************************************************ + * P R I D R E G I S T E R ( 1 5 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Company Opts | Company ID | Procesor ID | Revision | PRId + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_PRId $15 +#define R_C0_PRId 15 +#define C0_PRID C0_PRID /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_PRIdCoOpt 24 /* Company options (R) */ +#define M_PRIdCoOpt (0xff << S_PRIdCoOpt) +#define S_PRIdCoID 16 /* Company ID (R) */ +#define M_PRIdCoID (0xff << S_PRIdCoID) +#define S_PRIdImp 8 /* Implementation ID (R) */ +#define M_PRIdImp (0xff << S_PRIdImp) +#define S_PRIdRev 0 /* Revision (R) */ +#define M_PRIdRev (0xff << S_PRIdRev) + +#define M_PRId0Fields 0x00000000 +#define M_PRIdRFields 0xffffffff +/* + * Values in the Company ID field + */ +#define K_PRIdCoID_MIPS 1 +#define K_PRIdCoID_Broadcom 2 +#define K_PRIdCoID_Alchemy 3 +#define K_PRIdCoID_SiByte 4 +#define K_PRIdCoID_SandCraft 5 +#define K_PRIdCoID_Philips 6 +#define K_PRIdCoID_NextAvailable 7 /* Next available encoding */ + + +/* + * Values in the implementation number field + */ +#define K_PRIdImp_Jade 0x80 +#define K_PRIdImp_Opal 0x81 +#define K_PRIdImp_Ruby 0x82 +#define K_PRIdImp_JadeLite 0x83 +#define K_PRIdImp_4KEc 0x84 /* Emerald with TLB MMU */ +#define K_PRIdImp_4KEmp 0x85 /* Emerald with FM MMU */ +#define K_PRIdImp_4KSc 0x86 /* Coral */ + +#define K_PRIdImp_R3000 0x01 +#define K_PRIdImp_R4000 0x04 +#define K_PRIdImp_R10000 0x09 +#define K_PRIdImp_R4300 0x0b +#define K_PRIdImp_R5000 0x23 +#define K_PRIdImp_R5200 0x28 +#define K_PRIdImp_R5400 0x54 + +/* + ************************************************************************ + * C O N F I G R E G I S T E R ( 1 6 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |M| |B| A | A | | K | Config + * | | Reserved for Implementations|E| T | R | Reserved | 0 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Config $16 +#define R_C0_Config 16 +#define C0_CONFIG C0_Config /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_ConfigMore 31 /* Additional config registers present (R) */ +#define M_ConfigMore (0x1 << S_ConfigMore) +#define S_ConfigImpl 16 /* Implementation-specific fields */ +#define M_ConfigImpl (0x7fff << S_ConfigImpl) +#define S_ConfigBE 15 /* Denotes big-endian operation (R) */ +#define M_ConfigBE (0x1 << S_ConfigBE) +#define S_ConfigAT 13 /* Architecture type (R) */ +#define M_ConfigAT (0x3 << S_ConfigAT) +#define S_ConfigAR 10 /* Architecture revision (R) */ +#define M_ConfigAR (0x7 << S_ConfigAR) +#define S_ConfigMT 7 /* MMU Type (R) */ +#define M_ConfigMT (0x7 << S_ConfigMT) +#define S_ConfigK0 0 /* Kseg0 coherency algorithm (R/W) */ +#define M_ConfigK0 (0x7 << S_ConfigK0) + +/* + * The following definitions are technically part of the "reserved for + * implementations" field, but are the semi-standard definition used in + * fixed-mapping MMUs to control the cacheability of kuseg and kseg2/3 + * references. For that reason, they are included here, but may be + * overridden by true implementation-specific definitions + */ +#define S_ConfigK23 28 /* Kseg2/3 coherency algorithm (FM MMU only) (R/W) */ +#define M_ConfigK23 (0x7 << S_ConfigK23) +#define S_ConfigKU 25 /* Kuseg coherency algorithm (FM MMU only) (R/W) */ +#define M_ConfigKU (0x7 << S_ConfigKU) + +#define M_Config0Fields 0x00000078 +#define M_ConfigRFields 0x8000ff80 + +/* + * Values in the AT field + */ +#define K_ConfigAT_MIPS32 0 /* MIPS32 */ +#define K_ConfigAT_MIPS64S 1 /* MIPS64 with 32-bit addresses */ +#define K_ConfigAT_MIPS64 2 /* MIPS64 with 32/64-bit addresses */ + +/* + * Values in the MT field + */ +#define K_ConfigMT_NoMMU 0 /* No MMU */ +#define K_ConfigMT_TLBMMU 1 /* Standard TLB MMU */ +#define K_ConfigMT_BATMMU 2 /* Standard BAT MMU */ +#define K_ConfigMT_FMMMU 3 /* Standard Fixed Mapping MMU */ + + +/* + ************************************************************************ + * C O N F I G 1 R E G I S T E R ( 1 6, SELECT 1 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |M| MMU Size | IS | IL | IA | DS | DL | DA |C|M|P|W|C|E|F| Config1 + * | | | | | | | | |2|D|C|R|A|P|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Config1 $16,1 +#define R_C0_Config1 16 + +#define S_Config1More 31 /* Additional Config registers present (R) */ +#define M_Config1More (0x1 << S_Config1More) +#define S_Config1MMUSize 25 /* Number of MMU entries - 1 (R) */ +#define M_Config1MMUSize (0x3f << S_Config1MMUSize) +#define S_Config1IS 22 /* Icache sets per way (R) */ +#define M_Config1IS (0x7 << S_Config1IS) +#define S_Config1IL 19 /* Icache line size (R) */ +#define M_Config1IL (0x7 << S_Config1IL) +#define S_Config1IA 16 /* Icache associativity - 1 (R) */ +#define M_Config1IA (0x7 << S_Config1IA) +#define S_Config1DS 13 /* Dcache sets per way (R) */ +#define M_Config1DS (0x7 << S_Config1DS) +#define S_Config1DL 10 /* Dcache line size (R) */ +#define M_Config1DL (0x7 << S_Config1DL) +#define S_Config1DA 7 /* Dcache associativity (R) */ +#define M_Config1DA (0x7 << S_Config1DA) +#define S_Config1C2 6 /* Coprocessor 2 present (R) */ +#define M_Config1C2 (0x1 << S_Config1C2) +#define S_Config1MD 5 /* Denotes MDMX present (R) */ +#define M_Config1MD (0x1 << S_Config1MD) +#define S_Config1PC 4 /* Denotes performance counters present (R) */ +#define M_Config1PC (0x1 << S_Config1PC) +#define S_Config1WR 3 /* Denotes watch registers present (R) */ +#define M_Config1WR (0x1 << S_Config1WR) +#define S_Config1CA 2 /* Denotes MIPS-16 present (R) */ +#define M_Config1CA (0x1 << S_Config1CA) +#define S_Config1EP 1 /* Denotes EJTAG present (R) */ +#define M_Config1EP (0x1 << S_Config1EP) +#define S_Config1FP 0 /* Denotes floating point present (R) */ +#define M_Config1FP (0x1 << S_Config1FP) + +#define M_Config10Fields 0x00000060 +#define M_Config1RFields 0x7fffff9f + +/* + * The following macro generates a table that is indexed + * by the Icache or Dcache sets field in Config1 and + * contains the decoded value of sets per way + */ +#define Config1CacheSets() \ + HALF(64); \ + HALF(128); \ + HALF(256); \ + HALF(512); \ + HALF(1024); \ + HALF(2048); \ + HALF(4096); \ + HALF(8192); + +/* + * The following macro generates a table that is indexed + * by the Icache or Dcache line size field in Config1 and + * contains the decoded value of the cache line size, in bytes + */ +#define Config1CacheLineSize() \ + HALF(0); \ + HALF(4); \ + HALF(8); \ + HALF(16); \ + HALF(32); \ + HALF(64); \ + HALF(128); \ + HALF(256); + + +/* + ************************************************************************ + * C O N F I G 2 R E G I S T E R ( 1 6, SELECT 2 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |M| | | | | | | | | | | | |S|T| Config1 + * | | | | | | | | | | | | | |M|L| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Config2 $16,2 +#define R_C0_Config2 16 + +#define S_Config2More 31 /* Additional Config registers present (R) */ +#define M_Config2More (0x1 << S_Config2More) +#define S_Config2SM 1 /* Denotes SmartMIPS ASE present (R) */ +#define M_Config2SM (0x1 << S_Config2SM) +#define S_Config2TL 0 /* Denotes Tracing Logic present (R) */ +#define M_Config2TL (0x1 << S_Config2TL) + +#define M_Config20Fields 0xfffffffc +#define M_Config2RFields 0x00000003 + +/* + ************************************************************************ + * L L A D D R R E G I S T E R ( 1 7 ) * + ************************************************************************ + * + * 6 6 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // LL Physical Address | LLAddr + * +-+-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_LLAddr $17 +#define R_C0_LLAddr 17 +#define C0_LLADDR C0_LLAddr /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_LLAddr0Fields 0x00000000 +#define M_LLAddrRFields 0x00000000 +#define M_LLAddr0Fields64 UNS64Const(0x0000000000000000) +#define M_LLAddrRFields64 UNS64Const(0x0000000000000000) + + +/* + ************************************************************************ + * W A T C H L O R E G I S T E R ( 1 8 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // Watch Virtual Address |I|R|W| WatchLo + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_WatchLo $18 +#define R_C0_WatchLo 18 +#define C0_WATCHLO C0_WatchLo /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_WatchLoVAddr 3 /* Watch virtual address (R/W) */ +#define M_WatchLoVAddr (0x1fffffff << S_WatchLoVAddr) +#define S_WatchLoI 2 /* Enable Istream watch (R/W) */ +#define M_WatchLoI (0x1 << S_WatchLoI) +#define S_WatchLoR 1 /* Enable data read watch (R/W) */ +#define M_WatchLoR (0x1 << S_WatchLoR) +#define S_WatchLoW 0 /* Enable data write watch (R/W) */ +#define M_WatchLoW (0x1 << S_WatchLoW) + +#define M_WatchLo0Fields 0x00000000 +#define M_WatchLoRFields 0x00000000 +#define M_WatchLo0Fields64 UNS64Const(0x0000000000000000) +#define M_WatchLoRFields64 UNS64Const(0x0000000000000000) + +#define M_WatchLoEnables (M_WatchLoI | M_WatchLoR | M_WatchLoW) + + +/* + ************************************************************************ + * W A T C H H I R E G I S T E R ( 1 9 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |M|G| Rsvd | ASID | Rsvd | Mask | 0 | WatchHi + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_WatchHi $19 +#define R_C0_WatchHi 19 +#define C0_WATCHHI C0_WatchHi /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_WatchHiM 31 /* Denotes additional Watch registers present (R) */ +#define M_WatchHiM (0x1 << S_WatchHiM) +#define S_WatchHiG 30 /* Enable ASID-independent Watch match (R/W) */ +#define M_WatchHiG (0x1 << S_WatchHiG) +#define S_WatchHiASID 16 /* ASID value to match (R/W) */ +#define M_WatchHiASID (0xff << S_WatchHiASID) +#define S_WatchHiMask 3 /* Address inhibit mask (R/W) */ +#define M_WatchHiMask (0x1ff << S_WatchHiMask) + +#define M_WatchHi0Fields 0x3f00f007 +#define M_WatchHiRFields 0x80000000 + + +/* + ************************************************************************ + * X C O N T E X T R E G I S T E R ( 2 0 ) * + ************************************************************************ + * + * 6 // 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // PTEBase | R | BadVPN2<39:13> | 0 | XContext + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_XContext $20 +#define R_C0_XContext 20 +#define C0_EXTCTXT C0_XContext /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_XContextBadVPN2 4 /* BadVPN2 (R) */ +#define S_XContextBadVPN S_XContextBadVPN2 + +#define M_XContext0Fields 0x0000000f + + +/* + ************************************************************************ + * D E B U G R E G I S T E R ( 2 3 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |D|D|N|L|D|H|C|I|M|C|D|I|D|D| | |N|S| |D|D|D|D|D|D| + * |B|M|o|S|o|a|o|B|C|a|B|E|D|D|EJTAG|DExcCode |o|S| |I|I|D|D|B|S| + * |D| |D|N|z|l|u|u|h|c|u|X|B|B| ver | |S|t| |N|B|B|B|p|S| + * | | |C|M|e|t|n|s|e|h|s|I|S|L| | |S| | 0 |T| |S|L| | | Debug + * | | |R| | | |t|E|c|e|E| |I|I| | |t| | | | | | | | | + * | | | | | | |D|P|k|E|P| |m|m| | | | | | | | | | | | + * | | | | | | |M| |P|P| | |p|p| | | | | | | | | | | | + * | | | | | | | | | | | | |r|r| | | | | | | | | | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_Debug $23 /* EJTAG */ +#define R_C0_Debug 23 + +#define S_DebugDBD 31 /* Debug branch delay (R) */ +#define M_DebugDBD (0x1 << S_DebugDBD) +#define S_DebugDM 30 /* Debug mode (R) */ +#define M_DebugDM (0x1 << S_DebugDM) +#define S_DebugNoDCR 29 /* No debug control register present (R) */ +#define M_DebugNoDCR (0x1 << S_DebugNoDCR) +#define S_DebugLSNM 28 /* Load/Store Normal Memory (R/W) */ +#define M_DebugLSNM (0x1 << S_DebugLSNM) +#define S_DebugDoze 27 /* Doze (R) */ +#define M_DebugDoze (0x1 << S_DebugDoze) +#define S_DebugHalt 26 /* Halt (R) */ +#define M_DebugHalt (0x1 << S_DebugHalt) +#define S_DebugCountDM 25 /* Count register behavior in debug mode (R/W) */ +#define M_DebugCountDM (0x1 << S_DebugCountDM) +#define S_DebugIBusEP 24 /* Imprecise Instn Bus Error Pending (R/W) */ +#define M_DebugIBusEP (0x1 << S_DebugIBusEP) +#define S_DebugMCheckP 23 /* Imprecise Machine Check Pending (R/W) */ +#define M_DebugMCheckP (0x1 << S_DebugMCheckP) +#define S_DebugCacheEP 22 /* Imprecise Cache Error Pending (R/W) */ +#define M_DebugCacheEP (0x1 << S_DebugCacheEP) +#define S_DebugDBusEP 21 /* Imprecise Data Bus Error Pending (R/W) */ +#define M_DebugDBusEP (0x1 << S_DebugDBusEP) +#define S_DebugIEXI 20 /* Imprecise Exception Inhibit (R/W) */ +#define M_DebugIEXI (0x1 << S_DebugIEXI) +#define S_DebugDDBSImpr 19 /* Debug data break store imprecise (R) */ +#define M_DebugDDBSImpr (0x1 << S_DebugDDBSImpr) +#define S_DebugDDBLImpr 18 /* Debug data break load imprecise (R) */ +#define M_DebugDDBLImpr (0x1 << S_DebugDDBLImpr) +#define S_DebugEJTAGver 15 /* EJTAG version number (R) */ +#define M_DebugEJTAGver (0x7 << S_DebugEJTAGver) +#define S_DebugDExcCode 10 /* Debug exception code (R) */ +#define M_DebugDExcCode (0x1f << S_DebugDExcCode) +#define S_DebugNoSSt 9 /* No single step implemented (R) */ +#define M_DebugNoSSt (0x1 << S_DebugNoSSt) +#define S_DebugSSt 8 /* Single step enable (R/W) */ +#define M_DebugSSt (0x1 << S_DebugSSt) +#define S_DebugDINT 5 /* Debug interrupt (R) */ +#define M_DebugDINT (0x1 << S_DebugDINT) +#define S_DebugDIB 4 /* Debug instruction break (R) */ +#define M_DebugDIB (0x1 << S_DebugDIB) +#define S_DebugDDBS 3 /* Debug data break store (R) */ +#define M_DebugDDBS (0x1 << S_DebugDDBS) +#define S_DebugDDBL 2 /* Debug data break load (R) */ +#define M_DebugDDBL (0x1 << S_DebugDDBL) +#define S_DebugDBp 1 /* Debug breakpoint (R) */ +#define M_DebugDBp (0x1 << S_DebugDBp) +#define S_DebugDSS 0 /* Debug single step (R) */ +#define M_DebugDSS (0x1 << S_DebugDSS) + +#define M_Debug0Fields 0x01f000c0 +#define M_DebugRFields 0xec0ffe3f + + +/* + ************************************************************************ + * D E P C R E G I S T E R ( 2 4 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // EJTAG Debug Exception PC | DEPC + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + +#define C0_DEPC $24 +#define R_C0_DEPC 24 + +#define M_DEEPC0Fields 0x00000000 +#define M_DEEPCRFields 0x00000000 +#define M_DEEPC0Fields64 UNS64Const(0x0000000000000000) +#define M_DEEPCRFields64 UNS64Const(0x0000000000000000) + + +/* + ************************************************************************ + * P E R F C N T R E G I S T E R ( 2 5 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | |I| | | |E| + * |M| 0 | Event |E|U|S|K|X| PerfCnt + * | | | | | | | |L| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Event Count | PerfCnt + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_PerfCnt $25 +#define R_C0_PerfCnt 25 +#define C0_PRFCNT0 C0_PerfCnt /* OBSOLETE - DO NOT USE IN NEW CODE */ +#define C0_PRFCNT1 C0_PerfCnt /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define S_PerfCntM 31 /* More performance counters exist (R) */ +#define M_PerfCntM (1 << S_PerfCntM) +#define S_PerfCntEvent 5 /* Enabled event (R/W) */ +#define M_PerfCntEvent (0x3f << S_PerfCntEvent) +#define S_PerfCntIE 4 /* Interrupt Enable (R/W) */ +#define M_PerfCntIE (1 << S_PerfCntIE) +#define S_PerfCntU 3 /* Enable counting in User Mode (R/W) */ +#define M_PerfCntU (1 << S_PerfCntU) +#define S_PerfCntS 2 /* Enable counting in Supervisor Mode (R/W) */ +#define M_PerfCntS (1 << S_PerfCntS) +#define S_PerfCntK 1 /* Enable counting in Kernel Mode (R/W) */ +#define M_PerfCntK (1 << S_PerfCntK) +#define S_PerfCntEXL 0 /* Enable counting while EXL==1 (R/W) */ +#define M_PerfCntEXL (1 << S_PerfCntEXL) + +#define M_PerfCnt0Fields 0x7ffff800 +#define M_PerfCntRFields 0x80000000 + + +/* + ************************************************************************ + * E R R C T L R E G I S T E R ( 2 6 ) * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Error Control | ErrCtl + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_ErrCtl $26 +#define R_C0_ErrCtl 26 +#define C0_ECC $26 /* OBSOLETE - DO NOT USE IN NEW CODE */ +#define R_C0_ECC 26 /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_ErrCtl0Fields 0x00000000 +#define M_ErrCtlRFields 0x00000000 + + +/* + ************************************************************************ + * C A C H E E R R R E G I S T E R ( 2 7 ) * CacheErr + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Cache Error Control | CacheErr + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_CacheErr $27 +#define R_C0_CacheErr 27 +#define C0_CACHE_ERR C0_CacheErr /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_CacheErr0Fields 0x00000000 +#define M_CachErrRFields 0x00000000 + + +/* + ************************************************************************ + * T A G L O R E G I S T E R ( 2 8 ) * TagLo + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TagLo | TagLo + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_TagLo $28 +#define R_C0_TagLo 28 +#define C0_TAGLO C0_TagLo /* OBSOLETE - DO NOT USE IN NEW CODE */ + +/* + * Some implementations use separate TagLo registers for the + * instruction and data caches. In those cases, the following + * definitions can be used in relevant code + */ + +#define C0_ITagLo $28,0 +#define C0_DTagLo $28,2 + +#define M_TagLo0Fields 0x00000000 +#define M_TagLoRFields 0x00000000 + + +/* + ************************************************************************ + * D A T A L O R E G I S T E R ( 2 8, SELECT 1 ) * DataLo + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | DataLo | DataLo + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_DataLo $28,1 +#define R_C0_DataLo 28 + +/* + * Some implementations use separate DataLo registers for the + * instruction and data caches. In those cases, the following + * definitions can be used in relevant code + */ + +#define C0_IDataLo $28,1 +#define C0_DDataLo $28,3 + +#define M_DataLo0Fields 0x00000000 +#define M_DataLoRFields 0xffffffff + + +/* + ************************************************************************ + * T A G H I R E G I S T E R ( 2 9 ) * TagHi + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TagHi | TagHi + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_TagHi $29 +#define R_C0_TagHi 29 +#define C0_TAGHI C0_TagHi /* OBSOLETE - DO NOT USE IN NEW CODE */ + +/* + * Some implementations use separate TagHi registers for the + * instruction and data caches. In those cases, the following + * definitions can be used in relevant code + */ + +#define C0_ITagHi $29,0 +#define C0_DTagHi $29,2 + +#define M_TagHi0Fields 0x00000000 +#define M_TagHiRFields 0x00000000 + + +/* + ************************************************************************ + * D A T A H I R E G I S T E R ( 2 9, SELECT 1 ) * DataHi + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | DataHi | DataHi + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_DataHi $29,1 +#define R_C0_DataHi 29 + +/* + * Some implementations use separate DataHi registers for the + * instruction and data caches. In those cases, the following + * definitions can be used in relevant code + */ + +#define C0_IDataHi $29,1 +#define C0_DDataHi $29,3 + +#define M_DataHi0Fields 0x00000000 +#define M_DataHiRFields 0xffffffff + + +/* + ************************************************************************ + * E R R O R E P C R E G I S T E R ( 3 0 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // Error PC | ErrorEPC + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_ErrorEPC $30 +#define R_C0_ErrorEPC 30 +#define C0_ERROR_EPC C0_ErrorEPC /* OBSOLETE - DO NOT USE IN NEW CODE */ + +#define M_ErrorEPC0Fields 0x00000000 +#define M_ErrorEPCRFields 0x00000000 +#define M_ErrorEPC0Fields64 UNS64Const(0x0000000000000000) +#define M_ErrorEPCRFields64 UNS64Const(0x0000000000000000) + + +/* + ************************************************************************ + * D E S A V E R E G I S T E R ( 3 1 ) * + ************************************************************************ + * + * 6 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 3 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | // EJTAG Register Save Value | DESAVE + * +-+//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C0_DESAVE $31 +#define R_C0_DESAVE 31 + +#define M_DESAVE0Fields 0x00000000 +#define M_DESAVERFields 0x00000000 +#define M_DESAVE0Fields64 UNS64Const(0x0000000000000000) +#define M_DESAVERFields64 UNS64Const(0x0000000000000000) + + +/* + ************************************************************************* + * C P 1 R E G I S T E R D E F I N I T I O N S * + ************************************************************************* + */ + + +/* + ************************************************************************* + * H A R D W A R E F P R N A M E S * + ************************************************************************* + */ + +#define fp0 $f0 +#define fp1 $f1 +#define fp2 $f2 +#define fp3 $f3 +#define fp4 $f4 +#define fp5 $f5 +#define fp6 $f6 +#define fp7 $f7 +#define fp8 $f8 +#define fp9 $f9 +#define fp10 $f10 +#define fp11 $f11 +#define fp12 $f12 +#define fp13 $f13 +#define fp14 $f14 +#define fp15 $f15 +#define fp16 $f16 +#define fp17 $f17 +#define fp18 $f18 +#define fp19 $f19 +#define fp20 $f20 +#define fp21 $f21 +#define fp22 $f22 +#define fp23 $f23 +#define fp24 $f24 +#define fp25 $f25 +#define fp26 $f26 +#define fp27 $f27 +#define fp28 $f28 +#define fp29 $f29 +#define fp30 $f30 +#define fp31 $f31 + +/* + * The following definitions are used to convert an FPR name + * into the corresponding even or odd name, respectively. + * This is used in macro substitution in the AVPs. + */ + +#define fp1_even $f0 +#define fp3_even $f2 +#define fp5_even $f4 +#define fp7_even $f6 +#define fp9_even $f8 +#define fp11_even $f10 +#define fp13_even $f12 +#define fp15_even $f14 +#define fp17_even $f16 +#define fp19_even $f18 +#define fp21_even $f20 +#define fp23_even $f22 +#define fp25_even $f24 +#define fp27_even $f26 +#define fp29_even $f28 +#define fp31_even $f30 + +#define fp0_odd $f1 +#define fp2_odd $f3 +#define fp4_odd $f5 +#define fp6_odd $f7 +#define fp8_odd $f9 +#define fp10_odd $f11 +#define fp12_odd $f13 +#define fp14_odd $f15 +#define fp16_odd $f17 +#define fp18_odd $f19 +#define fp20_odd $f21 +#define fp22_odd $f23 +#define fp24_odd $f25 +#define fp26_odd $f27 +#define fp28_odd $f29 +#define fp30_odd $f31 + + +/* + ************************************************************************* + * H A R D W A R E F P R I N D I C E S * + ************************************************************************* + * + * These definitions provide the index (number) of the FPR, as opposed + * to the assembler register name ($n). + */ + +#define R_fp0 0 +#define R_fp1 1 +#define R_fp2 2 +#define R_fp3 3 +#define R_fp4 4 +#define R_fp5 5 +#define R_fp6 6 +#define R_fp7 7 +#define R_fp8 8 +#define R_fp9 9 +#define R_fp10 10 +#define R_fp11 11 +#define R_fp12 12 +#define R_fp13 13 +#define R_fp14 14 +#define R_fp15 15 +#define R_fp16 16 +#define R_fp17 17 +#define R_fp18 18 +#define R_fp19 19 +#define R_fp20 20 +#define R_fp21 21 +#define R_fp22 22 +#define R_fp23 23 +#define R_fp24 24 +#define R_fp25 25 +#define R_fp26 26 +#define R_fp27 27 +#define R_fp28 28 +#define R_fp29 29 +#define R_fp30 30 +#define R_fp31 31 + + +/* + ************************************************************************* + * H A R D W A R E F C R N A M E S * + ************************************************************************* + */ + +#define fc0 $0 +#define fc25 $25 +#define fc26 $26 +#define fc28 $28 +#define fc31 $31 + + +/* + ************************************************************************* + * H A R D W A R E F C R I N D I C E S * + ************************************************************************* + * + * These definitions provide the index (number) of the FCR, as opposed + * to the assembler register name ($n). + */ + +#define R_fc0 0 +#define R_fc25 25 +#define R_fc26 26 +#define R_fc28 28 +#define R_fc31 31 + + +/* + ************************************************************************* + * H A R D W A R E F C C N A M E S * + ************************************************************************* + */ + +#define cc0 $fcc0 +#define cc1 $fcc1 +#define cc2 $fcc2 +#define cc3 $fcc3 +#define cc4 $fcc4 +#define cc5 $fcc5 +#define cc6 $fcc6 +#define cc7 $fcc7 + + +/* + ************************************************************************* + * H A R D W A R E F C C I N D I C E S * + ************************************************************************* + * + * These definitions provide the index (number) of the CC, as opposed + * to the assembler register name ($n). + */ + +#define R_cc0 0 +#define R_cc1 1 +#define R_cc2 2 +#define R_cc3 3 +#define R_cc4 4 +#define R_cc5 5 +#define R_cc6 6 +#define R_cc7 7 + + +/* + ************************************************************************ + * I M P L E M E N T A T I O N R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Reserved for Additional|3|P|D|S| Implementation| Revision | FIR + * | Configuration Bits |D|S| | | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FIR $0 +#define R_C1_FIR 0 + +#define S_FIRConfigS 16 +#define M_FIRConfigS (0x1 << S_FIRConfigS) +#define S_FIRConfigD 17 +#define M_FIRConfigD (0x1 << S_FIRConfigD) +#define S_FIRConfigPS 18 +#define M_FIRConfigPS (0x1 << S_FIRConfigPS) +#define S_FIRConfig3D 19 +#define M_FIRConfig3D (0x1 << S_FIRConfig3D) +#define M_FIRConfigAll (M_FIRConfigS|M_FIRConfigD|M_FIRConfigPS|M_FIRConfig3D) + +#define S_FIRImp 8 +#define M_FIRImp (0xff << S_FIRImp) + +#define S_FIRRev 0 +#define M_FIRRev (0xff << S_FIRRev) + +#define M_FIR0Fields 0xfff00000 +#define M_FIRRFields 0x000fffff + +/* + ************************************************************************ + * C O N D I T I O N C O D E S R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | CC | FCCR + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FCCR $25 +#define R_C1_FCCR 25 + +#define S_FCCRCC 0 +#define M_FCCRCC (0xff << S_FCCRCC) +#define S_FCCRCC7 7 +#define M_FCCRCC7 (0x1 << S_FCCRCC7) +#define S_FCCRCC6 6 +#define M_FCCRCC6 (0x1 << S_FCCRCC6) +#define S_FCCRCC5 5 +#define M_FCCRCC5 (0x1 << S_FCCRCC5) +#define S_FCCRCC4 4 +#define M_FCCRCC4 (0x1 << S_FCCRCC4) +#define S_FCCRCC3 3 +#define M_FCCRCC3 (0x1 << S_FCCRCC3) +#define S_FCCRCC2 2 +#define M_FCCRCC2 (0x1 << S_FCCRCC2) +#define S_FCCRCC1 1 +#define M_FCCRCC1 (0x1 << S_FCCRCC1) +#define S_FCCRCC0 0 +#define M_FCCRCC0 (0x1 << S_FCCRCC0) + +#define M_FCCR0Fields 0xffffff00 +#define M_FCCRRFields 0x000000ff + + +/* + ************************************************************************ + * E X C E P T I O N S R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Cause | 0 | Flags | 0 | FEXR + * | |E|V|Z|O|U|I| |V|Z|O|U|I| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FEXR $26 +#define R_C1_FEXR 26 + +#define S_FEXRExc 12 +#define M_FEXRExc (0x3f << S_FEXRExc) +#define S_FEXRExcE 17 +#define M_FEXRExcE (0x1 << S_FEXRExcE) +#define S_FEXRExcV 16 +#define M_FEXRExcV (0x1 << S_FEXRExcV) +#define S_FEXRExcZ 15 +#define M_FEXRExcZ (0x1 << S_FEXRExcZ) +#define S_FEXRExcO 14 +#define M_FEXRExcO (0x1 << S_FEXRExcO) +#define S_FEXRExcU 13 +#define M_FEXRExcU (0x1 << S_FEXRExcU) +#define S_FEXRExcI 12 +#define M_FEXRExcI (0x1 << S_FEXRExcI) + +#define S_FEXRFlg 2 +#define M_FEXRFlg (0x1f << S_FEXRFlg) +#define S_FEXRFlgV 6 +#define M_FEXRFlgV (0x1 << S_FEXRFlgV) +#define S_FEXRFlgZ 5 +#define M_FEXRFlgZ (0x1 << S_FEXRFlgZ) +#define S_FEXRFlgO 4 +#define M_FEXRFlgO (0x1 << S_FEXRFlgO) +#define S_FEXRFlgU 3 +#define M_FEXRFlgU (0x1 << S_FEXRFlgU) +#define S_FEXRFlgI 2 +#define M_FEXRFlgI (0x1 << S_FEXRFlgI) + +#define M_FEXR0Fields 0xfffc0f83 +#define M_FEXRRFields 0x00000000 + + +/* + ************************************************************************ + * E N A B L E S R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | 0 | Enables | 0 |F|RM | FENR + * | |V|Z|O|U|I| |S| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FENR $28 +#define R_C1_FENR 28 + +#define S_FENREna 7 +#define M_FENREna (0x1f << S_FENREna) +#define S_FENREnaV 11 +#define M_FENREnaV (0x1 << S_FENREnaV) +#define S_FENREnaZ 10 +#define M_FENREnaZ (0x1 << S_FENREnaZ) +#define S_FENREnaO 9 +#define M_FENREnaO (0x1 << S_FENREnaO) +#define S_FENREnaU 8 +#define M_FENREnaU (0x1 << S_FENREnaU) +#define S_FENREnaI 7 +#define M_FENREnaI (0x1 << S_FENREnaI) + +#define S_FENRFS 2 +#define M_FENRFS (0x1 << S_FENRFS) + +#define S_FENRRM 0 +#define M_FENRRM (0x3 << S_FENRRM) + +#define M_FENR0Fields 0xfffff078 +#define M_FENRRFields 0x00000000 + + +/* + ************************************************************************ + * C O N T R O L / S T A T U S R E G I S T E R * + ************************************************************************ + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | FCC |F|C|Imp| 0 | Cause | Enables | Flags | RM| FCSR + * |7|6|5|4|3|2|1|S|C| | |E|V|Z|O|U|I|V|Z|O|U|I|V|Z|O|U|I| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define C1_FCSR $31 +#define R_C1_FCSR 31 + +#define S_FCSRFCC7_1 25 /* Floating point condition codes 7..1 (R/W) */ +#define M_FCSRFCC7_1 (0x7f << S_FCSRFCC7_1) +#define S_FCSRCC7 31 +#define M_FCSRCC7 (0x1 << S_FCSRCC7) +#define S_FCSRCC6 30 +#define M_FCSRCC6 (0x1 << S_FCSRCC6) +#define S_FCSRCC5 29 +#define M_FCSRCC5 (0x1 << S_FCSRCC5) +#define S_FCSRCC4 28 +#define M_FCSRCC4 (0x1 << S_FCSRCC4) +#define S_FCSRCC3 27 +#define M_FCSRCC3 (0x1 << S_FCSRCC3) +#define S_FCSRCC2 26 +#define M_FCSRCC2 (0x1 << S_FCSRCC2) +#define S_FCSRCC1 25 +#define M_FCSRCC1 (0x1 << S_FCSRCC1) + +#define S_FCSRFS 24 /* Flush denorms to zero (R/W) */ +#define M_FCSRFS (0x1 << S_FCSRFS) + +#define S_FCSRCC0 23 /* Floating point condition code 0 (R/W) */ +#define M_FCSRCC0 (0x1 << S_FCSRCC0) +#define S_FCSRCC S_FCSRCC0 +#define M_FCSRCC M_FCSRCC0 + +#define S_FCSRImpl 21 /* Implementation-specific control bits (R/W) */ +#define M_FCSRImpl (0x3 << S_FCSRImpl) + +#define S_FCSRExc 12 /* Exception cause (R/W) */ +#define M_FCSRExc (0x3f << S_FCSRExc) +#define S_FCSRExcE 17 +#define M_FCSRExcE (0x1 << S_FCSRExcE) +#define S_FCSRExcV 16 +#define M_FCSRExcV (0x1 << S_FCSRExcV) +#define S_FCSRExcZ 15 +#define M_FCSRExcZ (0x1 << S_FCSRExcZ) +#define S_FCSRExcO 14 +#define M_FCSRExcO (0x1 << S_FCSRExcO) +#define S_FCSRExcU 13 +#define M_FCSRExcU (0x1 << S_FCSRExcU) +#define S_FCSRExcI 12 +#define M_FCSRExcI (0x1 << S_FCSRExcI) + +#define S_FCSREna 7 /* Exception enable (R/W) */ +#define M_FCSREna (0x1f << S_FCSREna) +#define S_FCSREnaV 11 +#define M_FCSREnaV (0x1 << S_FCSREnaV) +#define S_FCSREnaZ 10 +#define M_FCSREnaZ (0x1 << S_FCSREnaZ) +#define S_FCSREnaO 9 +#define M_FCSREnaO (0x1 << S_FCSREnaO) +#define S_FCSREnaU 8 +#define M_FCSREnaU (0x1 << S_FCSREnaU) +#define S_FCSREnaI 7 +#define M_FCSREnaI (0x1 << S_FCSREnaI) + +#define S_FCSRFlg 2 /* Exception flags (R/W) */ +#define M_FCSRFlg (0x1f << S_FCSRFlg) +#define S_FCSRFlgV 6 +#define M_FCSRFlgV (0x1 << S_FCSRFlgV) +#define S_FCSRFlgZ 5 +#define M_FCSRFlgZ (0x1 << S_FCSRFlgZ) +#define S_FCSRFlgO 4 +#define M_FCSRFlgO (0x1 << S_FCSRFlgO) +#define S_FCSRFlgU 3 +#define M_FCSRFlgU (0x1 << S_FCSRFlgU) +#define S_FCSRFlgI 2 +#define M_FCSRFlgI (0x1 << S_FCSRFlgI) + +#define S_FCSRRM 0 /* Rounding mode (R/W) */ +#define M_FCSRRM (0x3 << S_FCSRRM) + +#define M_FCSR0Fields 0x001c0000 +#define M_FCSRRFields 0x00000000 + +/* + * Values in the rounding mode field (of both FCSR and FCCR) + */ +#define K_FCSRRM_RN 0 +#define K_FCSRRM_RZ 1 +#define K_FCSRRM_RP 2 +#define K_FCSRRM_RM 3 + + +/* ********************************************************************* */ +/* Interface function definition */ + + +/* ********************************************************************* */ + +#endif /* __ARCHDEFS_H__ */ diff --git a/sdk-modifications/include/bit_ops.h b/sdk-modifications/include/bit_ops.h new file mode 100755 index 0000000..f823db7 --- /dev/null +++ b/sdk-modifications/include/bit_ops.h @@ -0,0 +1,58 @@ +/* + bit_ops.h + Functions for dealing with conversion of data between types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _BIT_OPS_H +#define _BIT_OPS_H + +/*----------------------------------------------------------------- +Functions to deal with little endian values stored in u8 arrays +-----------------------------------------------------------------*/ +static inline u16 u8array_to_u16 (const u8* item, int offset) { + return ( item[offset] | (item[offset + 1] << 8)); +} + +static inline u32 u8array_to_u32 (const u8* item, int offset) { + return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); +} + +static inline void u16_to_u8array (u8* item, int offset, u16 value) { + item[offset] = (u8)value; + item[offset + 1] = (u8)(value >> 8); +} + +static inline void u32_to_u8array (u8* item, int offset, u32 value) { + item[offset] = (u8)value; + item[offset + 1] = (u8)(value >> 8); + item[offset + 2] = (u8)(value >> 16); + item[offset + 3] = (u8)(value >> 24); +} + +#endif // _BIT_OPS_H diff --git a/sdk-modifications/include/console.h b/sdk-modifications/include/console.h new file mode 100755 index 0000000..f6d74a4 --- /dev/null +++ b/sdk-modifications/include/console.h @@ -0,0 +1,9 @@ +#ifndef __CONSOLE_H__ +#define __CONSOLE_H__ +#include "ds2io.h" + +extern int ConsoleInit(unsigned short front_color, unsigned short background_color, enum SCREEN_ID screen, unsigned int buf_size); + +extern int cprintf(const char *format, ...); + +#endif //__CONSOLE_H__ diff --git a/sdk-modifications/include/directory.h b/sdk-modifications/include/directory.h new file mode 100755 index 0000000..00046a9 --- /dev/null +++ b/sdk-modifications/include/directory.h @@ -0,0 +1,172 @@ +/* + directory.h + Reading, writing and manipulation of the directory structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _DIRECTORY_H +#define _DIRECTORY_H + +#include + +#include "fs_common.h" +#include "partition.h" + +#define DIR_ENTRY_DATA_SIZE 0x20 +#define MAX_FILENAME_LENGTH 256 +#define MAX_ALIAS_LENGTH 13 +#define LFN_ENTRY_LENGTH 13 +#define FAT16_ROOT_DIR_CLUSTER 0 + +#define DIR_SEPARATOR '/' + +// File attributes +#define ATTRIB_ARCH 0x20 // Archive +#define ATTRIB_DIR 0x10 // Directory +#define ATTRIB_LFN 0x0F // Long file name +#define ATTRIB_VOL 0x08 // Volume +#define ATTRIB_SYS 0x04 // System +#define ATTRIB_HID 0x02 // Hidden +#define ATTRIB_RO 0x01 // Read only + +typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE; + +typedef struct { + u32 cluster; + u32 sector; + s32 offset; +} DIR_ENTRY_POSITION; + +typedef struct { + u8 entryData[DIR_ENTRY_DATA_SIZE]; + DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry + char d_name[MAX_FILENAME_LENGTH + MAX_FILENAME_LENGTH*2]; //Store name string using UTF8 coding + //u16 unicodeFilename[MAX_FILENAME_LENGTH]; +} DIR_ENTRY; + +// Directory entry offsets +enum DIR_ENTRY_offset { + DIR_ENTRY_name = 0x00, + DIR_ENTRY_extension = 0x08, + DIR_ENTRY_attributes = 0x0B, + DIR_ENTRY_reserved = 0x0C, + DIR_ENTRY_cTime_ms = 0x0D, + DIR_ENTRY_cTime = 0x0E, + DIR_ENTRY_cDate = 0x10, + DIR_ENTRY_aDate = 0x12, + DIR_ENTRY_clusterHigh = 0x14, + DIR_ENTRY_mTime = 0x16, + DIR_ENTRY_mDate = 0x18, + DIR_ENTRY_cluster = 0x1A, + DIR_ENTRY_fileSize = 0x1C +}; + +/* +Returns true if the file specified by entry is a directory +*/ +static inline bool _FAT_directory_isDirectory (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) != 0); +} + +static inline bool _FAT_directory_isWritable (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO) == 0); +} + +static inline bool _FAT_directory_isDot (DIR_ENTRY* entry) { + return ((entry->d_name[0] == '.') && ((entry->d_name[1] == '\0') || + ((entry->d_name[1] == '.') && entry->d_name[2] == '\0'))); +} + +/* +Reads the first directory entry from the directory starting at dirCluster +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); + +/* +Reads the next directory entry after the one already pointed to by entry +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Gets the directory entry corrsponding to the supplied path +entry will be destroyed even if no directory entry is found +pathEnd specifies the end of the path string, for cutting strings short if needed + specify NULL to use the full length of path + pathEnd is only a suggestion, and the path string will be searched up until the next PATH_SEPARATOR + after pathEND. +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd); + +/* +Changes the current directory to the one specified by path +Returns true on success, false on failure +*/ +bool _FAT_directory_chdir (PARTITION* partition, const char* path); + +/* +Removes the directory entry specified by entry +Assumes that entry is valid +Returns true on success, false on failure +*/ +bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Add a directory entry to the directory specified by dirCluster +The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are +updated with the new directory entry position and alias. +Returns true on success, false on failure +*/ +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster); + +/* +Get the start cluster of a file from it's entry data +*/ +u32 _FAT_directory_entryGetCluster (const u8* entryData); + +/* +Fill in the file name and entry data of DIR_ENTRY* entry. +Assumes that the entry's dataStart and dataEnd are correct +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry); + +/* +Fill in a stat struct based on a file entry +*/ +void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st); + +#endif // _DIRECTORY_H diff --git a/sdk-modifications/include/ds2_cpu.h b/sdk-modifications/include/ds2_cpu.h new file mode 100755 index 0000000..d4b7144 --- /dev/null +++ b/sdk-modifications/include/ds2_cpu.h @@ -0,0 +1,57 @@ +#ifndef __DS2_CPU_H__ +#define __DS2_CPU_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//exception handle + + +//cache operationr +//invalidate instruction cache +extern void __icache_invalidate_all(void); + +//invalidate data cache +extern void __dcache_invalidate_all(void); + +//data cache writeback +extern void __dcache_writeback_all(void); + +//data cache writeback and invalidate +extern void _dcache_wback_inv(unsigned long addr, unsigned long size); + + +//interruption operation +//clear CPU's interrupt state and enable global interrupt +extern void sti(void); + +//disable global interrupt +extern void cli(void); + +//disable global interrupt and store the global interrupt state +//return: interrupt state +extern unsigned int spin_lock_irqsave(void); + +//restore global interrupt state +extern void spin_unlock_irqrestore(unsigned int val); + + +//CPU frequence +//There are 14 levels, 0 to 13, 13 level have the highest clock frequence +extern int ds2_setCPUclocklevel(unsigned int num); + +//print colock frequence CPU +extern void printf_clock(void); + +//delay n us +extern void udelay(unsigned int usec); + +//delay n ms +extern void mdelay(unsigned int msec); + +#ifdef __cplusplus +} +#endif + +#endif //__DS2_CPU_H__ diff --git a/sdk-modifications/include/ds2_cpuclock.h b/sdk-modifications/include/ds2_cpuclock.h new file mode 100644 index 0000000..3263ed0 --- /dev/null +++ b/sdk-modifications/include/ds2_cpuclock.h @@ -0,0 +1,21 @@ +#ifndef _DS2_CPUCLOCK_H__ +#define _DS2_CPUCLOCK_H__ + + +#define CPU_MAX_LEVEL_EX 18 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int ds2_getCPUClock(void); +extern int ds2_setCPULevel(unsigned int level); +extern void ds2_udelay(unsigned int usec); +extern void ds2_mdelay(unsigned int msec); + + +#ifdef __cplusplus +} +#endif + +#endif //__DS2_CPUCLOCK_H__ diff --git a/sdk-modifications/include/ds2_dma.h b/sdk-modifications/include/ds2_dma.h new file mode 100644 index 0000000..9a306cf --- /dev/null +++ b/sdk-modifications/include/ds2_dma.h @@ -0,0 +1,142 @@ +#ifndef _DS2_DMA_H__ +#define _DS2_DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define MAX_DMA_NUM 6 /* max 6 channels */ + + +// DMA request source register +#define DMAC_DRSR_RS_BIT 0 +#define DMAC_DRSR_RS_AUTO (8 << DMAC_DRSR_RS_BIT) + + +// DMA channel command register +#define DMAC_DCMD_SAI (1 << 23) /* source address increment */ +#define DMAC_DCMD_DAI (1 << 22) /* dest address increment */ + +#define DMAC_DCMD_SWDH_BIT 14 /* source port width */ +#define DMAC_DCMD_SWDH_32 (0 << DMAC_DCMD_SWDH_BIT) +#define DMAC_DCMD_SWDH_8 (1 << DMAC_DCMD_SWDH_BIT) +#define DMAC_DCMD_SWDH_16 (2 << DMAC_DCMD_SWDH_BIT) + +#define DMAC_DCMD_DWDH_BIT 12 /* dest port width */ +#define DMAC_DCMD_DWDH_32 (0 << DMAC_DCMD_DWDH_BIT) +#define DMAC_DCMD_DWDH_8 (1 << DMAC_DCMD_DWDH_BIT) + #define DMAC_DCMD_DWDH_16 (2 << DMAC_DCMD_DWDH_BIT) + +#define DMAC_DCMD_DS_BIT 8 /* transfer data size of a data unit */ +#define DMAC_DCMD_DS_32BIT (0 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_8BIT (1 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_16BIT (2 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_16BYTE (3 << DMAC_DCMD_DS_BIT) +#define DMAC_DCMD_DS_32BYTE (4 << DMAC_DCMD_DS_BIT) + +#define DMAC_DCMD_TM (1 << 7) /* transfer mode: 0-single 1-block */ + + +//detect if channel has completed job +#define DMAC_DCCSR_TT (1 << 3) /* transfer terminated */ +#define DMAC_BASE 0xB3020000 +#define REG32(addr) *((volatile u32 *)(addr)) +#define DMAC_DCCSR(n) (DMAC_BASE + (0x10 + (n) * 0x20)) /* DMA control/status */ +#define REG_DMAC_DCCSR(n) REG32(DMAC_DCCSR((n))) + +#define ds2_DMA_isBusy(n) \ + !( REG_DMAC_DCCSR((n)) & DMAC_DCCSR_TT ) + + +/* +Copy modes + +*/ + +#define DMA_MODE32BYTE DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM + +#define DMA_MODE16BYTE DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BYTE | DMAC_DCMD_TM + +#define DMA_MODE32BIT DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | \ + DMAC_DCMD_DS_32BIT + +#define DMA_MODE16BIT DMAC_DCMD_SWDH_16 | DMAC_DCMD_DWDH_16 | \ + DMAC_DCMD_DS_16BIT + +#define DMA_MODE8BIT DMAC_DCMD_SWDH_8 | DMAC_DCMD_DWDH_8 | \ + DMAC_DCMD_DS_8BIT | DMAC_DCMD_TM + +#define DMA_MODECOPY DMAC_DCMD_SAI + + + +extern int _dmaCopy(int ch, void *dest, void *src, unsigned int size, unsigned int flags); + +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bytes. + * size is in bytes and must be a multiple of 32. + * Both src and dest must be aligned to 32 bytes. + * Returns 0 on failure, non-zero on success. + */ +#define ds2_DMAcopy_32Byte(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE32BYTE) + +/* + * Copy 'size' bytes from src to dest, in blocks of 16 bytes. + * size is in bytes and must be a multiple of 16. + * Both src and dest must be aligned to 16 bytes. + * Returns 0 on failure, non-zero on success. + */ +#define ds2_DMAcopy_16Byte(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE16BYTE); + +/* + * Copy 'size' bytes from src to dest, in blocks of 32 bits (4 bytes). + * size is in bytes and must be a multiple of 4. + * Both src and dest must be aligned to 32 bits (4 bytes). + * Returns 0 on failure, non-zero on success. + */ +#define ds2_DMAcopy_32Bit(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE32BIT); + +/* + * Copy 'size' bytes from src to dest, in blocks of 16 bits (2 bytes). + * size is in bytes and must be a multiple of 2. + * Both src and dest must be aligned to 16 bits (2 bytes). + * Returns 0 on failure, non-zero on success. + */ +#define ds2_DMAcopy_16Bit(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE16BIT) + +/* + * Copy 'size' individual bytes (8 bits at a time) from src to dest. + * Returns 0 on failure, non-zero on success. + */ +#define ds2_DMAcopy_8Bit(ch, dest, src, size)\ + _dmaCopy(ch, dest, src, size, DMA_MODECOPY | DMA_MODE8BIT) + + + +//Stop DMA transfer +extern void dma_stop(int ch); + +#define ds2_DMA_stop(ch)\ + dma_stop(ch) + +//Wait DMA transfer over +extern int dma_wait_finish(int ch); + +#define ds2_DMA_wait(ch)\ + dma_wait_finish(ch) + + + +#ifdef __cplusplus +} +#endif + +#endif //__DMA_H__ + diff --git a/sdk-modifications/include/ds2_excpt.h b/sdk-modifications/include/ds2_excpt.h new file mode 100755 index 0000000..08fe77e --- /dev/null +++ b/sdk-modifications/include/ds2_excpt.h @@ -0,0 +1,55 @@ +#ifndef __DS2_EXCPT_H__ +#define __DS2_EXCPT_H__ + +#include +extern unsigned int Process_RA; +extern unsigned int Process_SP; + +#define SAVE_PROCESS_REGISTER() \ + do{ unsigned int sr ; \ + sr = read_c0_status(); \ + write_c0_status((sr&(~1))); \ + __asm__ __volatile__( \ + "sw $31,0x00(%0)\n\t" \ + "sw $29,0x00(%1)\n\t" \ + : \ + : "r" (&Process_RA),"r" (&Process_SP)); \ + write_c0_status(sr); \ + }while(0) + +#define RESTORE_PROCESS_REGISTER() \ + __asm__ __volatile__( \ + "lw $31,0x00(%0)\n\t" \ + "lw $29,0x00(%1)\n\t" \ + : \ + : "r" (&Process_RA),"r" (&Process_SP)) + +inline static void excpt_exit(x) \ +{ + unsigned int sr; + sr = read_c0_status(); + write_c0_status(sr & (~1)); + __asm__ __volatile__("lw $2,0x00(%0)\n\t" :: "r" (&x)); + RESTORE_PROCESS_REGISTER(); + write_c0_status(sr); + __asm__ __volatile__( + "jr $31\n\t" + "nop\n\t" + ); +} + +typedef void (*PFun_Exception_Handler)(unsigned int); + +//Setup handle to process the exception +//except_index: exception number +//except_handle: handle to process the exception +//arg: argument to the handle +extern int Setup_except_handle(unsigned int except_index, PFun_Exception_Handler except_handle, unsigned int arg); + +//Add a write watched exception, if the CPU write the addr, a exception will +// generated, the watch exception's number is 23 +//addr: address to be watched +extern void add_watch_point(unsigned int addr); + +#endif //__DS2_EXCPT_H__ + diff --git a/sdk-modifications/include/ds2_fcntl.h b/sdk-modifications/include/ds2_fcntl.h new file mode 100755 index 0000000..2c69221 --- /dev/null +++ b/sdk-modifications/include/ds2_fcntl.h @@ -0,0 +1,51 @@ +#ifndef __libc_fcntl_h__ +#define __libc_fcntl_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define O_RDONLY (1 << 0) +#define O_WRONLY (2 << 0) +#define O_RDWR (3 << 0) +#define O_APPEND (1 << 2) +#define O_CREAT (1 << 3) +#define O_DSYNC (1 << 4) +#define O_EXCL (1 << 5) +#define O_NOCTTY (1 << 6) +#define O_NONBLOCK (1 << 7) +#define O_RSYNC (1 << 8) +#define O_SYNC (1 << 9) +#define O_TRUNC (1 << 10) +#define O_CREATE O_CREAT + +#define O_ACCMODE 0x3 + +#define F_CLOEXEC (1 << 11) + +#define F_DUPFD 1 +#define F_GETFD 2 +#define F_SETFD 3 +#define F_GETFL 4 +#define F_SETFL 5 +#define F_GETLK 6 +#define F_SETLK 7 +#define F_SETLKW 8 +#define F_GETOWN 9 +#define F_SETOWN 10 +#define _F_LAST F_SETOWN + +#define _F_FILE_DESC (F_CLOEXEC) +#define _O_FILE_CREATE (O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC) +#define _O_FILE_STATUS (O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC) +#define _O_UNSUPPORTED (0) + +extern int open(const char* path, int oflag, ...); +extern int fcntl(int fildes, int cmd, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk-modifications/include/ds2_malloc.h b/sdk-modifications/include/ds2_malloc.h new file mode 100755 index 0000000..5f158f7 --- /dev/null +++ b/sdk-modifications/include/ds2_malloc.h @@ -0,0 +1,32 @@ +#ifndef __DS2_MALLOC_H__ +#define __DS2_MALLOC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void heapInit(unsigned int start, unsigned int end); + +extern void* Drv_alloc(unsigned int nbytes); +extern void Drv_deAlloc(void* address); +extern void* Drv_realloc(void* address, unsigned int nbytes); +extern void* Drv_calloc(unsigned int nmem, unsigned int size); + +#ifdef __cplusplus +} +#endif + +#define malloc Drv_alloc +#define calloc Drv_calloc +#define realloc Drv_realloc +#define free Drv_deAlloc + +#ifdef __cplusplus +#include +inline void* operator new ( size_t s ) { return malloc( s ); } +inline void* operator new[] ( size_t s ) { return malloc( s ); } +inline void operator delete ( void* p ) { free( p ); } +inline void operator delete[] ( void* p ) { free( p ); } +#endif + +#endif //__DS2_MALLOC_H__ diff --git a/sdk-modifications/include/ds2_mmc_api.h b/sdk-modifications/include/ds2_mmc_api.h new file mode 100755 index 0000000..28e75ef --- /dev/null +++ b/sdk-modifications/include/ds2_mmc_api.h @@ -0,0 +1,56 @@ +#ifndef __MMC_API_H__ +#define __MMC_API_H__ + +/* Error codes */ +enum mmc_result_t { + MMC_NO_RESPONSE = -1, + MMC_NO_ERROR = 0, + MMC_ERROR_OUT_OF_RANGE, + MMC_ERROR_ADDRESS, + MMC_ERROR_BLOCK_LEN, + MMC_ERROR_ERASE_SEQ, + MMC_ERROR_ERASE_PARAM, + MMC_ERROR_WP_VIOLATION, + MMC_ERROR_CARD_IS_LOCKED, + MMC_ERROR_LOCK_UNLOCK_FAILED, + MMC_ERROR_COM_CRC, + MMC_ERROR_ILLEGAL_COMMAND, + MMC_ERROR_CARD_ECC_FAILED, + MMC_ERROR_CC, + MMC_ERROR_GENERAL, + MMC_ERROR_UNDERRUN, + MMC_ERROR_OVERRUN, + MMC_ERROR_CID_CSD_OVERWRITE, + MMC_ERROR_STATE_MISMATCH, + MMC_ERROR_HEADER_MISMATCH, + MMC_ERROR_TIMEOUT, + MMC_ERROR_CRC, + MMC_ERROR_DRIVER_FAILURE, +}; + + +/* Get card's sectors*/ + +extern unsigned int MMC_GetSize(void); + + +/* initialize MMC/SD card */ +extern int MMC_Initialize(void); + +/* read a single block from MMC/SD card */ +extern int MMC_ReadBlock(unsigned int blockaddr, unsigned char *recbuf); + +/* read multi blocks from MMC/SD card */ +extern int MMC_ReadMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); + +/* write a block to MMC/SD card */ +extern int MMC_WriteBlock(unsigned int blockaddr, unsigned char *recbuf); + +/* write multi blocks to MMC/SD card */ +extern int MMC_WriteMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); + +/* detect MMC/SD card */ +extern int MMC_DetectStatus(void); + +#endif /* __MMC_API_H__ */ + diff --git a/sdk-modifications/include/ds2_timer.h b/sdk-modifications/include/ds2_timer.h new file mode 100755 index 0000000..3e5c3bc --- /dev/null +++ b/sdk-modifications/include/ds2_timer.h @@ -0,0 +1,50 @@ +#ifndef __DS2_TIMER_H__ +#define __DS2_TIMER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +* Function: register a timer interruptting periodly +* channel: timer id, from 0 to 1 +* period: interrupt period, unit is us, period < 2.5s +* handle: interrupt handle, if handle = NULL, the timer will not generate interrupt +* arg: argument to the interrupt handle +*/ +extern int initTimer(unsigned int channel, unsigned int period, void (*handle)(unsigned int), int arg); + +/* +* Function: set the timer run +*/ +extern void runTimer(unsigned int channel); + +/* +* Function: stop timer +*/ +extern void stopTimer(unsigned int channel); + +/* +* Function: reset timer +*/ +extern void resetTimer(unsigned int channel); + +/* +* Function: read value of timer +*/ +extern unsigned int readTimer(unsigned int channel); + + +#define SYSTIME_UNIT 42667 +/* +* Function: get the elapsed time since DS2 started +* it's uint is 42.667us, it will overflow after 50.9 horus since DS2 started +*/ +extern unsigned int getSysTime(void); + +#ifdef __cplusplus +} +#endif + +#endif //__DS2_TIMER_H__ + diff --git a/sdk-modifications/include/ds2_types.h b/sdk-modifications/include/ds2_types.h new file mode 100755 index 0000000..3ec59bf --- /dev/null +++ b/sdk-modifications/include/ds2_types.h @@ -0,0 +1,45 @@ +#ifndef __DS2_TYPES_H__ +#define __DS2_TYPES_H__ + +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef s8 +#define s8 char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef s16 +#define s16 short +#endif + +#ifndef u32 +#define u32 unsigned int +#endif + +#ifndef s32 +#define s32 int +#endif + +#ifndef u64 +#define u64 unsigned long long +#endif + +#ifndef s64 +#define s64 long long +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#endif //__DS2_TYPES_H__ diff --git a/sdk-modifications/include/ds2io.h b/sdk-modifications/include/ds2io.h new file mode 100755 index 0000000..e715cef --- /dev/null +++ b/sdk-modifications/include/ds2io.h @@ -0,0 +1,285 @@ +#ifndef __DS2IO_H__ +#define __DS2IO_H__ + +#ifndef BIT +#define BIT(a) (1< +#include "partition.h" +#include "directory.h" +#include "file_allocation_table.h" +//#include "unicode/unicode.h" +#include "fatdir_ex.h" +#include "fatfile_ex.h" + +//typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM} PARTITION_INTERFACE; + +struct IO_INTERFACE_STRUCT ; + +/* +Initialise any inserted block-devices. +Add the fat device driver to the devoptab, making it available for standard file functions. +cacheSize: The number of pages to allocate for each inserted block-device +setAsDefaultDevice: if true, make this the default device driver for file operations +*/ +bool fatInit (u32 cacheSize, bool setAsDefaultDevice); + +/* +Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. +*/ +bool fatInitDefault (void); + +/* +Special initialize for RPG card +*/ +bool fatInitRPG (void); + +/* +Mount the device specified by partitionNumber +PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice +PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +*/ +bool fatMountNormalInterface (PARTITION_INTERFACE partitionNumber, u32 cacheSize); + +/* +Mount a partition on a custom device +*/ +bool fatMountCustomInterface (struct IO_INTERFACE_STRUCT* device, u32 cacheSize); + +/* +Unmount the partition specified by partitionNumber +If there are open files, it will fail +*/ +bool fatUnmount (PARTITION_INTERFACE partitionNumber); + + +/* +Forcibly unmount the partition specified by partitionNumber +Any open files on the partition will become invalid +The cache will be invalidated, and any unflushed writes will be lost +*/ +bool fatUnsafeUnmount (PARTITION_INTERFACE partitionNumber); + +/* +Set the default device for access by fat: and fat0: +PD_DEFAULT is unallowed. +Doesn't do anything useful on GBA, since there is only one device +*/ +bool fatSetDefaultInterface (PARTITION_INTERFACE partitionNumber); + +#ifdef __cplusplus +} +#endif + +#endif // _LIBFAT_H diff --git a/sdk-modifications/include/fatdir.h b/sdk-modifications/include/fatdir.h new file mode 100755 index 0000000..529e401 --- /dev/null +++ b/sdk-modifications/include/fatdir.h @@ -0,0 +1,81 @@ +/* + fatdir.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-08-13 - Chishm + * Moved all externally visible directory related functions to fatdir + * Added _FAT_mkdir_r + + 2006-08-14 - Chishm + * Added directory iterator functions + + 2007-01-10 - Chishm + * Updated directory iterator functions for DevkitPro r20 +*/ + + +#ifndef _FATDIR_H +#define _FATDIR_H + +//#include +#include +//#include +#include "fs_common.h" +#include "directory.h" + +typedef struct { + PARTITION* partition; + DIR_ENTRY currentEntry; + u32 startCluster; + u32 posEntry; + bool inUse; + bool validEntry; +} DIR_STATE_STRUCT; + +extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); + +extern int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); + +extern int _FAT_unlink_r (struct _reent *r, const char *name); + +extern int _FAT_chdir_r (struct _reent *r, const char *name); + +extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); + +extern int _FAT_mkdir_r (struct _reent *r, const char *path, int mode); + +/* +Directory iterator functions +*/ +extern DIR_STATE_STRUCT* _FAT_diropen_r(struct _reent *r, DIR_STATE_STRUCT *dirState, const char *path); +extern int _FAT_dirreset_r (struct _reent *r, DIR_STATE_STRUCT *dirState); +extern int _FAT_dirnext_r (struct _reent *r, DIR_STATE_STRUCT *dirState, struct stat *filestat); +extern int _FAT_dirclose_r (struct _reent *r, DIR_STATE_STRUCT *dirState); + + +#endif // _FATDIR_H diff --git a/sdk-modifications/include/fatdir_ex.h b/sdk-modifications/include/fatdir_ex.h new file mode 100755 index 0000000..fbac46f --- /dev/null +++ b/sdk-modifications/include/fatdir_ex.h @@ -0,0 +1,18 @@ +#ifndef _FATDIR_EX_H_ +#define _FATDIR_EX_H_ + +#include "fatdir.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int dirnextl (DIR_ITER *dirState, char *filename, char *longFilename, struct stat *filestat); +int renamex( const char *oldName, const char *newName ); + +#ifdef __cplusplus +} +#endif + + +#endif//_FATDIR_EX_H_ diff --git a/sdk-modifications/include/fatfile.h b/sdk-modifications/include/fatfile.h new file mode 100755 index 0000000..4869562 --- /dev/null +++ b/sdk-modifications/include/fatfile.h @@ -0,0 +1,89 @@ +/* + fatfile.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-07-17 - Chishm + * Made all path inputs const char* + * Added _FAT_rename_r + + 2006-07-24 - Chishm + * Removed padding workaround from FILE_STRUCT + + 2006-08-13 - Chishm + * Moved all externally visible directory related functions to fatdir +*/ + + +#ifndef _FATFILE_H +#define _FATFILE_H + +//#include +#include + +#include "fs_common.h" +#include "partition.h" +#include "directory.h" + +typedef struct { + u32 cluster; + u32 sector; + s32 byte; +} FILE_POSITION; + +typedef struct { + int fd; + u32 filesize; + u32 startCluster; + u32 currentPosition; + FILE_POSITION rwPosition; + FILE_POSITION appendPosition; + bool read; + bool write; + bool append; + bool inUse; + PARTITION* partition; + DIR_ENTRY_POSITION dirEntryStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + DIR_ENTRY_POSITION dirEntryEnd; // Always points to the file's alias entry +} FILE_STRUCT; + +extern int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags); + +extern int _FAT_close_r (struct _reent *r, int fd); + +extern int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len); + +extern int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len); + +extern int _FAT_seek_r (struct _reent *r, int fd,int pos, int dir); + +extern int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st); + +#endif // _FATFILE_H diff --git a/sdk-modifications/include/fatfile_ex.h b/sdk-modifications/include/fatfile_ex.h new file mode 100755 index 0000000..c434b63 --- /dev/null +++ b/sdk-modifications/include/fatfile_ex.h @@ -0,0 +1,19 @@ +#ifndef _FATFILE_EX_H_ +#define _FATFILE_EX_H_ + +#include +#include "fatfile.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int freadex( void * buffer, int _size, int _n, FILE * f ); +int fwritex( const void * buffer, int _size, int _n, FILE * f ); + +#ifdef __cplusplus +} +#endif + + +#endif//_FATFILE_EX_H_ diff --git a/sdk-modifications/include/file_allocation_table.h b/sdk-modifications/include/file_allocation_table.h new file mode 100755 index 0000000..4fb4149 --- /dev/null +++ b/sdk-modifications/include/file_allocation_table.h @@ -0,0 +1,64 @@ +/* + file_allocation_table.h + Reading, writing and manipulation of the FAT structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-10-01 - Chishm + * Added _FAT_fat_linkFreeClusterCleared to clear a cluster when it is allocated +*/ + +#ifndef _FAT_H +#define _FAT_H + +#include "fs_common.h" +#include "partition.h" + +#define CLUSTER_EOF_16 0xFFFF +#define CLUSTER_EOF 0x0FFFFFFF +#define CLUSTER_FREE 0x0000 +#define CLUSTER_FIRST 0x0002 + +#define CLUSTERS_PER_FAT12 4085 +#define CLUSTERS_PER_FAT16 65525 + + +u32 _FAT_fat_nextCluster(PARTITION* partition, u32 cluster); + +u32 _FAT_fat_linkFreeCluster(PARTITION* partition, u32 cluster); +u32 _FAT_fat_linkFreeClusterCleared (PARTITION* partition, u32 cluster); + +bool _FAT_fat_clearLinks (PARTITION* partition, u32 cluster); + +u32 _FAT_fat_lastCluster (PARTITION* partition, u32 cluster); + +static inline u32 _FAT_fat_clusterToSector (PARTITION* partition, u32 cluster) { + return (cluster >= 2) ? ((cluster - 2) * partition->sectorsPerCluster) + partition->dataStart : partition->rootDirStart; +} + +#endif // _FAT_H diff --git a/sdk-modifications/include/filetime.h b/sdk-modifications/include/filetime.h new file mode 100755 index 0000000..fa651a7 --- /dev/null +++ b/sdk-modifications/include/filetime.h @@ -0,0 +1,44 @@ +/* + filetime.h + Conversion of file time and date values to various other types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _FILETIME_H +#define _FILETIME_H + +#include "fs_common.h" +#include + +u16 _FAT_filetime_getTimeFromRTC (void); +u16 _FAT_filetime_getDateFromRTC (void); + +time_t _FAT_filetime_to_time_t (u16 time, u16 date); + + +#endif // _FILETIME_H diff --git a/sdk-modifications/include/fs_api.h b/sdk-modifications/include/fs_api.h new file mode 100755 index 0000000..b3431b6 --- /dev/null +++ b/sdk-modifications/include/fs_api.h @@ -0,0 +1,151 @@ +#ifndef __FS_API_H__ +#define __FS_API_H__ +//v1.0 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/stat.h" +#include "fatfile.h" +#include "fatdir.h" + + +#define mode_t unsigned int +#define size_t unsigned int + +extern int fat_init(void); + +extern FILE_STRUCT* fat_fopen(const char *file, const char *mode); + +extern size_t fat_fread(void *buf, size_t size, size_t count, FILE_STRUCT *fp); + +extern size_t fat_fwrite(const void *buf, size_t size, size_t count, FILE_STRUCT *fp); + +extern int fat_fclose(FILE_STRUCT *fp); + +extern int fat_fseek(FILE_STRUCT *fp, long offset, int whence); + +extern long fat_ftell(FILE_STRUCT *fp); + +extern int fat_feof(FILE_STRUCT *fp); + +extern int fat_ferror(FILE_STRUCT *fp); + +extern void fat_clearerr(FILE_STRUCT *fp); + +extern int fat_fflush(FILE_STRUCT *fp); + +extern int fat_fgetc(FILE_STRUCT *fp); + +extern char* fat_fgets(char *buf, int n, FILE_STRUCT *fp); + +extern int fat_fputc(int ch, FILE_STRUCT *fp); + +extern int fat_fputs(const char *s, FILE_STRUCT *fp); + +extern int fat_remove(const char *filename); + +extern int fat_rename(const char *oldName, const char *newName); + +extern int fat_setHidden(const char *name, unsigned char hide); + +extern int fat_isHidden(struct stat *st); + +extern int fat_getShortName(const char *fullName, char *outName); + +extern void fat_rewind(FILE_STRUCT *fp); + +extern int fat_fstat(int fildes, struct stat *buf); + +extern int fat_fprintf(void* fp, const char *format, ...); + +extern int fat_fscanf(FILE_STRUCT *fp, const char *format, ...); + +extern DIR_STATE_STRUCT* fat_opendir(const char *name); + +extern DIR_ENTRY* fat_readdir(DIR_STATE_STRUCT *dirp); + +extern long fat_telldir(DIR_STATE_STRUCT *dirp); + +extern void fat_seekdir(DIR_STATE_STRUCT *dirp, long int loc); + +extern int fat_closedir(DIR_STATE_STRUCT *dirp); + +extern int fat_chdir(const char *path); + +extern char* fat_getcwd(char *buf, size_t size); + +extern int fat_mkdir(const char *path, mode_t mode); + +extern int fat_rmdir(const char *path); + +extern int fat_lstat(const char *path, struct stat *buf); + +extern DIR_ENTRY* fat_readdir_ex(DIR_STATE_STRUCT *dirp, struct stat *statbuf); + +#ifndef SEEK_SET +#define SEEK_SET 0 /* Seek from beginning of file. */ +#endif + +#ifndef SEEK_CUR +#define SEEK_CUR 1 /* Seek from current position. */ +#endif + +#ifndef SEEK_END +#define SEEK_END 2 /* Seek from end of file. */ +#endif + +//#define S_ISDIR(st) (st.st_mode & S_IFDIR) + +#define FILE FILE_STRUCT +#define fopen fat_fopen +#define fread fat_fread +#define fwrite fat_fwrite +#define fclose fat_fclose +#define fgets fat_fgets +#define fseek fat_fseek +#define ftell fat_ftell +#define feof fat_feof +#define ferror fat_ferror +#define fclearerr fat_clearerr +#define fflush fat_fflush +#define fgetc fat_fgetc +#define fgets fat_fgets +#define fputc fat_fputc +#define fputs fat_fputs +#define fprintf fat_fprintf +#define fscanf fat_fscanf +#define remove fat_remove + +#define DIR DIR_STATE_STRUCT +#define dirent DIR_ENTRY +#define opendir fat_opendir +#define readdir fat_readdir +#define telldir fat_telldir +#define seekdir fat_seekdir +#define closedir fat_closedir +#define chdir fat_chdir +#define getcwd fat_getcwd +#define mkdir fat_mkdir +#define rmdir fat_rmdir + +#define lstat fat_lstat +#define fstat fat_fstat + +#define S_ISHID(st_mode) ((st_mode & S_IHIDDEN) != 0) + +//the extended version of readdir_ex +#define readdir_ex fat_readdir_ex + +#define MAX_PATH 512 +#define MAX_FILE 512 + +//Misc function +extern bool fat_getDiskSpaceInfo( char * diskName, unsigned int *total, unsigned int *used, unsigned int *freeSpace ); + +#ifdef __cplusplus +} +#endif + +#endif //__FS_API_H__ diff --git a/sdk-modifications/include/fs_cache.h b/sdk-modifications/include/fs_cache.h new file mode 100755 index 0000000..b0ab9be --- /dev/null +++ b/sdk-modifications/include/fs_cache.h @@ -0,0 +1,118 @@ +/* + cache.h + The cache is not visible to the user. It should be flushed + when any file is closed or changes are made to the filesystem. + + This cache implements a least-used-page replacement policy. This will + distribute sectors evenly over the pages, so if less than the maximum + pages are used at once, they should all eventually remain in the cache. + This also has the benefit of throwing out old sectors, so as not to keep + too many stale pages around. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _CACHE_H +#define _CACHE_H + +#include "fs_common.h" +#include "disc_io/disc_io.h" + +#define CACHE_PAGE_SIZE BYTES_PER_READ + +typedef struct { + u32 sector; + u32 count; + bool dirty; +} CACHE_ENTRY; + +typedef struct { + const IO_INTERFACE* disc; + u32 numberOfPages; + CACHE_ENTRY* cacheEntries; + u8* pages; +} CACHE; + + +/* +Read data from a sector in the cache +If the sector is not in the cache, it will be swapped in +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, u32 sector, u32 offset, u32 size); + +/* +Write data to a sector in the cache +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); + +/* +Write data to a sector in the cache, zeroing the sector first +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, u32 sector, u32 offset, u32 size); + +/* +Read a full sector from the cache +*/ +static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, u32 sector) { + return _FAT_cache_readPartialSector (cache, buffer, sector, 0, BYTES_PER_READ); +} + +/* +Write a full sector to the cache +*/ +static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, u32 sector) { + return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ); +} + +/* +Write any dirty sectors back to disc and clear out the contents of the cache +*/ +bool _FAT_cache_flush (CACHE* cache); + +/* +Clear out the contents of the cache without writing any dirty sectors first +*/ +void _FAT_cache_invalidate (CACHE* cache); + +CACHE* _FAT_cache_constructor (u32 numberOfPages, const IO_INTERFACE* discInterface); + +void _FAT_cache_destructor (CACHE* cache); + +#endif // _CACHE_H diff --git a/sdk-modifications/include/fs_common.h b/sdk-modifications/include/fs_common.h new file mode 100755 index 0000000..c482775 --- /dev/null +++ b/sdk-modifications/include/fs_common.h @@ -0,0 +1,129 @@ +/* + common.h + Common definitions and included files for the FATlib + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _COMMON_H +#define _COMMON_H + +// When compiling for NDS, make sure NDS is defined +#ifndef NDS + #if defined ARM9 || defined ARM7 + #define NDS + #endif +#endif + +#if 0 +#ifdef NDS + #include +#else + #include "gba_types.h" +#endif +#endif + +#define BYTES_PER_READ 512 + +#ifndef NULL + #define NULL 0 +#endif + +#ifndef bool +#define bool int +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef u32 +#define u32 unsigned long +#endif + +#ifndef s32 +#define s32 long +#endif + +struct _reent +{ + /* FILE is a big struct and may change over time. To try to achieve binary + compatibility with future versions, put stdin,stdout,stderr here. + These are pointers into member __sf defined below. */ +// __FILE *_stdin, *_stdout, *_stderr; /* XXX */ + + int _errno; /* local copy of errno */ + +// int _inc; /* used by tmpnam */ + +// char *_emergency; + +// int __sdidinit; /* 1 means stdio has been init'd */ + +// int _current_category; /* unused */ +// _CONST char *_current_locale; /* unused */ + +// struct _mprec *_mp; + +// void _EXFNPTR(__cleanup, (struct _reent *)); + +// int _gamma_signgam; + + /* used by some fp conversion routines */ +// int _cvtlen; /* should be size_t */ +// char *_cvtbuf; + +// struct _rand48 *_r48; +// struct __tm *_localtime_buf; +// char *_asctime_buf; + + /* signal info */ +// void (**(_sig_func))(int); + + /* atexit stuff */ +// struct _atexit *_atexit; +// struct _atexit _atexit0; + +// struct _glue __sglue; /* root of glue chain */ +// __FILE *__sf; /* file descriptors */ +// struct _misc_reent *_misc; /* strtok, multibyte states */ +// char *_signal_buf; /* strsignal */ +}; + +#endif // _COMMON_H diff --git a/sdk-modifications/include/fs_unicode.h b/sdk-modifications/include/fs_unicode.h new file mode 100755 index 0000000..45e9d0a --- /dev/null +++ b/sdk-modifications/include/fs_unicode.h @@ -0,0 +1,16 @@ +#ifndef __FS_UNICODE_H__ +#define __FS_UNICODE_H__ + +extern void _FAT_utf8_to_unicode16( const char* src, u16* dest ); + +extern void _FAT_unicode16_to_utf8( const u16* src, char* dest); + +extern u32 _unistrnlen( const u16* unistr, u32 maxlen ); + +extern int _unistrncmp( const u16 * src, const u16 * dest, u32 maxlen ); + +extern const u16 * _unistrchr( const u16 * str, u16 unichar ); + +int _uniisalnum( u8 ch ); + +#endif //__FS_UNICODE_H__ diff --git a/sdk-modifications/include/mem_allocate.h b/sdk-modifications/include/mem_allocate.h new file mode 100755 index 0000000..844f6df --- /dev/null +++ b/sdk-modifications/include/mem_allocate.h @@ -0,0 +1,47 @@ +/* + mem_allocate.h + Memory allocation and destruction calls + Replace these calls with custom allocators if + malloc is unavailable + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _MEM_ALLOCATE_H +#define _MEM_ALLOCATE_H + +#include "ds2_malloc.h" + +static inline void* _FAT_mem_allocate (size_t size) { + return ((void*)malloc (size)); +} + +static inline void _FAT_mem_free (void* mem) { + return (free ((void*)mem)); +} + +#endif // _MEM_ALLOCATE_H diff --git a/sdk-modifications/include/mips.h b/sdk-modifications/include/mips.h new file mode 100755 index 0000000..3792565 --- /dev/null +++ b/sdk-modifications/include/mips.h @@ -0,0 +1,820 @@ +/************************************************************************** +* * +* PROJECT : MIPS port for uC/OS-II * +* * +* MODULE : MIPS.h * +* * +* AUTHOR : Michael Anburaj * +* URL : http://geocities.com/michaelanburaj/ * +* EMAIL: michaelanburaj@hotmail.com * +* * +* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board * +* * +* TOOL-CHAIN : SDE & Cygnus * +* * +* DESCRIPTION : * +* MIPS processor definitions. * +* The basic CPU definitions are found in the file archdefs.h, which * +* is included by mips.h. * +* * +* mips.h implements aliases for some of the definitions in archdefs.h * +* and adds various definitions. * +* * +**************************************************************************/ + + +#ifndef __MIPS_H__ +#define __MIPS_H__ + +#include "archdefs.h" + + +/* ********************************************************************* */ +/* Module configuration */ + + +/* ********************************************************************* */ +/* Interface macro & data definition */ + +#ifndef MSK +#define MSK(n) ((1 << (n)) - 1) +#endif + +/* CPU registers */ +#define SYS_CPUREG_ZERO 0 +#define SYS_CPUREG_AT 1 +#define SYS_CPUREG_V0 2 +#define SYS_CPUREG_V1 3 +#define SYS_CPUREG_A0 4 +#define SYS_CPUREG_A1 5 +#define SYS_CPUREG_A2 6 +#define SYS_CPUREG_A3 7 +#define SYS_CPUREG_T0 8 +#define SYS_CPUREG_T1 9 +#define SYS_CPUREG_T2 10 +#define SYS_CPUREG_T3 11 +#define SYS_CPUREG_T4 12 +#define SYS_CPUREG_T5 13 +#define SYS_CPUREG_T6 14 +#define SYS_CPUREG_T7 15 +#define SYS_CPUREG_S0 16 +#define SYS_CPUREG_S1 17 +#define SYS_CPUREG_S2 18 +#define SYS_CPUREG_S3 19 +#define SYS_CPUREG_S4 20 +#define SYS_CPUREG_S5 21 +#define SYS_CPUREG_S6 22 +#define SYS_CPUREG_S7 23 +#define SYS_CPUREG_T8 24 +#define SYS_CPUREG_T9 25 +#define SYS_CPUREG_K0 26 +#define SYS_CPUREG_K1 27 +#define SYS_CPUREG_GP 28 +#define SYS_CPUREG_SP 29 +#define SYS_CPUREG_S8 30 +#define SYS_CPUREG_FP SYS_CPUREG_S8 +#define SYS_CPUREG_RA 31 + + +/* CPU register fp ($30) has an alias s8 */ +#define s8 fp + + +/* Aliases for System Control Coprocessor (CP0) registers */ +#define C0_INDEX C0_Index +#define C0_RANDOM C0_Random +#define C0_ENTRYLO0 C0_EntryLo0 +#define C0_ENTRYLO1 C0_EntryLo1 +#define C0_CONTEXT C0_Context +#define C0_PAGEMASK C0_PageMask +#define C0_WIRED C0_Wired +#define C0_BADVADDR C0_BadVAddr +#define C0_COUNT C0_Count +#define C0_ENTRYHI C0_EntryHi +#define C0_COMPARE C0_Compare +#define C0_STATUS C0_Status +#define C0_CAUSE C0_Cause + +#ifdef C0_PRID /* ArchDefs has an obsolete def. of C0_PRID */ +#undef C0_PRID +#endif +#define C0_PRID C0_PRId + +#define C0_CONFIG C0_Config +#define C0_CONFIG1 C0_Config1 +#define C0_LLADDR C0_LLAddr +#define C0_WATCHLO C0_WatchLo +#define C0_WATCHHI C0_WatchHi +#define C0_DEBUG C0_Debug +#define C0_PERFCNT C0_PerfCnt +#define C0_ERRCTL C0_ErrCtl +#define C0_CACHEERR C0_CacheErr +#define C0_TAGLO C0_TagLo +#define C0_DATALO C0_DataLo +#define C0_TAGHI C0_TagHi +#define C0_DATAHI C0_DataHi +#define C0_ERROREPC C0_ErrorEPC +#if 0 +#define C0_DESAVE C0_DESAVE +#define C0_EPC C0_EPC +#define C0_DEPC C0_DEPC +#endif + +/* System Control Coprocessor (CP0) registers select fields */ +#define C0_INDEX_SEL 0 /* TLB Index */ +#define C0_RANDOM_SEL 0 /* TLB Random */ +#define C0_TLBLO0_SEL 0 /* TLB EntryLo0 */ +#define C0_TLBLO1_SEL 0 /* TLB EntryLo1 */ +#define C0_CONTEXT_SEL 0 /* Context */ +#define C0_PAGEMASK_SEL 0 /* TLB PageMask */ +#define C0_WIRED_SEL 0 /* TLB Wired */ +#define C0_BADVADDR_SEL 0 /* Bad Virtual Address */ +#define C0_COUNT_SEL 0 /* Count */ +#define C0_ENTRYHI_SEL 0 /* TLB EntryHi */ +#define C0_COMPARE_SEL 0 /* Compare */ +#define C0_STATUS_SEL 0 /* Processor Status */ +#define C0_CAUSE_SEL 0 /* Exception Cause */ +#define C0_EPC_SEL 0 /* Exception PC */ +#define C0_PRID_SEL 0 /* Processor Revision Indentifier */ +#define C0_CONFIG_SEL 0 /* Config */ +#define C0_CONFIG1_SEL 1 /* Config1 */ +#define C0_LLADDR_SEL 0 /* LLAddr */ +#define C0_WATCHLO_SEL 0 /* WatchpointLo */ +#define C0_WATCHHI_SEL 0 /* WatchpointHi */ +#define C0_DEBUG_SEL 0 /* EJTAG Debug Register */ +#define C0_DEPC_SEL 0 /* Program counter at last EJTAG debug exception */ +#define C0_PERFCNT_SEL 0 /* Performance counter interface */ +#define C0_ERRCTL_SEL 0 /* ERRCTL */ +#define C0_CACHEERR_SEL 0 /* CacheErr */ +#define C0_TAGLO_SEL 0 /* TagLo */ +#define C0_DATALO_SEL 1 /* DataLo */ +#define C0_DTAGLO_SEL 2 /* DTagLo */ +#define C0_TAGHI_SEL 0 /* TagHi */ +#define C0_DATAHI_SEL 1 /* DataHi */ +#define C0_DTAGHI_SEL 2 /* DTagHi */ +#define C0_ERROREPC_SEL 0 /* ErrorEPC */ +#define C0_DESAVE_SEL 0 /* EJTAG dbg exc. save register */ + + +/* C0_CONFIG register encoding */ + +#define C0_CONFIG_M_SHF S_ConfigMore +#define C0_CONFIG_M_MSK M_ConfigMore +#define C0_CONFIG_M_BIT C0_CONFIG_M_MSK + +#define C0_CONFIG_BE_SHF S_ConfigBE +#define C0_CONFIG_BE_MSK M_ConfigBE +#define C0_CONFIG_BE_BIT C0_CONFIG_BE_MSK + +#define C0_CONFIG_AT_SHF S_ConfigAT +#define C0_CONFIG_AT_MSK M_ConfigAT +#define C0_CONFIG_AT_MIPS32 K_ConfigAT_MIPS32 +#define C0_CONFIG_AT_MIPS64_32ADDR K_ConfigAT_MIPS64S +#define C0_CONFIG_AT_MIPS64 K_ConfigAT_MIPS64 + +#define C0_CONFIG_AR_SHF S_ConfigAR +#define C0_CONFIG_AR_MSK M_ConfigAR + +#define C0_CONFIG_MT_SHF S_ConfigMT +#define C0_CONFIG_MT_MSK M_ConfigMT +#define C0_CONFIG_MT_NONE K_ConfigMT_NoMMU +#define C0_CONFIG_MT_TLB K_ConfigMT_TLBMMU +#define C0_CONFIG_MT_BAT K_ConfigMT_BATMMU +#define C0_CONFIG_MT_NON_STD K_ConfigMT_FMMMU + +#define C0_CONFIG_K0_SHF S_ConfigK0 +#define C0_CONFIG_K0_MSK M_ConfigK0 +#define C0_CONFIG_K0_WTHRU_NOALLOC K_CacheAttrCWTnWA +#define C0_CONFIG_K0_WTHRU_ALLOC K_CacheAttrCWTWA +#define C0_CONFIG_K0_UNCACHED K_CacheAttrU +#define C0_CONFIG_K0_NONCOHERENT K_CacheAttrCN +#define C0_CONFIG_K0_COHERENTXCL K_CacheAttrCCE +#define C0_CONFIG_K0_COHERENTXCLW K_CacheAttrCCS +#define C0_CONFIG_K0_COHERENTUPD K_CacheAttrCCU +#define C0_CONFIG_K0_UNCACHED_ACCEL K_CacheAttrUA + + +/* WC field. + * + * This feature is present specifically to support configuration + * testing of the core in a lead vehicle, and is not supported + * in any other environment. Attempting to use this feature + * outside of the scope of a lead vehicle is a violation of the + * MIPS Architecture, and may cause unpredictable operation of + * the processor. + */ +#define C0_CONFIG_WC_SHF 19 +#define C0_CONFIG_WC_MSK (MSK(1) << C0_CONFIG_WC_SHF) +#define C0_CONFIG_WC_BIT C0_CONFIG_WC_MSK + + +/* C0_CONFIG1 register encoding */ + +#define C0_CONFIG1_MMUSIZE_SHF S_Config1MMUSize +#define C0_CONFIG1_MMUSIZE_MSK M_Config1MMUSize + +#define C0_CONFIG1_IS_SHF S_Config1IS +#define C0_CONFIG1_IS_MSK M_Config1IS + +#define C0_CONFIG1_IL_SHF S_Config1IL +#define C0_CONFIG1_IL_MSK M_Config1IL + +#define C0_CONFIG1_IA_SHF S_Config1IA +#define C0_CONFIG1_IA_MSK M_Config1IA + +#define C0_CONFIG1_DS_SHF S_Config1DS +#define C0_CONFIG1_DS_MSK M_Config1DS + +#define C0_CONFIG1_DL_SHF S_Config1DL +#define C0_CONFIG1_DL_MSK M_Config1DL + +#define C0_CONFIG1_DA_SHF S_Config1DA +#define C0_CONFIG1_DA_MSK M_Config1DA + +#define C0_CONFIG1_WR_SHF S_Config1WR +#define C0_CONFIG1_WR_MSK M_Config1WR +#define C0_CONFIG1_WR_BIT C0_CONFIG1_WR_MSK + +#define C0_CONFIG1_CA_SHF S_Config1CA +#define C0_CONFIG1_CA_MSK M_Config1CA +#define C0_CONFIG1_CA_BIT C0_CONFIG1_CA_MSK + +#define C0_CONFIG1_EP_SHF S_Config1EP +#define C0_CONFIG1_EP_MSK M_Config1EP +#define C0_CONFIG1_EP_BIT C0_CONFIG1_EP_MSK + +#define C0_CONFIG1_FP_SHF S_Config1FP +#define C0_CONFIG1_FP_MSK M_Config1FP +#define C0_CONFIG1_FP_BIT C0_CONFIG1_FP_MSK + + +/* C0_STATUS register encoding */ + +#define C0_STATUS_CU3_SHF S_StatusCU3 +#define C0_STATUS_CU3_MSK M_StatusCU3 +#define C0_STATUS_CU3_BIT C0_STATUS_CU3_MSK + +#define C0_STATUS_CU2_SHF S_StatusCU2 +#define C0_STATUS_CU2_MSK M_StatusCU2 +#define C0_STATUS_CU2_BIT C0_STATUS_CU2_MSK + +#define C0_STATUS_CU1_SHF S_StatusCU1 +#define C0_STATUS_CU1_MSK M_StatusCU1 +#define C0_STATUS_CU1_BIT C0_STATUS_CU1_MSK + +#define C0_STATUS_CU0_SHF S_StatusCU1 +#define C0_STATUS_CU0_MSK M_StatusCU1 +#define C0_STATUS_CU0_BIT C0_STATUS_CU0_MSK + +#define C0_STATUS_RP_SHF S_StatusRP +#define C0_STATUS_RP_MSK M_StatusRP +#define C0_STATUS_RP_BIT C0_STATUS_RP_MSK + +#define C0_STATUS_FR_SHF S_StatusFR +#define C0_STATUS_FR_MSK M_StatusFR +#define C0_STATUS_FR_BIT C0_STATUS_FR_MSK + +#define C0_STATUS_RE_SHF S_StatusRE +#define C0_STATUS_RE_MSK M_StatusRE +#define C0_STATUS_RE_BIT C0_STATUS_RE_MSK + +#define C0_STATUS_BEV_SHF S_StatusBEV +#define C0_STATUS_BEV_MSK M_StatusBEV +#define C0_STATUS_BEV_BIT C0_STATUS_BEV_MSK + +#define C0_STATUS_TS_SHF S_StatusTS +#define C0_STATUS_TS_MSK M_StatusTS +#define C0_STATUS_TS_BIT C0_STATUS_TS_MSK + +#define C0_STATUS_SR_SHF S_StatusSR +#define C0_STATUS_SR_MSK M_StatusSR +#define C0_STATUS_SR_BIT C0_STATUS_SR_MSK + +#define C0_STATUS_NMI_SHF S_StatusNMI +#define C0_STATUS_NMI_MSK M_StatusNMI +#define C0_STATUS_NMI_BIT C0_STATUS_NMI_MSK + +#define C0_STATUS_IM_SHF S_StatusIM +#define C0_STATUS_IM_MSK M_StatusIM +/* Note that the the definitions below indicate the interrupt number + * rather than the mask. + * (0..1 for SW interrupts and 2...7 for HW interrupts) + */ +#define C0_STATUS_IM_SW0 (S_StatusIM0 - S_StatusIM) +#define C0_STATUS_IM_SW1 (S_StatusIM1 - S_StatusIM) +#define C0_STATUS_IM_HW0 (S_StatusIM2 - S_StatusIM) +#define C0_STATUS_IM_HW1 (S_StatusIM3 - S_StatusIM) +#define C0_STATUS_IM_HW2 (S_StatusIM4 - S_StatusIM) +#define C0_STATUS_IM_HW3 (S_StatusIM5 - S_StatusIM) +#define C0_STATUS_IM_HW4 (S_StatusIM6 - S_StatusIM) +#define C0_STATUS_IM_HW5 (S_StatusIM7 - S_StatusIM) + +/* Max interrupt code */ +#define C0_STATUS_IM_MAX C0_STATUS_IM_HW5 + +#define C0_STATUS_KSU_SHF S_StatusKSU +#define C0_STATUS_KSU_MSK M_StatusKSU + +#define C0_STATUS_UM_SHF S_StatusUM +#define C0_STATUS_UM_MSK M_StatusUM +#define C0_STATUS_UM_BIT C0_STATUS_UM_MSK + +#define C0_STATUS_ERL_SHF S_StatusERL +#define C0_STATUS_ERL_MSK M_StatusERL +#define C0_STATUS_ERL_BIT C0_STATUS_ERL_MSK + +#define C0_STATUS_EXL_SHF S_StatusEXL +#define C0_STATUS_EXL_MSK M_StatusEXL +#define C0_STATUS_EXL_BIT C0_STATUS_EXL_MSK + +#define C0_STATUS_IE_SHF S_StatusIE +#define C0_STATUS_IE_MSK M_StatusIE +#define C0_STATUS_IE_BIT C0_STATUS_IE_MSK + + +/* C0_PRID register encoding */ + +#define C0_PRID_OPT_SHF S_PRIdCoOpt +#define C0_PRID_OPT_MSK M_PRIdCoOpt + +#define C0_PRID_COMP_SHF S_PRIdCoID +#define C0_PRID_COMP_MSK M_PRIdCoID +#define C0_PRID_COMP_MIPS K_PRIdCoID_MIPS +#define C0_PRID_COMP_NOT_MIPS32_64 0 + +#define C0_PRID_PRID_SHF S_PRIdImp +#define C0_PRID_PRID_MSK M_PRIdImp + +/* Jade */ +#define C0_PRID_PRID_4Kc K_PRIdImp_Jade +#define C0_PRID_PRID_4Kmp K_PRIdImp_JadeLite /* 4Km/4Kp */ +/* Emerald */ +#define C0_PRID_PRID_4KEc K_PRIdImp_4KEc +#define C0_PRID_PRID_4KEmp K_PRIdImp_4KEmp +/* Coral */ +#define C0_PRID_PRID_4KSc K_PRIdImp_4KSc +/* Opal */ +#define C0_PRID_PRID_5K K_PRIdImp_Opal +/* Ruby */ +#define C0_PRID_PRID_20Kc K_PRIdImp_Ruby +/* Other CPUs */ +#define C0_PRID_PRID_R4000 K_PRIdImp_R4000 +#define C0_PRID_PRID_RM52XX K_PRIdImp_R5200 +#define C0_PRID_PRID_RM70XX 0x27 + +#define C0_PRID_REV_SHF S_PRIdRev +#define C0_PRID_REV_MSK M_PRIdRev + + +#define MIPS_4Kc ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4Kc << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_4Kmp ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4Kmp << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_4KEc ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4KEc << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_4KEmp ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4KEmp << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_4KSc ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_4KSc << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_5K ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_5K << \ + C0_PRID_PRID_SHF) \ + ) + +#define MIPS_20Kc ( (C0_PRID_COMP_MIPS << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_20Kc << \ + C0_PRID_PRID_SHF) \ + ) + +#define QED_RM52XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_RM52XX << \ + C0_PRID_PRID_SHF) \ + ) + +#define QED_RM70XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \ + C0_PRID_COMP_SHF) | \ + (C0_PRID_PRID_RM70XX << \ + C0_PRID_PRID_SHF) \ + ) + +/* C0_ENTRYHI register encoding */ + +#define C0_ENTRYHI_VPN2_SHF S_EntryHiVPN2 +#define C0_ENTRYHI_VPN2_MSK M_EntryHiVPN2 + +#define C0_ENTRYHI_ASID_SHF S_EntryHiASID +#define C0_ENTRYHI_ASID_MSK M_EntryHiASID + + +/* C0_CAUSE register encoding */ + +#define C0_CAUSE_BD_SHF S_CauseBD +#define C0_CAUSE_BD_MSK M_CauseBD +#define C0_CAUSE_BD_BIT C0_CAUSE_BD_MSK + +#define C0_CAUSE_CE_SHF S_CauseCE +#define C0_CAUSE_CE_MSK M_CauseCE + +#define C0_CAUSE_IV_SHF S_CauseIV +#define C0_CAUSE_IV_MSK M_CauseIV +#define C0_CAUSE_IV_BIT C0_CAUSE_IV_MSK + +#define C0_CAUSE_WP_SHF S_CauseWP +#define C0_CAUSE_WP_MSK M_CauseWP +#define C0_CAUSE_WP_BIT C0_CAUSE_WP_MSK + +#define C0_CAUSE_IP_SHF S_CauseIP +#define C0_CAUSE_IP_MSK M_CauseIP + +#define C0_CAUSE_CODE_SHF S_CauseExcCode +#define C0_CAUSE_CODE_MSK M_CauseExcCode + +#define C0_CAUSE_CODE_INT EX_INT +#define C0_CAUSE_CODE_MOD EX_MOD +#define C0_CAUSE_CODE_TLBL EX_TLBL +#define C0_CAUSE_CODE_TLBS EX_TLBS +#define C0_CAUSE_CODE_ADEL EX_ADEL +#define C0_CAUSE_CODE_ADES EX_ADES +#define C0_CAUSE_CODE_IBE EX_IBE +#define C0_CAUSE_CODE_DBE EX_DBE +#define C0_CAUSE_CODE_SYS EX_SYS +#define C0_CAUSE_CODE_BP EX_BP +#define C0_CAUSE_CODE_RI EX_RI +#define C0_CAUSE_CODE_CPU EX_CPU +#define C0_CAUSE_CODE_OV EX_OV +#define C0_CAUSE_CODE_TR EV_TR +#define C0_CAUSE_CODE_FPE EX_FPE +#define C0_CAUSE_CODE_WATCH EX_WATCH +#define C0_CAUSE_CODE_MCHECK EX_MCHECK + +/* Max cause code */ +#define C0_CAUSE_CODE_MAX EX_MCHECK + + +/* C0_PAGEMASK register encoding */ +#define C0_PAGEMASK_MASK_SHF S_PageMaskMask +#define C0_PAGEMASK_MASK_MSK M_PageMaskMask +#define C0_PAGEMASK_MASK_4K K_PageMask4K +#define C0_PAGEMASK_MASK_16K K_PageMask16K +#define C0_PAGEMASK_MASK_64K K_PageMask64K +#define C0_PAGEMASK_MASK_256K K_PageMask256K +#define C0_PAGEMASK_MASK_1M K_PageMask1M +#define C0_PAGEMASK_MASK_4M K_PageMask4M +#define C0_PAGEMASK_MASK_16M K_PageMask16M + + +/* C0_ENTRYLO0 register encoding (equiv. to C0_ENTRYLO1) */ +#define C0_ENTRYLO0_PFN_SHF S_EntryLoPFN +#define C0_ENTRYLO0_PFN_MSK M_EntryLoPFN + +#define C0_ENTRYLO0_C_SHF S_EntryLoC +#define C0_ENTRYLO0_C_MSK M_EntryLoC + +#define C0_ENTRYLO0_D_SHF S_EntryLoD +#define C0_ENTRYLO0_D_MSK M_EntryLoD + +#define C0_ENTRYLO0_V_SHF S_EntryLoV +#define C0_ENTRYLO0_V_MSK M_EntryLoV + +#define C0_ENTRYLO0_G_SHF S_EntryLoG +#define C0_ENTRYLO0_G_MSK M_EntryLoG + + +/* FPU (CP1) FIR register encoding */ +#define C1_FIR_3D_SHF S_FIRConfig3D +#define C1_FIR_3D_MSK M_FIRConfig3D + +#define C1_FIR_PS_SHF S_FIRConfigPS +#define C1_FIR_PS_MSK M_FIRConfigPS + +#define C1_FIR_D_SHF S_FIRConfigD +#define C1_FIR_D_MSK M_FIRConfigD + +#define C1_FIR_S_SHF S_FIRConfigS +#define C1_FIR_S_MSK M_FIRConfigS + +#define C1_FIR_PRID_SHF S_FIRImp +#define C1_FIR_PRID_MSK M_FIRImp + +#define C1_FIR_REV_SHF S_FIRRev +#define C1_FIR_REV_MSK M_FIRRev + + +/* FPU (CP1) FCSR control/status register */ +#define C1_FCSR_FCC_SHF S_FCSRFCC7_1 +#define C1_FCSR_FCC_MSK M_FCSRFCC7_1 + +#define C1_FCSR_FS_SHF S_FCSRFS +#define C1_FCSR_FS_MSK M_FCSRFS +#define C1_FCSR_FS_BIT C1_FCSR_FS_MSK + +#define C1_FCSR_CC_SHF S_FCSRCC +#define C1_FCSR_CC_MSK M_FCSRCC + +#define C1_FCSR_IMPL_SHF S_FCSRImpl +#define C1_FCSR_IMPL_MSK M_FCSRImpl + +#define C1_FCSR_EXC_SHF S_FCSRExc +#define C1_FCSR_EXC_MSK M_FCSRExc + +#define C1_FCSR_ENA_SHF S_FCSREna +#define C1_FCSR_ENA_MSK M_FCSREna + +#define C1_FCSR_FLG_SHF S_FCSRFlg +#define C1_FCSR_FLG_MSK M_FCSRFlg + +#define C1_FCSR_RM_SHF S_FCSRRM +#define C1_FCSR_RM_MSK M_FCSRRM +#define C1_FCSR_RM_RN K_FCSRRM_RN +#define C1_FCSR_RM_RZ K_FCSRRM_RZ +#define C1_FCSR_RM_RP K_FCSRRM_RP +#define C1_FCSR_RM_RM K_FCSRRM_RM + + + +/* cache operations */ + +#define CACHE_OP( code, type ) ( ((code) << 2) | (type) ) + +#define ICACHE_INDEX_INVALIDATE CACHE_OP(0x0, 0) +#define ICACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 0) +#define ICACHE_INDEX_STORE_TAG CACHE_OP(0x2, 0) +#define DCACHE_INDEX_WRITEBACK_INVALIDATE CACHE_OP(0x0, 1) +#define DCACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 1) +#define DCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 1) +#define SCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 3) + +#define ICACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 0) +#define ICACHE_ADDR_FILL CACHE_OP(0x5, 0) +#define ICACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 0) +#define DCACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 1) +#define DCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 1) +#define DCACHE_ADDR_HIT_WRITEBACK CACHE_OP(0x6, 1) +#define DCACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 1) + +#define SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 3) + +/* Workaround for bug in early revisions of MIPS 4K family of + * processors. Only relevant in early engineering samples of test + * chips (RTL revision <= 3.0). + * + * The bug is described in : + * + * MIPS32 4K(tm) Processor Core Family RTL Errata Sheet + * MIPS Document No: MD00003 + * + * The bug is identified as : C16 + */ +#ifndef SET_MIPS0 +#define SET_MIPS0() +#define SET_PUSH() +#define SET_POP() +#endif +#define ICACHE_INVALIDATE_WORKAROUND(reg) \ +SET_PUSH(); \ +SET_MIPS0(); \ + la reg, 999f; \ +SET_POP(); \ + cache ICACHE_ADDR_FILL, 0(reg); \ + sync; \ + nop; nop; nop; nop; \ +999: + +/* EMPTY_PIPELINE is used for the below cache invalidation operations. + * When $I is invalidated, there will still be operations in the + * pipeline. We make sure these are 'nop' operations. + */ +#define EMPTY_PIPELINE nop; nop; nop; nop + +#define ICACHE_INDEX_INVALIDATE_OP(index,scratch) \ + ICACHE_INVALIDATE_WORKAROUND(scratch); \ + cache ICACHE_INDEX_INVALIDATE, 0(index); \ + EMPTY_PIPELINE + +#define ICACHE_ADDR_INVALIDATE_OP(addr,scratch) \ + ICACHE_INVALIDATE_WORKAROUND(scratch); \ + cache ICACHE_ADDR_HIT_INVALIDATE, 0(addr); \ + EMPTY_PIPELINE + +/* The sync used in the below macro is there in case we are installing + * a new instruction (flush $D, sync, invalidate $I sequence). + */ +#define SCACHE_ADDR_HIT_WB_INVALIDATE_OP(reg) \ + cache SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE, 0(reg); \ + sync; \ + EMPTY_PIPELINE + +/* Config1 cache field decoding */ +#define CACHE_CALC_SPW(s) ( 64 << (s) ) +#define CACHE_CALC_LS(l) ( (l) ? 2 << (l) : 0 ) +#define CACHE_CALC_BPW(l,s) ( CACHE_CALC_LS(l) * CACHE_CALC_SPW(s) ) +#define CACHE_CALC_ASSOC(a) ( (a) + 1 ) + + +/**** Move from/to Coprocessor operations ****/ + +/* We use ssnop instead of nop operations in order to handle + * superscalar CPUs. + * The "sll zero,zero,1" notation is compiler backwards compatible. + */ +#define SSNOP sll zero,zero,1 +#define NOPS SSNOP; SSNOP; SSNOP; SSNOP + +#define MFLO(dst) \ + mflo dst;\ + NOPS + +/* Workaround for bug in early revisions of MIPS 4K family of + * processors. + * + * This concerns the nop instruction before mtc0 in the + * MTC0 macro below. + * + * The bug is described in : + * + * MIPS32 4K(tm) Processor Core Family RTL Errata Sheet + * MIPS Document No: MD00003 + * + * The bug is identified as : C27 + */ + +#define MTC0(src, dst) \ + nop; \ + mtc0 src,dst;\ + NOPS + +#define DMTC0(src, dst) \ + nop; \ + dmtc0 src,dst;\ + NOPS + +#define MFC0(dst, src) \ + mfc0 dst,src;\ + NOPS + +#define DMFC0(dst, src) \ + dmfc0 dst,src;\ + NOPS + +#define MFC0_SEL_OPCODE(dst, src, sel)\ + .##word (0x40000000 | ((dst)<<16) | ((src)<<11) | (sel));\ + NOPS + +#define MTC0_SEL_OPCODE(dst, src, sel)\ + .##word (0x40800000 | ((dst)<<16) | ((src)<<11) | (sel));\ + NOPS + +#define LDC1(dst, src, offs)\ + .##word (0xd4000000 | ((src)<<21) | ((dst)<<16) | (offs)) + +#define SDC1(src, dst, offs)\ + .##word (0xf4000000 | ((dst)<<21) | ((src)<<16) | (offs)) + + +/* Instruction opcode fields */ +#define OPC_SPECIAL 0x0 +#define OPC_REGIM 0x1 +#define OPC_J 0x2 +#define OPC_JAL 0x3 +#define OPC_BEQ 0x4 +#define OPC_BNE 0x5 +#define OPC_BLEZ 0x6 +#define OPC_BGTZ 0x7 +#define OPC_COP1 0x11 +#define OPC_JALX 0x1D +#define OPC_BEQL 0x14 +#define OPC_BNEL 0x15 +#define OPC_BLEZL 0x16 +#define OPC_BGTZL 0x17 + +/* Instruction function fields */ +#define FUNC_JR 0x8 +#define FUNC_JALR 0x9 + +/* Instruction rt fields */ +#define RT_BLTZ 0x0 +#define RT_BGEZ 0x1 +#define RT_BLTZL 0x2 +#define RT_BGEZL 0x3 +#define RT_BLTZAL 0x10 +#define RT_BGEZAL 0x11 +#define RT_BLTZALL 0x12 +#define RT_BGEZALL 0x13 + +/* Instruction rs fields */ +#define RS_BC1 0x08 + +/* Access macros for instruction fields */ +#define MIPS_OPCODE( instr) ((instr) >> 26) +#define MIPS_FUNCTION(instr) ((instr) & MSK(6)) +#define MIPS_RT(instr) (((instr) >> 16) & MSK(5)) +#define MIPS_RS(instr) (((instr) >> 21) & MSK(5)) +#define MIPS_OFFSET(instr) ((instr) & 0xFFFF) +#define MIPS_TARGET(instr) ((instr) & MSK(26)) + +/* Instructions */ +#define OPCODE_DERET 0x4200001f +#define OPCODE_BREAK 0x0005000d +#define OPCODE_NOP 0 +#define OPCODE_JUMP(addr) ( (OPC_J << 26) | (((addr) >> 2) & 0x3FFFFFF) ) + +#define DERET .##word OPCODE_DERET + +/* MIPS16e opcodes and instruction field access macros */ + +#define MIPS16E_OPCODE(inst) (((inst) >> 11) & 0x1f) +#define MIPS16E_I8_FUNCTION(inst) (((inst) >> 8) & 0x7) +#define MIPS16E_X(inst) (((inst) >> 26) & 0x1) +#define MIPS16E_RR_FUNCTION(inst) (((inst) >> 0) & 0x1f) +#define MIPS16E_RY(inst) (((inst) >> 5) & 0x3) +#define MIPS16E_OPC_EXTEND 0x1e +#define MIPS16E_OPC_JAL_X 0x03 +#define MIPS16E_OPC_B 0x02 +#define MIPS16E_OPC_BEQZ 0x04 +#define MIPS16E_OPC_BNEZ 0x05 +#define MIPS16E_OPC_I8 0x0c +#define MIPS16E_I8_FUNC_BTEQZ 0x00 +#define MIPS16E_I8_FUNC_BTNEZ 0x01 +#define MIPS16E_X_JALX 0x01 +#define MIPS16E_OPC_RR 0x1d +#define MIPS16E_RR_FUNC_JALRC 0x00 +#define MIPS16E_RR_RY_JRRX 0x00 +#define MIPS16E_RR_RY_JRRA 0x01 +#define MIPS16E_RR_RY_JALR 0x02 +#define MIPS16E_RR_RY_JRCRX 0x04 +#define MIPS16E_RR_RY_JRCRA 0x05 +#define MIPS16E_RR_RY_JALRC 0x06 + +#define MIPS16E_OPCODE_BREAK 0xE805 +#define MIPS16E_OPCODE_NOP 0x6500 + +/* MIPS reset vector */ +#define MIPS_RESET_VECTOR 0x1fc00000 + +/* Clock periods per count register increment */ +#define MIPS4K_COUNT_CLK_PER_CYCLE 2 +#define MIPS5K_COUNT_CLK_PER_CYCLE 2 +#define MIPS20Kc_COUNT_CLK_PER_CYCLE 1 + + +/**** MIPS 4K/5K families specific fields of CONFIG register ****/ + +#define C0_CONFIG_MIPS4K5K_K23_SHF S_ConfigK23 +#define C0_CONFIG_MIPS4K5K_K23_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_K23_SHF) + +#define C0_CONFIG_MIPS4K5K_KU_SHF S_ConfigKU +#define C0_CONFIG_MIPS4K5K_KU_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_KU_SHF) + + +/**** MIPS 20Kc specific fields of CONFIG register ****/ + +#define C0_CONFIG_MIPS20KC_EC_SHF 28 +#define C0_CONFIG_MIPS20KC_EC_MSK (MSK(3) << C0_CONFIG_MIPS20KC_EC_SHF) + +#define C0_CONFIG_MIPS20KC_DD_SHF 27 +#define C0_CONFIG_MIPS20KC_DD_MSK (MSK(1) << C0_CONFIG_MIPS20KC_DD_SHF) +#define C0_CONFIG_MIPS20KC_DD_BIT C0_CONFIG_MIPS20KC_DD_MSK + +#define C0_CONFIG_MIPS20KC_LP_SHF 26 +#define C0_CONFIG_MIPS20KC_LP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_LP_SHF) +#define C0_CONFIG_MIPS20KC_LP_BIT C0_CONFIG_MIPS20KC_LP_MSK + +#define C0_CONFIG_MIPS20KC_SP_SHF 25 +#define C0_CONFIG_MIPS20KC_SP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_SP_SHF) +#define C0_CONFIG_MIPS20KC_SP_BIT C0_CONFIG_MIPS20KC_SP_MSK + +#define C0_CONFIG_MIPS20KC_TI_SHF 24 +#define C0_CONFIG_MIPS20KC_TI_MSK (MSK(1) << C0_CONFIG_MIPS20KC_TI_SHF) +#define C0_CONFIG_MIPS20KC_TI_BIT C0_CONFIG_MIPS20KC_TI_MSK + + +/* ********************************************************************* */ +/* Interface function definition */ + + +/* ********************************************************************* */ + +#endif /* #ifndef __MIPS_H__ */ diff --git a/sdk-modifications/include/mipsregs.h b/sdk-modifications/include/mipsregs.h new file mode 100755 index 0000000..5eaac44 --- /dev/null +++ b/sdk-modifications/include/mipsregs.h @@ -0,0 +1,985 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. + * Modified for further R[236]000 support by Paul M. Antoine, 1996. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2003 Maciej W. Rozycki + */ +#ifndef _ASM_MIPSREGS_H +#define _ASM_MIPSREGS_H + +#include +#include + +/* + * The following macros are especially useful for __asm__ + * inline assembler. + */ +#ifndef __STR +#define __STR(x) #x +#endif +#ifndef STR +#define STR(x) __STR(x) +#endif + +/* + * Configure language + */ +#ifdef __ASSEMBLY__ +#define _ULCAST_ +#else +#define _ULCAST_ (unsigned long) +#endif + +/* + * Coprocessor 0 register names + */ +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONF $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_INFO $7 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_DEBUG $23 +#define CP0_DEPC $24 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 +#define CP0_DESAVE $31 + +/* + * R4640/R4650 cp0 register names. These registers are listed + * here only for completeness; without MMU these CPUs are not useable + * by Linux. A future ELKS port might take make Linux run on them + * though ... + */ +#define CP0_IBASE $0 +#define CP0_IBOUND $1 +#define CP0_DBASE $2 +#define CP0_DBOUND $3 +#define CP0_CALG $17 +#define CP0_IWATCH $18 +#define CP0_DWATCH $19 + +/* + * Coprocessor 0 Set 1 register names + */ +#define CP0_S1_DERRADDR0 $26 +#define CP0_S1_DERRADDR1 $27 +#define CP0_S1_INTCONTROL $20 + +/* + * TX39 Series + */ +#define CP0_TX39_CACHE $7 + +/* + * Coprocessor 1 (FPU) register names + */ +#define CP1_REVISION $0 +#define CP1_STATUS $31 + +/* + * FPU Status Register Values + */ +/* + * Status Register Values + */ + +#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */ +#define FPU_CSR_COND 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND0 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND1 0x02000000 /* $fcc1 */ +#define FPU_CSR_COND2 0x04000000 /* $fcc2 */ +#define FPU_CSR_COND3 0x08000000 /* $fcc3 */ +#define FPU_CSR_COND4 0x10000000 /* $fcc4 */ +#define FPU_CSR_COND5 0x20000000 /* $fcc5 */ +#define FPU_CSR_COND6 0x40000000 /* $fcc6 */ +#define FPU_CSR_COND7 0x80000000 /* $fcc7 */ + +/* + * X the exception cause indicator + * E the exception enable + * S the sticky/flag bit +*/ +#define FPU_CSR_ALL_X 0x0003f000 +#define FPU_CSR_UNI_X 0x00020000 +#define FPU_CSR_INV_X 0x00010000 +#define FPU_CSR_DIV_X 0x00008000 +#define FPU_CSR_OVF_X 0x00004000 +#define FPU_CSR_UDF_X 0x00002000 +#define FPU_CSR_INE_X 0x00001000 + +#define FPU_CSR_ALL_E 0x00000f80 +#define FPU_CSR_INV_E 0x00000800 +#define FPU_CSR_DIV_E 0x00000400 +#define FPU_CSR_OVF_E 0x00000200 +#define FPU_CSR_UDF_E 0x00000100 +#define FPU_CSR_INE_E 0x00000080 + +#define FPU_CSR_ALL_S 0x0000007c +#define FPU_CSR_INV_S 0x00000040 +#define FPU_CSR_DIV_S 0x00000020 +#define FPU_CSR_OVF_S 0x00000010 +#define FPU_CSR_UDF_S 0x00000008 +#define FPU_CSR_INE_S 0x00000004 + +/* rounding mode */ +#define FPU_CSR_RN 0x0 /* nearest */ +#define FPU_CSR_RZ 0x1 /* towards zero */ +#define FPU_CSR_RU 0x2 /* towards +Infinity */ +#define FPU_CSR_RD 0x3 /* towards -Infinity */ + + +/* + * Values for PageMask register + */ +#ifdef CONFIG_CPU_VR41XX + +/* Why doesn't stupidity hurt ... */ + +#define PM_1K 0x00000000 +#define PM_4K 0x00001800 +#define PM_16K 0x00007800 +#define PM_64K 0x0001f800 +#define PM_256K 0x0007f800 + +#else + +#define PM_4K 0x00000000 +#define PM_16K 0x00006000 +#define PM_64K 0x0001e000 +#define PM_256K 0x0007e000 +#define PM_1M 0x001fe000 +#define PM_4M 0x007fe000 +#define PM_16M 0x01ffe000 +#define PM_64M 0x07ffe000 +#define PM_256M 0x1fffe000 + +#endif + +/* + * Values used for computation of new tlb entries + */ +#define PL_4K 12 +#define PL_16K 14 +#define PL_64K 16 +#define PL_256K 18 +#define PL_1M 20 +#define PL_4M 22 +#define PL_16M 24 +#define PL_64M 26 +#define PL_256M 28 + +/* + * R4x00 interrupt enable / cause bits + */ +#define IE_SW0 (_ULCAST_(1) << 8) +#define IE_SW1 (_ULCAST_(1) << 9) +#define IE_IRQ0 (_ULCAST_(1) << 10) +#define IE_IRQ1 (_ULCAST_(1) << 11) +#define IE_IRQ2 (_ULCAST_(1) << 12) +#define IE_IRQ3 (_ULCAST_(1) << 13) +#define IE_IRQ4 (_ULCAST_(1) << 14) +#define IE_IRQ5 (_ULCAST_(1) << 15) + +/* + * R4x00 interrupt cause bits + */ +#define C_SW0 (_ULCAST_(1) << 8) +#define C_SW1 (_ULCAST_(1) << 9) +#define C_IRQ0 (_ULCAST_(1) << 10) +#define C_IRQ1 (_ULCAST_(1) << 11) +#define C_IRQ2 (_ULCAST_(1) << 12) +#define C_IRQ3 (_ULCAST_(1) << 13) +#define C_IRQ4 (_ULCAST_(1) << 14) +#define C_IRQ5 (_ULCAST_(1) << 15) + +/* + * Bitfields in the R4xx0 cp0 status register + */ +#define ST0_IE 0x00000001 +#define ST0_EXL 0x00000002 +#define ST0_ERL 0x00000004 +#define ST0_KSU 0x00000018 +# define KSU_USER 0x00000010 +# define KSU_SUPERVISOR 0x00000008 +# define KSU_KERNEL 0x00000000 +#define ST0_UX 0x00000020 +#define ST0_SX 0x00000040 +#define ST0_KX 0x00000080 +#define ST0_DE 0x00010000 +#define ST0_CE 0x00020000 + +/* + * Bitfields in the R[23]000 cp0 status register. + */ +#define ST0_IEC 0x00000001 +#define ST0_KUC 0x00000002 +#define ST0_IEP 0x00000004 +#define ST0_KUP 0x00000008 +#define ST0_IEO 0x00000010 +#define ST0_KUO 0x00000020 +/* bits 6 & 7 are reserved on R[23]000 */ +#define ST0_ISC 0x00010000 +#define ST0_SWC 0x00020000 +#define ST0_CM 0x00080000 + +/* + * Bits specific to the R4640/R4650 + */ +#define ST0_UM (_ULCAST_(1) << 4) +#define ST0_IL (_ULCAST_(1) << 23) +#define ST0_DL (_ULCAST_(1) << 24) + +/* + * Bitfields in the TX39 family CP0 Configuration Register 3 + */ +#define TX39_CONF_ICS_SHIFT 19 +#define TX39_CONF_ICS_MASK 0x00380000 +#define TX39_CONF_ICS_1KB 0x00000000 +#define TX39_CONF_ICS_2KB 0x00080000 +#define TX39_CONF_ICS_4KB 0x00100000 +#define TX39_CONF_ICS_8KB 0x00180000 +#define TX39_CONF_ICS_16KB 0x00200000 + +#define TX39_CONF_DCS_SHIFT 16 +#define TX39_CONF_DCS_MASK 0x00070000 +#define TX39_CONF_DCS_1KB 0x00000000 +#define TX39_CONF_DCS_2KB 0x00010000 +#define TX39_CONF_DCS_4KB 0x00020000 +#define TX39_CONF_DCS_8KB 0x00030000 +#define TX39_CONF_DCS_16KB 0x00040000 + +#define TX39_CONF_CWFON 0x00004000 +#define TX39_CONF_WBON 0x00002000 +#define TX39_CONF_RF_SHIFT 10 +#define TX39_CONF_RF_MASK 0x00000c00 +#define TX39_CONF_DOZE 0x00000200 +#define TX39_CONF_HALT 0x00000100 +#define TX39_CONF_LOCK 0x00000080 +#define TX39_CONF_ICE 0x00000020 +#define TX39_CONF_DCE 0x00000010 +#define TX39_CONF_IRSIZE_SHIFT 2 +#define TX39_CONF_IRSIZE_MASK 0x0000000c +#define TX39_CONF_DRSIZE_SHIFT 0 +#define TX39_CONF_DRSIZE_MASK 0x00000003 + +/* + * Status register bits available in all MIPS CPUs. + */ +#define ST0_IM 0x0000ff00 +#define STATUSB_IP0 8 +#define STATUSF_IP0 (_ULCAST_(1) << 8) +#define STATUSB_IP1 9 +#define STATUSF_IP1 (_ULCAST_(1) << 9) +#define STATUSB_IP2 10 +#define STATUSF_IP2 (_ULCAST_(1) << 10) +#define STATUSB_IP3 11 +#define STATUSF_IP3 (_ULCAST_(1) << 11) +#define STATUSB_IP4 12 +#define STATUSF_IP4 (_ULCAST_(1) << 12) +#define STATUSB_IP5 13 +#define STATUSF_IP5 (_ULCAST_(1) << 13) +#define STATUSB_IP6 14 +#define STATUSF_IP6 (_ULCAST_(1) << 14) +#define STATUSB_IP7 15 +#define STATUSF_IP7 (_ULCAST_(1) << 15) +#define STATUSB_IP8 0 +#define STATUSF_IP8 (_ULCAST_(1) << 0) +#define STATUSB_IP9 1 +#define STATUSF_IP9 (_ULCAST_(1) << 1) +#define STATUSB_IP10 2 +#define STATUSF_IP10 (_ULCAST_(1) << 2) +#define STATUSB_IP11 3 +#define STATUSF_IP11 (_ULCAST_(1) << 3) +#define STATUSB_IP12 4 +#define STATUSF_IP12 (_ULCAST_(1) << 4) +#define STATUSB_IP13 5 +#define STATUSF_IP13 (_ULCAST_(1) << 5) +#define STATUSB_IP14 6 +#define STATUSF_IP14 (_ULCAST_(1) << 6) +#define STATUSB_IP15 7 +#define STATUSF_IP15 (_ULCAST_(1) << 7) +#define ST0_CH 0x00040000 +#define ST0_SR 0x00100000 +#define ST0_TS 0x00200000 +#define ST0_BEV 0x00400000 +#define ST0_RE 0x02000000 +#define ST0_FR 0x04000000 +#define ST0_CU 0xf0000000 +#define ST0_CU0 0x10000000 +#define ST0_CU1 0x20000000 +#define ST0_CU2 0x40000000 +#define ST0_CU3 0x80000000 +#define ST0_XX 0x80000000 /* MIPS IV naming */ + +/* + * Bitfields and bit numbers in the coprocessor 0 cause register. + * + * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. + */ +#define CAUSEB_EXCCODE 2 +#define CAUSEF_EXCCODE (_ULCAST_(31) << 2) +#define CAUSEB_IP 8 +#define CAUSEF_IP (_ULCAST_(255) << 8) +#define CAUSEB_IP0 8 +#define CAUSEF_IP0 (_ULCAST_(1) << 8) +#define CAUSEB_IP1 9 +#define CAUSEF_IP1 (_ULCAST_(1) << 9) +#define CAUSEB_IP2 10 +#define CAUSEF_IP2 (_ULCAST_(1) << 10) +#define CAUSEB_IP3 11 +#define CAUSEF_IP3 (_ULCAST_(1) << 11) +#define CAUSEB_IP4 12 +#define CAUSEF_IP4 (_ULCAST_(1) << 12) +#define CAUSEB_IP5 13 +#define CAUSEF_IP5 (_ULCAST_(1) << 13) +#define CAUSEB_IP6 14 +#define CAUSEF_IP6 (_ULCAST_(1) << 14) +#define CAUSEB_IP7 15 +#define CAUSEF_IP7 (_ULCAST_(1) << 15) +#define CAUSEB_IV 23 +#define CAUSEF_IV (_ULCAST_(1) << 23) +#define CAUSEB_CE 28 +#define CAUSEF_CE (_ULCAST_(3) << 28) +#define CAUSEB_BD 31 +#define CAUSEF_BD (_ULCAST_(1) << 31) + +/* + * Bits in the coprocessor 0 config register. + */ +/* Generic bits. */ +#define CONF_CM_CACHABLE_NO_WA 0 +#define CONF_CM_CACHABLE_WA 1 +#define CONF_CM_UNCACHED 2 +#define CONF_CM_CACHABLE_NONCOHERENT 3 +#define CONF_CM_CACHABLE_CE 4 +#define CONF_CM_CACHABLE_COW 5 +#define CONF_CM_CACHABLE_CUW 6 +#define CONF_CM_CACHABLE_ACCELERATED 7 +#define CONF_CM_CMASK 7 +#define CONF_BE (_ULCAST_(1) << 15) + +/* Bits common to various processors. */ +#define CONF_CU (_ULCAST_(1) << 3) +#define CONF_DB (_ULCAST_(1) << 4) +#define CONF_IB (_ULCAST_(1) << 5) +#define CONF_DC (_ULCAST_(7) << 6) +#define CONF_IC (_ULCAST_(7) << 9) +#define CONF_EB (_ULCAST_(1) << 13) +#define CONF_EM (_ULCAST_(1) << 14) +#define CONF_SM (_ULCAST_(1) << 16) +#define CONF_SC (_ULCAST_(1) << 17) +#define CONF_EW (_ULCAST_(3) << 18) +#define CONF_EP (_ULCAST_(15)<< 24) +#define CONF_EC (_ULCAST_(7) << 28) +#define CONF_CM (_ULCAST_(1) << 31) + +/* Bits specific to the R4xx0. */ +#define R4K_CONF_SW (_ULCAST_(1) << 20) +#define R4K_CONF_SS (_ULCAST_(1) << 21) +#define R4K_CONF_SB (_ULCAST_(3) << 22) + +/* Bits specific to the R5000. */ +#define R5K_CONF_SE (_ULCAST_(1) << 12) +#define R5K_CONF_SS (_ULCAST_(3) << 20) + +/* Bits specific to the R10000. */ +#define R10K_CONF_DN (_ULCAST_(3) << 3) +#define R10K_CONF_CT (_ULCAST_(1) << 5) +#define R10K_CONF_PE (_ULCAST_(1) << 6) +#define R10K_CONF_PM (_ULCAST_(3) << 7) +#define R10K_CONF_EC (_ULCAST_(15)<< 9) +#define R10K_CONF_SB (_ULCAST_(1) << 13) +#define R10K_CONF_SK (_ULCAST_(1) << 14) +#define R10K_CONF_SS (_ULCAST_(7) << 16) +#define R10K_CONF_SC (_ULCAST_(7) << 19) +#define R10K_CONF_DC (_ULCAST_(7) << 26) +#define R10K_CONF_IC (_ULCAST_(7) << 29) + +/* Bits specific to the VR41xx. */ +#define VR41_CONF_CS (_ULCAST_(1) << 12) +#define VR41_CONF_M16 (_ULCAST_(1) << 20) +#define VR41_CONF_AD (_ULCAST_(1) << 23) + +/* Bits specific to the R30xx. */ +#define R30XX_CONF_FDM (_ULCAST_(1) << 19) +#define R30XX_CONF_REV (_ULCAST_(1) << 22) +#define R30XX_CONF_AC (_ULCAST_(1) << 23) +#define R30XX_CONF_RF (_ULCAST_(1) << 24) +#define R30XX_CONF_HALT (_ULCAST_(1) << 25) +#define R30XX_CONF_FPINT (_ULCAST_(7) << 26) +#define R30XX_CONF_DBR (_ULCAST_(1) << 29) +#define R30XX_CONF_SB (_ULCAST_(1) << 30) +#define R30XX_CONF_LOCK (_ULCAST_(1) << 31) + +/* Bits specific to the TX49. */ +#define TX49_CONF_DC (_ULCAST_(1) << 16) +#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */ +#define TX49_CONF_HALT (_ULCAST_(1) << 18) +#define TX49_CONF_CWFON (_ULCAST_(1) << 27) + +/* Bits specific to the MIPS32/64 PRA. */ +#define MIPS_CONF_MT (_ULCAST_(7) << 7) +#define MIPS_CONF_AR (_ULCAST_(7) << 10) +#define MIPS_CONF_AT (_ULCAST_(3) << 13) +#define MIPS_CONF_M (_ULCAST_(1) << 31) + +/* + * R10000 performance counter definitions. + * + * FIXME: The R10000 performance counter opens a nice way to implement CPU + * time accounting with a precission of one cycle. I don't have + * R10000 silicon but just a manual, so ... + */ + +/* + * Events counted by counter #0 + */ +#define CE0_CYCLES 0 +#define CE0_INSN_ISSUED 1 +#define CE0_LPSC_ISSUED 2 +#define CE0_S_ISSUED 3 +#define CE0_SC_ISSUED 4 +#define CE0_SC_FAILED 5 +#define CE0_BRANCH_DECODED 6 +#define CE0_QW_WB_SECONDARY 7 +#define CE0_CORRECTED_ECC_ERRORS 8 +#define CE0_ICACHE_MISSES 9 +#define CE0_SCACHE_I_MISSES 10 +#define CE0_SCACHE_I_WAY_MISSPREDICTED 11 +#define CE0_EXT_INTERVENTIONS_REQ 12 +#define CE0_EXT_INVALIDATE_REQ 13 +#define CE0_VIRTUAL_COHERENCY_COND 14 +#define CE0_INSN_GRADUATED 15 + +/* + * Events counted by counter #1 + */ +#define CE1_CYCLES 0 +#define CE1_INSN_GRADUATED 1 +#define CE1_LPSC_GRADUATED 2 +#define CE1_S_GRADUATED 3 +#define CE1_SC_GRADUATED 4 +#define CE1_FP_INSN_GRADUATED 5 +#define CE1_QW_WB_PRIMARY 6 +#define CE1_TLB_REFILL 7 +#define CE1_BRANCH_MISSPREDICTED 8 +#define CE1_DCACHE_MISS 9 +#define CE1_SCACHE_D_MISSES 10 +#define CE1_SCACHE_D_WAY_MISSPREDICTED 11 +#define CE1_EXT_INTERVENTION_HITS 12 +#define CE1_EXT_INVALIDATE_REQ 13 +#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14 +#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15 + +/* + * These flags define in which priviledge mode the counters count events + */ +#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */ +#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */ +#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */ +#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */ + +#ifndef __ASSEMBLY__ + +#define CAUSE_EXCCODE(x) ((CAUSEF_EXCCODE & (x->cp0_cause)) >> CAUSEB_EXCCODE) +#define CAUSE_EPC(x) (x->cp0_epc + (((x->cp0_cause & CAUSEF_BD) >> CAUSEB_BD) << 2)) + +/* + * Functions to access the r10k performance counter and control registers + */ +#define read_r10k_perf_cntr(counter) \ +({ unsigned int __res; \ + __asm__ __volatile__( \ + "mfpc\t%0, "STR(counter) \ + : "=r" (__res)); \ + __res;}) + +#define write_r10k_perf_cntr(counter,val) \ + __asm__ __volatile__( \ + "mtpc\t%0, "STR(counter) \ + : : "r" (val)); + +#define read_r10k_perf_cntl(counter) \ +({ unsigned int __res; \ + __asm__ __volatile__( \ + "mfps\t%0, "STR(counter) \ + : "=r" (__res)); \ + __res;}) + +#define write_r10k_perf_cntl(counter,val) \ + __asm__ __volatile__( \ + "mtps\t%0, "STR(counter) \ + : : "r" (val)); + +/* + * Macros to access the system control coprocessor + */ + +#define __read_32bit_c0_register(source, sel) \ +({ int __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __read_64bit_c0_register(source, sel) \ +({ unsigned long __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmfc0\t%0, " #source "\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_c0_register(register, sel, value) \ +do { \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mtc0\t%z0, " #register "\n\t" \ + : : "Jr" (value)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ +} while (0) + +#define __write_64bit_c0_register(register, sel, value) \ +do { \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmtc0\t%z0, " #register "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ +} while (0) + +#define __read_ulong_c0_register(reg, sel) \ + ((sizeof(unsigned long) == 4) ? \ + __read_32bit_c0_register(reg, sel) : \ + __read_64bit_c0_register(reg, sel)) + +#define __write_ulong_c0_register(reg, sel, val) \ +do { \ + if (sizeof(unsigned long) == 4) \ + __write_32bit_c0_register(reg, sel, val); \ + else \ + __write_64bit_c0_register(reg, sel, val); \ +} while (0) + +/* + * These versions are only needed for systems with more than 38 bits of + * physical address space running the 32-bit kernel. That's none atm :-) + */ +#define __read_64bit_c0_split(source, sel) \ +({ \ + unsigned long long val; \ + unsigned long flags; \ + \ + local_irq_save(flags); \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%M0, " #source "\n\t" \ + "dsll\t%L0, %M0, 32\n\t" \ + "dsrl\t%M0, %M0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + ".set\tmips0" \ + : "=r" (val)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%M0, " #source ", " #sel "\n\t" \ + "dsll\t%L0, %M0, 32\n\t" \ + "dsrl\t%M0, %M0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + ".set\tmips0" \ + : "=r" (val)); \ + local_irq_restore(flags); \ + \ + val; \ +}) + +#define __write_64bit_c0_split(source, sel, val) \ +do { \ + unsigned long flags; \ + \ + local_irq_save(flags); \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ + "or\t%L0, %L0, %M0\n\t" \ + "dmtc0\t%L0, " #source "\n\t" \ + ".set\tmips0" \ + : : "r" (val)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ + "or\t%L0, %L0, %M0\n\t" \ + "dmtc0\t%L0, " #source ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "r" (val)); \ + local_irq_restore(flags); \ +} while (0) + +#define read_c0_index() __read_32bit_c0_register($0, 0) +#define write_c0_index(val) __write_32bit_c0_register($0, 0, val) + +#define read_c0_entrylo0() __read_ulong_c0_register($2, 0) +#define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val) + +#define read_c0_entrylo1() __read_ulong_c0_register($3, 0) +#define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val) + +#define read_c0_conf() __read_32bit_c0_register($3, 0) +#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) + +#define read_c0_context() __read_ulong_c0_register($4, 0) +#define write_c0_context(val) __write_ulong_c0_register($4, 0, val) + +#define read_c0_pagemask() __read_32bit_c0_register($5, 0) +#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) + +#define read_c0_wired() __read_32bit_c0_register($6, 0) +#define write_c0_wired(val) __write_32bit_c0_register($6, 0, val) + +#define read_c0_info() __read_32bit_c0_register($7, 0) + +#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */ +#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val) + +#define read_c0_count() __read_32bit_c0_register($9, 0) +#define write_c0_count(val) __write_32bit_c0_register($9, 0, val) + +#define read_c0_entryhi() __read_ulong_c0_register($10, 0) +#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val) + +#define read_c0_compare() __read_32bit_c0_register($11, 0) +#define write_c0_compare(val) __write_32bit_c0_register($11, 0, val) + +#define read_c0_status() __read_32bit_c0_register($12, 0) +#define write_c0_status(val) __write_32bit_c0_register($12, 0, val) + +#define read_c0_cause() __read_32bit_c0_register($13, 0) +#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) + +#define read_c0_prid() __read_32bit_c0_register($15, 0) + +#define read_c0_config() __read_32bit_c0_register($16, 0) +#define read_c0_config1() __read_32bit_c0_register($16, 1) +#define read_c0_config2() __read_32bit_c0_register($16, 2) +#define read_c0_config3() __read_32bit_c0_register($16, 3) +#define write_c0_config(val) __write_32bit_c0_register($16, 0, val) +#define write_c0_config1(val) __write_32bit_c0_register($16, 1, val) +#define write_c0_config2(val) __write_32bit_c0_register($16, 2, val) +#define write_c0_config3(val) __write_32bit_c0_register($16, 3, val) + +/* + * The WatchLo register. There may be upto 8 of them. + */ +#define read_c0_watchlo0() __read_ulong_c0_register($18, 0) +#define read_c0_watchlo1() __read_ulong_c0_register($18, 1) +#define read_c0_watchlo2() __read_ulong_c0_register($18, 2) +#define read_c0_watchlo3() __read_ulong_c0_register($18, 3) +#define read_c0_watchlo4() __read_ulong_c0_register($18, 4) +#define read_c0_watchlo5() __read_ulong_c0_register($18, 5) +#define read_c0_watchlo6() __read_ulong_c0_register($18, 6) +#define read_c0_watchlo7() __read_ulong_c0_register($18, 7) +#define write_c0_watchlo0(val) __write_ulong_c0_register($18, 0, val) +#define write_c0_watchlo1(val) __write_ulong_c0_register($18, 1, val) +#define write_c0_watchlo2(val) __write_ulong_c0_register($18, 2, val) +#define write_c0_watchlo3(val) __write_ulong_c0_register($18, 3, val) +#define write_c0_watchlo4(val) __write_ulong_c0_register($18, 4, val) +#define write_c0_watchlo5(val) __write_ulong_c0_register($18, 5, val) +#define write_c0_watchlo6(val) __write_ulong_c0_register($18, 6, val) +#define write_c0_watchlo7(val) __write_ulong_c0_register($18, 7, val) + +/* + * The WatchHi register. There may be upto 8 of them. + */ +#define read_c0_watchhi0() __read_32bit_c0_register($19, 0) +#define read_c0_watchhi1() __read_32bit_c0_register($19, 1) +#define read_c0_watchhi2() __read_32bit_c0_register($19, 2) +#define read_c0_watchhi3() __read_32bit_c0_register($19, 3) +#define read_c0_watchhi4() __read_32bit_c0_register($19, 4) +#define read_c0_watchhi5() __read_32bit_c0_register($19, 5) +#define read_c0_watchhi6() __read_32bit_c0_register($19, 6) +#define read_c0_watchhi7() __read_32bit_c0_register($19, 7) + +#define write_c0_watchhi0(val) __write_32bit_c0_register($19, 0, val) +#define write_c0_watchhi1(val) __write_32bit_c0_register($19, 1, val) +#define write_c0_watchhi2(val) __write_32bit_c0_register($19, 2, val) +#define write_c0_watchhi3(val) __write_32bit_c0_register($19, 3, val) +#define write_c0_watchhi4(val) __write_32bit_c0_register($19, 4, val) +#define write_c0_watchhi5(val) __write_32bit_c0_register($19, 5, val) +#define write_c0_watchhi6(val) __write_32bit_c0_register($19, 6, val) +#define write_c0_watchhi7(val) __write_32bit_c0_register($19, 7, val) + +#define read_c0_xcontext() __read_ulong_c0_register($20, 0) +#define write_c0_xcontext(val) __write_ulong_c0_register($20, 0, val) + +#define read_c0_intcontrol() __read_32bit_c0_register($20, 1) +#define write_c0_intcontrol(val) __write_32bit_c0_register($20, 1, val) + +#define read_c0_framemask() __read_32bit_c0_register($21, 0) +#define write_c0_framemask(val) __write_32bit_c0_register($21, 0, val) + +#define read_c0_debug() __read_32bit_c0_register($23, 0) +#define write_c0_debug(val) __write_32bit_c0_register($23, 0, val) + +#define read_c0_depc() __read_ulong_c0_register($24, 0) +#define write_c0_depc(val) __write_ulong_c0_register($24, 0, val) + +#define read_c0_ecc() __read_32bit_c0_register($26, 0) +#define write_c0_ecc(val) __write_32bit_c0_register($26, 0, val) + +#define read_c0_derraddr0() __read_ulong_c0_register($26, 1) +#define write_c0_derraddr0(val) __write_ulong_c0_register($26, 1, val) + +#define read_c0_cacheerr() __read_32bit_c0_register($27, 0) + +#define read_c0_derraddr1() __read_ulong_c0_register($27, 1) +#define write_c0_derraddr1(val) __write_ulong_c0_register($27, 1, val) + +#define read_c0_taglo() __read_32bit_c0_register($28, 0) +#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val) + +#define read_c0_taghi() __read_32bit_c0_register($29, 0) +#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val) + +#define read_c0_errorepc() __read_ulong_c0_register($30, 0) +#define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val) + +#define read_c0_epc() __read_ulong_c0_register($14, 0) +#define write_c0_epc(val) __write_ulong_c0_register($14, 0, val) + +#if 1 +/* + * Macros to access the system control coprocessor + */ +#define read_32bit_cp0_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "mfc0\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +#define read_32bit_cp0_set1_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "cfc0\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +/* + * For now use this only with interrupts disabled! + */ +#define read_64bit_cp0_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmfc0\t%0,"STR(source)"\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + __res;}) + +#define write_32bit_cp0_register(register,value) \ + __asm__ __volatile__( \ + "mtc0\t%0,"STR(register)"\n\t" \ + "nop" \ + : : "r" (value)); + +#define write_32bit_cp0_set1_register(register,value) \ + __asm__ __volatile__( \ + "ctc0\t%0,"STR(register)"\n\t" \ + "nop" \ + : : "r" (value)); + +#define write_64bit_cp0_register(register,value) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmtc0\t%0,"STR(register)"\n\t" \ + ".set\tmips0" \ + : : "r" (value)) + +/* + * This should be changed when we get a compiler that support the MIPS32 ISA. + */ +#define read_mips32_cp0_config1() \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tnoreorder\n\t" \ + ".set\tnoat\n\t" \ + "#.set\tmips64\n\t" \ + "#mfc0\t$1, $16, 1\n\t" \ + "#.set\tmips0\n\t" \ + ".word\t0x40018001\n\t" \ + "move\t%0,$1\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" \ + :"=r" (__res)); \ + __res;}) + +#endif +/* + * Macros to access the floating point coprocessor control registers + */ +#define read_32bit_cp1_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "cfc1\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +/* TLB operations. */ +static inline void tlb_probe(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbp\n\t" + ".set reorder"); +} + +static inline void tlb_read(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbr\n\t" + ".set reorder"); +} + +static inline void tlb_write_indexed(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbwi\n\t" + ".set reorder"); +} + +static inline void tlb_write_random(void) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + "tlbwr\n\t" + ".set reorder"); +} + +/* + * Manipulate bits in a c0 register. + */ +#define __BUILD_SET_C0(name,register) \ +static inline unsigned int \ +set_c0_##name(unsigned int set) \ +{ \ + unsigned int res; \ + \ + res = read_c0_##name(); \ + res |= set; \ + write_c0_##name(res); \ + \ + return res; \ +} \ + \ +static inline unsigned int \ +clear_c0_##name(unsigned int clear) \ +{ \ + unsigned int res; \ + \ + res = read_c0_##name(); \ + res &= ~clear; \ + write_c0_##name(res); \ + \ + return res; \ +} \ + \ +static inline unsigned int \ +change_c0_##name(unsigned int change, unsigned int new) \ +{ \ + unsigned int res; \ + \ + res = read_c0_##name(); \ + res &= ~change; \ + res |= (new & change); \ + write_c0_##name(res); \ + \ + return res; \ +} + +__BUILD_SET_C0(status,CP0_STATUS) +__BUILD_SET_C0(cause,CP0_CAUSE) +__BUILD_SET_C0(config,CP0_CONFIG) + +#define set_cp0_status(x) set_c0_status(x) +#define set_cp0_cause(x) set_c0_cause(x) +#define set_cp0_config(x) set_c0_config(x) + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_MIPSREGS_H */ diff --git a/sdk-modifications/include/mmc_api.h b/sdk-modifications/include/mmc_api.h new file mode 100755 index 0000000..28e75ef --- /dev/null +++ b/sdk-modifications/include/mmc_api.h @@ -0,0 +1,56 @@ +#ifndef __MMC_API_H__ +#define __MMC_API_H__ + +/* Error codes */ +enum mmc_result_t { + MMC_NO_RESPONSE = -1, + MMC_NO_ERROR = 0, + MMC_ERROR_OUT_OF_RANGE, + MMC_ERROR_ADDRESS, + MMC_ERROR_BLOCK_LEN, + MMC_ERROR_ERASE_SEQ, + MMC_ERROR_ERASE_PARAM, + MMC_ERROR_WP_VIOLATION, + MMC_ERROR_CARD_IS_LOCKED, + MMC_ERROR_LOCK_UNLOCK_FAILED, + MMC_ERROR_COM_CRC, + MMC_ERROR_ILLEGAL_COMMAND, + MMC_ERROR_CARD_ECC_FAILED, + MMC_ERROR_CC, + MMC_ERROR_GENERAL, + MMC_ERROR_UNDERRUN, + MMC_ERROR_OVERRUN, + MMC_ERROR_CID_CSD_OVERWRITE, + MMC_ERROR_STATE_MISMATCH, + MMC_ERROR_HEADER_MISMATCH, + MMC_ERROR_TIMEOUT, + MMC_ERROR_CRC, + MMC_ERROR_DRIVER_FAILURE, +}; + + +/* Get card's sectors*/ + +extern unsigned int MMC_GetSize(void); + + +/* initialize MMC/SD card */ +extern int MMC_Initialize(void); + +/* read a single block from MMC/SD card */ +extern int MMC_ReadBlock(unsigned int blockaddr, unsigned char *recbuf); + +/* read multi blocks from MMC/SD card */ +extern int MMC_ReadMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); + +/* write a block to MMC/SD card */ +extern int MMC_WriteBlock(unsigned int blockaddr, unsigned char *recbuf); + +/* write multi blocks to MMC/SD card */ +extern int MMC_WriteMultiBlock(unsigned int blockaddr, unsigned int blocknum, unsigned char *recbuf); + +/* detect MMC/SD card */ +extern int MMC_DetectStatus(void); + +#endif /* __MMC_API_H__ */ + diff --git a/sdk-modifications/include/partition.h b/sdk-modifications/include/partition.h new file mode 100755 index 0000000..0777b54 --- /dev/null +++ b/sdk-modifications/include/partition.h @@ -0,0 +1,131 @@ +/* + partition.h + Functions for mounting and dismounting partitions + on various block devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release +*/ + +#ifndef _PARTITION_H +#define _PARTITION_H + +#include "fs_common.h" + +#include "disc_io/disc.h" +#include "fs_cache.h" + +// Device name +extern const char* DEVICE_NAME; + +// Filesystem type +typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; + +#ifdef NDS +typedef enum {PI_DEFAULT, PI_SLOT_1, PI_SLOT_2, PI_CUSTOM} PARTITION_INTERFACE; +#else +typedef enum {PI_CART_SLOT} PARTITION_INTERFACE; +#endif + +typedef struct { + u32 fatStart; + u32 sectorsPerFat; + u32 lastCluster; + u32 firstFree; +} FAT; + +typedef struct { + const IO_INTERFACE* disc; + CACHE* cache; + // Info about the partition + bool readOnly; // If this is set, then do not try writing to the disc + FS_TYPE filesysType; + u32 totalSize; + u32 rootDirStart; + u32 rootDirCluster; + u32 numberOfSectors; + u32 dataStart; + u32 bytesPerSector; + u32 sectorsPerCluster; + u32 bytesPerCluster; + FAT fat; + // Values that may change after construction + u32 cwdCluster; // Current working directory cluser + u32 openFileCount; +} PARTITION; + +/* +Mount the device specified by partitionDevice +PD_DEFAULT is not allowed, use _FAT_partition_setDefaultDevice +PD_CUSTOM is not allowed, use _FAT_partition_mountCustomDevice +*/ +bool _FAT_partition_mount (PARTITION_INTERFACE partitionNumber, u32 cacheSize); + +/* +Mount a partition on a custom device +*/ +bool _FAT_partition_mountCustomInterface (const IO_INTERFACE* device, u32 cacheSize); + + +/* +Free Mount a partition on a custom device +*/ +bool _FAT_partition_freeMount( int partitionNumber, const IO_INTERFACE* device, u32 cacheSize); + + +/* +Unmount the partition specified by partitionNumber +If there are open files, it will fail +*/ +bool _FAT_partition_unmount (PARTITION_INTERFACE partitionNumber); + +/* +Forcibly unmount the partition specified by partitionNumber +Any open files on the partition will become invalid +The cache will be invalidated, and any unflushed writes will be lost +*/ +bool _FAT_partition_unsafeUnmount (PARTITION_INTERFACE partitionNumber); + +/* +Set the default device for access by fat: and fat0:, +based on the device number +*/ +bool _FAT_partition_setDefaultInterface (PARTITION_INTERFACE partitionNumber); + +/* +Set the default device for access by fat: and fat0:, +based on the partition pointer +*/ +bool _FAT_partition_setDefaultPartition (PARTITION* partition); + +/* +Return the partition specified in a path +For instance, "fat0:", "fat:", "/" and "fat:/" will all +return the default partition +*/ +PARTITION* _FAT_partition_getPartitionFromPath (const char* path); + +#endif // _PARTITION_H diff --git a/sdk-modifications/include/tcm.h b/sdk-modifications/include/tcm.h new file mode 100755 index 0000000..4de3333 --- /dev/null +++ b/sdk-modifications/include/tcm.h @@ -0,0 +1,10 @@ +#ifndef __TCM_H +#define __TCM_H + +/* +* Function: makes cpu to idle state. It will be waken up by RTC in the next second. +* Of course, it can be waken up by keys at any time. +*/ +int enable_enter_idle(void); + +#endif diff --git a/sdk-modifications/libsrc/core/ds2_cpuclock.c b/sdk-modifications/libsrc/core/ds2_cpuclock.c index 57f2143..145218d 100644 --- a/sdk-modifications/libsrc/core/ds2_cpuclock.c +++ b/sdk-modifications/libsrc/core/ds2_cpuclock.c @@ -192,7 +192,7 @@ static void detect_clockNew(void){ //udelay overclock void ds2_udelay(unsigned int usec) { - /*unsigned int i = usec * (_iclk / 2000000); + unsigned int i = usec * (_iclk / 2000000); __asm__ __volatile__ ( "\t.set noreorder\n" @@ -202,17 +202,17 @@ void ds2_udelay(unsigned int usec) ".set reorder\n" : "=r" (i) : "0" (i) - );*/ + ); } //mdelay overclock void ds2_mdelay(unsigned int msec) { - /*int i; + int i; for(i=0;i= SOUND_EMISSION_INTERVAL) { - if(ds2_checkAudiobuff() > 4) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT - 1) { LastSoundEmissionTime++; return; diff --git a/source/nds/gui.h b/source/nds/gui.h index b2eae62..e8302eb 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -24,7 +24,7 @@ #include "fs_api.h" #include "gcheat.h" -#define UP_SCREEN_UPDATE_METHOD 0 +#define UP_SCREEN_UPDATE_METHOD 1 #define DOWN_SCREEN_UPDATE_METHOD 2 #define MAX_GAMEPAD_MAP 16 -- cgit v1.2.3 From e7ac6f675f9faf5894aea8dd80e01c649933c322 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Tue, 5 Feb 2013 16:35:45 -0500 Subject: Disable the free space line in the options for the time being. Currently it invokes a recursive directory scan to calculate how much space is used first. --- source/nds/gui.c | 24 ++++++++++++++++++++++-- source/nds/message.h | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index 3d2ab70..764ca66 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1756,7 +1756,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) auto void latest_game_menu_end(); auto void language_set(); auto void game_fastforward(); +#ifdef ENABLE_FREE_SPACE auto void show_card_space(); +#endif auto void savestate_selitem(u32 sel, u32 y_pos); auto void game_state_menu_passive(); auto void gamestate_delette_menu_passive(); @@ -2772,6 +2774,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } } +#ifdef ENABLE_FREE_SPACE unsigned int freespace; void show_card_space () { @@ -2815,6 +2818,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) PRINT_STRING_BG(down_screen_addr, line_buffer, COLOR_INACTIVE_ITEM, COLOR_TRANS, 147, 40 + (display_option->line_number)*27); } +#endif char *screen_ratio_options[] = { (char*)&msg[MSG_VIDEO_ASPECT_RATIO_0], (char*)&msg[MSG_VIDEO_ASPECT_RATIO_1], @@ -3004,12 +3008,26 @@ u32 menu(u16 *screen, bool8 FirstInvocation) /* 02 */ STRING_SELECTION_OPTION(language_set, NULL, &msg[FMT_OPTIONS_LANGUAGE], language_options, &emu_config.language, sizeof(language_options) / sizeof(language_options[0]) /* number of possible languages */, NULL, ACTION_TYPE, 2), +#ifdef ENABLE_FREE_SPACE /* 03 */ STRING_SELECTION_OPTION(NULL, show_card_space, &msg[MSG_OPTIONS_CARD_CAPACITY], NULL, &desert, 2, NULL, PASSIVE_TYPE | HIDEN_TYPE, 3), +#endif - /* 04 */ ACTION_OPTION(load_default_setting, NULL, &msg[MSG_OPTIONS_RESET], NULL, 4), + /* 04 */ ACTION_OPTION(load_default_setting, NULL, &msg[MSG_OPTIONS_RESET], NULL, +#ifdef ENABLE_FREE_SPACE + 4 +#else + 3 +#endif + ), - /* 05 */ ACTION_OPTION(check_gbaemu_version, NULL, &msg[MSG_OPTIONS_VERSION], NULL, 5), + /* 05 */ ACTION_OPTION(check_gbaemu_version, NULL, &msg[MSG_OPTIONS_VERSION], NULL, +#ifdef ENABLE_FREE_SPACE + 5 +#else + 4 +#endif + ), }; MAKE_MENU(others, others_menu_init, NULL, NULL, NULL, 1, 1); @@ -3556,11 +3574,13 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void others_menu_init() { +#ifdef ENABLE_FREE_SPACE unsigned int total, used; //get card space info freespace = 0; fat_getDiskSpaceInfo("fat:", &total, &used, &freespace); +#endif } void choose_menu(MENU_TYPE *new_menu) diff --git a/source/nds/message.h b/source/nds/message.h index 3eb9e74..b5bb47b 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -48,7 +48,7 @@ enum MSG MSG_TOOLS_GAME_HOTKEY_GENERAL, FMT_OPTIONS_LANGUAGE, FMT_OPTIONS_CPU_FREQUENCY, - MSG_OPTIONS_CARD_CAPACITY, + MSG_OPTIONS_CARD_CAPACITY /* unused if !defined(ENABLE_FREE_SPACE) */, MSG_OPTIONS_RESET, MSG_OPTIONS_VERSION, MSG_SCREENSHOT_CREATE, -- cgit v1.2.3 From f2adea7bb2250876df3d1b6e076a6b5380c6b13e Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Tue, 5 Feb 2013 19:39:09 -0500 Subject: Force both manual and automatic frameskipping to be at or above 2. Resets the default value for all games which previously had this value configured. --- source/nds/entry.cpp | 14 +++++++++++--- source/nds/gui.c | 4 ++-- source/nds/gui.h | 22 ++++++++++++++++++++-- source/nds/message.h | 4 ++-- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 18802a0..6cbf3ef 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -390,7 +390,7 @@ void game_set_frameskip() } else { - Settings.SkipFrames = game_config.frameskip_value - 1 /* 1 -> 0 and so on */; + Settings.SkipFrames = game_config.frameskip_value + 1 /* 1 -> 2 and so on */; } } @@ -639,7 +639,6 @@ int sfc_main (int argc, char **argv) static unsigned int sync_last= 0; static unsigned int sync_next = 0; -static unsigned int auto_equivalent_skip = 0; static unsigned int skip_rate= 0; @@ -690,7 +689,16 @@ void S9xSyncSpeed () // If this is negative, we're late by syncdif*42.66 // microseconds. syncdif = sync_next - syncnow; - if (syncdif < 0 && syncdif >= -(frame_time / 2)) + if(skip_rate < 2 /* did not skip 2 frames yet */) + { + // Skip a minimum of 2 frames between rendered frames. + // This prevents the DSTwo-DS link from being too busy + // to return button statuses. + ++skip_rate; + IPPU.RenderThisFrame = FALSE; + sync_next += frame_time; + } + else if (syncdif < 0 && syncdif >= -(frame_time / 2)) { // We're late, but by less than half a frame. Draw it // anyway. If the next frame is too late, it'll be diff --git a/source/nds/gui.c b/source/nds/gui.c index 764ca66..4b5955a 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -2826,7 +2826,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) (char*)&msg[MSG_VIDEO_ASPECT_RATIO_3], (char*)&msg[MSG_VIDEO_ASPECT_RATIO_4]}; - char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_0], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_1], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; + char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; char *fluidity_options[] = { (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO], (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO] }; @@ -2858,7 +2858,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) &game_config.SoundSync, 2, NULL, ACTION_TYPE, 4), /* 05 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, - &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 5) + &game_config.frameskip_value, 10 /* auto (0) and 2..10 (1..9) make 10 option values */, NULL, ACTION_TYPE, 5) }; MAKE_MENU(graphics, NULL, NULL, NULL, NULL, 0, 0); diff --git a/source/nds/gui.h b/source/nds/gui.h index e8302eb..b390b69 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -50,7 +50,24 @@ struct _GAME_CONFIG { u32 clock_speed_number; u32 Reserved0; - u32 frameskip_value; + /* + * PreviouslyUsed_20130205_1 was formerly known as 'frameskip_value'; + * its values were in [0, 10]. 0 was automatic frameskipping and + * [1, 10] were mapped to skip 0 to 9 frames respectively. + * Version 1.29 changes the value range for 'frameskip_value' to + * [0, 8], with 0 as automatic frameskipping and [1, 10] to skip 2 to + * 9 frames. + * Change rationale: Frame skip values under 2 cause too much + * communication between the DSTwo and the DS, therefore the DS cannot + * timely send controller information. + * If this variable were to be used as is, the meaning of the option + * would be changed for values in [1, 8], and values in [9, 10] would + * cause undefined behavior, including crashes. + * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. + * DO NOT USE THIS VALUE FOR ANY PURPOSE OTHER THAN EXACTLY THE ONE + * FOR WHICH IT WAS INTENDED. + */ + u32 PreviouslyUsed_20130205_1; u32 graphic; u32 enable_audio; u32 Reserved1; @@ -60,7 +77,8 @@ struct _GAME_CONFIG u32 HotkeyTemporaryFastForward; u32 HotkeyToggleSound; u32 SoundSync; - u32 Reserved2[44]; + u32 frameskip_value; + u32 Reserved2[43]; }; typedef enum diff --git a/source/nds/message.h b/source/nds/message.h index b5bb47b..86389b1 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -70,8 +70,8 @@ enum MSG MSG_VIDEO_ASPECT_RATIO_4, MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC, - MSG_VIDEO_FRAME_SKIPPING_0, - MSG_VIDEO_FRAME_SKIPPING_1, + MSG_VIDEO_FRAME_SKIPPING_0 /* unused */, + MSG_VIDEO_FRAME_SKIPPING_1 /* unused */, MSG_VIDEO_FRAME_SKIPPING_2, MSG_VIDEO_FRAME_SKIPPING_3, MSG_VIDEO_FRAME_SKIPPING_4, -- cgit v1.2.3 From 9e87a7a2b2659785bc05266fbb3292b60aecdf27 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 00:34:01 -0500 Subject: Implement automatic CPU frequency switching, which improves battery life if playing games that don't use all of the MIPS CPU. If all of it is indeed needed, then the game will constantly play at 396 MHz. --- CATSFC/system/language.msg | 48 ++++++++- source/nds/entry.cpp | 244 +++++++++++++++++++++++++++------------------ source/nds/entry.h | 2 + source/nds/gui.c | 22 ++-- source/nds/gui.h | 23 ++++- source/nds/message.h | 7 ++ 6 files changed, 230 insertions(+), 116 deletions(-) diff --git a/CATSFC/system/language.msg b/CATSFC/system/language.msg index 4ae6ee6..410b9a6 100644 --- a/CATSFC/system/language.msg +++ b/CATSFC/system/language.msg @@ -66,7 +66,21 @@ Game-specific hotkey overrides... #FMT_OPTIONS_LANGUAGE Language %s #FMT_OPTIONS_CPU_FREQUENCY -CPU frequency %d +CPU frequency %s +#MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC +[-] Adjust as needed +#MSG_OPTIONS_CPU_FREQUENCY_0 +[0] 240 MHz +#MSG_OPTIONS_CPU_FREQUENCY_1 +[1] 300 MHz +#MSG_OPTIONS_CPU_FREQUENCY_2 +[2] 336 MHz +#MSG_OPTIONS_CPU_FREQUENCY_3 +[3] 360 MHz +#MSG_OPTIONS_CPU_FREQUENCY_4 +[4] 384 MHz +#MSG_OPTIONS_CPU_FREQUENCY_5 +[5] 396 MHz #MSG_OPTIONS_CARD_CAPACITY Card capacity #MSG_OPTIONS_RESET @@ -266,7 +280,21 @@ Game-specific hotkey overrides... #FMT_OPTIONS_LANGUAGE 语言 %s #FMT_OPTIONS_CPU_FREQUENCY -CPU主频 %d +CPU主频 %s +#MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC +[-] Adjust as needed +#MSG_OPTIONS_CPU_FREQUENCY_0 +[0] 240 MHz +#MSG_OPTIONS_CPU_FREQUENCY_1 +[1] 300 MHz +#MSG_OPTIONS_CPU_FREQUENCY_2 +[2] 336 MHz +#MSG_OPTIONS_CPU_FREQUENCY_3 +[3] 360 MHz +#MSG_OPTIONS_CPU_FREQUENCY_4 +[4] 384 MHz +#MSG_OPTIONS_CPU_FREQUENCY_5 +[5] 396 MHz #MSG_OPTIONS_CARD_CAPACITY 卡容量 #MSG_OPTIONS_RESET @@ -466,7 +494,21 @@ Raccourcis pour le jeu actuel... #FMT_OPTIONS_LANGUAGE Langue %s #FMT_OPTIONS_CPU_FREQUENCY -Fréquence CPU %d +Fréquence CPU %s +#MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC +[-] Selon le besoin +#MSG_OPTIONS_CPU_FREQUENCY_0 +[0] 240 MHz +#MSG_OPTIONS_CPU_FREQUENCY_1 +[1] 300 MHz +#MSG_OPTIONS_CPU_FREQUENCY_2 +[2] 336 MHz +#MSG_OPTIONS_CPU_FREQUENCY_3 +[3] 360 MHz +#MSG_OPTIONS_CPU_FREQUENCY_4 +[4] 384 MHz +#MSG_OPTIONS_CPU_FREQUENCY_5 +[5] 396 MHz #MSG_OPTIONS_CARD_CAPACITY Capacité de la carte #MSG_OPTIONS_RESET diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 6cbf3ef..08e95cb 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -642,10 +642,19 @@ static unsigned int sync_next = 0; static unsigned int skip_rate= 0; +#define CPU_DOWNCLOCK_EARLY_TIME 293 /* 1 = 42.667 us. 391 = 16.67 ms */ +#define CPU_DOWNCLOCK_DETERMINATION_INTERVAL 46874 /* 23437 = 1 s */ + +static unsigned int LastAutoCPUTime = 0; +unsigned int AutoCPUFrequency = 5; +static bool8 ConsistentlyEarly = FALSE; +static bool8 FastForwardLastFrame = FALSE; + void S9xSyncSpeed () { uint32 syncnow; int32 syncdif; + unsigned int LastAutoCPUFrequency = AutoCPUFrequency; #if 0 if (Settings.SoundSync == 2) @@ -657,8 +666,19 @@ void S9xSyncSpeed () #endif syncnow = getSysTime(); - if (game_fast_forward || temporary_fast_forward /* hotkey is held */) + bool8 FastForward = game_fast_forward || temporary_fast_forward /* hotkey is held */; + + if (game_config.clock_speed_number == 0) + if (FastForward && !FastForwardLastFrame) + HighFrequencyCPU (); + else if (!FastForward && FastForwardLastFrame) + GameFrequencyCPU (); + + FastForwardLastFrame = FastForward; + + if (FastForward) { + ConsistentlyEarly = FALSE; // don't use fast-forward to lower CPU sync_last = syncnow; sync_next = syncnow; @@ -670,137 +690,149 @@ void S9xSyncSpeed () IPPU.RenderThisFrame = true; } } - else if (Settings.SkipFrames == AUTO_FRAMERATE /* && !game_fast_forward && !temporary_fast_forward */) + else { - // frame_time is in getSysTime units: 42.667 microseconds. - int32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */; - if (sync_last > syncnow) // Overflow occurred! (every 50 hrs) + // Manual or automatic frame skipping, no fast-forward. + if (Settings.SkipFrames == AUTO_FRAMERATE) { - // Render this frame regardless, set the - // sync_next, and get the hell out. - IPPU.RenderThisFrame = TRUE; + // frame_time is in getSysTime units: 42.667 microseconds. + int32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */; + if (sync_last > syncnow) // Overflow occurred! (every 50 hrs) + { + // Render this frame regardless, set the + // sync_next, and get the hell out. + ConsistentlyEarly = FALSE; + AutoCPUFrequency = 5; + LastAutoCPUTime = syncnow; + + IPPU.RenderThisFrame = TRUE; + sync_last = syncnow; + sync_next = syncnow + frame_time; + goto finalise; + } sync_last = syncnow; - sync_next = syncnow + frame_time; - return; - } - sync_last = syncnow; - // If this is positive, we have syncdif*42.66 microseconds to - // spare. - // If this is negative, we're late by syncdif*42.66 - // microseconds. - syncdif = sync_next - syncnow; - if(skip_rate < 2 /* did not skip 2 frames yet */) - { - // Skip a minimum of 2 frames between rendered frames. - // This prevents the DSTwo-DS link from being too busy - // to return button statuses. - ++skip_rate; - IPPU.RenderThisFrame = FALSE; - sync_next += frame_time; - } - else if (syncdif < 0 && syncdif >= -(frame_time / 2)) - { - // We're late, but by less than half a frame. Draw it - // anyway. If the next frame is too late, it'll be - // skipped. - skip_rate = 0; - IPPU.RenderThisFrame = true; - sync_next += frame_time; - } - else if(syncdif < 0) - { - /* - * If we're consistently late, delay up to 8 frames. - * - * That really helps with certain games, such as - * Super Mario RPG and Yoshi's Island. - */ - if(++skip_rate < 10) + // If this is positive, we have syncdif*42.66 microseconds to + // spare. + // If this is negative, we're late by syncdif*42.66 + // microseconds. + syncdif = sync_next - syncnow; + if(skip_rate < 2 /* did not skip 2 frames yet */) { - if(syncdif >= -11719 /* not more than 500.0 ms late */) + // Skip a minimum of 2 frames between rendered frames. + // This prevents the DSTwo-DS link from being too busy + // to return button statuses. + ++skip_rate; + IPPU.RenderThisFrame = FALSE; + sync_next += frame_time; + } + else if(syncdif < 0) + { + ConsistentlyEarly = FALSE; + AutoCPUFrequency = 5; + LastAutoCPUTime = syncnow; + + /* + * If we're consistently late, delay up to 8 frames. + * + * That really helps with certain games, such as + * Super Mario RPG and Yoshi's Island. + */ + if(++skip_rate < 10) { - IPPU.RenderThisFrame = FALSE; - sync_next += frame_time; + if(syncdif >= -11719 /* not more than 500.0 ms late */) + { + IPPU.RenderThisFrame = FALSE; + sync_next += frame_time; + } + else + { //lag more than 0.5s, maybe paused + IPPU.RenderThisFrame = TRUE; + sync_next = syncnow + frame_time; + } } else - { //lag more than 0.5s, maybe paused + { + skip_rate = 0; IPPU.RenderThisFrame = TRUE; sync_next = syncnow + frame_time; } } - else + else // Early { + ConsistentlyEarly = ConsistentlyEarly && syncdif >= CPU_DOWNCLOCK_EARLY_TIME; skip_rate = 0; - IPPU.RenderThisFrame = TRUE; - sync_next = syncnow + frame_time; - } - } - else // Early - { - skip_rate = 0; - if (syncdif > 0) - { - do { - S9xProcessSound (0); + if (syncdif > 0) + { + do { + S9xProcessSound (0); #ifdef ACCUMULATE_JOYPAD /* * This call allows NDSSFC to synchronise the DS controller more often. * If porting a later version of Snes9x into NDSSFC, it is essential to * preserve it. */ - NDSSFCAccumulateJoypad (); + NDSSFCAccumulateJoypad (); #endif - syncdif = sync_next - getSysTime(); - } while (syncdif > 0); - } + syncdif = sync_next - getSysTime(); + } while (syncdif > 0); + } - IPPU.RenderThisFrame = TRUE; - sync_next += frame_time; - } + IPPU.RenderThisFrame = TRUE; + sync_next += frame_time; + } #if 0 - if(++framenum >= 60) - { - syncdif = syncnow - sync_last; - sync_last = syncnow; - framenum = 0; - //printf("T %d %d\n", syncdif*42667/1000, realframe); - realframe = 0; - } + if(++framenum >= 60) + { + syncdif = syncnow - sync_last; + sync_last = syncnow; + framenum = 0; + //printf("T %d %d\n", syncdif*42667/1000, realframe); + realframe = 0; + } #endif - } - else /* if (Settings.SkipFrames != AUTO_FRAMERATE && !game_fast_forward && !temporary_fast_forward) */ - { - // frame_time is in getSysTime units: 42.667 microseconds. - uint32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */; - sync_last = syncnow; - if (++skip_rate > Settings.SkipFrames) + } + else /* if (Settings.SkipFrames != AUTO_FRAMERATE) */ { - skip_rate = 0; - IPPU.RenderThisFrame = TRUE; - // Are we early? - syncdif = sync_next - syncnow; - if (syncdif > 0) + // frame_time is in getSysTime units: 42.667 microseconds. + uint32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */; + sync_last = syncnow; + if (++skip_rate > Settings.SkipFrames) { - do { - S9xProcessSound (0); + skip_rate = 0; + IPPU.RenderThisFrame = TRUE; + // Are we early? + syncdif = sync_next - syncnow; + if (syncdif > 0) + { + ConsistentlyEarly = ConsistentlyEarly && syncdif >= CPU_DOWNCLOCK_EARLY_TIME; + do { + S9xProcessSound (0); #ifdef ACCUMULATE_JOYPAD /* * This call allows NDSSFC to synchronise the DS controller more often. * If porting a later version of Snes9x into NDSSFC, it is essential to * preserve it. */ - NDSSFCAccumulateJoypad (); + NDSSFCAccumulateJoypad (); #endif - syncdif = sync_next - getSysTime(); - } while (syncdif > 0); - // After that little delay, what time is it? - syncnow = getSysTime(); + syncdif = sync_next - getSysTime(); + } while (syncdif > 0); + // After that little delay, what time is it? + syncnow = getSysTime(); + } + else + { + // Nope, we're late. + ConsistentlyEarly = FALSE; + AutoCPUFrequency = 5; + LastAutoCPUTime = syncnow; + } + sync_next = syncnow + frame_time * (Settings.SkipFrames + 1); + } + else + { + IPPU.RenderThisFrame = FALSE; } - sync_next = syncnow + frame_time * (Settings.SkipFrames + 1); - } - else - { - IPPU.RenderThisFrame = FALSE; } } @@ -887,6 +919,20 @@ void S9xSyncSpeed () next1.tv_usec %= 1000000; } #endif + +finalise: ; + + if (syncnow - LastAutoCPUTime >= CPU_DOWNCLOCK_DETERMINATION_INTERVAL) { + if (ConsistentlyEarly && AutoCPUFrequency > 0) + AutoCPUFrequency--; + + LastAutoCPUTime = syncnow; + ConsistentlyEarly = TRUE; + // will get unset if the CPU should stay the same at next check + } + + if (game_config.clock_speed_number == 0 && LastAutoCPUFrequency != AutoCPUFrequency) + GameFrequencyCPU (); } bool8 S9xOpenSoundDevice (int mode, bool8 stereo, int buffer_size) diff --git a/source/nds/entry.h b/source/nds/entry.h index a6bd350..2d3f7db 100644 --- a/source/nds/entry.h +++ b/source/nds/entry.h @@ -8,6 +8,8 @@ extern "C" { void game_restart(void); int load_gamepak(char* file); + + extern unsigned int AutoCPUFrequency; #ifdef __cplusplus } #endif diff --git a/source/nds/gui.c b/source/nds/gui.c index 4b5955a..2dad9c8 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -289,7 +289,6 @@ u32 game_enable_audio = 1; /****************************************************************************** ******************************************************************************/ static u32 menu_cheat_page = 0; -u32 clock_speed_number = 5; u32 gamepad_config_menu; /****************************************************************************** @@ -1665,8 +1664,10 @@ void GameFrequencyCPU() { u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 396 - if(clock_speed_number <= 5) - ds2_setCPUclocklevel(clock_speed_table[clock_speed_number]); + if (game_config.clock_speed_number == 0) + ds2_setCPUclocklevel(clock_speed_table[AutoCPUFrequency]); + else if(game_config.clock_speed_number <= 6) + ds2_setCPUclocklevel(clock_speed_table[game_config.clock_speed_number - 1]); } void savefast_int(void) @@ -1776,8 +1777,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) HighFrequencyCPU(); // Crank it up, leave quickly if(gamepak_name[0] != 0) { - game_config.clock_speed_number = clock_speed_number; - reorder_latest_file(); S9xAutoSaveSRAM (); save_game_config_file(); @@ -2828,6 +2827,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; + char *cpu_frequency_options[] = { (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_0], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_1], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_2], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_3], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_4], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_5] }; + char *fluidity_options[] = { (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO], (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO] }; char *on_off_options[] = { (char*)&msg[MSG_GENERAL_OFF], (char*)&msg[MSG_GENERAL_ON] }; @@ -3002,8 +3003,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_OPTIONS], NULL, 0), - //CPU speed - /* 01 */ NUMERIC_SELECTION_OPTION(NULL, &msg[FMT_OPTIONS_CPU_FREQUENCY], &clock_speed_number, 6, NULL, 1), + //CPU speed (string: shows MHz) + /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_OPTIONS_CPU_FREQUENCY], cpu_frequency_options, + &game_config.clock_speed_number, 7, NULL, PASSIVE_TYPE, 1), /* 02 */ STRING_SELECTION_OPTION(language_set, NULL, &msg[FMT_OPTIONS_LANGUAGE], language_options, &emu_config.language, sizeof(language_options) / sizeof(language_options[0]) /* number of possible languages */, NULL, ACTION_TYPE, 2), @@ -4113,8 +4115,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(gamepak_name[0] != 0) { - game_config.clock_speed_number = clock_speed_number; - reorder_latest_file(); S9xAutoSaveSRAM (); save_game_config_file(); @@ -4284,8 +4284,7 @@ u32 load_font() --------------------------------------------------------*/ void init_game_config(void) { - game_config.clock_speed_number = 5; // 396 MHz by default - clock_speed_number = 5; + game_config.clock_speed_number = 0; // "Auto" by default game_config.graphic = 3; // By default, have a good-looking aspect ratio game_config.frameskip_value = 0; // Automatic frame skipping game_config.SoundSync = 0; // Prefer fluid images by default @@ -4341,7 +4340,6 @@ void load_game_config_file(void) { fread(&game_config, 1, sizeof(GAME_CONFIG), fp); - clock_speed_number = game_config.clock_speed_number; game_set_frameskip(); game_set_fluidity(); } diff --git a/source/nds/gui.h b/source/nds/gui.h index b390b69..df1bff9 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -48,7 +48,25 @@ struct _EMU_CONFIG struct _GAME_CONFIG { - u32 clock_speed_number; + /* + * PreviouslyUsed_20130205_2 was formerly known as + * 'clock_speed_number'; its values were in [0, 5]. [0, 5] were mapped + * to 240, 300, 336, 360, 384 and 394 MHz respectively. + * Version 1.29 changes the value range for 'clock_speed_number' to + * [0, 6], with 0 as an automatic CPU speed setting. + * Change rationale: The default value becomes 0 instead of 5. + * If this variable were to be used as is, the meaning of the default + * value would change. Games which had a configuration file before + * 1.29 would be using the older default of 5 (394 MHz), the meaning + * of which would become 384 MHz instead of "staying the default". + * Games which did not have a configuration file before 1.29 would be + * using the correct default. + * This would confuse users or cause undue hassle. + * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. + * DO NOT USE THIS VALUE FOR ANY PURPOSE OTHER THAN EXACTLY THE ONE + * FOR WHICH IT WAS INTENDED. + */ + u32 PreviouslyUsed_20130205_2; u32 Reserved0; /* * PreviouslyUsed_20130205_1 was formerly known as 'frameskip_value'; @@ -78,7 +96,8 @@ struct _GAME_CONFIG u32 HotkeyToggleSound; u32 SoundSync; u32 frameskip_value; - u32 Reserved2[43]; + u32 clock_speed_number; + u32 Reserved2[42]; }; typedef enum diff --git a/source/nds/message.h b/source/nds/message.h index 86389b1..e58d7b8 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -48,6 +48,13 @@ enum MSG MSG_TOOLS_GAME_HOTKEY_GENERAL, FMT_OPTIONS_LANGUAGE, FMT_OPTIONS_CPU_FREQUENCY, + MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC, + MSG_OPTIONS_CPU_FREQUENCY_0, + MSG_OPTIONS_CPU_FREQUENCY_1, + MSG_OPTIONS_CPU_FREQUENCY_2, + MSG_OPTIONS_CPU_FREQUENCY_3, + MSG_OPTIONS_CPU_FREQUENCY_4, + MSG_OPTIONS_CPU_FREQUENCY_5, MSG_OPTIONS_CARD_CAPACITY /* unused if !defined(ENABLE_FREE_SPACE) */, MSG_OPTIONS_RESET, MSG_OPTIONS_VERSION, -- cgit v1.2.3 From 8c5f5ba1823ac57f78ef6bec72fca93c45d0d2fa Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 00:43:21 -0500 Subject: Document the auto CPU behavior a bit. --- source/nds/entry.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 08e95cb..5cca41e 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -642,6 +642,18 @@ static unsigned int sync_next = 0; static unsigned int skip_rate= 0; +/* + * Automatic CPU frequency support is here. + * Whenever, after one downclock determination interval, each frame rendered + * during it has been rendered at least as early as CPU_DOWNCLOCK_EARLY_TIME, + * lower the CPU frequency in response. + * If at least one frame has been early, but not early enough, the CPU + * frequency stays stable. + * If at least one frame has been late, the CPU will have be switched back + * to 396 MHz. + * This improves battery life to a certain extent. + */ + #define CPU_DOWNCLOCK_EARLY_TIME 293 /* 1 = 42.667 us. 391 = 16.67 ms */ #define CPU_DOWNCLOCK_DETERMINATION_INTERVAL 46874 /* 23437 = 1 s */ -- cgit v1.2.3 From 4ac61d443d5786db1b1e365e0005a1d5740183b0 Mon Sep 17 00:00:00 2001 From: BassAceGold Date: Wed, 6 Feb 2013 00:56:33 -0500 Subject: Load the game from plug-in launch arguments. Make the CATSFC system directory become the one transferred via arguments in that case. --- source/nds/gui.c | 276 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 143 insertions(+), 133 deletions(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index 2dad9c8..495e3c8 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -45,10 +45,13 @@ char rom_path[MAX_PATH]; char gamepak_name[MAX_PATH]; char gcheat_filename[MAX_PATH]; +//program arguments +char argv[2][MAX_PATH]; + // If adding a language, make sure you update the size of the array in // message.h too. char *lang[3] = - { + { "English", // 0 "简体中文", // 1 "Français", // 2 @@ -571,7 +574,7 @@ static int manage_filelist_info(struct FILE_LIST_INFO *filelist_infop, int flag) int i; void *pt; - //Increase all + //Increase all if(flag & 0x1) { i = NAME_MEM_SIZE; @@ -1095,7 +1098,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) //Path if(-1 == redraw) { draw_hscroll_over(0); - draw_hscroll_init(down_screen_addr, 49, 10, 170, COLOR_TRANS, + draw_hscroll_init(down_screen_addr, 49, 10, 170, COLOR_TRANS, COLOR_WHITE, default_dir_name); path_scroll = 0x8000; //first scroll left } @@ -1142,7 +1145,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) pt = file_list[m]; } - draw_hscroll_init(down_screen_addr, 41, 40 + k*27, 185, + draw_hscroll_init(down_screen_addr, 41, 40 + k*27, 185, COLOR_TRANS, color, pt); } @@ -1273,7 +1276,7 @@ u32 play_screen_snapshot(void) if(draw_yesno_dialog(DOWN_SCREEN, 115, msg[MSG_GENERAL_CONFIRM_WITH_A], msg[MSG_GENERAL_CANCEL_WITH_B])) return 1; - else + else return 0; } @@ -1378,7 +1381,7 @@ u32 play_screen_snapshot(void) time1= time0; } break; - + case CURSOR_DOWN: if(!pause) { @@ -1386,21 +1389,21 @@ u32 play_screen_snapshot(void) time1= time0; } break; - + case CURSOR_LEFT: time1 = ticks; if(i > 1) i -= 2; else if(i == 1) i= file_num -1; else i= file_num -2; break; - + case CURSOR_RIGHT: time1 = ticks; break; - + case CURSOR_SELECT: if(!pause) - { + { time1 = -1; pause= 1; } @@ -1408,15 +1411,15 @@ u32 play_screen_snapshot(void) { time1 = ticks; pause= 0; - } + } break; - - case CURSOR_BACK: + + case CURSOR_BACK: if(screenp) free((void*)screenp); //deconstruct filelist_info struct manage_filelist_info(&filelist_info, -1); repeat = 0; - break; + break; default: gui_action= CURSOR_NONE; break; @@ -1456,7 +1459,7 @@ int search_dir(char *directory, char* directory_path) //while((current_file = readdir(current_dir)) != NULL) while((current_file = readdir_ex(current_dir, &st)) != NULL) { - //Is directory + //Is directory if(S_ISDIR(st.st_mode)) { if(strcmp(".", current_file->d_name) || strcmp("..", current_file->d_name)) @@ -1635,7 +1638,7 @@ int save_state(char* file, void* screen) n = ftell(fp); ds2_getTime(&time); - sprintf(str, "%02d-%02d %02d:%02d:%02d", + sprintf(str, "%02d-%02d %02d:%02d:%02d", time.month, time.day, time.hours, time.minutes, time.seconds); PRINT_STRING_BG(screen, str, COLOR_WHITE, COLOR_BLACK, 0, 0); @@ -1709,7 +1712,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) MENU_TYPE *current_menu = NULL; MENU_OPTION_TYPE *current_option = NULL; MENU_OPTION_TYPE *display_option = NULL; - + u32 current_option_num; // u32 parent_option_num; u32 string_select; @@ -1801,7 +1804,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) strcat(line_buffer, "/"); strcat(line_buffer, tmp_filename); - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); @@ -1833,71 +1836,36 @@ u32 menu(u16 *screen, bool8 FirstInvocation) choose_menu(current_menu); } } - - bool Get_Args(char *file, char **filebuf) - { - FILE* dat = fat_fopen(file, "rb"); - if(dat) - { - int i = 0; - while(!fat_feof (dat)) - { - fat_fgets(filebuf[i], 512, dat); - int len = strlen(filebuf[i]); - if(filebuf[i][len - 1] == '\n') - filebuf[i][len - 1] = '\0'; - i++; - } - - fat_fclose(dat); - fat_remove(file); - return i; - } - return 0; - } - int CheckLoad_Arg() - { - char args[2][512]; - char *argarray[2]; - - argarray[0] = args[0]; - argarray[1] = args[1]; - - if(!Get_Args("/plgargs.dat", argarray)) - return 0; - - fat_remove("plgargs.dat"); - - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); - draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); - ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); + int Menu_loadGame(char *filename){ + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); + draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); + ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - HighFrequencyCPU(); - int load_result = load_gamepak(args[1]); - LowFrequencyCPU(); + HighFrequencyCPU(); + int load_result = load_gamepak(filename); + LowFrequencyCPU(); - if(load_result == -1) - { - first_load = 1; - gamepak_name[0] = '\0'; - return 0; - } + if(load_result == -1) + { + first_load = 1; + gamepak_name[0] = '\0'; + return 0; + } - strcpy(gamepak_name, args[1]); - first_load = 0; - load_game_config_file(); + strcpy(gamepak_name, filename); + first_load = 0; + load_game_config_file(); - return_value = 1; - repeat = 0; + return_value = 1; + repeat = 0; - reorder_latest_file(); - get_savestate_filelist(); + reorder_latest_file(); + get_savestate_filelist(); - game_fast_forward= 0; - return 1; - - } + game_fast_forward= 0; + return 1; + } void menu_restart() { @@ -2111,7 +2079,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } } } - + void menu_load_state() { if(!first_load) @@ -2151,7 +2119,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) //right if(gui_action == CURSOR_SELECT) { - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(up_screen_addr, 36, 75, 190, COLOR_MSSG, msg[MSG_PROGRESS_SAVED_STATE_LOADING]); HighFrequencyCPU(); @@ -2235,7 +2203,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } else if(current_option_num == 2) //delette single { - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); if(SavedStateFileExists(delette_savestate_num)) { @@ -2303,7 +2271,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { m= current_menu->screen_focus -1; draw_hscroll_over(m+1); - draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string); } else @@ -2313,7 +2281,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) m= current_menu->focus_option - current_menu->screen_focus+2; for(n= 0; n < SUBMENU_ROW_NUM-1; n++) - draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[m+n].display_string); } } @@ -2321,7 +2289,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(current_option_num == 0) { draw_hscroll_over(0); - draw_hscroll_init(down_screen_addr, 50, 9, 180, + draw_hscroll_init(down_screen_addr, 50, 9, 180, COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[0].display_string); } @@ -2334,7 +2302,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(m >= SUBMENU_ROW_NUM) m -= 1; draw_hscroll_over(m+1); - draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string); } @@ -2348,7 +2316,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { m = current_menu->screen_focus -1; draw_hscroll_over(m+1); - draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string); } else @@ -2363,7 +2331,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(k > SUBMENU_ROW_NUM) k = SUBMENU_ROW_NUM; for(n= 1; n < k; n++) - draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[m+n].display_string); } } @@ -2375,7 +2343,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(current_option_num == 0) { draw_hscroll_over(0); - draw_hscroll_init(down_screen_addr, 50, 9, 180, + draw_hscroll_init(down_screen_addr, 50, 9, 180, COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[0].display_string); } } @@ -2390,7 +2358,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) m = current_menu->screen_focus -1; draw_hscroll_over(m+1); - draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, + draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200, COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string); } break; @@ -2666,7 +2634,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) mm = *(display_option->current_option); sprintf(line_buffer, *(display_option->display_string), str[mm]); - + PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, 27, 38 + (display_option-> line_number)*32); } @@ -2757,7 +2725,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) draw_string_vcenter(down_screen_addr, 36, 95, 190, COLOR_MSSG, msg[MSG_CHANGE_LANGUAGE_WAITING]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - load_language_msg(LANGUAGE_PACK, emu_config.language); + load_language_msg(LANGUAGE_PACK, emu_config.language); // gui_change_icon(emu_config.language); // uncomment if images change per language [Neb] if(first_load) @@ -2846,18 +2814,18 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_VIDEO_AUDIO], NULL, 0), - /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_VIDEO_ASPECT_RATIO], screen_ratio_options, + /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_VIDEO_ASPECT_RATIO], screen_ratio_options, &game_config.graphic, 5, NULL, PASSIVE_TYPE, 1), - /* 02 */ STRING_SELECTION_OPTION(game_fastforward, NULL, &msg[FMT_VIDEO_FAST_FORWARD], on_off_options, + /* 02 */ STRING_SELECTION_OPTION(game_fastforward, NULL, &msg[FMT_VIDEO_FAST_FORWARD], on_off_options, &game_fast_forward, 2, NULL, ACTION_TYPE, 2), - + /* 03 */ STRING_SELECTION_OPTION(game_disableAudio, NULL, &msg[FMT_AUDIO_SOUND], sound_seletion, &game_enable_audio, 2, NULL, ACTION_TYPE, 3), - + /* 04 */ STRING_SELECTION_OPTION(game_set_fluidity, NULL, &msg[FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE], fluidity_options, &game_config.SoundSync, 2, NULL, ACTION_TYPE, 4), - + /* 05 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, &game_config.frameskip_value, 10 /* auto (0) and 2..10 (1..9) make 10 option values */, NULL, ACTION_TYPE, 5) }; @@ -2905,9 +2873,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_CHEATS], NULL,0), - /* 01 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, + /* 01 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, ((CHEATS_PER_PAGE * menu_cheat_page) + 0), 1), - /* 02 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, + /* 02 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, ((CHEATS_PER_PAGE * menu_cheat_page) + 1), 2), /* 03 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive, ((CHEATS_PER_PAGE * menu_cheat_page) + 2), 3), @@ -2974,7 +2942,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) /*-------------------------------------------------------- Tools --------------------------------------------------------*/ - MENU_OPTION_TYPE tools_options[] = + MENU_OPTION_TYPE tools_options[] = { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_TOOLS], NULL, 0), @@ -2986,10 +2954,10 @@ u32 menu(u16 *screen, bool8 FirstInvocation) // /* 02 */ SUBMENU_OPTION(&tools_keyremap_menu, &msg[MSG_SUB_MENU_31], NULL, 2), -// /* 03 */ STRING_SELECTION_OPTION(time_backward_action, NULL, &msg[MSG_SUB_MENU_302], on_off_options, +// /* 03 */ STRING_SELECTION_OPTION(time_backward_action, NULL, &msg[MSG_SUB_MENU_302], on_off_options, // &game_config.backward, 2, NULL, ACTION_TYPE, 3), -// /* 04 */ NUMERIC_SELECTION_ACTION_OPTION(time_period_action, time_period_passive, &msg[MSG_SUB_MENU_32], +// /* 04 */ NUMERIC_SELECTION_ACTION_OPTION(time_period_action, time_period_passive, &msg[MSG_SUB_MENU_32], // &game_config.backward_time, 6, NULL, 4) }; @@ -3038,7 +3006,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) Load_game --------------------------------------------------------*/ MENU_TYPE latest_game_menu; - + MENU_OPTION_TYPE load_game_options[] = { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_LOAD_GAME_MENU_TITLE], NULL, 0), @@ -3169,7 +3137,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) show_icon(down_screen_addr, &ICON_MSEL, 173, 131); } else { - show_icon(down_screen_addr, &ICON_NEXIT, 187, 75); + show_icon(down_screen_addr, &ICON_NEXIT, 187, 75); show_icon(down_screen_addr, &ICON_MNSEL, 173, 131); } draw_string_vcenter(down_screen_addr, 175, 131, 75, COLOR_WHITE, line_buffer); @@ -3364,7 +3332,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { ext_pos= strrchr(emu_config.latest_file[k], '/'); if(ext_pos != NULL) - draw_hscroll_init(down_screen_addr, 26, 40 + k*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + k*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, ext_pos+1); else break; @@ -3422,7 +3390,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void latest_game_menu_end() { u32 k; - + for(k= 0; k < 5; k++) { if(emu_config.latest_file[k][0] != '\0') @@ -3442,12 +3410,12 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { draw_hscroll_over(current_option_num-1); ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/'); - draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, ext_pos+1); } current_option_num += 1; - if(current_option_num >= latest_game_menu.num_options) + if(current_option_num >= latest_game_menu.num_options) current_option_num = 0; current_option = current_menu->options + current_option_num; @@ -3456,7 +3424,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { draw_hscroll_over(current_option_num-1); ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/'); - draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, COLOR_TRANS, COLOR_ACTIVE_ITEM, ext_pos+1); } @@ -3468,7 +3436,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { draw_hscroll_over(current_option_num-1); ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/'); - draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, COLOR_TRANS, COLOR_INACTIVE_ITEM, ext_pos+1); } @@ -3481,7 +3449,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { draw_hscroll_over(current_option_num-1); ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/'); - draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, + draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200, COLOR_TRANS, COLOR_ACTIVE_ITEM, ext_pos+1); } @@ -3562,7 +3530,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void game_fastforward() { } - + void reload_cheats_page() @@ -3610,7 +3578,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) mdelay(100); // to prevent ds2_setBacklight() from crashing ds2_setBacklight(3); } - + wait_Allkey_release(0); bg_screenp= (u16*)malloc(256*192*2); @@ -3619,7 +3587,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(gamepak_name[0] == 0) { first_load = 1; - if(CheckLoad_Arg()) + //try auto loading games passed through argv first + if(Menu_loadGame(argv[1])) repeat = 0; else { @@ -3642,7 +3611,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) choose_menu(&main_menu); // Menu loop - + while(repeat) { display_option = current_menu->options; @@ -3691,7 +3660,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) focus_option = line_num; } current_menu -> focus_option = focus_option; - + i = focus_option - screen_focus; display_option += i +1; @@ -3737,7 +3706,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) color= COLOR_ACTIVE_ITEM; else color= COLOR_INACTIVE_ITEM; - + PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, 23, 40 + i*27); } } @@ -3767,7 +3736,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) current_option_num = (inputdata.y / 80) * 3 + (inputdata.x / 86); current_option = current_menu->options + current_option_num; - + if(current_option -> option_type & HIDEN_TYPE) break; else if(current_option->option_type & ACTION_TYPE) @@ -3776,9 +3745,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) choose_menu(current_option->sub_menu); } /* This is the majority case, covering all menus except save states, screen shots, and game loading */ - else if(current_menu != (main_menu.options + 1)->sub_menu + else if(current_menu != (main_menu.options + 1)->sub_menu && current_menu != ((main_menu.options +1)->sub_menu->options + 3)->sub_menu - && current_menu != (main_menu.options +3)->sub_menu + && current_menu != (main_menu.options +3)->sub_menu && current_menu != ((main_menu.options +3)->sub_menu->options + 1)->sub_menu && current_menu != (main_menu.options +6)->sub_menu && current_menu != ((main_menu.options +6)->sub_menu->options + 2)->sub_menu) @@ -3846,9 +3815,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) next_option_num = 3; else break; - + struct _MENU_OPTION_TYPE *next_option = current_menu->options + next_option_num; - + if(next_option_num == 1 /* write */ || next_option_num == 2 /* read */) { u32 current_option_val = *(next_option->current_option); @@ -3893,7 +3862,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } break; } - + gui_action = CURSOR_SELECT; if(next_option -> option_type & HIDEN_TYPE) break; @@ -3920,9 +3889,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) next_option_num = 2; else break; - + struct _MENU_OPTION_TYPE *next_option = current_menu->options + next_option_num; - + if(next_option_num == 2) { u32 current_option_val = *(next_option->current_option); @@ -3960,7 +3929,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } break; } - + gui_action = CURSOR_SELECT; if(next_option -> option_type & HIDEN_TYPE) break; @@ -4093,7 +4062,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) choose_menu(current_option->sub_menu); break; - case CURSOR_BACK: + case CURSOR_BACK: if(current_menu != &main_menu) choose_menu(current_menu->options->sub_menu); else @@ -4112,7 +4081,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) destroy_dynamic_cheats(); if(bg_screenp != NULL) free((void*)bg_screenp); - + if(gamepak_name[0] != 0) { reorder_latest_file(); @@ -4120,7 +4089,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) save_game_config_file(); } save_emu_config_file(); - + ds2_clearScreen(DOWN_SCREEN, 0); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); copy_screen(up_screen_addr, (void*) screen, 0, 0, 256, 192); @@ -4396,7 +4365,7 @@ int save_game_config_file(void) sprintf(game_config_filename, "%s/%s", DEFAULT_CFG_DIR, gamepak_name); pt = strrchr(game_config_filename, '.'); - if(NULL == pt) + if(NULL == pt) return -1; *pt = '\0'; @@ -4472,7 +4441,7 @@ void reorder_latest_file(void) else break; } - + strcpy(emu_config.latest_file[i-1], full_file); } return ; @@ -4638,7 +4607,7 @@ void get_newest_savestate(char *name_buffer) get_savestate_filename(latest_save, name_buffer); } -static void get_timestamp_string(char *buffer, u16 msg_id, u16 year, u16 mon, +static void get_timestamp_string(char *buffer, u16 msg_id, u16 year, u16 mon, u16 day, u16 wday, u16 hour, u16 min, u16 sec, u32 msec) { char *weekday_strings[] = @@ -4646,7 +4615,7 @@ static void get_timestamp_string(char *buffer, u16 msg_id, u16 year, u16 mon, "SUN", "MON", "TUE", "WED", "TUR", "FRI", "SAT" }; - sprintf(buffer, "%s %02d/%02d/%04d %02d:%02d:%02d", weekday_strings[wday], + sprintf(buffer, "%s %02d/%02d/%04d %02d:%02d:%02d", weekday_strings[wday], day, mon, year, hour, min, sec); } @@ -4671,7 +4640,7 @@ static u32 save_ss_bmp(u16 *image) change_ext(gamepak_name, ss_filename, "_"); ds2_getTime(¤t_time); - sprintf(save_ss_path, "%s/%s%02d%02d%02d%02d%02d.bmp", DEFAULT_SS_DIR, ss_filename, + sprintf(save_ss_path, "%s/%s%02d%02d%02d%02d%02d.bmp", DEFAULT_SS_DIR, ss_filename, current_time.month, current_time.day, current_time.hours, current_time.minutes, current_time.seconds); for(y = 0; y < 192; y++) @@ -4706,7 +4675,7 @@ void quit(void) __asm__ __volatile__("or %0, $0, $ra" : "=r" (reg_ra) :); - + dbg_printf("return address= %08x\n", reg_ra); */ @@ -4732,6 +4701,37 @@ u32 file_length(FILE* file) /* * GUI Initialize */ +static bool Get_Args(char *file, char **filebuf){ + FILE* dat = fat_fopen(file, "rb"); + if(dat){ + int i = 0; + while(!fat_feof (dat)){ + fat_fgets(filebuf[i], 512, dat); + int len = strlen(filebuf[i]); + if(filebuf[i][len - 1] == '\n') + filebuf[i][len - 1] = '\0'; + i++; + } + + fat_fclose(dat); + fat_remove(file); + return i; + } + return 0; +} + +int CheckLoad_Arg(){ + char *argarray[2]; + argarray[0] = argv[0]; + argarray[1] = argv[1]; + + if(!Get_Args("/plgargs.dat", argarray)) + return 0; + + fat_remove("plgargs.dat"); + return 1; +} + void gui_init(u32 lang_id) { int flag; @@ -4749,7 +4749,17 @@ void gui_init(u32 lang_id) //Find the "CATSFC" system directory DIR *current_dir; - strcpy(main_path, "fat:/CATSFC"); + if(CheckLoad_Arg()){ + //copy new folder location + strcpy(main_path, "fat:"); + strcat(main_path, argv[0]); + //strip off the binary name + char *endStr = strrchr(main_path, '/'); + *endStr = '\0'; + } + else + strcpy(main_path, "fat:/CATSFC"); + current_dir = opendir(main_path); if(current_dir) closedir(current_dir); -- cgit v1.2.3 From ea330e8f79c16894deda51509e769cbd02ff83df Mon Sep 17 00:00:00 2001 From: BassAceGold Date: Wed, 6 Feb 2013 02:04:39 -0500 Subject: Fix settings not getting loaded with a ROM provided by plugin arguments. --- source/nds/entry.cpp | 2 +- source/nds/entry.h | 2 +- source/nds/gui.c | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 5cca41e..8b1724e 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -499,7 +499,7 @@ void game_restart(void) S9xReset (); } -int load_gamepak(char* file) +int load_gamepak(const char* file) { CPU.Flags = 0; // mdelay(50); // Delete this delay diff --git a/source/nds/entry.h b/source/nds/entry.h index 2d3f7db..0728768 100644 --- a/source/nds/entry.h +++ b/source/nds/entry.h @@ -7,7 +7,7 @@ extern "C" { void game_restart(void); - int load_gamepak(char* file); + int load_gamepak(const char* file); extern unsigned int AutoCPUFrequency; #ifdef __cplusplus diff --git a/source/nds/gui.c b/source/nds/gui.c index 495e3c8..427f7d7 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1853,7 +1853,21 @@ u32 menu(u16 *screen, bool8 FirstInvocation) return 0; } - strcpy(gamepak_name, filename); + char tempPath[MAX_PATH]; + strcpy(tempPath, filename); + + //update folders and names for settings/config uses + char *dirEnd = strrchr(tempPath, '/'); + //make sure a valid path was provided + if(!dirEnd) + return 0; + + //copy file name as gamepak_name + strcpy(gamepak_name, dirEnd+1); + //then strip filename from directory path and set it + *dirEnd = '\0'; + strcpy(g_default_rom_dir, tempPath); + first_load = 0; load_game_config_file(); -- cgit v1.2.3 From a358ef69a85a7252ed6b5a30496c49b28b26eecd Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 02:18:35 -0500 Subject: Make all gamepak loads call LoadGameAndItsData, that way its "Loading" screen, current gamepak variables, game config stuff and so on are all consistent. --- source/nds/gui.c | 106 ++++++++++++++----------------------------------------- 1 file changed, 27 insertions(+), 79 deletions(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index 427f7d7..f71f70f 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1788,56 +1788,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) quit(); } - void menu_load() - { - char *file_ext[] = { ".smc", ".sfc", ".zip", NULL }; - - if(gamepak_name[0] != 0) - { - S9xAutoSaveSRAM (); - save_game_config_file(); - } - - if(load_file(file_ext, tmp_filename, g_default_rom_dir) != -1) - { - strcpy(line_buffer, g_default_rom_dir); - strcat(line_buffer, "/"); - strcat(line_buffer, tmp_filename); - - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); - draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); - ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - - HighFrequencyCPU(); - int load_result = load_gamepak(line_buffer); - LowFrequencyCPU(); - if(load_result == -1) - { - first_load = 1; - gamepak_name[0] = '\0'; - return; - } - - strcpy(gamepak_name, tmp_filename); - first_load = 0; - load_game_config_file(); -// time_period_action(); - - return_value = 1; - repeat = 0; - - reorder_latest_file(); - get_savestate_filelist(); - - game_fast_forward= 0; - } - else - { - choose_menu(current_menu); - } - } - - int Menu_loadGame(char *filename){ + int LoadGameAndItsData(char *filename){ draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); @@ -1881,6 +1832,30 @@ u32 menu(u16 *screen, bool8 FirstInvocation) return 1; } + void menu_load() + { + char *file_ext[] = { ".smc", ".sfc", ".zip", NULL }; + + if(gamepak_name[0] != 0) + { + S9xAutoSaveSRAM (); + save_game_config_file(); + } + + if(load_file(file_ext, tmp_filename, g_default_rom_dir) != -1) + { + strcpy(line_buffer, g_default_rom_dir); + strcat(line_buffer, "/"); + strcat(line_buffer, tmp_filename); + + LoadGameAndItsData(line_buffer); + } + else + { + choose_menu(current_menu); + } + } + void menu_restart() { if(!first_load) @@ -3486,10 +3461,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { char *ext_pos; - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, 0); - draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); - ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - if(gamepak_name[0] != 0) { S9xAutoSaveSRAM (); @@ -3509,36 +3480,13 @@ u32 menu(u16 *screen, bool8 FirstInvocation) ext_pos = emu_config.latest_file[current_option_num -1]; - HighFrequencyCPU(); - int load_result = load_gamepak(ext_pos); - LowFrequencyCPU(); - - if(load_result == -1) { - first_load = 1; - return; - } - - strcpy(g_default_rom_dir, ext_pos); - ext_pos = strrchr(g_default_rom_dir, '/'); - *ext_pos= '\0'; - strcpy(gamepak_name, ext_pos+1); - - - load_game_config_file(); -// time_period_action(); - - reorder_latest_file(); - get_savestate_filelist(); - game_fast_forward= 0; + LoadGameAndItsData(ext_pos); get_newest_savestate(tmp_filename); if(tmp_filename[0] != '\0') { load_state(tmp_filename); } - - return_value = 1; - repeat = 0; } void game_fastforward() @@ -3602,7 +3550,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { first_load = 1; //try auto loading games passed through argv first - if(Menu_loadGame(argv[1])) + if(LoadGameAndItsData(argv[1])) repeat = 0; else { -- cgit v1.2.3 From 9829c836089c44d5c8cc7e3d0f7007ab33b0cb1a Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 02:31:55 -0500 Subject: Fix the loading screen for a ROM appearing for a split second after the splash screen. Fix uninitialised memory access in Check_LoadArg. --- source/nds/gui.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index f71f70f..5d969a2 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -3550,7 +3550,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { first_load = 1; //try auto loading games passed through argv first - if(LoadGameAndItsData(argv[1])) + if(strlen(argv[1]) > 0 && LoadGameAndItsData(argv[1])) repeat = 0; else { @@ -4683,6 +4683,8 @@ static bool Get_Args(char *file, char **filebuf){ } int CheckLoad_Arg(){ + argv[0][0] = '\0'; // Initialise the first byte to be a NULL in case + argv[1][0] = '\0'; // there are no arguments to avoid uninit. memory char *argarray[2]; argarray[0] = argv[0]; argarray[1] = argv[1]; -- cgit v1.2.3 From b08a201ea2de43d70047673114c705a26887ea4b Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 02:53:53 -0500 Subject: Allow all audio buffers to get full again before declaring underflow. --- source/nds/entry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 8b1724e..a5a98de 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -1053,7 +1053,7 @@ void S9xProcessSound (unsigned int) unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT - 1) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT) { LastSoundEmissionTime++; return; -- cgit v1.2.3 From 772e24ae503310eb1ee0d5ed5061eebb138e5808 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 03:46:48 -0500 Subject: Reinstate frame skipping options 0 and 1, but keep the new meaning (>= 2 equivalent skip level) for automatic frame skipping. Remove the automatic CPU frequency option, which was making audio emit 0.25 second of silence every so often. --- CATSFC/system/language.msg | 6 ------ source/nds/entry.cpp | 2 +- source/nds/gui.c | 16 ++++++-------- source/nds/gui.h | 53 ++++++++++++---------------------------------- source/nds/message.h | 5 ++--- 5 files changed, 24 insertions(+), 58 deletions(-) diff --git a/CATSFC/system/language.msg b/CATSFC/system/language.msg index 410b9a6..3261266 100644 --- a/CATSFC/system/language.msg +++ b/CATSFC/system/language.msg @@ -67,8 +67,6 @@ Game-specific hotkey overrides... Language %s #FMT_OPTIONS_CPU_FREQUENCY CPU frequency %s -#MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC -[-] Adjust as needed #MSG_OPTIONS_CPU_FREQUENCY_0 [0] 240 MHz #MSG_OPTIONS_CPU_FREQUENCY_1 @@ -281,8 +279,6 @@ Game-specific hotkey overrides... 语言 %s #FMT_OPTIONS_CPU_FREQUENCY CPU主频 %s -#MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC -[-] Adjust as needed #MSG_OPTIONS_CPU_FREQUENCY_0 [0] 240 MHz #MSG_OPTIONS_CPU_FREQUENCY_1 @@ -495,8 +491,6 @@ Raccourcis pour le jeu actuel... Langue %s #FMT_OPTIONS_CPU_FREQUENCY Fréquence CPU %s -#MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC -[-] Selon le besoin #MSG_OPTIONS_CPU_FREQUENCY_0 [0] 240 MHz #MSG_OPTIONS_CPU_FREQUENCY_1 diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index a5a98de..ca27249 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -390,7 +390,7 @@ void game_set_frameskip() } else { - Settings.SkipFrames = game_config.frameskip_value + 1 /* 1 -> 2 and so on */; + Settings.SkipFrames = game_config.frameskip_value - 1 /* 1 -> 0 and so on */; } } diff --git a/source/nds/gui.c b/source/nds/gui.c index 5d969a2..838b5b9 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1667,10 +1667,8 @@ void GameFrequencyCPU() { u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 396 - if (game_config.clock_speed_number == 0) - ds2_setCPUclocklevel(clock_speed_table[AutoCPUFrequency]); - else if(game_config.clock_speed_number <= 6) - ds2_setCPUclocklevel(clock_speed_table[game_config.clock_speed_number - 1]); + if(game_config.clock_speed_number <= 5) + ds2_setCPUclocklevel(clock_speed_table[game_config.clock_speed_number]); } void savefast_int(void) @@ -2782,9 +2780,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) (char*)&msg[MSG_VIDEO_ASPECT_RATIO_3], (char*)&msg[MSG_VIDEO_ASPECT_RATIO_4]}; - char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; + char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_0], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_1], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] }; - char *cpu_frequency_options[] = { (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_0], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_1], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_2], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_3], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_4], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_5] }; + char *cpu_frequency_options[] = { (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_0], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_1], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_2], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_3], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_4], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_5] }; char *fluidity_options[] = { (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO], (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO] }; @@ -2816,7 +2814,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) &game_config.SoundSync, 2, NULL, ACTION_TYPE, 4), /* 05 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options, - &game_config.frameskip_value, 10 /* auto (0) and 2..10 (1..9) make 10 option values */, NULL, ACTION_TYPE, 5) + &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 5) }; MAKE_MENU(graphics, NULL, NULL, NULL, NULL, 0, 0); @@ -2962,7 +2960,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) //CPU speed (string: shows MHz) /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_OPTIONS_CPU_FREQUENCY], cpu_frequency_options, - &game_config.clock_speed_number, 7, NULL, PASSIVE_TYPE, 1), + &game_config.clock_speed_number, 6, NULL, PASSIVE_TYPE, 1), /* 02 */ STRING_SELECTION_OPTION(language_set, NULL, &msg[FMT_OPTIONS_LANGUAGE], language_options, &emu_config.language, sizeof(language_options) / sizeof(language_options[0]) /* number of possible languages */, NULL, ACTION_TYPE, 2), @@ -4215,7 +4213,7 @@ u32 load_font() --------------------------------------------------------*/ void init_game_config(void) { - game_config.clock_speed_number = 0; // "Auto" by default + game_config.clock_speed_number = 5; // 396 MHz by default game_config.graphic = 3; // By default, have a good-looking aspect ratio game_config.frameskip_value = 0; // Automatic frame skipping game_config.SoundSync = 0; // Prefer fluid images by default diff --git a/source/nds/gui.h b/source/nds/gui.h index df1bff9..6bb9ed8 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -48,44 +48,9 @@ struct _EMU_CONFIG struct _GAME_CONFIG { - /* - * PreviouslyUsed_20130205_2 was formerly known as - * 'clock_speed_number'; its values were in [0, 5]. [0, 5] were mapped - * to 240, 300, 336, 360, 384 and 394 MHz respectively. - * Version 1.29 changes the value range for 'clock_speed_number' to - * [0, 6], with 0 as an automatic CPU speed setting. - * Change rationale: The default value becomes 0 instead of 5. - * If this variable were to be used as is, the meaning of the default - * value would change. Games which had a configuration file before - * 1.29 would be using the older default of 5 (394 MHz), the meaning - * of which would become 384 MHz instead of "staying the default". - * Games which did not have a configuration file before 1.29 would be - * using the correct default. - * This would confuse users or cause undue hassle. - * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. - * DO NOT USE THIS VALUE FOR ANY PURPOSE OTHER THAN EXACTLY THE ONE - * FOR WHICH IT WAS INTENDED. - */ - u32 PreviouslyUsed_20130205_2; + u32 clock_speed_number; u32 Reserved0; - /* - * PreviouslyUsed_20130205_1 was formerly known as 'frameskip_value'; - * its values were in [0, 10]. 0 was automatic frameskipping and - * [1, 10] were mapped to skip 0 to 9 frames respectively. - * Version 1.29 changes the value range for 'frameskip_value' to - * [0, 8], with 0 as automatic frameskipping and [1, 10] to skip 2 to - * 9 frames. - * Change rationale: Frame skip values under 2 cause too much - * communication between the DSTwo and the DS, therefore the DS cannot - * timely send controller information. - * If this variable were to be used as is, the meaning of the option - * would be changed for values in [1, 8], and values in [9, 10] would - * cause undefined behavior, including crashes. - * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. - * DO NOT USE THIS VALUE FOR ANY PURPOSE OTHER THAN EXACTLY THE ONE - * FOR WHICH IT WAS INTENDED. - */ - u32 PreviouslyUsed_20130205_1; + u32 frameskip_value; u32 graphic; u32 enable_audio; u32 Reserved1; @@ -95,8 +60,18 @@ struct _GAME_CONFIG u32 HotkeyTemporaryFastForward; u32 HotkeyToggleSound; u32 SoundSync; - u32 frameskip_value; - u32 clock_speed_number; + /* + * PreviouslyUsed_20130206_1 was for a second meaning of + * frameskip_value that is now dropped. + * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. + */ + u32 PreviouslyUsed_20130206_1; + /* + * PreviouslyUsed_20130206_2 was for a second meaning of + * clock_speed_number that is now dropped. + * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. + */ + u32 PreviouslyUsed_20130206_2; u32 Reserved2[42]; }; diff --git a/source/nds/message.h b/source/nds/message.h index e58d7b8..64c3a6c 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -48,7 +48,6 @@ enum MSG MSG_TOOLS_GAME_HOTKEY_GENERAL, FMT_OPTIONS_LANGUAGE, FMT_OPTIONS_CPU_FREQUENCY, - MSG_OPTIONS_CPU_FREQUENCY_AUTOMATIC, MSG_OPTIONS_CPU_FREQUENCY_0, MSG_OPTIONS_CPU_FREQUENCY_1, MSG_OPTIONS_CPU_FREQUENCY_2, @@ -77,8 +76,8 @@ enum MSG MSG_VIDEO_ASPECT_RATIO_4, MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC, - MSG_VIDEO_FRAME_SKIPPING_0 /* unused */, - MSG_VIDEO_FRAME_SKIPPING_1 /* unused */, + MSG_VIDEO_FRAME_SKIPPING_0, + MSG_VIDEO_FRAME_SKIPPING_1, MSG_VIDEO_FRAME_SKIPPING_2, MSG_VIDEO_FRAME_SKIPPING_3, MSG_VIDEO_FRAME_SKIPPING_4, -- cgit v1.2.3 From b277570daee54faf93804f5ae2d5e82e8fa11708 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 04:38:18 -0500 Subject: Quit saving the files so often for nothing; that uses up erase cycles on storage cards! Instead, save them once when the menu that contains the settings that the user changed is exited, IF the settings' values changed, OR once when updating the list of most-recently played games. Automatically save the SRAM in most cases, including game changes. This commit also makes it unnecessary to save the game config of the previous game when loading another, makes it load certain settings correctly, and MAY make it avoid creating a file for a game's settings if the user never changes them from the defaults. --- source/nds/gui.c | 58 +++++++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index 838b5b9..581c905 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -1718,6 +1718,9 @@ u32 menu(u16 *screen, bool8 FirstInvocation) u16 *bg_screenp; u32 bg_screenp_color; + GAME_CONFIG PreviousGameConfig; // Compared with current settings to + EMU_CONFIG PreviousEmuConfig; // determine if they need to be saved + auto void choose_menu(); auto void menu_return(); auto void menu_exit(); @@ -1776,17 +1779,32 @@ u32 menu(u16 *screen, bool8 FirstInvocation) void menu_exit() { HighFrequencyCPU(); // Crank it up, leave quickly - if(gamepak_name[0] != 0) - { - reorder_latest_file(); + if(gamepak_name[0] != 0) + { S9xAutoSaveSRAM (); - save_game_config_file(); } - save_emu_config_file(); quit(); } + void SaveConfigsIfNeeded() + { + if (memcmp(&PreviousGameConfig, &game_config, sizeof(GAME_CONFIG)) != 0) + save_game_config_file(); + if (memcmp(&PreviousEmuConfig, &emu_config, sizeof(EMU_CONFIG)) != 0) + save_emu_config_file(); + } + + void PreserveConfigs() + { + memcpy(&PreviousGameConfig, &game_config, sizeof(GAME_CONFIG)); + memcpy(&PreviousEmuConfig, &emu_config, sizeof(EMU_CONFIG)); + } + int LoadGameAndItsData(char *filename){ + if (gamepak_name[0] != '\0') { + S9xAutoSaveSRAM(); + } + draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); @@ -1819,6 +1837,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) first_load = 0; load_game_config_file(); + PreserveConfigs(); // Make the emulator not save what we've JUST read + // but it will save the emulator configuration below for latest files return_value = 1; repeat = 0; @@ -1834,12 +1854,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { char *file_ext[] = { ".smc", ".sfc", ".zip", NULL }; - if(gamepak_name[0] != 0) - { - S9xAutoSaveSRAM (); - save_game_config_file(); - } - if(load_file(file_ext, tmp_filename, g_default_rom_dir) != -1) { strcpy(line_buffer, g_default_rom_dir); @@ -2056,10 +2070,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); - //save game config - reorder_latest_file(); - save_game_config_file(); - SavedStateCacheInvalidate (); mdelay(500); // let the progress message linger @@ -2722,7 +2732,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) ds2_flipScreen(UP_SCREEN, 1); } - save_emu_config_file(); LowFrequencyCPU(); // and back down wait_Allkey_release(0); } @@ -3459,12 +3468,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { char *ext_pos; - if(gamepak_name[0] != 0) - { - S9xAutoSaveSRAM (); - save_game_config_file(); - } - if(bg_screenp != NULL) { bg_screenp_color = COLOR16(43, 11, 11); } @@ -3521,11 +3524,13 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(NULL != current_menu) { if(current_menu->end_function) current_menu->end_function(); + SaveConfigsIfNeeded(); } current_menu = new_menu; current_option_num= current_menu -> focus_option; current_option = new_menu->options + current_option_num; + PreserveConfigs(); if(current_menu->init_function) current_menu->init_function(); } @@ -4038,18 +4043,11 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if (current_menu && current_menu->end_function) current_menu->end_function(); + SaveConfigsIfNeeded(); destroy_dynamic_cheats(); if(bg_screenp != NULL) free((void*)bg_screenp); - if(gamepak_name[0] != 0) - { - reorder_latest_file(); - S9xAutoSaveSRAM (); - save_game_config_file(); - } - save_emu_config_file(); - ds2_clearScreen(DOWN_SCREEN, 0); ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); copy_screen(up_screen_addr, (void*) screen, 0, 0, 256, 192); -- cgit v1.2.3 From 3c3a97219dbe3a2e7555e6f65eb093d4f3435e49 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 04:57:12 -0500 Subject: Fix 2 compiler warnings in gui.c. --- source/nds/gui.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index 581c905..9ce602c 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -2852,10 +2852,12 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { /* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_SAVED_STATES], NULL, 0), - /* 01 */ NUMERIC_SELECTION_ACTION_OPTION(menu_save_state, NULL, &msg[FMT_SAVED_STATE_CREATE], &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 1), + // savestate_index is still a signed int + /* 01 */ NUMERIC_SELECTION_ACTION_OPTION(menu_save_state, NULL, &msg[FMT_SAVED_STATE_CREATE], (u32*) &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 1), + // savestate_index is still a signed int /* 02 */ NUMERIC_SELECTION_ACTION_OPTION(menu_load_state, NULL, - &msg[FMT_SAVED_STATE_LOAD], &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 2), + &msg[FMT_SAVED_STATE_LOAD], (u32*) &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 2), /* 03 */ SUBMENU_OPTION(&gamestate_delette_menu, &msg[MSG_SAVED_STATE_DELETE_GENERAL], NULL, 5), }; -- cgit v1.2.3 From 3dc666810732dcabb95a3bd1d02d4fcee0befd3f Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 05:59:22 -0500 Subject: Raise the sound frequency from 22050 Hz to 32000 Hz, which is like the SNES. Use sound interpolation to make it sound even more like the SNES. --- source/nds/ds2sound.h | 21 ++++++++++++--------- source/nds/entry.cpp | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/source/nds/ds2sound.h b/source/nds/ds2sound.h index f51a6e1..8c0e2bf 100644 --- a/source/nds/ds2sound.h +++ b/source/nds/ds2sound.h @@ -1,21 +1,24 @@ // The sound buffer sizes used on the DS2's side, for each value of // Settings.SoundPlaybackRate. +// * Don't buffer too much, otherwise audio is delayed from video. +// * Don't go below one frame (20 milliseconds). +// * Buffer sizes must be multiples of 128. #define DS2_BUFFER_SIZE_4 512 /* tested working */ -#define DS2_BUFFER_SIZE_5 1024 /* like the SNES! tested working, but slow */ -#define DS2_BUFFER_SIZE_6 1024 /* tested working, slow because of upsampling */ -#define DS2_BUFFER_SIZE_7 1024 /* tested working, slow because of upsampling */ +#define DS2_BUFFER_SIZE_5 640 /* like the SNES! tested working */ +#define DS2_BUFFER_SIZE_6 896 /* tested working */ +#define DS2_BUFFER_SIZE_7 1024 /* tested working */ // The sampling rate for the sound, in Hz, for each value of // Settings.SoundPlaybackRate. #define SND_SAMPLE_RATE_1 8000 #define SND_SAMPLE_RATE_2 11025 #define SND_SAMPLE_RATE_3 16000 -#define SND_SAMPLE_RATE_4 22050 -#define SND_SAMPLE_RATE_5 32000 +#define SND_SAMPLE_RATE_4 22050 /* NDSSFC 1.06 - CATSFC 1.28 used this one */ +#define SND_SAMPLE_RATE_5 32000 /* like the SNES! */ #define SND_SAMPLE_RATE_6 44100 -#define SND_SAMPLE_RATE_7 48000 +#define SND_SAMPLE_RATE_7 48000 /* CATSFC 1.25 made using this one possible */ // Settings in use. The number should match in all three settings. -#define DS2_BUFFER_SIZE DS2_BUFFER_SIZE_4 -#define SND_SAMPLE_RATE SND_SAMPLE_RATE_4 -#define SNES9X_SRATE_ID 4 +#define DS2_BUFFER_SIZE DS2_BUFFER_SIZE_5 +#define SND_SAMPLE_RATE SND_SAMPLE_RATE_5 +#define SNES9X_SRATE_ID 5 diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index ca27249..723374c 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -425,7 +425,7 @@ void init_sfc_setting(void) //sound settings Settings.APUEnabled = Settings.NextAPUEnabled = TRUE; Settings.FixFrequency = 1; - + Settings.InterpolatedSound = TRUE; Settings.H_Max = SNES_CYCLES_PER_SCANLINE; Settings.SkipFrames = AUTO_FRAMERATE; @@ -1042,7 +1042,7 @@ void S9xGenerateSound () } } -#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)) +#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128) - 1) /* -1 is for roundoff errors */ unsigned int LastSoundEmissionTime = 0; void S9xProcessSound (unsigned int) -- cgit v1.2.3 From 04037a309694dc56e3139f676b409ba7deab9298 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 06:27:11 -0500 Subject: When changing languages, quit doing the "Changing language, please wait..." as it only takes a few milliseconds. --- CATSFC/system/language.msg | 12 ------------ source/nds/gui.c | 14 -------------- source/nds/message.h | 3 --- 3 files changed, 29 deletions(-) diff --git a/CATSFC/system/language.msg b/CATSFC/system/language.msg index 3261266..f43d77d 100644 --- a/CATSFC/system/language.msg +++ b/CATSFC/system/language.msg @@ -191,10 +191,6 @@ Saving a screenshot... OK! #MSG_PROGRESS_SCREENSHOT_CREATION_FAILED Failed! -#MSG_CHANGE_LANGUAGE -Changing language... -#MSG_CHANGE_LANGUAGE_WAITING -Please wait... #MSG_NO_SLIDE No screenshots found #MSG_PLAYING_SLIDE @@ -403,10 +399,6 @@ Press the buttons you wish to use to perform this action. 完成! #MSG_PROGRESS_SCREENSHOT_CREATION_FAILED 失败! -#MSG_CHANGE_LANGUAGE -正在修改... -#MSG_CHANGE_LANGUAGE_WAITING -请稍候! #MSG_NO_SLIDE 此目录没有屏幕快照,取消放映 #MSG_PLAYING_SLIDE @@ -615,10 +607,6 @@ Capture de l'écran... Terminé! #MSG_PROGRESS_SCREENSHOT_CREATION_FAILED Échec! -#MSG_CHANGE_LANGUAGE -Changement de la langue... -#MSG_CHANGE_LANGUAGE_WAITING -Veuillez patienter... #MSG_NO_SLIDE Aucune capture d'écran trouvée #MSG_PLAYING_SLIDE diff --git a/source/nds/gui.c b/source/nds/gui.c index 9ce602c..5e02a55 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -2709,21 +2709,8 @@ u32 menu(u16 *screen, bool8 FirstInvocation) if(gui_action == CURSOR_LEFT || gui_action == CURSOR_RIGHT) { HighFrequencyCPU(); // crank it up - if(bg_screenp != NULL) - { - bg_screenp_color = COLOR16(43, 11, 11); - memcpy(bg_screenp, down_screen_addr, 256*192*2); - } - else - bg_screenp_color = COLOR_BG; - - draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color); - draw_string_vcenter(down_screen_addr, 36, 75, 190, COLOR_MSSG, msg[MSG_CHANGE_LANGUAGE]); - draw_string_vcenter(down_screen_addr, 36, 95, 190, COLOR_MSSG, msg[MSG_CHANGE_LANGUAGE_WAITING]); - ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD); load_language_msg(LANGUAGE_PACK, emu_config.language); - // gui_change_icon(emu_config.language); // uncomment if images change per language [Neb] if(first_load) { @@ -2733,7 +2720,6 @@ u32 menu(u16 *screen, bool8 FirstInvocation) } LowFrequencyCPU(); // and back down - wait_Allkey_release(0); } } diff --git a/source/nds/message.h b/source/nds/message.h index 64c3a6c..c7e79b8 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -121,9 +121,6 @@ enum MSG MSG_PROGRESS_SCREENSHOT_CREATION_SUCCEEDED, MSG_PROGRESS_SCREENSHOT_CREATION_FAILED, - MSG_CHANGE_LANGUAGE, - MSG_CHANGE_LANGUAGE_WAITING, - MSG_NO_SLIDE, MSG_PLAYING_SLIDE, MSG_PAUSE_SLIDE, -- cgit v1.2.3 From ebf48b1bf77d0093277640fd514877b3b26baeac Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 15:51:23 -0500 Subject: Yeah... Despite the audio optimisations, sound still crackles with display double-buffering. Disable that, again. --- source/nds/gui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/nds/gui.h b/source/nds/gui.h index 6bb9ed8..290a927 100644 --- a/source/nds/gui.h +++ b/source/nds/gui.h @@ -24,7 +24,7 @@ #include "fs_api.h" #include "gcheat.h" -#define UP_SCREEN_UPDATE_METHOD 1 +#define UP_SCREEN_UPDATE_METHOD 0 #define DOWN_SCREEN_UPDATE_METHOD 2 #define MAX_GAMEPAD_MAP 16 -- cgit v1.2.3 From 0b165c3133b2c97bfe2eaf6195f36094c1213164 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 16:16:43 -0500 Subject: Use key pictograms from Pictochat to display keys for yes/no dialog(ue)s. --- CATSFC/system/language.msg | 43 +++++++++++++++++++++------------- source/nds/gui.c | 58 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 18 deletions(-) diff --git a/CATSFC/system/language.msg b/CATSFC/system/language.msg index f43d77d..de160aa 100644 --- a/CATSFC/system/language.msg +++ b/CATSFC/system/language.msg @@ -10,6 +10,17 @@ STARTVERSION # 4. See the comment line ABOVE a message for its context. For example: # > #MSG_MAIN_MENU_SAVED_STATES # > Saved states +# 5. You may use * in your message to insert a pictogram representing +# a DS key. These replacements are case-sensitive. +# Definitions are as follows: +# *A (A Button) inserts a circle containing the letter A +# *B (B Button) a circle containing the letter B +# *X (X Button) a circle containing the letter X +# *Y (Y Button) a circle containing the letter Y +# *L (L shoulder button) a cut rectangle containing the letter L +# *R (R shoulder button) a cut rectangle containing the letter R +# *S (START button) a smaller ST +# *s (SELECT button) a smaller SEL ENDVERSION ENDCOMMENT @@ -98,9 +109,9 @@ Toggle sound #MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS Press the buttons you wish to use to perform this action. #MSG_HOTKEY_DELETE_WITH_A -[A] Clear +*A Clear #MSG_HOTKEY_CANCEL_WITH_B -[B] Cancel +*B Cancel #MSG_LOAD_GAME_RECENTLY_PLAYED Recently played games #MSG_LOAD_GAME_FROM_CARD @@ -146,9 +157,9 @@ Off #MSG_GENERAL_ON On #MSG_GENERAL_CONFIRM_WITH_A -[A] Confirm +*A Confirm #MSG_GENERAL_CANCEL_WITH_B -[B] Cancel +*B Cancel #MSG_AUDIO_ENABLED On #MSG_AUDIO_MUTED @@ -306,9 +317,9 @@ Toggle sound #MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS Press the buttons you wish to use to perform this action. #MSG_HOTKEY_DELETE_WITH_A -[A] Clear +*A Clear #MSG_HOTKEY_CANCEL_WITH_B -[B] Cancel +*B Cancel #MSG_LOAD_GAME_RECENTLY_PLAYED 最近玩过的游戏 #MSG_LOAD_GAME_FROM_CARD @@ -354,9 +365,9 @@ Press the buttons you wish to use to perform this action. #MSG_GENERAL_ON 开 #MSG_GENERAL_CONFIRM_WITH_A -[A] 确认 +*A 确认 #MSG_GENERAL_CANCEL_WITH_B -[B] 取消 +*B 取消 #MSG_AUDIO_ENABLED 开 #MSG_AUDIO_MUTED @@ -414,9 +425,9 @@ Press the buttons you wish to use to perform this action. #MSG_PLAY_SLIDE4 按键 右 下一帧 #MSG_PLAY_SLIDE5 -按键 A 暂停 +按键 *A 暂停 #MSG_PLAY_SLIDE6 -按键 B 返回菜单 +按键 *B 返回菜单 #MSG_PROGRESS_LOADING_GAME 正在装载游戏... #MSG_EMULATOR_NAME @@ -514,9 +525,9 @@ Avance rapide temporaire #MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS Appuyez sur les boutons que vous voulez utiliser pour effectuer cette action. #MSG_HOTKEY_DELETE_WITH_A -[A] Effacer +*A Effacer #MSG_HOTKEY_CANCEL_WITH_B -[B] Annuler +*B Annuler #MSG_LOAD_GAME_RECENTLY_PLAYED Jeux joués récemment #MSG_LOAD_GAME_FROM_CARD @@ -562,9 +573,9 @@ Hors fonction #MSG_GENERAL_ON En fonction #MSG_GENERAL_CONFIRM_WITH_A -[A] Confirmer +*A Confirmer #MSG_GENERAL_CANCEL_WITH_B -[B] Annuler +*B Annuler #MSG_AUDIO_ENABLED Activé #MSG_AUDIO_MUTED @@ -622,9 +633,9 @@ GAUCHE Précédente #MSG_PLAY_SLIDE4 DROITE Suivante #MSG_PLAY_SLIDE5 -A Pause +*A Pause #MSG_PLAY_SLIDE6 -B Retour au menu +*B Retour au menu #MSG_PROGRESS_LOADING_GAME Chargement... #MSG_EMULATOR_NAME diff --git a/source/nds/gui.c b/source/nds/gui.c index 5e02a55..7270891 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -4140,7 +4140,61 @@ int load_language_msg(char *filename, u32 language) break; len= strlen(pt); - memcpy(dst, pt, len); + // memcpy(dst, pt, len); + + // Replace key definitions (*letter) with Pictochat icons + // while copying. + unsigned int curChar; + for (curChar = 0; curChar < len; curChar++) + { + if (pt[curChar] == '*') + { + switch (pt[curChar + 1]) + { + case 'A': + memcpy(&dst[curChar], HOTKEY_A_DISPLAY, 2); + curChar++; + break; + case 'B': + memcpy(&dst[curChar], HOTKEY_B_DISPLAY, 2); + curChar++; + break; + case 'X': + memcpy(&dst[curChar], HOTKEY_X_DISPLAY, 2); + curChar++; + break; + case 'Y': + memcpy(&dst[curChar], HOTKEY_Y_DISPLAY, 2); + curChar++; + break; + case 'L': + memcpy(&dst[curChar], HOTKEY_L_DISPLAY, 2); + curChar++; + break; + case 'R': + memcpy(&dst[curChar], HOTKEY_R_DISPLAY, 2); + curChar++; + break; + case 'S': + memcpy(&dst[curChar], HOTKEY_START_DISPLAY, 2); + curChar++; + break; + case 's': + memcpy(&dst[curChar], HOTKEY_SELECT_DISPLAY, 2); + curChar++; + break; + case '\0': + dst[curChar] = pt[curChar]; + break; + default: + memcpy(&dst[curChar], &pt[curChar], 2); + curChar++; + break; + } + } + else + dst[curChar] = pt[curChar]; + } dst += len; //at a line return, when "\n" paded, this message not end @@ -4163,7 +4217,7 @@ int load_language_msg(char *filename, u32 language) else//a message end { if(*(dst-2) == 0x0D) - dst -= 1; + dst -= 1; *(dst-1) = '\0'; msg[++loop] = dst; } -- cgit v1.2.3 From 90de0280db8e33d9e54a65639be6ec76510e4bb0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 16:24:09 -0500 Subject: gui.c: Require all keys to be released after the B, A or X button or the Touch Screen is pressed. This avoids bringing up, or exiting from, multiple menus if you happen to press something for longer than 1/5 second. The modification does not apply to the directional pad in all menus, or the L and R buttons in file selectors. --- source/nds/gui.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/nds/gui.c b/source/nds/gui.c index 7270891..f0671b0 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -836,6 +836,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) { case CURSOR_TOUCH: ds2_getrawInput(&inputdata); + wait_Allkey_release(0); // ___ 33 This screen has 6 possible rows. Touches // ___ 60 above or below these are ignored. // . . . (+27) @@ -1001,6 +1002,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) break; case CURSOR_SELECT: + wait_Allkey_release(0); //file selected if(selected_item_on_list + 1 <= num_files) { @@ -1040,6 +1042,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) case CURSOR_BACK: { + wait_Allkey_release(0); char *ext_pos; strcpy(filelist_info.current_path, default_dir_name); @@ -1057,6 +1060,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name) } case CURSOR_EXIT: + wait_Allkey_release(0); return_value = -1; repeat = 0; break; @@ -3672,6 +3676,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { case CURSOR_TOUCH: ds2_getrawInput(&inputdata); + wait_Allkey_release(0); /* Back button at the top of every menu but the main one */ if(current_menu != &main_menu && inputdata.x > 231 && inputdata.y <= 25) { @@ -4006,9 +4011,11 @@ u32 menu(u16 *screen, bool8 FirstInvocation) break; case CURSOR_EXIT: + wait_Allkey_release(0); break; case CURSOR_SELECT: + wait_Allkey_release(0); if(current_option->option_type & ACTION_TYPE) current_option->action_function(); else if(current_option->option_type & SUBMENU_TYPE) @@ -4016,6 +4023,7 @@ u32 menu(u16 *screen, bool8 FirstInvocation) break; case CURSOR_BACK: + wait_Allkey_release(0); if(current_menu != &main_menu) choose_menu(current_menu->options->sub_menu); else -- cgit v1.2.3 From 5e3426d0d26bb25810aca6593416ac0125ea6e8f Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Wed, 6 Feb 2013 19:07:39 -0500 Subject: Remove 320 KiB of memory allocations in APU emulation that were completely unused but constantly re-zeroed. Frees up 320 KiB for other uses, and saves ~4 milliseconds at emulator startup, when resetting the APU and when loading a new game. --- source/apu.cpp | 19 +------------------ source/apu.h | 2 -- source/nds/dma_adj.h | 3 +++ source/nds/entry.cpp | 1 - source/snes9x.h | 1 - 5 files changed, 4 insertions(+), 22 deletions(-) diff --git a/source/apu.cpp b/source/apu.cpp index d60cc75..769d2bc 100644 --- a/source/apu.cpp +++ b/source/apu.cpp @@ -116,18 +116,14 @@ void S9xTraceSoundDSP (const char *s, int i1 = 0, int i2 = 0, int i3 = 0, bool8 S9xInitAPU () { IAPU.RAM = (uint8 *) malloc (0x10000); - IAPU.ShadowRAM = (uint8 *) malloc (0x10000); - IAPU.CachedSamples = (uint8 *) malloc (0x40000); - if (!IAPU.RAM || !IAPU.ShadowRAM || !IAPU.CachedSamples) + if (!IAPU.RAM) { S9xDeinitAPU (); return (FALSE); } memset(IAPU.RAM, 0, 0x10000); - memset(IAPU.ShadowRAM, 0, 0x10000); - memset(IAPU.CachedSamples, 0, 0x40000); return (TRUE); } @@ -139,16 +135,6 @@ void S9xDeinitAPU () free ((char *) IAPU.RAM); IAPU.RAM = NULL; } - if (IAPU.ShadowRAM) - { - free ((char *) IAPU.ShadowRAM); - IAPU.ShadowRAM = NULL; - } - if (IAPU.CachedSamples) - { - free ((char *) IAPU.CachedSamples); - IAPU.CachedSamples = NULL; - } } EXTERN_C uint8 APUROM [64]; @@ -171,10 +157,7 @@ void S9xResetAPU () { memcpy(IAPU.RAM+(i<<8), IAPU.RAM, 0x100); } - - memcpy (IAPU.ShadowRAM, IAPU.RAM, 0x10000); - ZeroMemory (IAPU.CachedSamples, 0x40000); ZeroMemory (APU.OutPorts, 4); IAPU.DirectPage = IAPU.RAM; // memmove converted: Different mallocs [Neb] diff --git a/source/apu.h b/source/apu.h index 67b2525..b675dfd 100644 --- a/source/apu.h +++ b/source/apu.h @@ -104,8 +104,6 @@ struct SIAPU uint8 *WaitAddress1; uint8 *WaitAddress2; uint32 WaitCounter; - uint8 *ShadowRAM; - uint8 *CachedSamples; uint8 _Carry; uint8 _Zero; uint8 _Overflow; diff --git a/source/nds/dma_adj.h b/source/nds/dma_adj.h index 62b0098..dd4a6e4 100644 --- a/source/nds/dma_adj.h +++ b/source/nds/dma_adj.h @@ -8,7 +8,10 @@ extern "C" { #endif struct SPointerAdjustments { + /* These are used by the DSTWO-NDS side code. */ unsigned int GFXScreen; + + /* These are used by Snes9x. */ }; extern struct SPointerAdjustments PtrAdj; diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 723374c..ae52ff0 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -432,7 +432,6 @@ void init_sfc_setting(void) Settings.ShutdownMaster = TRUE; Settings.FrameTimePAL = 20000; Settings.FrameTimeNTSC = 16667; - Settings.DisableSampleCaching = FALSE; Settings.DisableMasterVolume = FALSE; Settings.Mouse = TRUE; Settings.SuperScope = TRUE; diff --git a/source/snes9x.h b/source/snes9x.h index 6c93855..2661923 100644 --- a/source/snes9x.h +++ b/source/snes9x.h @@ -341,7 +341,6 @@ struct SSettings{ int SoundMixInterval; bool8 SoundEnvelopeHeightReading; bool8 DisableSoundEcho; - bool8 DisableSampleCaching; bool8 DisableMasterVolume; bool8 SoundSync; bool8 InterpolatedSound; -- cgit v1.2.3 From 55895f01f73ba1b4fab7095fa5cb8cf7884846ed Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 02:38:45 -0500 Subject: De-interleave the ROM using DMA. This helps the more esoteric jumbo memory maps load faster. --- source/memmap.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++----- source/nds/dma_adj.h | 1 + 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/source/memmap.cpp b/source/memmap.cpp index 755f7a0..20110f9 100644 --- a/source/memmap.cpp +++ b/source/memmap.cpp @@ -113,6 +113,12 @@ #include "unzip/unzip.h" +#ifdef DS2_DMA +#include "ds2_cpu.h" +#include "ds2_dma.h" +#include "dma_adj.h" +#endif + #ifdef __W32_HEAP #include #endif @@ -414,7 +420,11 @@ bool8 CMemory::Init () RAM = (uint8 *) malloc (0x20000); SRAM = (uint8 *) malloc (0x20000); VRAM = (uint8 *) malloc (0x10000); +#ifdef DS2_DMA + ROM = (uint8 *) AlignedMalloc (MAX_ROM_SIZE + 0x200 + 0x8000, 32, &PtrAdj.ROM); +#else ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000); +#endif memset (RAM, 0, 0x20000); memset (SRAM, 0, 0x20000); memset (VRAM, 0, 0x10000); @@ -451,9 +461,9 @@ bool8 CMemory::Init () // Add 0x8000 to ROM image pointer to stop SuperFX code accessing // unallocated memory (can cause crash on some ports). - ROM += 0x8000; + ROM += 0x8000; // still 32-byte aligned - C4RAM = ROM + 0x400000 + 8192 * 8; + C4RAM = ROM + 0x400000 + 8192 * 8; // still 32-byte aligned ::ROM = ROM; ::SRAM = SRAM; ::RegRAM = FillRAM; @@ -468,7 +478,6 @@ bool8 CMemory::Init () SuperFX.pvRom = (uint8 *) ROM; #endif - // DS2 DMA notes: Can this be sped up with DMA from a block of zeroes? [Neb] ZeroMemory (IPPU.TileCache [TILE_2BIT], MAX_2BIT_TILES * 128); ZeroMemory (IPPU.TileCache [TILE_4BIT], MAX_4BIT_TILES * 128); ZeroMemory (IPPU.TileCache [TILE_8BIT], MAX_8BIT_TILES * 128); @@ -508,7 +517,11 @@ void CMemory::Deinit () if (ROM) { ROM -= 0x8000; +#ifdef DS2_RAM + AlignedFree ((char *) ROM, PtrAdj.ROM); +#else free ((char *) ROM); +#endif ROM = NULL; } @@ -642,9 +655,21 @@ again: ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) || (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score))) { +#ifdef DS2_DMA + __dcache_writeback_all(); + { + unsigned int i; + for (i = 0; i < TotalFileSize; i += 512) + { + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, Memory.ROM + i, Memory.ROM + i + 512, 512); + ds2_DMA_wait(2); + ds2_DMA_stop(2); + } + } +#else // memmove required: Overlapping addresses [Neb] - // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512); +#endif TotalFileSize -= 512; S9xMessage (S9X_INFO, S9X_HEADER_WARNING, "Try specifying the -nhd command line option if the game doesn't work\n"); @@ -653,7 +678,7 @@ again: orig_lo_score = lo_score = ScoreLoROM (FALSE); } - CalculatedSize = (TotalFileSize / 0x2000) * 0x2000; + CalculatedSize = TotalFileSize & ~0x1FFF; // round down to lower 0x2000 ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize); if(CalculatedSize >0x400000&& @@ -961,7 +986,20 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize) { // memmove required: Overlapping addresses [Neb] // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] +#ifdef DS2_DMA + __dcache_writeback_all(); + { + unsigned int i; + for (i = 0; i < calc_size; i += 512) + { + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, ptr + i, ptr + i + 512, 512); + ds2_DMA_wait(2); + ds2_DMA_stop(2); + } + } +#else memmove (ptr, ptr + 512, calc_size); +#endif HeaderCount++; FileSize -= 512; } @@ -1203,25 +1241,47 @@ void S9xDeinterleaveType2 (bool8 reset) ((i & 12) >> 2); } - // DS2 DMA notes: ROM needs to be 32-byte aligned [Neb] +#ifdef DS2_DMA + unsigned int TmpAdj; + uint8 *tmp = (uint8 *) AlignedMalloc (0x10000, 32, &TmpAdj); +#else uint8 *tmp = (uint8 *) malloc (0x10000); +#endif if (tmp) { +#ifdef DS2_DMA + __dcache_writeback_all(); +#endif for (i = 0; i < nblocks * 2; i++) { for (int j = i; j < nblocks * 2; j++) { if (blocks [j] == i) { +#ifdef DS2_DMA + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); + ds2_DMA_wait(2); + ds2_DMA_stop(2); + + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, &Memory.ROM [blocks [j] * 0x10000], + &Memory.ROM [blocks [i] * 0x10000], 0x10000); + ds2_DMA_wait(2); + ds2_DMA_stop(2); + + ds2_DMAcopy_32Byte (2 /* channel: emu internal */, &Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); + ds2_DMA_wait(2); + ds2_DMA_stop(2); +#else // memmove converted: Different mallocs [Neb] memcpy (tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); + // memmove converted: Different addresses, or identical if blocks[i] == blocks[j] [Neb] - // DS2 DMA notes: Don't do DMA at all if blocks[i] == blocks[j] [Neb] memcpy (&Memory.ROM [blocks [j] * 0x10000], &Memory.ROM [blocks [i] * 0x10000], 0x10000); // memmove converted: Different mallocs [Neb] memcpy (&Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); +#endif uint8 b = blocks [j]; blocks [j] = blocks [i]; blocks [i] = b; @@ -1633,7 +1693,6 @@ bool8 CMemory::LoadSRAM (const char *filename) { // S-RAM file has a header - remove it // memmove required: Overlapping addresses [Neb] - // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] memmove (::SRAM, ::SRAM + 512, size); } if (len == size + SRTC_SRAM_PAD) @@ -2573,12 +2632,24 @@ void CMemory::SuperFXROMMap () // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K // block is repeated twice in each 64K block. +#ifdef DS2_DMA + __dcache_writeback_all(); +#endif for (c = 0; c < 64; c++) { +#ifdef DS2_DMA + ds2_DMAcopy_32Byte(2 /* channel: emu internal */, &ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); + ds2_DMAcopy_32Byte(3 /* channel: emu internal 2 */, &ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); + ds2_DMA_wait(2); + ds2_DMA_wait(3); + ds2_DMA_stop(2); + ds2_DMA_stop(3); +#else // memmove converted: Different addresses [Neb] memcpy (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); // memmove converted: Different addresses [Neb] memcpy (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); +#endif } WriteProtectROM (); diff --git a/source/nds/dma_adj.h b/source/nds/dma_adj.h index dd4a6e4..3852f09 100644 --- a/source/nds/dma_adj.h +++ b/source/nds/dma_adj.h @@ -12,6 +12,7 @@ struct SPointerAdjustments { unsigned int GFXScreen; /* These are used by Snes9x. */ + unsigned int ROM; }; extern struct SPointerAdjustments PtrAdj; -- cgit v1.2.3 From ea8ff33951d53f0e71801052c540dcc1bd0f7f42 Mon Sep 17 00:00:00 2001 From: SignZ Date: Thu, 7 Feb 2013 04:56:34 -0500 Subject: EN: Added a German translation. DE: Deutsche Übersetzung hinzugefügt. --- CATSFC/system/language.msg | 209 +++++++++++++++++++++++++++++++++++++++++++++ source/nds/gui.c | 11 ++- source/nds/message.h | 7 +- 3 files changed, 221 insertions(+), 6 deletions(-) diff --git a/CATSFC/system/language.msg b/CATSFC/system/language.msg index de160aa..d6b67d8 100644 --- a/CATSFC/system/language.msg +++ b/CATSFC/system/language.msg @@ -648,3 +648,212 @@ Remettre tous les paramètres à zéro? Veuillez patienter... ENDFRENCH + +STARTGERMAN + +#MSG_MAIN_MENU_NEW_GAME +Neues Spiel +#MSG_MAIN_MENU_RETURN_TO_GAME +Zurück zum Spiel +#MSG_MAIN_MENU_RESET_GAME +Reset +#MSG_MAIN_MENU_VIDEO_AUDIO +Video & Audio +#MSG_MAIN_MENU_SAVED_STATES +Speicherstände +#MSG_MAIN_MENU_CHEATS +Cheats +#MSG_MAIN_MENU_TOOLS +Tools +#MSG_MAIN_MENU_OPTIONS +Optionen +#MSG_MAIN_MENU_EXIT +Beenden +#FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE +Flüssigkeit %s +#MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO +Bevorzuge flüssiges Video +#MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO +Bevorzuge flüssiges Audio +#FMT_VIDEO_ASPECT_RATIO +Bildformat %s +#FMT_VIDEO_FAST_FORWARD +Schnellvorlauf %s +#FMT_VIDEO_FRAME_SKIPPING +Frames übersp. %s +#FMT_AUDIO_SOUND +Musik %s +#FMT_SAVED_STATE_CREATE +Speicherstand erstellen %d +#FMT_SAVED_STATE_LOAD +Speicherstand laden %d +#MSG_SAVED_STATE_DELETE_GENERAL +Speicherstände löschen... +#FMT_CHEAT_PAGE +Cheatseite %d +#MSG_CHEAT_LOAD_FROM_FILE +Cheatdatei laden +#MSG_TOOLS_SCREENSHOT_GENERAL +Screenshots... +#MSG_TOOLS_GLOBAL_HOTKEY_GENERAL +Globale Hotkeys... +#MSG_TOOLS_GAME_HOTKEY_GENERAL +Spielspezifische Hotkeys... +#FMT_OPTIONS_LANGUAGE +Sprache %s +#FMT_OPTIONS_CPU_FREQUENCY +CPU Frequenz %s +#MSG_OPTIONS_CPU_FREQUENCY_0 +[0] 240 MHz +#MSG_OPTIONS_CPU_FREQUENCY_1 +[1] 300 MHz +#MSG_OPTIONS_CPU_FREQUENCY_2 +[2] 336 MHz +#MSG_OPTIONS_CPU_FREQUENCY_3 +[3] 360 MHz +#MSG_OPTIONS_CPU_FREQUENCY_4 +[4] 384 MHz +#MSG_OPTIONS_CPU_FREQUENCY_5 +[5] 396 MHz +#MSG_OPTIONS_CARD_CAPACITY +Kartengröße +#MSG_OPTIONS_RESET +Werkseinstellungen +#MSG_OPTIONS_VERSION +Versionsinformation +#MSG_SCREENSHOT_CREATE +Screenshot speichern +#MSG_SCREENSHOT_BROWSE +Screenshots durchsuchen +#MSG_HOTKEY_MAIN_MENU +Hauptmenü +#MSG_HOTKEY_TEMPORARY_FAST_FORWARD +Temp. Schnellvorlauf +#MSG_HOTKEY_SOUND_TOGGLE +Audio umschalten +#MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS +Knöpfe für dieses Ereignis drücken. +#MSG_HOTKEY_DELETE_WITH_A +*A Löschen +#MSG_HOTKEY_CANCEL_WITH_B +*B Abbrechen +#MSG_LOAD_GAME_RECENTLY_PLAYED +Zuletzt gespielt +#MSG_LOAD_GAME_FROM_CARD +Wähle ein Spiel von der Karte aus +#MSG_LOAD_GAME_MENU_TITLE +Wähle ein Spiel +#MSG_VIDEO_ASPECT_RATIO_0 +[0] Vollbild +#MSG_VIDEO_ASPECT_RATIO_1 +[1] Unten, quadratische Pixel +#MSG_VIDEO_ASPECT_RATIO_2 +[2] Oben, quadratische Pixel +#MSG_VIDEO_ASPECT_RATIO_3 +[3] Mitte, quadratische Pixel +#MSG_VIDEO_ASPECT_RATIO_4 +[4] Vollbild, geglättet +#MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC +[-] Automatisch +#MSG_VIDEO_FRAME_SKIPPING_0 +[0] Alle Frames anzeigen +#MSG_VIDEO_FRAME_SKIPPING_1 +[1] Zeige 1 von 2 Frames +#MSG_VIDEO_FRAME_SKIPPING_2 +[2] Zeige 1 von 3 Frames +#MSG_VIDEO_FRAME_SKIPPING_3 +[3] Zeige 1 von 4 Frames +#MSG_VIDEO_FRAME_SKIPPING_4 +[4] Zeige 1 von 5 Frames +#MSG_VIDEO_FRAME_SKIPPING_5 +[5] Zeige 1 von 6 Frames +#MSG_VIDEO_FRAME_SKIPPING_6 +[6] Zeige 1 von 7 Frames +#MSG_VIDEO_FRAME_SKIPPING_7 +[7] Zeige 1 von 8 Frames +#MSG_VIDEO_FRAME_SKIPPING_8 +[8] Zeige 1 von 9 Frames +#MSG_VIDEO_FRAME_SKIPPING_9 +[9] Zeige 1 von 10 Frames +#MSG_VIDEO_FRAME_SKIPPING_10 +[10] Zeige 1 von 11 Frames +#MSG_GENERAL_OFF +Aus +#MSG_GENERAL_ON +An +#MSG_GENERAL_CONFIRM_WITH_A +*A Bestätigen +#MSG_GENERAL_CANCEL_WITH_B +*B Abbrechen +#MSG_AUDIO_ENABLED +An +#MSG_AUDIO_MUTED +Stumm +#MSG_TOP_SCREEN_NO_GAME_LOADED +Kein Spiel geladen +#MSG_CHEAT_ELEMENT_NOT_LOADED + +#MSG_SAVESTATE_FULL +An dieser Stelle existiert bereits ein Speicherstand. Überschreiben? +#MSG_PROGRESS_SAVED_STATE_CREATING +Speichern... +#MSG_PROGRESS_SAVED_STATE_CREATION_FAILED +Fehlgeschlagen! +#MSG_PROGRESS_SAVED_STATE_CREATION_SUCCEEDED +OK! +#MSG_TOP_SCREEN_NO_SAVED_STATE_IN_SLOT +Kein Speicherstand +#MSG_PROGRESS_SAVED_STATE_CORRUPTED +Der Speicherstand ist nicht vorhanden oder kaputt. +#MSG_PROGRESS_SAVED_STATE_LOADING +Laden... +#MSG_PROGRESS_SAVED_STATE_LOAD_FAILED +Fehlgeschlagen! +#MSG_PROGRESS_SAVED_STATE_LOAD_SUCCEEDED +OK! +#MSG_SAVED_STATE_DELETE_ALL +Alle Speicherstände löschen +#FMT_SAVED_STATE_DELETE_ONE +Lösche Speicherstand %d +#MSG_DELETE_ALL_SAVESTATE_WARING +Wirklich alle Speicherstände löschen? +#FMT_DIALOG_SAVED_STATE_DELETE_ONE +Wirklich Speicherstand %d löschen? +#MSG_PROGRESS_SAVED_STATE_ALREADY_EMPTY +Hier ist bereits nichts. +#MSG_PROGRESS_SCREENSHOT_CREATING +Speichere Screenshot... +#MSG_PROGRESS_SCREENSHOT_CREATION_SUCCEEDED +OK! +#MSG_PROGRESS_SCREENSHOT_CREATION_FAILED +Fehlgeschlagen! +#MSG_NO_SLIDE +Keine Screenshots gefunden +#MSG_PLAYING_SLIDE +Zeigen... +#MSG_PAUSE_SLIDE +Pause... +#MSG_PLAY_SLIDE1 +Key UP Geschw. hoch +#MSG_PLAY_SLIDE2 +Key DOWN Geschw. runter +#MSG_PLAY_SLIDE3 +Key LEFT Voriges Bild +#MSG_PLAY_SLIDE4 +Key RIGHT Nächstes Bild +#MSG_PLAY_SLIDE5 +Key A Pause +#MSG_PLAY_SLIDE6 +Key B Zurück zum Menü +#MSG_PROGRESS_LOADING_GAME +Laden... +#MSG_EMULATOR_NAME +CATSFC SNES emulator +#MSG_WORD_EMULATOR_VERSION +Version +#MSG_DIALOG_RESET +Alle Einstellungen zurücksetzen? +#MSG_PROGRESS_RESETTING +Bitte warten... + +ENDGERMAN diff --git a/source/nds/gui.c b/source/nds/gui.c index f0671b0..190fcc9 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -50,14 +50,15 @@ char argv[2][MAX_PATH]; // If adding a language, make sure you update the size of the array in // message.h too. -char *lang[3] = +char *lang[4] = { "English", // 0 "简体中文", // 1 - "Français", // 2 + "Français", // 2 + "Deutsch", // 3 }; -char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lang[2] }; +char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lang[2], (char *) &lang[3] }; /****************************************************************************** * Macro definition @@ -4105,6 +4106,10 @@ int load_language_msg(char *filename, u32 language) strcpy(start, "STARTFRENCH"); strcpy(end, "ENDFRENCH"); break; + case GERMAN: + strcpy(start, "STARTGERMAN"); + strcpy(end, "ENDGERMAN"); + break; } u32 cmplen = strlen(start); diff --git a/source/nds/message.h b/source/nds/message.h index c7e79b8..538bc3b 100644 --- a/source/nds/message.h +++ b/source/nds/message.h @@ -145,13 +145,14 @@ enum MSG enum LANGUAGE { ENGLISH, CHINESE_SIMPLIFIED, - FRENCH + FRENCH, + GERMAN }; -extern char* lang[3]; // Allocated in gui.c, needs to match the languages ^ +extern char* lang[4]; // Allocated in gui.c, needs to match the languages ^ char *msg[MSG_END+1]; -char msg_data[16 * 1024]; +char msg_data[32 * 1024]; #endif //__MESSAGE_H__ -- cgit v1.2.3 From 07b9c9e8c1f4cdbb94ac9c1bd7c8272fab7d5f21 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 17:33:04 -0500 Subject: README.md: Add more recent information about frame skipping and fluidity. --- README.md | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5fb7351..d205989 100644 --- a/README.md +++ b/README.md @@ -84,19 +84,24 @@ menu's "Load a cheat file" option. In the Video & audio menu, the **Frame skipping** option allows you to select a number of frames to skip between rendered frames. -* Setting this to 0 will show every single frame, but this will slow down the - game considerably, as the DSTWO would only have enough processing power to - emulate **and** render a few frames per second. It has enough power to - emulate all frames and render **some**, though. + +As of version 1.29, the default is - (Keep up with the game). For most games, +this setting keeps video and audio fluid, without the sudden slowdowns of +previous versions when many sprites fill the screen. The DS controller buttons +are also responsive at this setting. + +For some games, you may need to adjust frame skipping. +* If a game runs at 5 frames per second, like *Yoshi's Island*, + *Kirby Super Star*, *Star Fox* or *Super Mario RPG*, setting frame skipping + to 1 will allow you to jump, move or shoot at the right times. +* If you want to show more frames per second in a game that already shows 20, + setting frame skipping to 1 or 0 will cause more frames to appear, + but your DS button input may stop responding for 2 entire seconds every so + often. The audio will also be stretched. (This is similar to NDSGBA.) * Setting this to 10 will skip 10 frames and render one, but this will severely desynchronise the audio. You will also find yourself unable to - perform actions during the correct frame with the controller. -* Setting this to - (Keep up with the game) will make the emulator try to - render the game at its correct speed, dropping frames as needed (up to 8). - -It is recommended to start with frame skipping 4 (Show 1 frame every 5) and -go to 3 or 2 if the game doesn't run with major slowdowns with them. If you -don't like the slowdowns, return to frame skipping 4 or -. + perform actions during the correct frame with the DS buttons. It is advised + to set frame skipping to the lowest value with which you can play a game. # Fluidity @@ -105,12 +110,13 @@ By default, video fluidity is preferred over audio fluidity in games. * Preferring video fluidity makes audio skip certain notes, up to 23 milliseconds, in order to render more video. In many games, this - difference is not audible. - Use this option if you want to play games that require precise controls or - fluid imagery more than precise audio emulation. You can also use this option - when watching game introductions, endings and cutscenes. + difference is not audible, but you may hear certain audio glitches if a game + depends highly on timing for its audio. + Use this option if you want to play games that require fluid imagery more + than precise audio emulation. You can also use this option when watching game + introductions, endings and cutscenes. * Preferring audio fluidity makes video skip certain images, up to - 166 milliseconds, in order to render audio closer to 32,000 times per second. + 46 milliseconds, in order to render audio closer to 32,000 times per second. Use this option if you want to play games mainly for their soundtracks, or in a game's sound test mode. You can also use this option to experiment with the green berry glitch in Super Mario World that makes TIME go over and under 100 -- cgit v1.2.3 From 635c87890530777a2e7b2f4c45a72f8f51c7d5f0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 17:58:37 -0500 Subject: Allow the user to be pressing a button when the emulator starts. This allows the Loading screen to disappear, and allows invoking New Game straight away. --- source/nds/gui.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/nds/gui.c b/source/nds/gui.c index 190fcc9..4299db2 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -3535,9 +3535,10 @@ u32 menu(u16 *screen, bool8 FirstInvocation) { // assume that the backlight is already at 3 when the emulator starts mdelay(100); // to prevent ds2_setBacklight() from crashing ds2_setBacklight(3); + // also allow the user to press A for New Game right away + wait_Allkey_release(0); } - wait_Allkey_release(0); bg_screenp= (u16*)malloc(256*192*2); repeat = 1; -- cgit v1.2.3 From 5680258a6a7d8f59649de6a2aad490b4e15054b0 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 18:47:15 -0500 Subject: Stop inlining the regular tile drawing code. That was a micro-optimisation, and this revert brings the code a bit closer to mainline Snes9x. --- source/tile.cpp | 65 +-------------------------------------------------------- 1 file changed, 1 insertion(+), 64 deletions(-) diff --git a/source/tile.cpp b/source/tile.cpp index 653a6d7..87d1fac 100644 --- a/source/tile.cpp +++ b/source/tile.cpp @@ -589,71 +589,8 @@ void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, { TILE_PREAMBLE register uint8 *bp; - uint8 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - switch (Tile & (H_FLIP | V_FLIP)) - { - case 0: - bp = pCache + StartLine; - for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL) - { - for (uint8 N = 0; N < 8; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = bp[N])) - { - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } - } - break; - case H_FLIP: - bp = pCache + StartLine; - for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL) - { - for (uint8 N = 0; N < 8; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N])) - { - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } - } - break; - case H_FLIP | V_FLIP: - bp = pCache + 56 - StartLine; - for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL) - { - for (uint8 N = 0; N < 8; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N])) - { - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } - } - break; - case V_FLIP: - bp = pCache + 56 - StartLine; - for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL) - { - for (uint8 N = 0; N < 8; N++) - { - if (GFX.Z1 > Depth [N] && (Pixel = bp[N])) - { - Screen [N] = ScreenColors [Pixel]; - Depth [N] = GFX.Z2; - } - } - } - break; - default: - break; - } + RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4) } void DrawClippedTile16 (uint32 Tile, uint32 Offset, -- cgit v1.2.3 From 703d522c4c9ef83dda0bd386a6c5ac8870a8df50 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 20:08:44 -0500 Subject: Remove remnants of a failed auto-CPU implementation. Changing CPU speeds on-the-fly is just not stable on the DSTwo. --- source/nds/entry.cpp | 62 +--------------------------------------------------- 1 file changed, 1 insertion(+), 61 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index ae52ff0..d82ed85 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -641,26 +641,6 @@ static unsigned int sync_next = 0; static unsigned int skip_rate= 0; -/* - * Automatic CPU frequency support is here. - * Whenever, after one downclock determination interval, each frame rendered - * during it has been rendered at least as early as CPU_DOWNCLOCK_EARLY_TIME, - * lower the CPU frequency in response. - * If at least one frame has been early, but not early enough, the CPU - * frequency stays stable. - * If at least one frame has been late, the CPU will have be switched back - * to 396 MHz. - * This improves battery life to a certain extent. - */ - -#define CPU_DOWNCLOCK_EARLY_TIME 293 /* 1 = 42.667 us. 391 = 16.67 ms */ -#define CPU_DOWNCLOCK_DETERMINATION_INTERVAL 46874 /* 23437 = 1 s */ - -static unsigned int LastAutoCPUTime = 0; -unsigned int AutoCPUFrequency = 5; -static bool8 ConsistentlyEarly = FALSE; -static bool8 FastForwardLastFrame = FALSE; - void S9xSyncSpeed () { uint32 syncnow; @@ -679,17 +659,8 @@ void S9xSyncSpeed () bool8 FastForward = game_fast_forward || temporary_fast_forward /* hotkey is held */; - if (game_config.clock_speed_number == 0) - if (FastForward && !FastForwardLastFrame) - HighFrequencyCPU (); - else if (!FastForward && FastForwardLastFrame) - GameFrequencyCPU (); - - FastForwardLastFrame = FastForward; - if (FastForward) { - ConsistentlyEarly = FALSE; // don't use fast-forward to lower CPU sync_last = syncnow; sync_next = syncnow; @@ -712,14 +683,10 @@ void S9xSyncSpeed () { // Render this frame regardless, set the // sync_next, and get the hell out. - ConsistentlyEarly = FALSE; - AutoCPUFrequency = 5; - LastAutoCPUTime = syncnow; - IPPU.RenderThisFrame = TRUE; sync_last = syncnow; sync_next = syncnow + frame_time; - goto finalise; + return; } sync_last = syncnow; // If this is positive, we have syncdif*42.66 microseconds to @@ -738,10 +705,6 @@ void S9xSyncSpeed () } else if(syncdif < 0) { - ConsistentlyEarly = FALSE; - AutoCPUFrequency = 5; - LastAutoCPUTime = syncnow; - /* * If we're consistently late, delay up to 8 frames. * @@ -770,7 +733,6 @@ void S9xSyncSpeed () } else // Early { - ConsistentlyEarly = ConsistentlyEarly && syncdif >= CPU_DOWNCLOCK_EARLY_TIME; skip_rate = 0; if (syncdif > 0) { @@ -815,7 +777,6 @@ void S9xSyncSpeed () syncdif = sync_next - syncnow; if (syncdif > 0) { - ConsistentlyEarly = ConsistentlyEarly && syncdif >= CPU_DOWNCLOCK_EARLY_TIME; do { S9xProcessSound (0); #ifdef ACCUMULATE_JOYPAD @@ -831,13 +792,6 @@ void S9xSyncSpeed () // After that little delay, what time is it? syncnow = getSysTime(); } - else - { - // Nope, we're late. - ConsistentlyEarly = FALSE; - AutoCPUFrequency = 5; - LastAutoCPUTime = syncnow; - } sync_next = syncnow + frame_time * (Settings.SkipFrames + 1); } else @@ -930,20 +884,6 @@ void S9xSyncSpeed () next1.tv_usec %= 1000000; } #endif - -finalise: ; - - if (syncnow - LastAutoCPUTime >= CPU_DOWNCLOCK_DETERMINATION_INTERVAL) { - if (ConsistentlyEarly && AutoCPUFrequency > 0) - AutoCPUFrequency--; - - LastAutoCPUTime = syncnow; - ConsistentlyEarly = TRUE; - // will get unset if the CPU should stay the same at next check - } - - if (game_config.clock_speed_number == 0 && LastAutoCPUFrequency != AutoCPUFrequency) - GameFrequencyCPU (); } bool8 S9xOpenSoundDevice (int mode, bool8 stereo, int buffer_size) -- cgit v1.2.3 From 4676a520e1b181e5891550331100b2629d7cbd7f Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Thu, 7 Feb 2013 22:27:44 -0500 Subject: Synchronise fractions of a hertz correctly in the audio output timing code to avoid buffer overruns. Buffer overruns pause the game for about half a second. --- source/nds/entry.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index d82ed85..af832f9 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -981,8 +981,20 @@ void S9xGenerateSound () } } -#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128) - 1) /* -1 is for roundoff errors */ -unsigned int LastSoundEmissionTime = 0; +#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)) +#define TRUE_SOUND_EMISSION_INTERVAL ((((double) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128) +#define SOUND_EMISSION_INTERVAL_ERROR ((int) ((TRUE_SOUND_EMISSION_INTERVAL - SOUND_EMISSION_INTERVAL) * FIXED_POINT)) +static unsigned int LastSoundEmissionTime = 0; + +/* + * Accumulated error in the sound emission time. The unit is as follows: + * FIXED_POINT = 42.667 microseconds. + * As the error goes past FIXED_POINT, the new target for sound emission + * becomes 42.667 microseconds LATER. This helps with sound buffer overruns, + * correctly dealing with the fact that 42.667 microseconds does not fit + * an integer number of times in 1/32000 second (or whatever sampling rate). + */ +static unsigned int SoundEmissionTimeError = 0; void S9xProcessSound (unsigned int) { @@ -1009,6 +1021,12 @@ void S9xProcessSound (unsigned int) else { LastSoundEmissionTime += SOUND_EMISSION_INTERVAL; + SoundEmissionTimeError += SOUND_EMISSION_INTERVAL_ERROR; + if (SoundEmissionTimeError > FIXED_POINT) + { + LastSoundEmissionTime += SoundEmissionTimeError >> FIXED_POINT_SHIFT; + SoundEmissionTimeError &= FIXED_POINT_REMAINDER; + } } /* Number of samples to generate now */ int sample_count = so.buffer_size; -- cgit v1.2.3 From d4fcf2697c9a45594e3ee0b8bf82e480ddd0b69b Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 8 Feb 2013 03:22:27 -0500 Subject: Require one audio buffer to be free again. Otherwise, if the 4 buffers get full, it's already game over, and getAudiobuff becomes NULL for about 400 milliseconds, stopping all emulation. --- source/nds/entry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index af832f9..77620bf 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -1004,7 +1004,7 @@ void S9xProcessSound (unsigned int) unsigned int Now = getSysTime(); if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL) { - if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT) + if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT - 1) { LastSoundEmissionTime++; return; @@ -1022,7 +1022,7 @@ void S9xProcessSound (unsigned int) { LastSoundEmissionTime += SOUND_EMISSION_INTERVAL; SoundEmissionTimeError += SOUND_EMISSION_INTERVAL_ERROR; - if (SoundEmissionTimeError > FIXED_POINT) + if (SoundEmissionTimeError >= FIXED_POINT) { LastSoundEmissionTime += SoundEmissionTimeError >> FIXED_POINT_SHIFT; SoundEmissionTimeError &= FIXED_POINT_REMAINDER; -- cgit v1.2.3