1
0
Fork 0
forked from len0rd/rockbox

codec: sid: add cRSID-1.0 for 21st century SID playback

Plain import of the library parts first. Adaptions to Rockbox will
follow. A *lot* of kudos go to Mihaly Horvath for creating this library
from his already lightweight cSID-light, mainly for Rockbox. Besides a
lot of other things, he made his algorithms integer-only and
significantly improved the C64 emulation, so finally RSIDs could be
played as well as PSIDs. TinySID was nice for what it is, but this is a
quantum leap in SID playback quality for Rockbox. Check for example:

https://hvsc.csdb.dk/MUSICIANS/P/Page_Jason/Eighth.sid
https://hvsc.csdb.dk/MUSICIANS/J/Jeff/Blowing.sid

Change-Id: I353e12fbfd7cd8696b834616e55743e7b844a73e
This commit is contained in:
Wolfram Sang 2022-03-04 18:37:30 +01:00 committed by Solomon Peachy
parent 1c26f565bf
commit e8135fea5a
12 changed files with 2525 additions and 0 deletions

View file

@ -0,0 +1,197 @@
//C64 emulation (SID-playback related)
#include "../libcRSID.h"
#include "MEM.c"
#include "CPU.c"
#include "CIA.c"
#include "VIC.c"
#include "SID.c"
cRSID_C64instance* cRSID_createC64 (cRSID_C64instance* C64, unsigned short samplerate) { //init a basic PAL C64 instance
if(samplerate) C64->SampleRate = samplerate;
else C64->SampleRate = samplerate = 44100;
C64->SampleClockRatio = (985248<<4)/samplerate; //shifting (multiplication) enhances SampleClockRatio precision
C64->Attenuation = 26;
C64->CPU.C64 = C64;
cRSID_createSIDchip ( C64, &C64->SID[1], 8580, 0xD400 ); //default C64 setup with only 1 SID and 2 CIAs and 1 VIC
cRSID_createCIAchip ( C64, &C64->CIA[1], 0xDC00 );
cRSID_createCIAchip ( C64, &C64->CIA[2], 0xDD00 );
cRSID_createVICchip ( C64, &C64->VIC, 0xD000 );
//if(C64->RealSIDmode) {
cRSID_setROMcontent ( C64 );
//}
cRSID_initC64(C64);
return C64;
}
void cRSID_setC64 (cRSID_C64instance* C64) { //set hardware-parameters (Models, SIDs) for playback of loaded SID-tune
enum C64clocks { C64_PAL_CPUCLK=985248, C64_NTSC_CPUCLK=1022727 };
enum C64scanlines { C64_PAL_SCANLINES = 312, C64_NTSC_SCANLINES = 263 };
enum C64scanlineCycles { C64_PAL_SCANLINE_CYCLES = 63, C64_NTSC_SCANLINE_CYCLES = 65 };
//enum C64framerates { PAL_FRAMERATE = 50, NTSC_FRAMERATE = 60 }; //Hz
static const unsigned int CPUspeeds[] = { C64_NTSC_CPUCLK, C64_PAL_CPUCLK };
static const unsigned short ScanLines[] = { C64_NTSC_SCANLINES, C64_PAL_SCANLINES };
static const unsigned char ScanLineCycles[] = { C64_NTSC_SCANLINE_CYCLES, C64_PAL_SCANLINE_CYCLES };
//unsigned char FrameRates[] = { NTSC_FRAMERATE, PAL_FRAMERATE };
static const short Attenuations[]={0,26,43,137}; //increase for 2SID (to 43) and 3SID (to 137)
short SIDmodel;
unsigned char SIDchipCount;
C64->VideoStandard = ( (C64->SIDheader->ModelFormatStandard & 0x0C) >> 2 ) != 2;
if (C64->SampleRate==0) C64->SampleRate = 44100;
C64->CPUfrequency = CPUspeeds[C64->VideoStandard];
C64->SampleClockRatio = ( C64->CPUfrequency << 4 ) / C64->SampleRate; //shifting (multiplication) enhances SampleClockRatio precision
C64->VIC.RasterLines = ScanLines[C64->VideoStandard];
C64->VIC.RasterRowCycles = ScanLineCycles[C64->VideoStandard];
C64->FrameCycles = C64->VIC.RasterLines * C64->VIC.RasterRowCycles; ///C64->SampleRate / PAL_FRAMERATE; //1x speed tune with VIC Vertical-blank timing
C64->PrevRasterLine=-1; //so if $d012 is set once only don't disturb FrameCycleCnt
C64->SID[1].ChipModel = (C64->SIDheader->ModelFormatStandard&0x30) >= 0x20? 8580:6581;
SIDmodel = C64->SIDheader->ModelFormatStandard & 0xC0;
if (SIDmodel) SIDmodel = (SIDmodel >= 0x80) ? 8580:6581; else SIDmodel = C64->SID[1].ChipModel;
cRSID_createSIDchip ( C64, &C64->SID[2], SIDmodel, 0xD000 + C64->SIDheader->SID2baseAddress*16 );
SIDmodel = C64->SIDheader->ModelFormatStandardH & 0x03;
if (SIDmodel) SIDmodel = (SIDmodel >= 0x02) ? 8580:6581; else SIDmodel = C64->SID[1].ChipModel;
cRSID_createSIDchip ( C64, &C64->SID[3], SIDmodel, 0xD000 + C64->SIDheader->SID3baseAddress*16 );
SIDchipCount = 1 + (C64->SID[2].BaseAddress > 0) + (C64->SID[3].BaseAddress > 0);
C64->Attenuation = Attenuations[SIDchipCount];
}
void cRSID_initC64 (cRSID_C64instance* C64) { //C64 Reset
cRSID_initSIDchip( &C64->SID[1] );
cRSID_initCIAchip( &C64->CIA[1] ); cRSID_initCIAchip( &C64->CIA[2] );
cRSID_initMem(C64);
cRSID_initCPU( &C64->CPU, (cRSID_readMemC64(C64,0xFFFD)<<8) + cRSID_readMemC64(C64,0xFFFC) );
C64->IRQ = C64->NMI = 0;
}
int cRSID_emulateC64 (cRSID_C64instance *C64) {
static unsigned char InstructionCycles;
static int Output;
//Cycle-based part of emulations:
while (C64->SampleCycleCnt <= C64->SampleClockRatio) {
if (!C64->RealSIDmode) {
if (C64->FrameCycleCnt >= C64->FrameCycles) {
C64->FrameCycleCnt -= C64->FrameCycles;
if (C64->Finished) { //some tunes (e.g. Barbarian, A-Maze-Ing) doesn't always finish in 1 frame
cRSID_initCPU ( &C64->CPU, C64->PlayAddress ); //(PSID docs say bank-register should always be set for each call's region)
C64->Finished=0; //C64->SampleCycleCnt=0; //PSID workaround for some tunes (e.g. Galdrumway):
if (C64->TimerSource==0) C64->IObankRD[0xD019] = 0x81; //always simulate to player-calls that VIC-IRQ happened
else C64->IObankRD[0xDC0D] = 0x83; //always simulate to player-calls that CIA TIMERA/TIMERB-IRQ happened
}}
if (C64->Finished==0) {
if ( (InstructionCycles = cRSID_emulateCPU()) >= 0xFE ) { InstructionCycles=6; C64->Finished=1; }
}
else InstructionCycles=7; //idle between player-calls
C64->FrameCycleCnt += InstructionCycles;
C64->IObankRD[0xDC04] += InstructionCycles; //very simple CIA1 TimerA simulation for PSID (e.g. Delta-Mix_E-Load_loader)
}
else { //RealSID emulations:
if ( cRSID_handleCPUinterrupts(&C64->CPU) ) { C64->Finished=0; InstructionCycles=7; }
else if (C64->Finished==0) {
if ( (InstructionCycles = cRSID_emulateCPU()) >= 0xFE ) {
InstructionCycles=6; C64->Finished=1;
}
}
else InstructionCycles=7; //idle between IRQ-calls
C64->IRQ = C64->NMI = 0; //prepare for collecting IRQ sources
C64->IRQ |= cRSID_emulateCIA (&C64->CIA[1], InstructionCycles);
C64->NMI |= cRSID_emulateCIA (&C64->CIA[2], InstructionCycles);
C64->IRQ |= cRSID_emulateVIC (&C64->VIC, InstructionCycles);
}
C64->SampleCycleCnt += (InstructionCycles<<4);
cRSID_emulateADSRs (&C64->SID[1], InstructionCycles);
if ( C64->SID[2].BaseAddress != 0 ) cRSID_emulateADSRs (&C64->SID[2], InstructionCycles);
if ( C64->SID[3].BaseAddress != 0 ) cRSID_emulateADSRs (&C64->SID[3], InstructionCycles);
}
C64->SampleCycleCnt -= C64->SampleClockRatio;
//Samplerate-based part of emulations:
if (!C64->RealSIDmode) { //some PSID tunes use CIA TOD-clock (e.g. Kawasaki Synthesizer Demo)
--C64->TenthSecondCnt;
if (C64->TenthSecondCnt <= 0) {
C64->TenthSecondCnt = C64->SampleRate / 10;
++(C64->IObankRD[0xDC08]);
if(C64->IObankRD[0xDC08]>=10) {
C64->IObankRD[0xDC08]=0; ++(C64->IObankRD[0xDC09]);
//if(C64->IObankRD[0xDC09]%
}
}
}
Output = cRSID_emulateWaves (&C64->SID[1]);
if ( C64->SID[2].BaseAddress != 0 ) Output += cRSID_emulateWaves (&C64->SID[2]);
if ( C64->SID[3].BaseAddress != 0 ) Output += cRSID_emulateWaves (&C64->SID[3]);
return Output;
}
static inline short cRSID_playPSIDdigi(cRSID_C64instance* C64) {
enum PSIDdigiSpecs { DIGI_VOLUME = 1200 }; //80 };
static unsigned char PlaybackEnabled=0, NybbleCounter=0, RepeatCounter=0, Shifts;
static unsigned short SampleAddress, RatePeriod;
static short Output=0;
static int PeriodCounter;
if (C64->IObankWR[0xD41D]) {
PlaybackEnabled = (C64->IObankWR[0xD41D] >= 0xFE);
PeriodCounter = 0; NybbleCounter = 0;
SampleAddress = C64->IObankWR[0xD41E] + (C64->IObankWR[0xD41F]<<8);
RepeatCounter = C64->IObankWR[0xD43F];
}
C64->IObankWR[0xD41D] = 0;
if (PlaybackEnabled) {
RatePeriod = C64->IObankWR[0xD45D] + (C64->IObankWR[0xD45E]<<8);
if (RatePeriod) PeriodCounter += C64->CPUfrequency / RatePeriod;
if ( PeriodCounter >= C64->SampleRate ) {
PeriodCounter -= C64->SampleRate;
if ( SampleAddress < C64->IObankWR[0xD43D] + (C64->IObankWR[0xD43E]<<8) ) {
if (NybbleCounter) {
Shifts = C64->IObankWR[0xD47D] ? 4:0;
++SampleAddress;
}
else Shifts = C64->IObankWR[0xD47D] ? 0:4;
Output = ( ( (C64->RAMbank[SampleAddress]>>Shifts) & 0xF) - 8 ) * DIGI_VOLUME; //* (C64->IObankWR[0xD418]&0xF);
NybbleCounter^=1;
}
else if (RepeatCounter) {
SampleAddress = C64->IObankWR[0xD47F] + (C64->IObankWR[0xD47E]<<8);
RepeatCounter--;
}
}
}
return Output;
}

View file

@ -0,0 +1,93 @@
//cRSID CIA emulation
void cRSID_createCIAchip (cRSID_C64instance* C64, cRSID_CIAinstance* CIA, unsigned short baseaddress) {
CIA->C64 = C64;
CIA->ChipModel = 0;
CIA->BaseAddress = baseaddress;
CIA->BasePtrWR = &C64->IObankWR[baseaddress]; CIA->BasePtrRD = &C64->IObankRD[baseaddress];
cRSID_initCIAchip(CIA);
}
void cRSID_initCIAchip (cRSID_CIAinstance* CIA) {
unsigned char i;
for (i=0; i<0x10; ++i) CIA->BasePtrWR[i] = CIA->BasePtrRD[i] = 0x00;
}
static inline char cRSID_emulateCIA (cRSID_CIAinstance* CIA, char cycles) {
static int Tmp;
enum CIAregisters { PORTA=0, PORTB=1, DDRA=2, DDRB=3,
TIMERAL=4, TIMERAH=5, TIMERBL=6, TIMERBH=7, //Write:Set Timer-latch, Read: read Timer
TOD_TENTHSECONDS=8, TOD_SECONDS=9, TOD_MINUTES=0xA, TOD_HOURS=0xB,
SERIAL_DATA=0xC, INTERRUPTS=0xD, CONTROLA=0xE, CONTROLB=0xF };
enum InterruptBitVal { INTERRUPT_HAPPENED=0x80, SET_OR_CLEAR_FLAGS=0x80, //(Read or Write operation determines which one:)
FLAGn=0x10, SERIALPORT=0x08, ALARM=0x04, TIMERB=0x02, TIMERA=0x01 }; //flags/masks of interrupt-sources
enum ControlAbitVal { ENABLE_TIMERA=0x01, PORTB6_TIMERA=0x02, TOGGLED_PORTB6=0x04, ONESHOT_TIMERA=0x08,
FORCELOADA_STROBE=0x10, TIMERA_FROM_CNT=0x20, SERIALPORT_IS_OUTPUT=0x40, TIMEOFDAY_50Hz=0x80 };
enum ControlBbitVal { ENABLE_TIMERB=0x01, PORTB7_TIMERB=0x02, TOGGLED_PORTB7=0x04, ONESHOT_TIMERB=0x08,
FORCELOADB_STROBE=0x10, TIMERB_FROM_CPUCLK=0x00, TIMERB_FROM_CNT=0x20, TIMERB_FROM_TIMERA=0x40,
TIMERB_FROM_TIMERA_AND_CNT = 0x60, TIMEOFDAY_WRITE_SETS_ALARM = 0x80 };
//TimerA
if (CIA->BasePtrWR[CONTROLA] & FORCELOADA_STROBE) { //force latch into counter (strobe-input)
CIA->BasePtrRD[TIMERAH] = CIA->BasePtrWR[TIMERAH]; CIA->BasePtrRD[TIMERAL] = CIA->BasePtrWR[TIMERAL];
}
else if ( (CIA->BasePtrWR[CONTROLA] & (ENABLE_TIMERA|TIMERA_FROM_CNT)) == ENABLE_TIMERA ) { //Enabled, counts Phi2
Tmp = ( (CIA->BasePtrRD[TIMERAH]<<8) + CIA->BasePtrRD[TIMERAL] ) - cycles; //count timer
if (Tmp <= 0) { //Timer counted down
Tmp += (CIA->BasePtrWR[TIMERAH]<<8) + CIA->BasePtrWR[TIMERAL]; //reload timer
if (CIA->BasePtrWR[CONTROLA] & ONESHOT_TIMERA) CIA->BasePtrWR[CONTROLA] &= ~ENABLE_TIMERA; //disable if one-shot
CIA->BasePtrRD[INTERRUPTS] |= TIMERA;
if (CIA->BasePtrWR[INTERRUPTS] & TIMERA) { //generate interrupt if mask allows
CIA->BasePtrRD[INTERRUPTS] |= INTERRUPT_HAPPENED;
}
}
CIA->BasePtrRD[TIMERAH] = (Tmp >> 8); CIA->BasePtrRD[TIMERAL] = Tmp & 0xFF;
}
CIA->BasePtrWR[CONTROLA] &= ~FORCELOADA_STROBE; //strobe is edge-sensitive
CIA->BasePtrRD[CONTROLA] = CIA->BasePtrWR[CONTROLA]; //control-registers are readable
//TimerB
if (CIA->BasePtrWR[CONTROLB] & FORCELOADB_STROBE) { //force latch into counter (strobe-input)
CIA->BasePtrRD[TIMERBH] = CIA->BasePtrWR[TIMERBH]; CIA->BasePtrRD[TIMERBL] = CIA->BasePtrWR[TIMERBL];
} //what about clocking TimerB by TimerA? (maybe not used in any music)
else if ( (CIA->BasePtrWR[CONTROLB] & (ENABLE_TIMERB|TIMERB_FROM_TIMERA)) == ENABLE_TIMERB ) { //Enabled, counts Phi2
Tmp = ( (CIA->BasePtrRD[TIMERBH]<<8) + CIA->BasePtrRD[TIMERBL] ) - cycles;//count timer
if (Tmp <= 0) { //Timer counted down
Tmp += (CIA->BasePtrWR[TIMERBH]<<8) + CIA->BasePtrWR[TIMERBL]; //reload timer
if (CIA->BasePtrWR[CONTROLB] & ONESHOT_TIMERB) CIA->BasePtrWR[CONTROLB] &= ~ENABLE_TIMERB; //disable if one-shot
CIA->BasePtrRD[INTERRUPTS] |= TIMERB;
if (CIA->BasePtrWR[INTERRUPTS] & TIMERB) { //generate interrupt if mask allows
CIA->BasePtrRD[INTERRUPTS] |= INTERRUPT_HAPPENED;
}
}
CIA->BasePtrRD[TIMERBH] = (Tmp >> 8); CIA->BasePtrRD[TIMERBL] = Tmp & 0xFF;
}
CIA->BasePtrWR[CONTROLB] &= ~FORCELOADB_STROBE; //strobe is edge-sensitive
CIA->BasePtrRD[CONTROLB] = CIA->BasePtrWR[CONTROLB]; //control-registers are readable
return (CIA->BasePtrRD[INTERRUPTS] & INTERRUPT_HAPPENED);
}
static inline void cRSID_writeCIAIRQmask (cRSID_CIAinstance* CIA, unsigned char value) {
if (value&0x80) CIA->BasePtrWR[0xD] |= (value&0x1F);
else CIA->BasePtrWR[0xD] &= ~(value&0x1F);
}
static inline void cRSID_acknowledgeCIAIRQ (cRSID_CIAinstance* CIA) {
CIA->BasePtrRD[0xD] = 0x00; //reading a CIA interrupt-register clears its read-part and IRQ-flag
}
//static inline void cRSID_writeCIARWreg () {
//mirroring write-latch to read-latch for Readable-Writeable registers?
//}

View file

@ -0,0 +1,423 @@
//cRSID CPU-emulation
void cRSID_initCPU (cRSID_CPUinstance* CPU, unsigned short mempos) {
CPU->PC = mempos; CPU->A = 0; CPU->X = 0; CPU->Y = 0; CPU->ST = 0x04; CPU->SP = 0xFF; CPU->PrevNMI = 0;
}
unsigned char cRSID_emulateCPU (void) { //the CPU emulation for SID/PRG playback (ToDo: CIA/VIC-IRQ/NMI/RESET vectors, BCD-mode)
enum StatusFlagBitValues { N=0x80, V=0x40, B=0x10, D=0x08, I=0x04, Z=0x02, C=0x01 };
static const unsigned char FlagSwitches[]={0x01,0x21,0x04,0x24,0x00,0x40,0x08,0x28}, BranchFlags[]={0x80,0x40,0x01,0x02};
static cRSID_C64instance* const C64 = &cRSID_C64; //could be a parameter but function-call is faster this way if only 1 main CPU exists
static cRSID_CPUinstance* const CPU = &C64->CPU;
static char Cycles, SamePage;
static unsigned char IR, ST, X, Y;
static short int A, SP, T;
static unsigned int PC, Addr, PrevPC;
inline void loadReg (void) { PC = CPU->PC; SP = CPU->SP; ST = CPU->ST; A = CPU->A; X = CPU->X; Y = CPU->Y; }
inline void storeReg (void) { CPU->PC = PC; CPU->SP = SP; CPU->ST = ST; CPU->A = A; CPU->X = X; CPU->Y = Y; }
inline unsigned char rd (register unsigned short address) {
static unsigned char value;
value = *cRSID_getMemReadPtr(address);
if (C64->RealSIDmode) {
if ( C64->RAMbank[1] & 3 ) {
if (address==0xDC0D) { cRSID_acknowledgeCIAIRQ( &C64->CIA[1] ); }
else if (address==0xDD0D) { cRSID_acknowledgeCIAIRQ( &C64->CIA[2] ); }
}
}
return value;
}
inline void wr (register unsigned short address, register unsigned char data) {
*cRSID_getMemWritePtr(address)=data;
if ( C64->RealSIDmode && (C64->RAMbank[1] & 3) ) {
//if(data&1) { //only writing 1 to $d019 bit0 would acknowledge, not any value (but RMW instructions write $d019 back before mod.)
if (address==0xD019) { cRSID_acknowledgeVICrasterIRQ( &C64->VIC ); }
//}
}
}
inline void wr2 (register unsigned short address, register unsigned char data) { //PSID-hack specific memory-write
static int Tmp;
*cRSID_getMemWritePtr(address)=data;
if ( C64->RAMbank[1] & 3 ) {
if (C64->RealSIDmode) {
if (address==0xDC0D) cRSID_writeCIAIRQmask( &C64->CIA[1], data );
else if (address==0xDD0D) cRSID_writeCIAIRQmask( &C64->CIA[2], data );
else if (address==0xDD0C) C64->IObankRD[address]=data; //mirror WR to RD (e.g. Wonderland_XIII_tune_1.sid)
//#ifdef CRSID_PLATFORM_PC //just for info displayer
// else if (address==0xDC05 || address==0xDC04) C64->FrameCycles = ( (C64->IObankWR[0xDC04] + (C64->IObankWR[0xDC05]<<8)) );
//#endif
else if(address==0xD019 && data&1) { //only writing 1 to $d019 bit0 would acknowledge
cRSID_acknowledgeVICrasterIRQ( &C64->VIC );
}
}
else {
switch (address) {
case 0xDC05: case 0xDC04:
if (C64->TimerSource ) { //dynamic CIA-setting (Galway/Rubicon workaround)
C64->FrameCycles = ( (C64->IObankWR[0xDC04] + (C64->IObankWR[0xDC05]<<8)) ); //<< 4) / C64->SampleClockRatio;
}
break;
case 0xDC08: C64->IObankRD[0xDC08] = data; break; //refresh TOD-clock
case 0xDC09: C64->IObankRD[0xDC09] = data; break; //refresh TOD-clock
case 0xD012: //dynamic VIC IRQ-rasterline setting (Microprose Soccer V1 workaround)
if (C64->PrevRasterLine>=0) { //was $d012 set before? (or set only once?)
if (C64->IObankWR[0xD012] != C64->PrevRasterLine) {
Tmp = C64->IObankWR[0xD012] - C64->PrevRasterLine;
if (Tmp<0) Tmp += C64->VIC.RasterLines;
C64->FrameCycleCnt = C64->FrameCycles - Tmp * C64->VIC.RasterRowCycles;
}
}
C64->PrevRasterLine = C64->IObankWR[0xD012];
break;
}
}
}
}
inline void addrModeImmediate (void) { ++PC; Addr=PC; Cycles=2; } //imm.
inline void addrModeZeropage (void) { ++PC; Addr=rd(PC); Cycles=3; } //zp
inline void addrModeAbsolute (void) { ++PC; Addr = rd(PC); ++PC; Addr += rd(PC)<<8; Cycles=4; } //abs
inline void addrModeZeropageXindexed (void) { ++PC; Addr = (rd(PC) + X) & 0xFF; Cycles=4; } //zp,x (with zeropage-wraparound of 6502)
inline void addrModeZeropageYindexed (void) { ++PC; Addr = (rd(PC) + Y) & 0xFF; Cycles=4; } //zp,y (with zeropage-wraparound of 6502)
inline void addrModeXindexed (void) { // abs,x (only STA is 5 cycles, others are 4 if page not crossed, RMW:7)
++PC; Addr = rd(PC) + X; ++PC; SamePage = (Addr <= 0xFF); Addr += rd(PC)<<8; Cycles=5;
}
inline void addrModeYindexed (void) { // abs,y (only STA is 5 cycles, others are 4 if page not crossed, RMW:7)
++PC; Addr = rd(PC) + Y; ++PC; SamePage = (Addr <= 0xFF); Addr += rd(PC)<<8; Cycles=5;
}
inline void addrModeIndirectYindexed (void) { // (zp),y (only STA is 6 cycles, others are 5 if page not crossed, RMW:8)
++PC; Addr = rd(rd(PC)) + Y; SamePage = (Addr <= 0xFF); Addr += rd( (rd(PC)+1)&0xFF ) << 8; Cycles=6;
}
inline void addrModeXindexedIndirect (void) { // (zp,x)
++PC; Addr = ( rd(rd(PC)+X)&0xFF ) + ( ( rd(rd(PC)+X+1)&0xFF ) << 8 ); Cycles=6;
}
inline void clrC (void) { ST &= ~C; } //clear Carry-flag
inline void setC (unsigned char expr) { ST &= ~C; ST |= (expr!=0); } //set Carry-flag if expression is not zero
inline void clrNZC (void) { ST &= ~(N|Z|C); } //clear flags
inline void clrNVZC (void) { ST &= ~(N|V|Z|C); } //clear flags
inline void setNZbyA (void) { ST &= ~(N|Z); ST |= ((!A)<<1) | (A&N); } //set Negative-flag and Zero-flag based on result in Accumulator
inline void setNZbyT (void) { T&=0xFF; ST &= ~(N|Z); ST |= ((!T)<<1) | (T&N); }
inline void setNZbyX (void) { ST &= ~(N|Z); ST |= ((!X)<<1) | (X&N); } //set Negative-flag and Zero-flag based on result in X-register
inline void setNZbyY (void) { ST &= ~(N|Z); ST |= ((!Y)<<1) | (Y&N); } //set Negative-flag and Zero-flag based on result in Y-register
inline void setNZbyM (void) { ST &= ~(N|Z); ST |= ((!rd(Addr))<<1) | (rd(Addr)&N); } //set Negative-flag and Zero-flag based on result at Memory-Address
inline void setNZCbyAdd (void) { ST &= ~(N|Z|C); ST |= (A&N)|(A>255); A&=0xFF; ST|=(!A)<<1; } //after increase/addition
inline void setVbyAdd (unsigned char M) { ST &= ~V; ST |= ( (~(T^M)) & (T^A) & N ) >> 1; } //calculate V-flag from A and T (previous A) and input2 (Memory)
inline void setNZCbySub (signed short* obj) { ST &= ~(N|Z|C); ST |= (*obj&N) | (*obj>=0); *obj&=0xFF; ST |= ((!(*obj))<<1); }
inline void push (unsigned char value) { C64->RAMbank[0x100+SP] = value; --SP; SP&=0xFF; } //push a value to stack
inline unsigned char pop (void) { ++SP; SP&=0xFF; return C64->RAMbank[0x100+SP]; } //pop a value from stack
loadReg(); PrevPC=PC;
IR = rd(PC); Cycles=2; SamePage=0; //'Cycles': ensure smallest 6510 runtime (for implied/register instructions)
if(IR&1) { //nybble2: 1/5/9/D:accu.instructions, 3/7/B/F:illegal opcodes
switch ( (IR & 0x1F) >> 1 ) { //value-forming to cause jump-table //PC wraparound not handled inside to save codespace
case 0: case 1: addrModeXindexedIndirect(); break; //(zp,x)
case 2: case 3: addrModeZeropage(); break;
case 4: case 5: addrModeImmediate(); break;
case 6: case 7: addrModeAbsolute(); break;
case 8: case 9: addrModeIndirectYindexed(); break; //(zp),y (5..6 cycles, 8 for R-M-W)
case 0xA: addrModeZeropageXindexed(); break; //zp,x
case 0xB: if ((IR&0xC0)!=0x80) addrModeZeropageXindexed(); //zp,x for illegal opcodes
else addrModeZeropageYindexed(); //zp,y for LAX/SAX illegal opcodes
break;
case 0xC: case 0xD: addrModeYindexed(); break;
case 0xE: addrModeXindexed(); break;
case 0xF: if ((IR&0xC0)!=0x80) addrModeXindexed(); //abs,x for illegal opcodes
else addrModeYindexed(); //abs,y for LAX/SAX illegal opcodes
break;
}
Addr&=0xFFFF;
switch ( (IR & 0xE0) >> 5 ) { //value-forming to cause gapless case-values and faster jump-table creation from switch-case
case 0: if ( (IR&0x1F) != 0xB ) { //ORA / SLO(ASO)=ASL+ORA
if ( (IR&3) == 3 ) { clrNZC(); setC(rd(Addr)>=N); wr( Addr, rd(Addr)<<1 ); Cycles+=2; } //for SLO
else Cycles -= SamePage;
A |= rd(Addr); setNZbyA(); //ORA
}
else { A&=rd(Addr); setNZbyA(); setC(A>=N); } //ANC (AND+Carry=bit7)
break;
case 1: if ( (IR&0x1F) != 0xB ) { //AND / RLA (ROL+AND)
if ( (IR&3) == 3 ) { //for RLA
T = (rd(Addr)<<1) + (ST&C); clrNZC(); setC(T>255); T&=0xFF; wr(Addr,T); Cycles+=2;
}
else Cycles -= SamePage;
A &= rd(Addr); setNZbyA(); //AND
}
else { A&=rd(Addr); setNZbyA(); setC(A>=N); } //ANC (AND+Carry=bit7)
break;
case 2: if ( (IR&0x1F) != 0xB ) { //EOR / SRE(LSE)=LSR+EOR
if ( (IR&3) == 3 ) { clrNZC(); setC(rd(Addr)&1); wr(Addr,rd(Addr)>>1); Cycles+=2; } //for SRE
else Cycles -= SamePage;
A ^= rd(Addr); setNZbyA(); //EOR
}
else { A&=rd(Addr); setC(A&1); A>>=1; A&=0xFF; setNZbyA(); } //ALR(ASR)=(AND+LSR)
break;
case 3: if ( (IR&0x1F) != 0xB ) { //RRA (ROR+ADC) / ADC
if( (IR&3) == 3 ) { //for RRA
T = (rd(Addr)>>1) + ((ST&C)<<7); clrNZC(); setC(T&1); wr(Addr,T); Cycles+=2;
}
else Cycles -= SamePage;
T=A; A += rd(Addr)+(ST&C); setNZCbyAdd(); setVbyAdd(rd(Addr)); //ADC
}
else { // ARR (AND+ROR, bit0 not going to C, but C and bit7 get exchanged.)
A &= rd(Addr); T += rd(Addr) + (ST&C);
clrNVZC(); setC(T>255); setVbyAdd(rd(Addr)); //V-flag set by intermediate ADC mechanism: (A&mem)+mem
T=A; A = (A>>1) + ((ST&C)<<7); setC(T>=N); setNZbyA();
}
break;
case 4: if ( (IR&0x1F) == 0xB ) { A = X & rd(Addr); setNZbyA(); } //XAA (TXA+AND), highly unstable on real 6502!
else if ( (IR&0x1F) == 0x1B ) { SP = A&X; wr( Addr, SP&((Addr>>8)+1) ); } //TAS(SHS) (SP=A&X, mem=S&H} - unstable on real 6502
else { wr2( Addr, A & (((IR&3)==3)? X:0xFF) ); } //STA / SAX (at times same as AHX/SHX/SHY) (illegal)
break;
case 5: if ( (IR&0x1F) != 0x1B ) { A=rd(Addr); if((IR&3)==3) X=A; } //LDA / LAX (illegal, used by my 1 rasterline player) (LAX #imm is unstable on C64)
else { A=X=SP = rd(Addr) & SP; } //LAS(LAR)
setNZbyA(); Cycles -= SamePage;
break;
case 6: if( (IR&0x1F) != 0xB ) { // CMP / DCP(DEC+CMP)
if ( (IR&3) == 3 ) { wr(Addr,rd(Addr)-1); Cycles+=2;} //DCP
else Cycles -= SamePage;
T = A-rd(Addr);
}
else { X = T = (A&X) - rd(Addr); } //SBX(AXS) //SBX (AXS) (CMP+DEX at the same time)
setNZCbySub(&T);
break;
case 7: if( (IR&3)==3 && (IR&0x1F)!=0xB ) { wr( Addr, rd(Addr)+1 ); Cycles+=2; } //ISC(ISB)=INC+SBC / SBC
else Cycles -= SamePage;
T=A; A -= rd(Addr) + !(ST&C);
setNZCbySub(&A); setVbyAdd(~rd(Addr));
break;
}
}
else if (IR&2) { //nybble2: 2:illegal/LDX, 6:A/X/INC/DEC, A:Accu-shift/reg.transfer/NOP, E:shift/X/INC/DEC
switch (IR & 0x1F) { //Addressing modes
case 2: addrModeImmediate(); break;
case 6: addrModeZeropage(); break;
case 0xE: addrModeAbsolute(); break;
case 0x16: if ( (IR&0xC0) != 0x80 ) addrModeZeropageXindexed(); //zp,x
else addrModeZeropageYindexed(); //zp,y
break;
case 0x1E: if ( (IR&0xC0) != 0x80 ) addrModeXindexed(); //abs,x
else addrModeYindexed(); //abs,y
break;
}
Addr&=0xFFFF;
switch ( (IR & 0xE0) >> 5 ) {
case 0: clrC(); case 1:
if((IR&0xF)==0xA) { A = (A<<1) + (ST&C); setNZCbyAdd(); } //ASL/ROL (Accu)
else { T = (rd(Addr)<<1) + (ST&C); setC(T>255); setNZbyT(); wr(Addr,T); Cycles+=2; } //RMW (Read-Write-Modify)
break;
case 2: clrC(); case 3:
if((IR&0xF)==0xA) { T=A; A=(A>>1)+((ST&C)<<7); setC(T&1); A&=0xFF; setNZbyA(); } //LSR/ROR (Accu)
else { T = (rd(Addr)>>1) + ((ST&C)<<7); setC(rd(Addr)&1); setNZbyT(); wr(Addr,T); Cycles+=2; } //memory (RMW)
break;
case 4: if (IR&4) {wr2(Addr,X);} //STX
else if(IR&0x10) SP=X; //TXS
else { A=X; setNZbyA(); } //TXA
break;
case 5: if ( (IR&0xF) != 0xA ) { X=rd(Addr); Cycles -= SamePage; } //LDX
else if (IR & 0x10) X=SP; //TSX
else X=A; //TAX
setNZbyX();
break;
case 6: if (IR&4) { wr(Addr,rd(Addr)-1); setNZbyM(); Cycles+=2; } //DEC
else { --X; setNZbyX(); } //DEX
break;
case 7: if (IR&4) { wr(Addr,rd(Addr)+1); setNZbyM(); Cycles+=2; } //INC/NOP
break;
}
}
else if ( (IR & 0xC) == 8 ) { //nybble2: 8:register/statusflag
if ( IR&0x10 ) {
if ( IR == 0x98 ) { A=Y; setNZbyA(); } //TYA
else { //CLC/SEC/CLI/SEI/CLV/CLD/SED
if (FlagSwitches[IR>>5] & 0x20) ST |= (FlagSwitches[IR>>5] & 0xDF);
else ST &= ~( FlagSwitches[IR>>5] & 0xDF );
}
}
else {
switch ( (IR & 0xF0) >> 5 ) {
case 0: push(ST); Cycles=3; break; //PHP
case 1: ST=pop(); Cycles=4; break; //PLP
case 2: push(A); Cycles=3; break; //PHA
case 3: A=pop(); setNZbyA(); Cycles=4; break; //PLA
case 4: --Y; setNZbyY(); break; //DEY
case 5: Y=A; setNZbyY(); break; //TAY
case 6: ++Y; setNZbyY(); break; //INY
case 7: ++X; setNZbyX(); break; //INX
}
}
}
else { //nybble2: 0: control/branch/Y/compare 4: Y/compare C:Y/compare/JMP
if ( (IR&0x1F) == 0x10 ) { //BPL/BMI/BVC/BVS/BCC/BCS/BNE/BEQ relative branch
++PC;
T=rd(PC); if (T & 0x80) T-=0x100;
if (IR & 0x20) {
if (ST & BranchFlags[IR>>6]) { PC+=T; Cycles=3; }
}
else {
if ( !(ST & BranchFlags[IR>>6]) ) { PC+=T; Cycles=3; } //plus 1 cycle if page is crossed?
}
}
else { //nybble2: 0:Y/control/Y/compare 4:Y/compare C:Y/compare/JMP
switch (IR&0x1F) { //Addressing modes
case 0: addrModeImmediate(); break; //imm. (or abs.low for JSR/BRK)
case 4: addrModeZeropage(); break;
case 0xC: addrModeAbsolute(); break;
case 0x14: addrModeZeropageXindexed(); break; //zp,x
case 0x1C: addrModeXindexed(); break; //abs,x
}
Addr&=0xFFFF;
switch ( (IR & 0xE0) >> 5 ) {
case 0: if( !(IR&4) ) { //BRK / NOP-absolute/abs,x/zp/zp,x
push((PC+2-1)>>8); push((PC+2-1)&0xFF); push(ST|B); ST |= I; //BRK
PC = rd(0xFFFE) + (rd(0xFFFF)<<8) - 1; Cycles=7;
}
else if (IR == 0x1C) Cycles -= SamePage; //NOP abs,x
break;
case 1: if (IR & 0xF) { //BIT / NOP-abs,x/zp,x
if ( !(IR&0x10) ) { ST &= 0x3D; ST |= (rd(Addr)&0xC0) | ( (!(A&rd(Addr))) << 1 ); } //BIT
else if (IR == 0x3C) Cycles -= SamePage; //NOP abs,x
}
else { //JSR
push((PC+2-1)>>8); push((PC+2-1)&0xFF);
PC=rd(Addr)+rd(Addr+1)*256-1; Cycles=6;
}
break;
case 2: if (IR & 0xF) { //JMP / NOP-abs,x/zp/zp,x
if (IR == 0x4C) { //JMP
PC = Addr-1; Cycles=3;
rd(Addr+1); //a read from jump-address highbyte is used in some tunes with jmp DD0C (e.g. Wonderland_XIII_tune_1.sid)
//if (Addr==PrevPC) {storeReg(); C64->Returned=1; return 0xFF;} //turn self-jump mainloop (after init) into idle time
}
else if (IR==0x5C) Cycles -= SamePage; //NOP abs,x
}
else { //RTI
ST=pop(); T=pop(); PC = (pop()<<8) + T - 1; Cycles=6;
if (C64->Returned && SP>=0xFF) { ++PC; storeReg(); return 0xFE; }
}
break;
case 3: if (IR & 0xF) { //JMP() (indirect) / NOP-abs,x/zp/zp,x
if (IR == 0x6C) { //JMP() (indirect)
PC = rd( (Addr&0xFF00) + ((Addr+1)&0xFF) ); //(with highbyte-wraparound bug)
PC = (PC<<8) + rd(Addr) - 1; Cycles=5;
}
else if (IR == 0x7C) Cycles -= SamePage; //NOP abs,x
}
else { //RTS
if (SP>=0xFF) {storeReg(); C64->Returned=1; return 0xFF;} //Init returns, provide idle-time between IRQs
T=pop(); PC = (pop()<<8) + T; Cycles=6;
}
break;
case 4: if (IR & 4) { wr2( Addr, Y ); } //STY / NOP #imm
break;
case 5: Y=rd(Addr); setNZbyY(); Cycles -= SamePage; //LDY
break;
case 6: if ( !(IR&0x10) ) { //CPY / NOP abs,x/zp,x
T=Y-rd(Addr); setNZCbySub(&T); //CPY
}
else if (IR==0xDC) Cycles -= SamePage; //NOP abs,x
break;
case 7: if ( !(IR&0x10) ) { //CPX / NOP abs,x/zp,x
T=X-rd(Addr); setNZCbySub(&T); //CPX
}
else if (IR==0xFC) Cycles -= SamePage; //NOP abs,x
break;
}
}
}
++PC; //PC&=0xFFFF;
storeReg();
if (!C64->RealSIDmode) { //substitute KERNAL IRQ-return in PSID (e.g. Microprose Soccer)
if ( (C64->RAMbank[1]&3)>1 && PrevPC<0xE000 && (PC==0xEA31 || PC==0xEA81 || PC==0xEA7E) ) return 0xFE;
}
return Cycles;
}
//handle entering into IRQ and NMI interrupt
static inline char cRSID_handleCPUinterrupts (cRSID_CPUinstance* CPU) {
enum StatusFlagBitValues { B=0x10, I=0x04 };
inline void push (unsigned char value) { CPU->C64->RAMbank[0x100+CPU->SP] = value; --CPU->SP; CPU->SP&=0xFF; } //push a value to stack
if (CPU->C64->NMI > CPU->PrevNMI) { //if IRQ and NMI at the same time, NMI is serviced first
push(CPU->PC>>8); push(CPU->PC&0xFF); push(CPU->ST); CPU->ST |= I;
CPU->PC = *cRSID_getMemReadPtr(0xFFFA) + (*cRSID_getMemReadPtr(0xFFFB)<<8); //NMI-vector
CPU->PrevNMI = CPU->C64->NMI;
return 1;
}
else if ( CPU->C64->IRQ && !(CPU->ST&I) ) {
push(CPU->PC>>8); push(CPU->PC&0xFF); push(CPU->ST); CPU->ST |= I;
CPU->PC = *cRSID_getMemReadPtr(0xFFFE) + (*cRSID_getMemReadPtr(0xFFFF)<<8); //maskable IRQ-vector
CPU->PrevNMI = CPU->C64->NMI;
return 1;
}
CPU->PrevNMI = CPU->C64->NMI; //prepare for NMI edge-detection
return 0;
}

View file

@ -0,0 +1,132 @@
//Emulation of C64 memories and memory bus (PLA & MUXes)
static inline unsigned char* cRSID_getMemReadPtr (register unsigned short address) {
//cRSID_C64instance* const C64 = &cRSID_C64; //for faster (?) operation we use a global object as memory
if (address<0xA000) return &cRSID_C64.RAMbank[address];
else if ( 0xD000<=address && address<0xE000 && (cRSID_C64.RAMbank[1]&3) ) {
if (0xD400 <= address && address < 0xD419) return &cRSID_C64.IObankWR[address]; //emulate bitfading aka SID-read of last written reg (e.g. Lift Off ROR $D400,x)
return &cRSID_C64.IObankRD[address];
}
else if ( (address<0xC000 && (cRSID_C64.RAMbank[1]&3)==3)
|| (0xE000<=address && (cRSID_C64.RAMbank[1]&2)) ) return &cRSID_C64.ROMbanks[address];
return &cRSID_C64.RAMbank[address];
}
static inline unsigned char* cRSID_getMemReadPtrC64 (cRSID_C64instance* C64, register unsigned short address) {
if (address<0xA000) return &C64->RAMbank[address];
else if ( 0xD000<=address && address<0xE000 && (C64->RAMbank[1]&3) ) {
if (0xD400 <= address && address < 0xD419) return &cRSID_C64.IObankWR[address]; //emulate peculiar SID-read (e.g. Lift Off)
return &C64->IObankRD[address];
}
else if ( (address<0xC000 && (C64->RAMbank[1]&3)==3)
|| (0xE000<=address && (C64->RAMbank[1]&2)) ) return &C64->ROMbanks[address];
return &C64->RAMbank[address];
}
static inline unsigned char* cRSID_getMemWritePtr (register unsigned short address) {
//cRSID_C64instance* const C64 = &cRSID_C64; //for faster (?) operation we use a global object as memory
if (address<0xD000 || 0xE000<=address) return &cRSID_C64.RAMbank[address];
else if ( cRSID_C64.RAMbank[1]&3 ) { //handle SID-mirrors! (CJ in the USA workaround (writing above $d420, except SID2/SID3))
if (0xD420 <= address && address < 0xD800) { //CIA/VIC mirrors needed?
if ( !(cRSID_C64.PSIDdigiMode && 0xD418 <= address && address < 0xD500)
&& !(cRSID_C64.SID[2].BaseAddress <= address && address < cRSID_C64.SID[2].BaseAddress+0x20)
&& !(cRSID_C64.SID[3].BaseAddress <= address && address < cRSID_C64.SID[3].BaseAddress+0x20) ) {
return &cRSID_C64.IObankWR[ 0xD400 + (address&0x1F) ]; //write to $D400..D41F if not in SID2/SID3 address-space
}
else return &cRSID_C64.IObankWR[address];
}
else return &cRSID_C64.IObankWR[address];
}
return &cRSID_C64.RAMbank[address];
}
static inline unsigned char* cRSID_getMemWritePtrC64 (cRSID_C64instance* C64, register unsigned short address) {
if (address<0xD000 || 0xE000<=address) return &C64->RAMbank[address];
else if ( C64->RAMbank[1]&3 ) { //handle SID-mirrors! (CJ in the USA workaround (writing above $d420, except SID2/SID3/PSIDdigi))
if (0xD420 <= address && address < 0xD800) { //CIA/VIC mirrors needed?
if ( !(cRSID_C64.PSIDdigiMode && 0xD418 <= address && address < 0xD500)
&& !(C64->SID[2].BaseAddress <= address && address < C64->SID[2].BaseAddress+0x20)
&& !(C64->SID[3].BaseAddress <= address && address < C64->SID[3].BaseAddress+0x20) ) {
return &C64->IObankWR[ 0xD400 + (address&0x1F) ]; //write to $D400..D41F if not in SID2/SID3 address-space
}
else return &C64->IObankWR[address];
}
else return &C64->IObankWR[address];
}
return &C64->RAMbank[address];
}
static inline unsigned char cRSID_readMem (register unsigned short address) {
return *cRSID_getMemReadPtr(address);
}
static inline unsigned char cRSID_readMemC64 (cRSID_C64instance* C64, register unsigned short address) {
return *cRSID_getMemReadPtrC64(C64,address);
}
static inline void cRSID_writeMem (register unsigned short address, register unsigned char data) {
*cRSID_getMemWritePtr(address)=data;
}
static inline void cRSID_writeMemC64 (cRSID_C64instance* C64, register unsigned short address, register unsigned char data) {
*cRSID_getMemWritePtrC64(C64,address)=data;
}
void cRSID_setROMcontent (cRSID_C64instance* C64) { //fill KERNAL/BASIC-ROM areas with content needed for SID-playback
int i;
static const unsigned char ROM_IRQreturnCode[9] = {0xAD,0x0D,0xDC,0x68,0xA8,0x68,0xAA,0x68,0x40}; //CIA1-acknowledge IRQ-return
static const unsigned char ROM_NMIstartCode[5] = {0x78,0x6c,0x18,0x03,0x40}; //SEI and jmp($0318)
static const unsigned char ROM_IRQBRKstartCode[19] = { //Full IRQ-return (handling BRK with the same RAM vector as IRQ)
0x48,0x8A,0x48,0x98,0x48,0xBA,0xBD,0x04,0x01,0x29,0x10,0xEA,0xEA,0xEA,0xEA,0xEA,0x6C,0x14,0x03
};
for (i=0xA000; i<0x10000; ++i) C64->ROMbanks[i] = 0x60; //RTS (at least return if some unsupported call is made to ROM)
for (i=0xEA31; i<0xEA7E; ++i) C64->ROMbanks[i] = 0xEA; //NOP (full IRQ-return leading to simple IRQ-return without other tasks)
for (i=0; i<9; ++i) C64->ROMbanks [0xEA7E + i] = ROM_IRQreturnCode[i];
for (i=0; i<4; ++i) C64->ROMbanks [0xFE43 + i] = ROM_NMIstartCode[i];
for (i=0; i<19; ++i) C64->ROMbanks[0xFF48 + i] = ROM_IRQBRKstartCode[i];
C64->ROMbanks[0xFFFB] = 0xFE; C64->ROMbanks[0xFFFA] = 0x43; //ROM NMI-vector
C64->ROMbanks[0xFFFF] = 0xFF; C64->ROMbanks[0xFFFE] = 0x48; //ROM IRQ-vector
//copy KERNAL & BASIC ROM contents into the RAM under them? (So PSIDs that don't select bank correctly will work better.)
for (i=0xA000; i<0x10000; ++i) C64->RAMbank[i]=C64->ROMbanks[i];
}
void cRSID_initMem (cRSID_C64instance* C64) { //set default values that normally KERNEL ensures after startup/reset (only SID-playback related)
static int i;
//data required by both PSID and RSID (according to HVSC SID_file_format.txt):
cRSID_writeMemC64( C64, 0x02A6, C64->VideoStandard ); //$02A6 should be pre-set to: 0:NTSC / 1:PAL
cRSID_writeMemC64( C64, 0x0001, 0x37 ); //initialize bank-reg. (ROM-banks and IO enabled)
//if (C64->ROMbanks[0xE000]==0) { //wasn't a KERNAL-ROM loaded? (e.g. PSID)
cRSID_writeMemC64( C64, 0x00CB, 0x40 ); //Some tunes might check for keypress here (e.g. Master Blaster Intro)
//if(C64->RealSIDmode) {
cRSID_writeMemC64( C64, 0x0315, 0xEA ); cRSID_writeMemC64( C64, 0x0314, 0x31 ); //IRQ
cRSID_writeMemC64( C64, 0x0319, 0xEA/*0xFE*/ ); cRSID_writeMemC64( C64, 0x0318, 0x81/*0x47*/ ); //NMI
//}
for (i=0xD000; i<0xD7FF; ++i) C64->IObankRD[i] = C64->IObankWR[i] = 0; //initialize the whole IO area for a known base-state
if(C64->RealSIDmode) {C64->IObankWR[0xD012] = 0x37; C64->IObankWR[0xD011] = 0x8B;} //else C64->IObankWR[0xD012] = 0;
//C64->IObankWR[0xD019] = 0; //PSID: rasterrow: any value <= $FF, IRQ:enable later if there is VIC-timingsource
C64->IObankRD[0xDC00]=0x10; C64->IObankRD[0xDC01]=0xFF; //Imitate CIA1 keyboard/joy port, some tunes check if buttons are not pressed
if (C64->VideoStandard) { C64->IObankWR[0xDC04]=0x24; C64->IObankWR[0xDC05]=0x40; } //initialize CIAs
else { C64->IObankWR[0xDC04]=0x95; C64->IObankWR[0xDC05]=0x42; }
if(C64->RealSIDmode) C64->IObankWR[0xDC0D] = 0x81; //Reset-default, but for PSID CIA1 TimerA IRQ should be enabled anyway if SID is CIA-timed
C64->IObankWR[0xDC0E] = 0x01; //some tunes (and PSID doc) expect already running CIA (Reset-default)
C64->IObankWR[0xDC0F] = 0x00; //All counters other than CIA1 TimerA should be disabled and set to 0xFF for PSID:
C64->IObankWR[0xDD04] = C64->IObankWR[0xDD05] = 0xFF; //C64->IObankWR[0xDD0E] = C64->IObank[0xDD0F] = 0x00;
//}
}

View file

@ -0,0 +1,276 @@
//cRSID SID emulation engine
void cRSID_createSIDchip (cRSID_C64instance* C64, cRSID_SIDinstance* SID, unsigned short model, unsigned short baseaddress) {
SID->C64 = C64;
SID->ChipModel = model;
if( baseaddress>=0xD400 && (baseaddress<0xD800 || (0xDE00<=baseaddress && baseaddress<=0xDFE0)) ) { //check valid address, avoid Color-RAM
SID->BaseAddress = baseaddress; SID->BasePtr = &C64->IObankWR[baseaddress];
}
else { SID->BaseAddress=0x0000; SID->BasePtr = NULL; }
cRSID_initSIDchip(SID);
}
void cRSID_initSIDchip (cRSID_SIDinstance* SID) {
static unsigned char Channel;
for (Channel = 0; Channel < 21; Channel+=7) {
SID->ADSRstate[Channel] = 0; SID->RateCounter[Channel] = 0;
SID->EnvelopeCounter[Channel] = 0; SID->ExponentCounter[Channel] = 0;
SID->PhaseAccu[Channel] = 0; SID->PrevPhaseAccu[Channel] = 0;
SID->NoiseLFSR[Channel] = 0x7FFFFF;
SID->PrevWavGenOut[Channel] = 0; SID->PrevWavData[Channel] = 0;
}
SID->SyncSourceMSBrise = 0; SID->RingSourceMSB = 0;
SID->PrevLowPass = SID->PrevBandPass = SID->PrevVolume = 0;
}
void cRSID_emulateADSRs (cRSID_SIDinstance *SID, char cycles) {
enum ADSRstateBits { GATE_BITVAL=0x01, ATTACK_BITVAL=0x80, DECAYSUSTAIN_BITVAL=0x40, HOLDZEROn_BITVAL=0x10 };
static const short ADSRprescalePeriods[16] = {
9, 32, 63, 95, 149, 220, 267, 313, 392, 977, 1954, 3126, 3907, 11720, 19532, 31251
};
static const unsigned char ADSRexponentPeriods[256] = {
1, 30, 30, 30, 30, 30, 30, 16, 16, 16, 16, 16, 16, 16, 16,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, //pos0:1 pos6:30 pos14:16 pos26:8
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, //pos54:4 //pos93:2
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
static unsigned char Channel, PrevGate, AD, SR;
static unsigned short PrescalePeriod;
static unsigned char *ChannelPtr, *ADSRstatePtr, *EnvelopeCounterPtr, *ExponentCounterPtr;
static unsigned short *RateCounterPtr;
for (Channel=0; Channel<21; Channel+=7) {
ChannelPtr=&SID->BasePtr[Channel]; AD=ChannelPtr[5]; SR=ChannelPtr[6];
ADSRstatePtr = &(SID->ADSRstate[Channel]);
RateCounterPtr = &(SID->RateCounter[Channel]);
EnvelopeCounterPtr = &(SID->EnvelopeCounter[Channel]);
ExponentCounterPtr = &(SID->ExponentCounter[Channel]);
PrevGate = (*ADSRstatePtr & GATE_BITVAL);
if ( PrevGate != (ChannelPtr[4] & GATE_BITVAL) ) { //gatebit-change?
if (PrevGate) *ADSRstatePtr &= ~ (GATE_BITVAL | ATTACK_BITVAL | DECAYSUSTAIN_BITVAL); //falling edge
else *ADSRstatePtr = (GATE_BITVAL | ATTACK_BITVAL | DECAYSUSTAIN_BITVAL | HOLDZEROn_BITVAL); //rising edge
}
if (*ADSRstatePtr & ATTACK_BITVAL) PrescalePeriod = ADSRprescalePeriods[ AD >> 4 ];
else if (*ADSRstatePtr & DECAYSUSTAIN_BITVAL) PrescalePeriod = ADSRprescalePeriods[ AD & 0x0F ];
else PrescalePeriod = ADSRprescalePeriods[ SR & 0x0F ];
*RateCounterPtr += cycles; if (*RateCounterPtr >= 0x8000) *RateCounterPtr -= 0x8000; //*RateCounterPtr &= 0x7FFF; //can wrap around (ADSR delay-bug: short 1st frame)
if (PrescalePeriod <= *RateCounterPtr && *RateCounterPtr < PrescalePeriod+cycles) { //ratecounter shot (matches rateperiod) (in genuine SID ratecounter is LFSR)
*RateCounterPtr -= PrescalePeriod; //reset rate-counter on period-match
if ( (*ADSRstatePtr & ATTACK_BITVAL) || ++(*ExponentCounterPtr) == ADSRexponentPeriods[*EnvelopeCounterPtr] ) {
*ExponentCounterPtr = 0;
if (*ADSRstatePtr & HOLDZEROn_BITVAL) {
if (*ADSRstatePtr & ATTACK_BITVAL) {
++(*EnvelopeCounterPtr);
if (*EnvelopeCounterPtr==0xFF) *ADSRstatePtr &= ~ATTACK_BITVAL;
}
else if ( !(*ADSRstatePtr & DECAYSUSTAIN_BITVAL) || *EnvelopeCounterPtr != (SR&0xF0)+(SR>>4) ) {
--(*EnvelopeCounterPtr); //resid adds 1 cycle delay, we omit that mechanism here
if (*EnvelopeCounterPtr==0) *ADSRstatePtr &= ~HOLDZEROn_BITVAL;
}}}}}
}
int cRSID_emulateWaves (cRSID_SIDinstance *SID) {
enum SIDspecs { CHANNELS=3+1, VOLUME_MAX=0xF, D418_DIGI_VOLUME=2 }; //digi-channel is counted too
enum WaveFormBits { NOISE_BITVAL=0x80, PULSE_BITVAL=0x40, SAW_BITVAL=0x20, TRI_BITVAL=0x10 };
enum ControlBits { TEST_BITVAL=0x08, RING_BITVAL=0x04, SYNC_BITVAL=0x02, GATE_BITVAL=0x01 };
enum FilterBits { OFF3_BITVAL=0x80, HIGHPASS_BITVAL=0x40, BANDPASS_BITVAL=0x20, LOWPASS_BITVAL=0x10 };
#include "SID.h"
static const unsigned char FilterSwitchVal[] = {1,1,1,1,1,1,1,2,2,2,2,2,2,2,4};
static char MainVolume;
static unsigned char Channel, WF, TestBit, Envelope, FilterSwitchReso, VolumeBand;
static unsigned int Utmp, PhaseAccuStep, MSB, WavGenOut, PW;
static int Tmp, Feedback, Steepness, PulsePeak;
static int FilterInput, Cutoff, Resonance, FilterOutput, NonFilted, Output;
static unsigned char *ChannelPtr;
static int *PhaseAccuPtr;
inline unsigned short combinedWF( const unsigned char* WFarray, unsigned short oscval) {
static unsigned char Pitch;
static unsigned short Filt;
if (SID->ChipModel==6581 && WFarray!=PulseTriangle) oscval &= 0x7FFF;
Pitch = ChannelPtr[1] ? ChannelPtr[1] : 1; //avoid division by zero
Filt = 0x7777 + (0x8888/Pitch);
SID->PrevWavData[Channel] = ( WFarray[oscval>>4]*Filt + SID->PrevWavData[Channel]*(0xFFFF-Filt) ) >> 16;
return SID->PrevWavData[Channel] << 8;
}
FilterInput = NonFilted = 0;
FilterSwitchReso = SID->BasePtr[0x17]; VolumeBand=SID->BasePtr[0x18];
//Waveform-generator //(phase accumulator and waveform-selector)
for (Channel=0; Channel<21; Channel+=7) {
ChannelPtr=&(SID->BasePtr[Channel]);
WF = ChannelPtr[4]; TestBit = ( (WF & TEST_BITVAL) != 0 );
PhaseAccuPtr = &(SID->PhaseAccu[Channel]);
PhaseAccuStep = ( (ChannelPtr[1]<<8) + ChannelPtr[0] ) * SID->C64->SampleClockRatio;
if (TestBit || ((WF & SYNC_BITVAL) && SID->SyncSourceMSBrise)) *PhaseAccuPtr = 0;
else { //stepping phase-accumulator (oscillator)
*PhaseAccuPtr += PhaseAccuStep;
if (*PhaseAccuPtr >= 0x10000000) *PhaseAccuPtr -= 0x10000000;
}
*PhaseAccuPtr &= 0xFFFFFFF;
MSB = *PhaseAccuPtr & 0x8000000;
SID->SyncSourceMSBrise = (MSB > (SID->PrevPhaseAccu[Channel] & 0x8000000)) ? 1 : 0;
if (WF & NOISE_BITVAL) { //noise waveform
Tmp = SID->NoiseLFSR[Channel]; //clock LFSR all time if clockrate exceeds observable at given samplerate (last term):
if ( ((*PhaseAccuPtr & 0x1000000) != (SID->PrevPhaseAccu[Channel] & 0x1000000)) || PhaseAccuStep >= 0x1000000 ) {
Feedback = ( (Tmp & 0x400000) ^ ((Tmp & 0x20000) << 5) ) != 0;
Tmp = ( (Tmp << 1) | Feedback|TestBit ) & 0x7FFFFF; //TEST-bit turns all bits in noise LFSR to 1 (on real SID slowly, in approx. 8000 microseconds ~ 300 samples)
SID->NoiseLFSR[Channel] = Tmp;
} //we simply zero output when other waveform is mixed with noise. On real SID LFSR continuously gets filled by zero and locks up. ($C1 waveform with pw<8 can keep it for a while.)
WavGenOut = (WF & 0x70) ? 0 : ((Tmp & 0x100000) >> 5) | ((Tmp & 0x40000) >> 4) | ((Tmp & 0x4000) >> 1) | ((Tmp & 0x800) << 1)
| ((Tmp & 0x200) << 2) | ((Tmp & 0x20) << 5) | ((Tmp & 0x04) << 7) | ((Tmp & 0x01) << 8);
}
else if (WF & PULSE_BITVAL) { //simple pulse
PW = ( ((ChannelPtr[3]&0xF) << 8) + ChannelPtr[2] ) << 4; //PW=0000..FFF0 from SID-register
Utmp = (int) (PhaseAccuStep >> 13); if (0 < PW && PW < Utmp) PW = Utmp; //Too thin pulsewidth? Correct...
Utmp ^= 0xFFFF; if (PW > Utmp) PW = Utmp; //Too thin pulsewidth? Correct it to a value representable at the current samplerate
Utmp = *PhaseAccuPtr >> 12;
if ( (WF&0xF0) == PULSE_BITVAL ) { //simple pulse, most often used waveform, make it sound as clean as possible (by making it trapezoid)
Steepness = (PhaseAccuStep>=4096) ? 0xFFFFFFF/PhaseAccuStep : 0xFFFF; //rising/falling-edge steepness (add/sub at samples)
if (TestBit) WavGenOut = 0xFFFF;
else if (Utmp<PW) { //rising edge (interpolation)
PulsePeak = (0xFFFF-PW) * Steepness; //very thin pulses don't make a full swing between 0 and max but make a little spike
if (PulsePeak>0xFFFF) PulsePeak=0xFFFF; //but adequately thick trapezoid pulses reach the maximum level
Tmp = PulsePeak - (PW-Utmp)*Steepness; //draw the slope from the peak
WavGenOut = (Tmp<0)? 0:Tmp; //but stop at 0-level
}
else { //falling edge (interpolation)
PulsePeak = PW*Steepness; //very thin pulses don't make a full swing between 0 and max but make a little spike
if (PulsePeak>0xFFFF) PulsePeak=0xFFFF; //adequately thick trapezoid pulses reach the maximum level
Tmp = (0xFFFF-Utmp)*Steepness - PulsePeak; //draw the slope from the peak
WavGenOut = (Tmp>=0)? 0xFFFF:Tmp; //but stop at max-level
}}
else { //combined pulse
WavGenOut = (Utmp >= PW || TestBit) ? 0xFFFF:0;
if (WF & TRI_BITVAL) {
if (WF & SAW_BITVAL) { //pulse+saw+triangle (waveform nearly identical to tri+saw)
if (WavGenOut) WavGenOut = combinedWF( PulseSawTriangle, Utmp);
}
else { //pulse+triangle
Tmp = *PhaseAccuPtr ^ ( (WF&RING_BITVAL)? SID->RingSourceMSB : 0 );
if (WavGenOut) WavGenOut = combinedWF( PulseTriangle, Tmp >> 12);
}}
else if (WF & SAW_BITVAL) { //pulse+saw
if(WavGenOut) WavGenOut = combinedWF( PulseSawtooth, Utmp);
}}
}
else if (WF & SAW_BITVAL) { //sawtooth
WavGenOut = *PhaseAccuPtr >> 12; //saw (this row would be enough for simple but aliased-at-high-pitch saw)
if (WF & TRI_BITVAL) WavGenOut = combinedWF( SawTriangle, WavGenOut); //saw+triangle
else { //simple cleaned (bandlimited) saw
Steepness = (PhaseAccuStep>>4)/288; if(Steepness==0) Steepness=1; //avoid division by zero in next steps
WavGenOut += (WavGenOut * Steepness) >> 16; //1st half (rising edge) of asymmetric triangle-like saw waveform
if (WavGenOut>0xFFFF) WavGenOut = 0xFFFF - ( ((WavGenOut-0x10000)<<16) / Steepness ); //2nd half (falling edge, reciprocal steepness)
}}
else if (WF & TRI_BITVAL) { //triangle (this waveform has no harsh edges, so it doesn't suffer from strong aliasing at high pitches)
Tmp = *PhaseAccuPtr ^ ( WF&RING_BITVAL? SID->RingSourceMSB : 0 );
WavGenOut = ( Tmp ^ (Tmp&0x8000000? 0xFFFFFFF:0) ) >> 11;
}
WavGenOut &= 0xFFFF;
if (WF&0xF0) SID->PrevWavGenOut[Channel] = WavGenOut; //emulate waveform 00 floating wave-DAC (utilized by SounDemon digis)
else WavGenOut = SID->PrevWavGenOut[Channel]; //(on real SID waveform00 decays, we just simply keep the value to avoid clicks)
SID->PrevPhaseAccu[Channel] = *PhaseAccuPtr;
SID->RingSourceMSB = MSB;
//routing the channel signal to either the filter or the unfiltered master output depending on filter-switch SID-registers
Envelope = SID->ChipModel==8580 ? SID->EnvelopeCounter[Channel] : ADSR_DAC_6581[SID->EnvelopeCounter[Channel]];
if (FilterSwitchReso & FilterSwitchVal[Channel]) {
FilterInput += ( ((int)WavGenOut-0x8000) * Envelope ) >> 8;
}
else if ( Channel!=14 || !(VolumeBand & OFF3_BITVAL) ) {
NonFilted += ( ((int)WavGenOut-0x8000) * Envelope ) >> 8;
}
}
//update readable SID1-registers (some SID tunes might use 3rd channel ENV3/OSC3 value as control)
SID->C64->IObankRD[SID->BaseAddress+0x1B] = WavGenOut>>8; //OSC3, ENV3 (some players rely on it, unfortunately even for timing)
SID->C64->IObankRD[SID->BaseAddress+0x1C] = SID->EnvelopeCounter[14]; //Envelope
//Filter
Cutoff = (SID->BasePtr[0x16] << 3) + (SID->BasePtr[0x15] & 7);
Resonance = FilterSwitchReso >> 4;
if (SID->ChipModel == 8580) {
Cutoff = CutoffMul8580_44100Hz[Cutoff];
Resonance = Resonances8580[Resonance];
}
else { //6581
Cutoff += (FilterInput*105)>>16; if (Cutoff>0x7FF) Cutoff=0x7FF; else if (Cutoff<0) Cutoff=0; //MOSFET-VCR control-voltage-modulation
Cutoff = CutoffMul6581_44100Hz[Cutoff]; //(resistance-modulation aka 6581 filter distortion) emulation
Resonance = Resonances6581[Resonance];
}
FilterOutput=0;
Tmp = FilterInput + ((SID->PrevBandPass * Resonance)>>12) + SID->PrevLowPass;
if (VolumeBand & HIGHPASS_BITVAL) FilterOutput -= Tmp;
Tmp = SID->PrevBandPass - ( (Tmp * Cutoff) >> 12 );
SID->PrevBandPass = Tmp;
if (VolumeBand & BANDPASS_BITVAL) FilterOutput -= Tmp;
Tmp = SID->PrevLowPass + ( (Tmp * Cutoff) >> 12 );
SID->PrevLowPass = Tmp;
if (VolumeBand & LOWPASS_BITVAL) FilterOutput += Tmp;
//Output stage
//For $D418 volume-register digi playback: an AC / DC separation for $D418 value at low (20Hz or so) cutoff-frequency,
//sending AC (highpass) value to a 4th 'digi' channel mixed to the master output, and set ONLY the DC (lowpass) value to the volume-control.
//This solved 2 issues: Thanks to the lowpass filtering of the volume-control, SID tunes where digi is played together with normal SID channels,
//won't sound distorted anymore, and the volume-clicks disappear when setting SID-volume. (This is useful for fade-in/out tunes like Hades Nebula, where clicking ruins the intro.)
if (SID->C64->RealSIDmode) {
Tmp = (signed int) ( (VolumeBand&0xF) << 12 );
NonFilted += (Tmp - SID->PrevVolume) * D418_DIGI_VOLUME; //highpass is digi, adding it to output must be before digifilter-code
SID->PrevVolume += (Tmp - SID->PrevVolume) >> 10; //arithmetic shift amount determines digi lowpass-frequency
MainVolume = SID->PrevVolume >> 12; //lowpass is main volume
}
else MainVolume = VolumeBand & 0xF;
Output = ((NonFilted+FilterOutput) * MainVolume) / ( (CHANNELS*VOLUME_MAX) + SID->C64->Attenuation );
return Output; // master output
}

View file

@ -0,0 +1,824 @@
//SID-tables: combined waveform,etc. (Keep them static because they're included locally inside the wave-generator function.)
static const unsigned char ADSR_DAC_6581[] = {
0x00,0x02,0x03,0x04,0x05,0x06,0x07,0x09,0x09,0x0B,0x0B,0x0D,0x0D,0x0F,0x10,0x12,
0x11,0x13,0x14,0x15,0x16,0x17,0x18,0x1A,0x1A,0x1C,0x1C,0x1E,0x1E,0x20,0x21,0x23, //used at output of ADSR envelope generator
0x21,0x23,0x24,0x25,0x26,0x27,0x28,0x2A,0x2A,0x2C,0x2C,0x2E,0x2E,0x30,0x31,0x33, //(not used for wave-generator because of 8bit-only resolution)
0x32,0x34,0x35,0x36,0x37,0x38,0x39,0x3B,0x3B,0x3D,0x3D,0x3F,0x3F,0x41,0x42,0x44,
0x40,0x42,0x42,0x44,0x44,0x46,0x47,0x49,0x49,0x4A,0x4B,0x4D,0x4D,0x4F,0x50,0x52,
0x51,0x53,0x53,0x55,0x55,0x57,0x58,0x5A,0x5A,0x5B,0x5C,0x5E,0x5E,0x60,0x61,0x63,
0x61,0x62,0x63,0x65,0x65,0x67,0x68,0x6A,0x69,0x6B,0x6C,0x6E,0x6E,0x70,0x71,0x73,
0x72,0x73,0x74,0x76,0x76,0x78,0x79,0x7B,0x7A,0x7C,0x7D,0x7F,0x7F,0x81,0x82,0x84,
0x7B,0x7D,0x7E,0x80,0x80,0x82,0x83,0x85,0x84,0x86,0x87,0x89,0x89,0x8B,0x8C,0x8D,
0x8C,0x8E,0x8F,0x91,0x91,0x93,0x94,0x96,0x95,0x97,0x98,0x9A,0x9A,0x9C,0x9D,0x9E,
0x9C,0x9E,0x9F,0xA1,0xA1,0xA3,0xA4,0xA5,0xA5,0xA7,0xA8,0xAA,0xAA,0xAC,0xAC,0xAE,
0xAD,0xAF,0xB0,0xB2,0xB2,0xB4,0xB5,0xB6,0xB6,0xB8,0xB9,0xBB,0xBB,0xBD,0xBD,0xBF,
0xBB,0xBD,0xBE,0xC0,0xC0,0xC2,0xC2,0xC4,0xC4,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCD,
0xCC,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDE,
0xDC,0xDE,0xDF,0xE1,0xE1,0xE3,0xE3,0xE5,0xE5,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xEE,
0xED,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFF
};
static const unsigned short Resonances8580[] = { //generated by curvegen.c
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x16A0,0x14BF,0x1306,0x1172,0x1000,0x0EAC,0x0D74,0x0C56,0x0B50,0x0A5F,0x0983,0x08B9,0x0800,0x0756,0x06BA,0x062B
//0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE8, 0xD5, 0xC5, 0xB3, 0xA4, 0x97, 0x8A, 0x80, 0x77, 0x6E, 0x66 <- calculated then refined manually to sound best
};
static const unsigned short Resonances6581[] = { //generated by curvegen.c
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x168F,0x168F,0x168F,0x168F,0x168F,0x168F,0x1555,0x1249,0x1000,0x0E38,0x0CCC,0x0BA2,0x0AAA,0x09D8,0x0924,0x0888
//0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xF9, 0xF6, 0xF2, 0xEC, 0xE4, 0xCD, 0xBA, 0xAB, 0x9E, 0x92, 0x86 <- calculated then refined manually to sound best
};
static const unsigned short CutoffMul8580_44100Hz[] = { //generated by curvegen.c
0x006,0x00A,0x00D,0x011,0x014,0x018,0x01B,0x01F,0x022,0x026,0x029,0x02D,0x030,0x034,0x037,0x03B,
0x03E,0x041,0x045,0x048,0x04C,0x04F,0x053,0x056,0x059,0x05D,0x060,0x064,0x067,0x06B,0x06E,0x071,
0x075,0x078,0x07C,0x07F,0x082,0x086,0x089,0x08D,0x090,0x093,0x097,0x09A,0x09D,0x0A1,0x0A4,0x0A7,
0x0AB,0x0AE,0x0B2,0x0B5,0x0B8,0x0BC,0x0BF,0x0C2,0x0C6,0x0C9,0x0CC,0x0D0,0x0D3,0x0D6,0x0D9,0x0DD,
0x0E0,0x0E3,0x0E7,0x0EA,0x0ED,0x0F1,0x0F4,0x0F7,0x0FA,0x0FE,0x101,0x104,0x108,0x10B,0x10E,0x111,
0x115,0x118,0x11B,0x11E,0x122,0x125,0x128,0x12B,0x12F,0x132,0x135,0x138,0x13C,0x13F,0x142,0x145,
0x149,0x14C,0x14F,0x152,0x155,0x159,0x15C,0x15F,0x162,0x165,0x169,0x16C,0x16F,0x172,0x175,0x178,
0x17C,0x17F,0x182,0x185,0x188,0x18B,0x18F,0x192,0x195,0x198,0x19B,0x19E,0x1A2,0x1A5,0x1A8,0x1AB,
0x1AE,0x1B1,0x1B4,0x1B7,0x1BB,0x1BE,0x1C1,0x1C4,0x1C7,0x1CA,0x1CD,0x1D0,0x1D3,0x1D7,0x1DA,0x1DD,
0x1E0,0x1E3,0x1E6,0x1E9,0x1EC,0x1EF,0x1F2,0x1F5,0x1F9,0x1FC,0x1FF,0x202,0x205,0x208,0x20B,0x20E,
0x211,0x214,0x217,0x21A,0x21D,0x220,0x223,0x226,0x229,0x22C,0x22F,0x232,0x235,0x238,0x23B,0x23E,
0x241,0x244,0x247,0x24A,0x24D,0x250,0x253,0x256,0x259,0x25C,0x25F,0x262,0x265,0x268,0x26B,0x26E,
0x271,0x274,0x277,0x27A,0x27D,0x280,0x283,0x286,0x289,0x28C,0x28F,0x292,0x295,0x297,0x29A,0x29D,
0x2A0,0x2A3,0x2A6,0x2A9,0x2AC,0x2AF,0x2B2,0x2B5,0x2B8,0x2BB,0x2BD,0x2C0,0x2C3,0x2C6,0x2C9,0x2CC,
0x2CF,0x2D2,0x2D5,0x2D7,0x2DA,0x2DD,0x2E0,0x2E3,0x2E6,0x2E9,0x2EB,0x2EE,0x2F1,0x2F4,0x2F7,0x2FA,
0x2FD,0x2FF,0x302,0x305,0x308,0x30B,0x30E,0x310,0x313,0x316,0x319,0x31C,0x31F,0x321,0x324,0x327,
0x32A,0x32D,0x32F,0x332,0x335,0x338,0x33B,0x33D,0x340,0x343,0x346,0x349,0x34B,0x34E,0x351,0x354,
0x356,0x359,0x35C,0x35F,0x362,0x364,0x367,0x36A,0x36D,0x36F,0x372,0x375,0x378,0x37A,0x37D,0x380,
0x382,0x385,0x388,0x38B,0x38D,0x390,0x393,0x396,0x398,0x39B,0x39E,0x3A0,0x3A3,0x3A6,0x3A8,0x3AB,
0x3AE,0x3B1,0x3B3,0x3B6,0x3B9,0x3BB,0x3BE,0x3C1,0x3C3,0x3C6,0x3C9,0x3CB,0x3CE,0x3D1,0x3D3,0x3D6,
0x3D9,0x3DB,0x3DE,0x3E1,0x3E3,0x3E6,0x3E9,0x3EB,0x3EE,0x3F1,0x3F3,0x3F6,0x3F8,0x3FB,0x3FE,0x400,
0x403,0x406,0x408,0x40B,0x40D,0x410,0x413,0x415,0x418,0x41A,0x41D,0x420,0x422,0x425,0x427,0x42A,
0x42D,0x42F,0x432,0x434,0x437,0x439,0x43C,0x43F,0x441,0x444,0x446,0x449,0x44B,0x44E,0x451,0x453,
0x456,0x458,0x45B,0x45D,0x460,0x462,0x465,0x467,0x46A,0x46D,0x46F,0x472,0x474,0x477,0x479,0x47C,
0x47E,0x481,0x483,0x486,0x488,0x48B,0x48D,0x490,0x492,0x495,0x497,0x49A,0x49C,0x49F,0x4A1,0x4A4,
0x4A6,0x4A9,0x4AB,0x4AE,0x4B0,0x4B3,0x4B5,0x4B8,0x4BA,0x4BC,0x4BF,0x4C1,0x4C4,0x4C6,0x4C9,0x4CB,
0x4CE,0x4D0,0x4D3,0x4D5,0x4D7,0x4DA,0x4DC,0x4DF,0x4E1,0x4E4,0x4E6,0x4E8,0x4EB,0x4ED,0x4F0,0x4F2,
0x4F5,0x4F7,0x4F9,0x4FC,0x4FE,0x501,0x503,0x505,0x508,0x50A,0x50D,0x50F,0x511,0x514,0x516,0x519,
0x51B,0x51D,0x520,0x522,0x524,0x527,0x529,0x52C,0x52E,0x530,0x533,0x535,0x537,0x53A,0x53C,0x53E,
0x541,0x543,0x546,0x548,0x54A,0x54D,0x54F,0x551,0x554,0x556,0x558,0x55B,0x55D,0x55F,0x562,0x564,
0x566,0x568,0x56B,0x56D,0x56F,0x572,0x574,0x576,0x579,0x57B,0x57D,0x580,0x582,0x584,0x586,0x589,
0x58B,0x58D,0x590,0x592,0x594,0x596,0x599,0x59B,0x59D,0x5A0,0x5A2,0x5A4,0x5A6,0x5A9,0x5AB,0x5AD,
0x5AF,0x5B2,0x5B4,0x5B6,0x5B8,0x5BB,0x5BD,0x5BF,0x5C1,0x5C4,0x5C6,0x5C8,0x5CA,0x5CD,0x5CF,0x5D1,
0x5D3,0x5D5,0x5D8,0x5DA,0x5DC,0x5DE,0x5E1,0x5E3,0x5E5,0x5E7,0x5E9,0x5EC,0x5EE,0x5F0,0x5F2,0x5F4,
0x5F7,0x5F9,0x5FB,0x5FD,0x5FF,0x602,0x604,0x606,0x608,0x60A,0x60C,0x60F,0x611,0x613,0x615,0x617,
0x619,0x61C,0x61E,0x620,0x622,0x624,0x626,0x629,0x62B,0x62D,0x62F,0x631,0x633,0x635,0x638,0x63A,
0x63C,0x63E,0x640,0x642,0x644,0x646,0x649,0x64B,0x64D,0x64F,0x651,0x653,0x655,0x657,0x65A,0x65C,
0x65E,0x660,0x662,0x664,0x666,0x668,0x66A,0x66C,0x66F,0x671,0x673,0x675,0x677,0x679,0x67B,0x67D,
0x67F,0x681,0x683,0x685,0x688,0x68A,0x68C,0x68E,0x690,0x692,0x694,0x696,0x698,0x69A,0x69C,0x69E,
0x6A0,0x6A2,0x6A4,0x6A6,0x6A8,0x6AB,0x6AD,0x6AF,0x6B1,0x6B3,0x6B5,0x6B7,0x6B9,0x6BB,0x6BD,0x6BF,
0x6C1,0x6C3,0x6C5,0x6C7,0x6C9,0x6CB,0x6CD,0x6CF,0x6D1,0x6D3,0x6D5,0x6D7,0x6D9,0x6DB,0x6DD,0x6DF,
0x6E1,0x6E3,0x6E5,0x6E7,0x6E9,0x6EB,0x6ED,0x6EF,0x6F1,0x6F3,0x6F5,0x6F7,0x6F9,0x6FB,0x6FD,0x6FF,
0x701,0x703,0x705,0x707,0x709,0x70B,0x70C,0x70E,0x710,0x712,0x714,0x716,0x718,0x71A,0x71C,0x71E,
0x720,0x722,0x724,0x726,0x728,0x72A,0x72C,0x72E,0x72F,0x731,0x733,0x735,0x737,0x739,0x73B,0x73D,
0x73F,0x741,0x743,0x745,0x746,0x748,0x74A,0x74C,0x74E,0x750,0x752,0x754,0x756,0x758,0x759,0x75B,
0x75D,0x75F,0x761,0x763,0x765,0x767,0x769,0x76A,0x76C,0x76E,0x770,0x772,0x774,0x776,0x778,0x779,
0x77B,0x77D,0x77F,0x781,0x783,0x785,0x786,0x788,0x78A,0x78C,0x78E,0x790,0x791,0x793,0x795,0x797,
0x799,0x79B,0x79D,0x79E,0x7A0,0x7A2,0x7A4,0x7A6,0x7A7,0x7A9,0x7AB,0x7AD,0x7AF,0x7B1,0x7B2,0x7B4,
0x7B6,0x7B8,0x7BA,0x7BB,0x7BD,0x7BF,0x7C1,0x7C3,0x7C4,0x7C6,0x7C8,0x7CA,0x7CC,0x7CD,0x7CF,0x7D1,
0x7D3,0x7D5,0x7D6,0x7D8,0x7DA,0x7DC,0x7DE,0x7DF,0x7E1,0x7E3,0x7E5,0x7E6,0x7E8,0x7EA,0x7EC,0x7ED,
0x7EF,0x7F1,0x7F3,0x7F5,0x7F6,0x7F8,0x7FA,0x7FC,0x7FD,0x7FF,0x801,0x803,0x804,0x806,0x808,0x80A,
0x80B,0x80D,0x80F,0x810,0x812,0x814,0x816,0x817,0x819,0x81B,0x81D,0x81E,0x820,0x822,0x823,0x825,
0x827,0x829,0x82A,0x82C,0x82E,0x82F,0x831,0x833,0x835,0x836,0x838,0x83A,0x83B,0x83D,0x83F,0x841,
0x842,0x844,0x846,0x847,0x849,0x84B,0x84C,0x84E,0x850,0x851,0x853,0x855,0x856,0x858,0x85A,0x85B,
0x85D,0x85F,0x860,0x862,0x864,0x865,0x867,0x869,0x86A,0x86C,0x86E,0x86F,0x871,0x873,0x874,0x876,
0x878,0x879,0x87B,0x87D,0x87E,0x880,0x881,0x883,0x885,0x886,0x888,0x88A,0x88B,0x88D,0x88F,0x890,
0x892,0x893,0x895,0x897,0x898,0x89A,0x89C,0x89D,0x89F,0x8A0,0x8A2,0x8A4,0x8A5,0x8A7,0x8A8,0x8AA,
0x8AC,0x8AD,0x8AF,0x8B0,0x8B2,0x8B4,0x8B5,0x8B7,0x8B8,0x8BA,0x8BC,0x8BD,0x8BF,0x8C0,0x8C2,0x8C4,
0x8C5,0x8C7,0x8C8,0x8CA,0x8CB,0x8CD,0x8CF,0x8D0,0x8D2,0x8D3,0x8D5,0x8D6,0x8D8,0x8DA,0x8DB,0x8DD,
0x8DE,0x8E0,0x8E1,0x8E3,0x8E4,0x8E6,0x8E8,0x8E9,0x8EB,0x8EC,0x8EE,0x8EF,0x8F1,0x8F2,0x8F4,0x8F5,
0x8F7,0x8F9,0x8FA,0x8FC,0x8FD,0x8FF,0x900,0x902,0x903,0x905,0x906,0x908,0x909,0x90B,0x90C,0x90E,
0x90F,0x911,0x912,0x914,0x916,0x917,0x919,0x91A,0x91C,0x91D,0x91F,0x920,0x922,0x923,0x925,0x926,
0x928,0x929,0x92B,0x92C,0x92E,0x92F,0x931,0x932,0x934,0x935,0x936,0x938,0x939,0x93B,0x93C,0x93E,
0x93F,0x941,0x942,0x944,0x945,0x947,0x948,0x94A,0x94B,0x94D,0x94E,0x950,0x951,0x952,0x954,0x955,
0x957,0x958,0x95A,0x95B,0x95D,0x95E,0x960,0x961,0x962,0x964,0x965,0x967,0x968,0x96A,0x96B,0x96D,
0x96E,0x96F,0x971,0x972,0x974,0x975,0x977,0x978,0x979,0x97B,0x97C,0x97E,0x97F,0x981,0x982,0x983,
0x985,0x986,0x988,0x989,0x98A,0x98C,0x98D,0x98F,0x990,0x992,0x993,0x994,0x996,0x997,0x999,0x99A,
0x99B,0x99D,0x99E,0x9A0,0x9A1,0x9A2,0x9A4,0x9A5,0x9A6,0x9A8,0x9A9,0x9AB,0x9AC,0x9AD,0x9AF,0x9B0,
0x9B2,0x9B3,0x9B4,0x9B6,0x9B7,0x9B8,0x9BA,0x9BB,0x9BD,0x9BE,0x9BF,0x9C1,0x9C2,0x9C3,0x9C5,0x9C6,
0x9C7,0x9C9,0x9CA,0x9CC,0x9CD,0x9CE,0x9D0,0x9D1,0x9D2,0x9D4,0x9D5,0x9D6,0x9D8,0x9D9,0x9DA,0x9DC,
0x9DD,0x9DE,0x9E0,0x9E1,0x9E2,0x9E4,0x9E5,0x9E6,0x9E8,0x9E9,0x9EA,0x9EC,0x9ED,0x9EE,0x9F0,0x9F1,
0x9F2,0x9F4,0x9F5,0x9F6,0x9F8,0x9F9,0x9FA,0x9FC,0x9FD,0x9FE,0xA00,0xA01,0xA02,0xA04,0xA05,0xA06,
0xA07,0xA09,0xA0A,0xA0B,0xA0D,0xA0E,0xA0F,0xA11,0xA12,0xA13,0xA14,0xA16,0xA17,0xA18,0xA1A,0xA1B,
0xA1C,0xA1D,0xA1F,0xA20,0xA21,0xA23,0xA24,0xA25,0xA26,0xA28,0xA29,0xA2A,0xA2C,0xA2D,0xA2E,0xA2F,
0xA31,0xA32,0xA33,0xA34,0xA36,0xA37,0xA38,0xA3A,0xA3B,0xA3C,0xA3D,0xA3F,0xA40,0xA41,0xA42,0xA44,
0xA45,0xA46,0xA47,0xA49,0xA4A,0xA4B,0xA4C,0xA4E,0xA4F,0xA50,0xA51,0xA53,0xA54,0xA55,0xA56,0xA58,
0xA59,0xA5A,0xA5B,0xA5C,0xA5E,0xA5F,0xA60,0xA61,0xA63,0xA64,0xA65,0xA66,0xA67,0xA69,0xA6A,0xA6B,
0xA6C,0xA6E,0xA6F,0xA70,0xA71,0xA72,0xA74,0xA75,0xA76,0xA77,0xA79,0xA7A,0xA7B,0xA7C,0xA7D,0xA7F,
0xA80,0xA81,0xA82,0xA83,0xA85,0xA86,0xA87,0xA88,0xA89,0xA8B,0xA8C,0xA8D,0xA8E,0xA8F,0xA91,0xA92,
0xA93,0xA94,0xA95,0xA96,0xA98,0xA99,0xA9A,0xA9B,0xA9C,0xA9E,0xA9F,0xAA0,0xAA1,0xAA2,0xAA3,0xAA5,
0xAA6,0xAA7,0xAA8,0xAA9,0xAAA,0xAAC,0xAAD,0xAAE,0xAAF,0xAB0,0xAB1,0xAB3,0xAB4,0xAB5,0xAB6,0xAB7,
0xAB8,0xAB9,0xABB,0xABC,0xABD,0xABE,0xABF,0xAC0,0xAC2,0xAC3,0xAC4,0xAC5,0xAC6,0xAC7,0xAC8,0xACA,
0xACB,0xACC,0xACD,0xACE,0xACF,0xAD0,0xAD1,0xAD3,0xAD4,0xAD5,0xAD6,0xAD7,0xAD8,0xAD9,0xADB,0xADC,
0xADD,0xADE,0xADF,0xAE0,0xAE1,0xAE2,0xAE3,0xAE5,0xAE6,0xAE7,0xAE8,0xAE9,0xAEA,0xAEB,0xAEC,0xAEE,
0xAEF,0xAF0,0xAF1,0xAF2,0xAF3,0xAF4,0xAF5,0xAF6,0xAF7,0xAF9,0xAFA,0xAFB,0xAFC,0xAFD,0xAFE,0xAFF,
0xB00,0xB01,0xB02,0xB04,0xB05,0xB06,0xB07,0xB08,0xB09,0xB0A,0xB0B,0xB0C,0xB0D,0xB0E,0xB0F,0xB11,
0xB12,0xB13,0xB14,0xB15,0xB16,0xB17,0xB18,0xB19,0xB1A,0xB1B,0xB1C,0xB1D,0xB1E,0xB20,0xB21,0xB22,
0xB23,0xB24,0xB25,0xB26,0xB27,0xB28,0xB29,0xB2A,0xB2B,0xB2C,0xB2D,0xB2E,0xB2F,0xB30,0xB32,0xB33,
0xB34,0xB35,0xB36,0xB37,0xB38,0xB39,0xB3A,0xB3B,0xB3C,0xB3D,0xB3E,0xB3F,0xB40,0xB41,0xB42,0xB43,
0xB44,0xB45,0xB46,0xB47,0xB48,0xB49,0xB4B,0xB4C,0xB4D,0xB4E,0xB4F,0xB50,0xB51,0xB52,0xB53,0xB54,
0xB55,0xB56,0xB57,0xB58,0xB59,0xB5A,0xB5B,0xB5C,0xB5D,0xB5E,0xB5F,0xB60,0xB61,0xB62,0xB63,0xB64,
0xB65,0xB66,0xB67,0xB68,0xB69,0xB6A,0xB6B,0xB6C,0xB6D,0xB6E,0xB6F,0xB70,0xB71,0xB72,0xB73,0xB74,
0xB75,0xB76,0xB77,0xB78,0xB79,0xB7A,0xB7B,0xB7C,0xB7D,0xB7E,0xB7F,0xB80,0xB81,0xB82,0xB83,0xB84,
0xB85,0xB86,0xB87,0xB88,0xB89,0xB8A,0xB8B,0xB8C,0xB8D,0xB8E,0xB8F,0xB8F,0xB90,0xB91,0xB92,0xB93,
0xB94,0xB95,0xB96,0xB97,0xB98,0xB99,0xB9A,0xB9B,0xB9C,0xB9D,0xB9E,0xB9F,0xBA0,0xBA1,0xBA2,0xBA3,
0xBA4,0xBA5,0xBA6,0xBA7,0xBA7,0xBA8,0xBA9,0xBAA,0xBAB,0xBAC,0xBAD,0xBAE,0xBAF,0xBB0,0xBB1,0xBB2,
0xBB3,0xBB4,0xBB5,0xBB6,0xBB7,0xBB8,0xBB8,0xBB9,0xBBA,0xBBB,0xBBC,0xBBD,0xBBE,0xBBF,0xBC0,0xBC1,
0xBC2,0xBC3,0xBC4,0xBC5,0xBC5,0xBC6,0xBC7,0xBC8,0xBC9,0xBCA,0xBCB,0xBCC,0xBCD,0xBCE,0xBCF,0xBD0,
0xBD1,0xBD1,0xBD2,0xBD3,0xBD4,0xBD5,0xBD6,0xBD7,0xBD8,0xBD9,0xBDA,0xBDB,0xBDB,0xBDC,0xBDD,0xBDE,
0xBDF,0xBE0,0xBE1,0xBE2,0xBE3,0xBE4,0xBE4,0xBE5,0xBE6,0xBE7,0xBE8,0xBE9,0xBEA,0xBEB,0xBEC,0xBED,
0xBED,0xBEE,0xBEF,0xBF0,0xBF1,0xBF2,0xBF3,0xBF4,0xBF5,0xBF5,0xBF6,0xBF7,0xBF8,0xBF9,0xBFA,0xBFB,
0xBFC,0xBFC,0xBFD,0xBFE,0xBFF,0xC00,0xC01,0xC02,0xC03,0xC03,0xC04,0xC05,0xC06,0xC07,0xC08,0xC09,
0xC0A,0xC0A,0xC0B,0xC0C,0xC0D,0xC0E,0xC0F,0xC10,0xC10,0xC11,0xC12,0xC13,0xC14,0xC15,0xC16,0xC16,
0xC17,0xC18,0xC19,0xC1A,0xC1B,0xC1C,0xC1C,0xC1D,0xC1E,0xC1F,0xC20,0xC21,0xC21,0xC22,0xC23,0xC24,
0xC25,0xC26,0xC27,0xC27,0xC28,0xC29,0xC2A,0xC2B,0xC2C,0xC2C,0xC2D,0xC2E,0xC2F,0xC30,0xC31,0xC31,
0xC32,0xC33,0xC34,0xC35,0xC36,0xC36,0xC37,0xC38,0xC39,0xC3A,0xC3B,0xC3B,0xC3C,0xC3D,0xC3E,0xC3F,
0xC3F,0xC40,0xC41,0xC42,0xC43,0xC44,0xC44,0xC45,0xC46,0xC47,0xC48,0xC48,0xC49,0xC4A,0xC4B,0xC4C,
0xC4D,0xC4D,0xC4E,0xC4F,0xC50,0xC51,0xC51,0xC52,0xC53,0xC54,0xC55,0xC55,0xC56,0xC57,0xC58,0xC59,
0xC59,0xC5A,0xC5B,0xC5C,0xC5D,0xC5D,0xC5E,0xC5F,0xC60,0xC61,0xC61,0xC62,0xC63,0xC64,0xC64,0xC65,
0xC66,0xC67,0xC68,0xC68,0xC69,0xC6A,0xC6B,0xC6C,0xC6C,0xC6D,0xC6E,0xC6F,0xC6F,0xC70,0xC71,0xC72,
0xC73,0xC73,0xC74,0xC75,0xC76,0xC76,0xC77,0xC78,0xC79,0xC7A,0xC7A,0xC7B,0xC7C,0xC7D,0xC7D,0xC7E,
0xC7F,0xC80,0xC80,0xC81,0xC82,0xC83,0xC83,0xC84,0xC85,0xC86,0xC87,0xC87,0xC88,0xC89,0xC8A,0xC8A,
0xC8B,0xC8C,0xC8D,0xC8D,0xC8E,0xC8F,0xC90,0xC90,0xC91,0xC92,0xC93,0xC93,0xC94,0xC95,0xC96,0xC96,
0xC97,0xC98,0xC99,0xC99,0xC9A,0xC9B,0xC9C,0xC9C,0xC9D,0xC9E,0xC9F,0xC9F,0xCA0,0xCA1,0xCA1,0xCA2,
0xCA3,0xCA4,0xCA4,0xCA5,0xCA6,0xCA7,0xCA7,0xCA8,0xCA9,0xCAA,0xCAA,0xCAB,0xCAC,0xCAC,0xCAD,0xCAE,
0xCAF,0xCAF,0xCB0,0xCB1,0xCB2,0xCB2,0xCB3,0xCB4,0xCB4,0xCB5,0xCB6,0xCB7,0xCB7,0xCB8,0xCB9,0xCB9,
0xCBA,0xCBB,0xCBC,0xCBC,0xCBD,0xCBE,0xCBE,0xCBF,0xCC0,0xCC1,0xCC1,0xCC2,0xCC3,0xCC3,0xCC4,0xCC5,
0xCC6,0xCC6,0xCC7,0xCC8,0xCC8,0xCC9,0xCCA,0xCCA,0xCCB,0xCCC,0xCCD,0xCCD,0xCCE,0xCCF,0xCCF,0xCD0,
0xCD1,0xCD1,0xCD2,0xCD3,0xCD4,0xCD4,0xCD5,0xCD6,0xCD6,0xCD7,0xCD8,0xCD8,0xCD9,0xCDA,0xCDA,0xCDB,
0xCDC,0xCDC,0xCDD,0xCDE,0xCDF,0xCDF,0xCE0,0xCE1,0xCE1,0xCE2,0xCE3,0xCE3,0xCE4,0xCE5,0xCE5,0xCE6,
0xCE7,0xCE7,0xCE8,0xCE9,0xCE9,0xCEA,0xCEB,0xCEB,0xCEC,0xCED,0xCED,0xCEE,0xCEF,0xCEF,0xCF0,0xCF1,
0xCF1,0xCF2,0xCF3,0xCF3,0xCF4,0xCF5,0xCF5,0xCF6,0xCF7,0xCF7,0xCF8,0xCF9,0xCF9,0xCFA,0xCFB,0xCFB,
0xCFC,0xCFD,0xCFD,0xCFE,0xCFF,0xCFF,0xD00,0xD01,0xD01,0xD02,0xD03,0xD03,0xD04,0xD05,0xD05,0xD06,
0xD07,0xD07,0xD08,0xD09,0xD09,0xD0A,0xD0A,0xD0B,0xD0C,0xD0C,0xD0D,0xD0E,0xD0E,0xD0F,0xD10,0xD10,
0xD11,0xD12,0xD12,0xD13,0xD13,0xD14,0xD15,0xD15,0xD16,0xD17,0xD17,0xD18,0xD19,0xD19,0xD1A,0xD1A,
0xD1B,0xD1C,0xD1C,0xD1D,0xD1E,0xD1E,0xD1F,0xD1F,0xD20,0xD21,0xD21,0xD22,0xD23,0xD23,0xD24,0xD25,
0xD25,0xD26,0xD26,0xD27,0xD28,0xD28,0xD29,0xD29,0xD2A,0xD2B,0xD2B,0xD2C,0xD2D,0xD2D,0xD2E,0xD2E,
0xD2F,0xD30,0xD30,0xD31,0xD32,0xD32,0xD33,0xD33,0xD34,0xD35,0xD35,0xD36,0xD36,0xD37,0xD38,0xD38
};
static const unsigned short CutoffMul6581_44100Hz[] = { //generated by curvegen.c
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,0x081,
0x081,0x086,0x08B,0x08F,0x094,0x099,0x09D,0x0A2,0x0A6,0x0AB,0x0B0,0x0B4,0x0B9,0x0BE,0x0C2,0x0C7,
0x0CB,0x0D0,0x0D5,0x0D9,0x0DE,0x0E2,0x0E7,0x0EB,0x0F0,0x0F5,0x0F9,0x0FE,0x102,0x107,0x10B,0x110,
0x114,0x119,0x11D,0x122,0x126,0x12B,0x12F,0x134,0x138,0x13D,0x141,0x146,0x14A,0x14F,0x153,0x157,
0x15C,0x160,0x165,0x169,0x16E,0x172,0x176,0x17B,0x17F,0x183,0x188,0x18C,0x191,0x195,0x199,0x19E,
0x1A2,0x1A6,0x1AB,0x1AF,0x1B3,0x1B8,0x1BC,0x1C0,0x1C5,0x1C9,0x1CD,0x1D2,0x1D6,0x1DA,0x1DE,0x1E3,
0x1E7,0x1EB,0x1EF,0x1F4,0x1F8,0x1FC,0x200,0x205,0x209,0x20D,0x211,0x215,0x21A,0x21E,0x222,0x226,
0x22A,0x22F,0x233,0x237,0x23B,0x23F,0x243,0x248,0x24C,0x250,0x254,0x258,0x25C,0x260,0x265,0x269,
0x26D,0x271,0x275,0x279,0x27D,0x281,0x285,0x289,0x28D,0x292,0x296,0x29A,0x29E,0x2A2,0x2A6,0x2AA,
0x2AE,0x2B2,0x2B6,0x2BA,0x2BE,0x2C2,0x2C6,0x2CA,0x2CE,0x2D2,0x2D6,0x2DA,0x2DE,0x2E2,0x2E6,0x2EA,
0x2EE,0x2F2,0x2F6,0x2FA,0x2FD,0x301,0x305,0x309,0x30D,0x311,0x315,0x319,0x31D,0x321,0x325,0x328,
0x32C,0x330,0x334,0x338,0x33C,0x340,0x344,0x347,0x34B,0x34F,0x353,0x357,0x35B,0x35E,0x362,0x366,
0x36A,0x36E,0x371,0x375,0x379,0x37D,0x381,0x384,0x388,0x38C,0x390,0x393,0x397,0x39B,0x39F,0x3A2,
0x3A6,0x3AA,0x3AE,0x3B1,0x3B5,0x3B9,0x3BD,0x3C0,0x3C4,0x3C8,0x3CB,0x3CF,0x3D3,0x3D6,0x3DA,0x3DE,
0x3E1,0x3E5,0x3E9,0x3EC,0x3F0,0x3F4,0x3F7,0x3FB,0x3FF,0x402,0x406,0x409,0x40D,0x411,0x414,0x418,
0x41B,0x41F,0x423,0x426,0x42A,0x42D,0x431,0x435,0x438,0x43C,0x43F,0x443,0x446,0x44A,0x44D,0x451,
0x455,0x458,0x45C,0x45F,0x463,0x466,0x46A,0x46D,0x471,0x474,0x478,0x47B,0x47F,0x482,0x486,0x489,
0x48C,0x490,0x493,0x497,0x49A,0x49E,0x4A1,0x4A5,0x4A8,0x4AB,0x4AF,0x4B2,0x4B6,0x4B9,0x4BD,0x4C0,
0x4C3,0x4C7,0x4CA,0x4CE,0x4D1,0x4D4,0x4D8,0x4DB,0x4DE,0x4E2,0x4E5,0x4E8,0x4EC,0x4EF,0x4F3,0x4F6,
0x4F9,0x4FD,0x500,0x503,0x507,0x50A,0x50D,0x510,0x514,0x517,0x51A,0x51E,0x521,0x524,0x528,0x52B,
0x52E,0x531,0x535,0x538,0x53B,0x53E,0x542,0x545,0x548,0x54B,0x54F,0x552,0x555,0x558,0x55B,0x55F,
0x562,0x565,0x568,0x56C,0x56F,0x572,0x575,0x578,0x57B,0x57F,0x582,0x585,0x588,0x58B,0x58F,0x592,
0x595,0x598,0x59B,0x59E,0x5A1,0x5A5,0x5A8,0x5AB,0x5AE,0x5B1,0x5B4,0x5B7,0x5BA,0x5BD,0x5C1,0x5C4,
0x5C7,0x5CA,0x5CD,0x5D0,0x5D3,0x5D6,0x5D9,0x5DC,0x5DF,0x5E2,0x5E5,0x5E9,0x5EC,0x5EF,0x5F2,0x5F5,
0x5F8,0x5FB,0x5FE,0x601,0x604,0x607,0x60A,0x60D,0x610,0x613,0x616,0x619,0x61C,0x61F,0x622,0x625,
0x628,0x62B,0x62E,0x631,0x634,0x637,0x63A,0x63D,0x640,0x643,0x645,0x648,0x64B,0x64E,0x651,0x654,
0x657,0x65A,0x65D,0x660,0x663,0x666,0x669,0x66B,0x66E,0x671,0x674,0x677,0x67A,0x67D,0x680,0x682,
0x685,0x688,0x68B,0x68E,0x691,0x694,0x696,0x699,0x69C,0x69F,0x6A2,0x6A5,0x6A7,0x6AA,0x6AD,0x6B0,
0x6B3,0x6B6,0x6B8,0x6BB,0x6BE,0x6C1,0x6C4,0x6C6,0x6C9,0x6CC,0x6CF,0x6D2,0x6D4,0x6D7,0x6DA,0x6DD,
0x6DF,0x6E2,0x6E5,0x6E8,0x6EA,0x6ED,0x6F0,0x6F3,0x6F5,0x6F8,0x6FB,0x6FE,0x700,0x703,0x706,0x708,
0x70B,0x70E,0x711,0x713,0x716,0x719,0x71B,0x71E,0x721,0x723,0x726,0x729,0x72B,0x72E,0x731,0x733,
0x736,0x739,0x73B,0x73E,0x741,0x743,0x746,0x749,0x74B,0x74E,0x750,0x753,0x756,0x758,0x75B,0x75E,
0x760,0x763,0x765,0x768,0x76B,0x76D,0x770,0x772,0x775,0x778,0x77A,0x77D,0x77F,0x782,0x784,0x787,
0x78A,0x78C,0x78F,0x791,0x794,0x796,0x799,0x79B,0x79E,0x7A0,0x7A3,0x7A5,0x7A8,0x7AB,0x7AD,0x7B0,
0x7B2,0x7B5,0x7B7,0x7BA,0x7BC,0x7BF,0x7C1,0x7C4,0x7C6,0x7C9,0x7CB,0x7CE,0x7D0,0x7D2,0x7D5,0x7D7,
0x7DA,0x7DC,0x7DF,0x7E1,0x7E4,0x7E6,0x7E9,0x7EB,0x7ED,0x7F0,0x7F2,0x7F5,0x7F7,0x7FA,0x7FC,0x7FF,
0x801,0x803,0x806,0x808,0x80B,0x80D,0x80F,0x812,0x814,0x817,0x819,0x81B,0x81E,0x820,0x823,0x825,
0x827,0x82A,0x82C,0x82E,0x831,0x833,0x835,0x838,0x83A,0x83D,0x83F,0x841,0x844,0x846,0x848,0x84B,
0x84D,0x84F,0x852,0x854,0x856,0x858,0x85B,0x85D,0x85F,0x862,0x864,0x866,0x869,0x86B,0x86D,0x86F,
0x872,0x874,0x876,0x879,0x87B,0x87D,0x87F,0x882,0x884,0x886,0x888,0x88B,0x88D,0x88F,0x892,0x894,
0x896,0x898,0x89A,0x89D,0x89F,0x8A1,0x8A3,0x8A6,0x8A8,0x8AA,0x8AC,0x8AE,0x8B1,0x8B3,0x8B5,0x8B7,
0x8BA,0x8BC,0x8BE,0x8C0,0x8C2,0x8C4,0x8C7,0x8C9,0x8CB,0x8CD,0x8CF,0x8D2,0x8D4,0x8D6,0x8D8,0x8DA,
0x8DC,0x8DF,0x8E1,0x8E3,0x8E5,0x8E7,0x8E9,0x8EB,0x8EE,0x8F0,0x8F2,0x8F4,0x8F6,0x8F8,0x8FA,0x8FC,
0x8FF,0x901,0x903,0x905,0x907,0x909,0x90B,0x90D,0x90F,0x912,0x914,0x916,0x918,0x91A,0x91C,0x91E,
0x920,0x922,0x924,0x926,0x928,0x92B,0x92D,0x92F,0x931,0x933,0x935,0x937,0x939,0x93B,0x93D,0x93F,
0x941,0x943,0x945,0x947,0x949,0x94B,0x94D,0x94F,0x951,0x953,0x955,0x957,0x959,0x95B,0x95D,0x95F,
0x961,0x963,0x965,0x967,0x969,0x96B,0x96D,0x96F,0x971,0x973,0x975,0x977,0x979,0x97B,0x97D,0x97F,
0x981,0x983,0x985,0x987,0x989,0x98B,0x98D,0x98F,0x991,0x993,0x995,0x997,0x999,0x99B,0x99C,0x99E,
0x9A0,0x9A2,0x9A4,0x9A6,0x9A8,0x9AA,0x9AC,0x9AE,0x9B0,0x9B2,0x9B3,0x9B5,0x9B7,0x9B9,0x9BB,0x9BD,
0x9BF,0x9C1,0x9C3,0x9C5,0x9C6,0x9C8,0x9CA,0x9CC,0x9CE,0x9D0,0x9D2,0x9D4,0x9D5,0x9D7,0x9D9,0x9DB,
0x9DD,0x9DF,0x9E1,0x9E2,0x9E4,0x9E6,0x9E8,0x9EA,0x9EC,0x9ED,0x9EF,0x9F1,0x9F3,0x9F5,0x9F7,0x9F8,
0x9FA,0x9FC,0x9FE,0xA00,0xA02,0xA03,0xA05,0xA07,0xA09,0xA0B,0xA0C,0xA0E,0xA10,0xA12,0xA14,0xA15,
0xA17,0xA19,0xA1B,0xA1C,0xA1E,0xA20,0xA22,0xA24,0xA25,0xA27,0xA29,0xA2B,0xA2C,0xA2E,0xA30,0xA32,
0xA33,0xA35,0xA37,0xA39,0xA3A,0xA3C,0xA3E,0xA40,0xA41,0xA43,0xA45,0xA47,0xA48,0xA4A,0xA4C,0xA4E,
0xA4F,0xA51,0xA53,0xA54,0xA56,0xA58,0xA5A,0xA5B,0xA5D,0xA5F,0xA60,0xA62,0xA64,0xA65,0xA67,0xA69,
0xA6B,0xA6C,0xA6E,0xA70,0xA71,0xA73,0xA75,0xA76,0xA78,0xA7A,0xA7B,0xA7D,0xA7F,0xA80,0xA82,0xA84,
0xA85,0xA87,0xA89,0xA8A,0xA8C,0xA8E,0xA8F,0xA91,0xA92,0xA94,0xA96,0xA97,0xA99,0xA9B,0xA9C,0xA9E,
0xAA0,0xAA1,0xAA3,0xAA4,0xAA6,0xAA8,0xAA9,0xAAB,0xAAC,0xAAE,0xAB0,0xAB1,0xAB3,0xAB5,0xAB6,0xAB8,
0xAB9,0xABB,0xABC,0xABE,0xAC0,0xAC1,0xAC3,0xAC4,0xAC6,0xAC8,0xAC9,0xACB,0xACC,0xACE,0xACF,0xAD1,
0xAD3,0xAD4,0xAD6,0xAD7,0xAD9,0xADA,0xADC,0xADE,0xADF,0xAE1,0xAE2,0xAE4,0xAE5,0xAE7,0xAE8,0xAEA,
0xAEB,0xAED,0xAEE,0xAF0,0xAF2,0xAF3,0xAF5,0xAF6,0xAF8,0xAF9,0xAFB,0xAFC,0xAFE,0xAFF,0xB01,0xB02,
0xB04,0xB05,0xB07,0xB08,0xB0A,0xB0B,0xB0D,0xB0E,0xB10,0xB11,0xB13,0xB14,0xB16,0xB17,0xB19,0xB1A,
0xB1C,0xB1D,0xB1F,0xB20,0xB22,0xB23,0xB24,0xB26,0xB27,0xB29,0xB2A,0xB2C,0xB2D,0xB2F,0xB30,0xB32,
0xB33,0xB35,0xB36,0xB37,0xB39,0xB3A,0xB3C,0xB3D,0xB3F,0xB40,0xB42,0xB43,0xB44,0xB46,0xB47,0xB49,
0xB4A,0xB4C,0xB4D,0xB4E,0xB50,0xB51,0xB53,0xB54,0xB55,0xB57,0xB58,0xB5A,0xB5B,0xB5C,0xB5E,0xB5F,
0xB61,0xB62,0xB63,0xB65,0xB66,0xB68,0xB69,0xB6A,0xB6C,0xB6D,0xB6F,0xB70,0xB71,0xB73,0xB74,0xB75,
0xB77,0xB78,0xB7A,0xB7B,0xB7C,0xB7E,0xB7F,0xB80,0xB82,0xB83,0xB84,0xB86,0xB87,0xB89,0xB8A,0xB8B,
0xB8D,0xB8E,0xB8F,0xB91,0xB92,0xB93,0xB95,0xB96,0xB97,0xB99,0xB9A,0xB9B,0xB9D,0xB9E,0xB9F,0xBA1,
0xBA2,0xBA3,0xBA5,0xBA6,0xBA7,0xBA8,0xBAA,0xBAB,0xBAC,0xBAE,0xBAF,0xBB0,0xBB2,0xBB3,0xBB4,0xBB6,
0xBB7,0xBB8,0xBB9,0xBBB,0xBBC,0xBBD,0xBBF,0xBC0,0xBC1,0xBC2,0xBC4,0xBC5,0xBC6,0xBC8,0xBC9,0xBCA,
0xBCB,0xBCD,0xBCE,0xBCF,0xBD0,0xBD2,0xBD3,0xBD4,0xBD5,0xBD7,0xBD8,0xBD9,0xBDB,0xBDC,0xBDD,0xBDE,
0xBE0,0xBE1,0xBE2,0xBE3,0xBE4,0xBE6,0xBE7,0xBE8,0xBE9,0xBEB,0xBEC,0xBED,0xBEE,0xBF0,0xBF1,0xBF2,
0xBF3,0xBF5,0xBF6,0xBF7,0xBF8,0xBF9,0xBFB,0xBFC,0xBFD,0xBFE,0xBFF,0xC01,0xC02,0xC03,0xC04,0xC05,
0xC07,0xC08,0xC09,0xC0A,0xC0B,0xC0D,0xC0E,0xC0F,0xC10,0xC11,0xC13,0xC14,0xC15,0xC16,0xC17,0xC19,
0xC1A,0xC1B,0xC1C,0xC1D,0xC1E,0xC20,0xC21,0xC22,0xC23,0xC24,0xC25,0xC27,0xC28,0xC29,0xC2A,0xC2B,
0xC2C,0xC2E,0xC2F,0xC30,0xC31,0xC32,0xC33,0xC34,0xC36,0xC37,0xC38,0xC39,0xC3A,0xC3B,0xC3C,0xC3E,
0xC3F,0xC40,0xC41,0xC42,0xC43,0xC44,0xC46,0xC47,0xC48,0xC49,0xC4A,0xC4B,0xC4C,0xC4D,0xC4F,0xC50,
0xC51,0xC52,0xC53,0xC54,0xC55,0xC56,0xC57,0xC59,0xC5A,0xC5B,0xC5C,0xC5D,0xC5E,0xC5F,0xC60,0xC61,
0xC62,0xC63,0xC65,0xC66,0xC67,0xC68,0xC69,0xC6A,0xC6B,0xC6C,0xC6D,0xC6E,0xC6F,0xC71,0xC72,0xC73,
0xC74,0xC75,0xC76,0xC77,0xC78,0xC79,0xC7A,0xC7B,0xC7C,0xC7D,0xC7E,0xC7F,0xC81,0xC82,0xC83,0xC84,
0xC85,0xC86,0xC87,0xC88,0xC89,0xC8A,0xC8B,0xC8C,0xC8D,0xC8E,0xC8F,0xC90,0xC91,0xC92,0xC93,0xC94,
0xC95,0xC96,0xC97,0xC99,0xC9A,0xC9B,0xC9C,0xC9D,0xC9E,0xC9F,0xCA0,0xCA1,0xCA2,0xCA3,0xCA4,0xCA5,
0xCA6,0xCA7,0xCA8,0xCA9,0xCAA,0xCAB,0xCAC,0xCAD,0xCAE,0xCAF,0xCB0,0xCB1,0xCB2,0xCB3,0xCB4,0xCB5,
0xCB6,0xCB7,0xCB8,0xCB9,0xCBA,0xCBB,0xCBC,0xCBD,0xCBE,0xCBF,0xCC0,0xCC1,0xCC2,0xCC3,0xCC4,0xCC5,
0xCC6,0xCC7,0xCC8,0xCC9,0xCCA,0xCCA,0xCCB,0xCCC,0xCCD,0xCCE,0xCCF,0xCD0,0xCD1,0xCD2,0xCD3,0xCD4,
0xCD5,0xCD6,0xCD7,0xCD8,0xCD9,0xCDA,0xCDB,0xCDC,0xCDD,0xCDE,0xCDF,0xCE0,0xCE0,0xCE1,0xCE2,0xCE3,
0xCE4,0xCE5,0xCE6,0xCE7,0xCE8,0xCE9,0xCEA,0xCEB,0xCEC,0xCED,0xCEE,0xCEF,0xCEF,0xCF0,0xCF1,0xCF2,
0xCF3,0xCF4,0xCF5,0xCF6,0xCF7,0xCF8,0xCF9,0xCFA,0xCFA,0xCFB,0xCFC,0xCFD,0xCFE,0xCFF,0xD00,0xD01,
0xD02,0xD03,0xD04,0xD04,0xD05,0xD06,0xD07,0xD08,0xD09,0xD0A,0xD0B,0xD0C,0xD0D,0xD0D,0xD0E,0xD0F,
0xD10,0xD11,0xD12,0xD13,0xD14,0xD15,0xD15,0xD16,0xD17,0xD18,0xD19,0xD1A,0xD1B,0xD1C,0xD1C,0xD1D,
0xD1E,0xD1F,0xD20,0xD21,0xD22,0xD23,0xD23,0xD24,0xD25,0xD26,0xD27,0xD28,0xD29,0xD29,0xD2A,0xD2B,
0xD2C,0xD2D,0xD2E,0xD2F,0xD2F,0xD30,0xD31,0xD32,0xD33,0xD34,0xD34,0xD35,0xD36,0xD37,0xD38,0xD39,
0xD3A,0xD3A,0xD3B,0xD3C,0xD3D,0xD3E,0xD3F,0xD3F,0xD40,0xD41,0xD42,0xD43,0xD44,0xD44,0xD45,0xD46,
0xD47,0xD48,0xD48,0xD49,0xD4A,0xD4B,0xD4C,0xD4D,0xD4D,0xD4E,0xD4F,0xD50,0xD51,0xD51,0xD52,0xD53,
0xD54,0xD55,0xD55,0xD56,0xD57,0xD58,0xD59,0xD5A,0xD5A,0xD5B,0xD5C,0xD5D,0xD5D,0xD5E,0xD5F,0xD60,
0xD61,0xD61,0xD62,0xD63,0xD64,0xD65,0xD65,0xD66,0xD67,0xD68,0xD69,0xD69,0xD6A,0xD6B,0xD6C,0xD6C,
0xD6D,0xD6E,0xD6F,0xD70,0xD70,0xD71,0xD72,0xD73,0xD73,0xD74,0xD75,0xD76,0xD77,0xD77,0xD78,0xD79,
0xD7A,0xD7A,0xD7B,0xD7C,0xD7D,0xD7D,0xD7E,0xD7F,0xD80,0xD80,0xD81,0xD82,0xD83,0xD83,0xD84,0xD85,
0xD86,0xD86,0xD87,0xD88,0xD89,0xD89,0xD8A,0xD8B,0xD8C,0xD8C,0xD8D,0xD8E,0xD8F,0xD8F,0xD90,0xD91,
0xD92,0xD92,0xD93,0xD94,0xD94,0xD95,0xD96,0xD97,0xD97,0xD98,0xD99,0xD9A,0xD9A,0xD9B,0xD9C,0xD9C,
0xD9D,0xD9E,0xD9F,0xD9F,0xDA0,0xDA1,0xDA1,0xDA2,0xDA3,0xDA4,0xDA4,0xDA5,0xDA6,0xDA6,0xDA7,0xDA8,
0xDA9,0xDA9,0xDAA,0xDAB,0xDAB,0xDAC,0xDAD,0xDAE,0xDAE,0xDAF,0xDB0,0xDB0,0xDB1,0xDB2,0xDB2,0xDB3,
0xDB4,0xDB5,0xDB5,0xDB6,0xDB7,0xDB7,0xDB8,0xDB9,0xDB9,0xDBA,0xDBB,0xDBB,0xDBC,0xDBD,0xDBD,0xDBE,
0xDBF,0xDC0,0xDC0,0xDC1,0xDC2,0xDC2,0xDC3,0xDC4,0xDC4,0xDC5,0xDC6,0xDC6,0xDC7,0xDC8,0xDC8,0xDC9,
0xDCA,0xDCA,0xDCB,0xDCC,0xDCC,0xDCD,0xDCE,0xDCE,0xDCF,0xDD0,0xDD0,0xDD1,0xDD2,0xDD2,0xDD3,0xDD4,
0xDD4,0xDD5,0xDD6,0xDD6,0xDD7,0xDD8,0xDD8,0xDD9,0xDD9,0xDDA,0xDDB,0xDDB,0xDDC,0xDDD,0xDDD,0xDDE,
0xDDF,0xDDF,0xDE0,0xDE1,0xDE1,0xDE2,0xDE2,0xDE3,0xDE4,0xDE4,0xDE5,0xDE6,0xDE6,0xDE7,0xDE8,0xDE8,
0xDE9,0xDE9,0xDEA,0xDEB,0xDEB,0xDEC,0xDED,0xDED,0xDEE,0xDEE,0xDEF,0xDF0,0xDF0,0xDF1,0xDF2,0xDF2,
0xDF3,0xDF3,0xDF4,0xDF5,0xDF5,0xDF6,0xDF7,0xDF7,0xDF8,0xDF8,0xDF9,0xDFA,0xDFA,0xDFB,0xDFB,0xDFC,
0xDFD,0xDFD,0xDFE,0xDFE,0xDFF,0xE00,0xE00,0xE01,0xE02,0xE02,0xE03,0xE03,0xE04,0xE05,0xE05,0xE06,
0xE06,0xE07,0xE08,0xE08,0xE09,0xE09,0xE0A,0xE0A,0xE0B,0xE0C,0xE0C,0xE0D,0xE0D,0xE0E,0xE0F,0xE0F,
0xE10,0xE10,0xE11,0xE12,0xE12,0xE13,0xE13,0xE14,0xE14,0xE15,0xE16,0xE16,0xE17,0xE17,0xE18,0xE18,
0xE19,0xE1A,0xE1A,0xE1B,0xE1B,0xE1C,0xE1C,0xE1D,0xE1E,0xE1E,0xE1F,0xE1F,0xE20,0xE20,0xE21,0xE22,
0xE22,0xE23,0xE23,0xE24,0xE24,0xE25,0xE26,0xE26,0xE27,0xE27,0xE28,0xE28,0xE29,0xE29,0xE2A,0xE2B,
0xE2B,0xE2C,0xE2C,0xE2D,0xE2D,0xE2E,0xE2E,0xE2F,0xE30,0xE30,0xE31,0xE31,0xE32,0xE32,0xE33,0xE33,
0xE34,0xE34,0xE35,0xE36,0xE36,0xE37,0xE37,0xE38,0xE38,0xE39,0xE39,0xE3A,0xE3A,0xE3B,0xE3B,0xE3C,
0xE3C,0xE3D,0xE3E,0xE3E,0xE3F,0xE3F,0xE40,0xE40,0xE41,0xE41,0xE42,0xE42,0xE43,0xE43,0xE44,0xE44
};
static const unsigned char SawTriangle [] = {
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,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,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,0x03,0x03,
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,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,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,0x07,0x07,0x07,0x07,
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,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,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,0x03,0x03,
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,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,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,0x0E,0x0E,0x0E,0x0E,0x0F,0x0F,0x0F,0x0F,
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,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,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,0x03,0x03,
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,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,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,0x07,0x07,0x07,0x07,
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,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,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,0x03,0x03,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1E,0x1E,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
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,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,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,0x03,0x03,
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,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,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,0x07,0x07,0x07,0x07,
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,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,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,0x03,0x03,
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,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,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,0x0E,0x0E,0x0E,0x0E,0x0F,0x0F,0x0F,0x1F,
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,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,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,0x03,0x03,
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,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,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,0x07,0x07,0x07,0x07,
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,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,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,0x03,0x03,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,
0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3E,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
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,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,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,0x03,0x03,
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,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,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,0x07,0x07,0x07,0x07,
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,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,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,0x03,0x03,
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,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,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,0x0E,0x0E,0x0E,0x0E,0x0F,0x0F,0x0F,0x0F,
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,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,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,0x03,0x03,
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,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,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,0x07,0x07,0x07,0x07,
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,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,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,0x03,0x03,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1E,0x1E,0x1F,0x1F,0x1F,0x1F,0x3F,0x3F,
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,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,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,0x03,0x03,
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,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,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,0x07,0x07,0x07,0x07,
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,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,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,0x03,0x03,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x0E,0x0F,0x0F,0x1F,0x1F,
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,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,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,0x80,0x00,0x83,0x83,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x87,0x87,0x87,0x8F,
0xC0,0xE0,0xE0,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xC0,0xE0,0xE0,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xE0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE3,0xE3,
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF1,
0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,
0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
static const unsigned char PulseTriangle [] = { //can be substituted by PulseSaw with mirroring the upper half (like with triangle-waveform)
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,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,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,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,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,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,0x07,
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,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,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,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,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,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,0x1C,0x00,0x3C,0x3F,0x3F,
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,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,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,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,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,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,0x0C,0x5E,0x5F,
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,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,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,0x40,0x00,0x00,0x00,0x40,0x40,0x60,0x60,0x6F,
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,0x40,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x60,0x40,0x40,0x60,0x60,0x60,0x60,0x70,0x77,
0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60,0x60,0x60,0x40,0x40,0x40,0x60,0x60,0x60,0x60,0x70,0x60,0x60,0x60,0x70,0x70,0x70,0x78,0x7B,
0x60,0x60,0x60,0x70,0x60,0x70,0x70,0x70,0x70,0x70,0x70,0x78,0x78,0x78,0x78,0x7C,0x78,0x78,0x78,0x7C,0x78,0x7C,0x7C,0x7E,0x7C,0x7E,0x7E,0x7F,0x7F,0x7F,0x7F,0x7F,
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,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,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,0x80,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x8E,0x9F,
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,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xAF,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xA0,0xA0,0xA0,0xA0,0xB7,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xA0,0x80,0x80,0x80,0x80,0x80,0x80,0xA0,0xA0,0xA0,0xA0,0xA0,0xB0,0xA0,0xB0,0xB0,0xBB,
0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xB0,0xB0,0xA0,0xB0,0xB0,0xB8,0xB0,0xB8,0xB8,0xBC,0xB0,0xB8,0xB8,0xB8,0xB8,0xBC,0xBC,0xBE,0xBC,0xBC,0xBE,0xBF,0xBE,0xBF,0xBF,0xBF,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0x80,0x80,0x80,0xC0,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xCF,
0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,0xC0,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xD7,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xD0,0xD0,0xD9,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xD0,0xC0,0xD0,0xD0,0xD0,0xD0,0xD8,0xD8,0xDC,0xD0,0xD0,0xD8,0xD8,0xD8,0xDC,0xDC,0xDE,0xDC,0xDC,0xDE,0xDF,0xDE,0xDF,0xDF,0xDF,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xC0,0xE0,0xE0,0xE0,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE7,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE8,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE8,0xEC,0xE0,0xE0,0xE0,0xE8,0xE8,0xE8,0xEC,0xEE,0xEC,0xEC,0xEC,0xEE,0xEE,0xEF,0xEF,0xEF,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,0xF0,0xF0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF4,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF4,0xF0,0xF4,0xF4,0xF6,0xF6,0xF7,0xF7,0xF7,
0xF0,0xF0,0xF0,0xF8,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFA,0xFA,0xFB,0xFB,0xFB,
0xF8,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFC,0xFD,0xFD,0xFD,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xF8,
0xFB,0xFB,0xFB,0xFA,0xFA,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xF0,0xF0,0xF0,
0xF7,0xF7,0xF7,0xF6,0xF6,0xF4,0xF4,0xF0,0xF4,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF4,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0xE0,0xF0,0xF0,0xF0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xEF,0xEF,0xEF,0xEE,0xEE,0xEC,0xEC,0xE8,0xEE,0xEC,0xE8,0xE8,0xE8,0xE0,0xE0,0xE0,0xEC,0xE8,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE8,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE7,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xC0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xE0,0xE0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xDF,0xDF,0xDF,0xDE,0xDF,0xDE,0xDC,0xDC,0xDE,0xDC,0xDC,0xD8,0xD8,0xD8,0xD0,0xD0,0xDC,0xD8,0xD8,0xD0,0xD0,0xD0,0xD0,0xC0,0xD0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xD9,0xD0,0xD0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xD7,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x80,0xC0,0xC0,0xC0,0x80,0x80,0x80,0x80,0x80,
0xCF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x80,0xC0,0x80,0x80,0x80,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x80,0x80,0xC0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0xC0,0xC0,0xC0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0xBF,0xBF,0xBF,0xBE,0xBF,0xBE,0xBC,0xBC,0xBE,0xBC,0xBC,0xB8,0xB8,0xB8,0xB8,0xB0,0xBC,0xB8,0xB8,0xB0,0xB8,0xB0,0xB0,0xB0,0xB0,0xB0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,
0xBB,0xB0,0xB0,0xA0,0xB0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0x80,0x80,0x80,0x80,0x80,0xA0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0xB7,0xB0,0xA0,0xA0,0xA0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0xAF,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x80,0x00,0x00,0x00,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x80,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,
0x9F,0x9E,0x88,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,
0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x80,0x80,0x00,0x80,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,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,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,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,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7E,0x7E,0x7C,0x7E,0x7C,0x7C,0x78,0x7C,0x78,0x78,0x78,0x7C,0x78,0x78,0x78,0x78,0x70,0x70,0x70,0x78,0x70,0x70,0x60,0x70,0x60,0x60,0x60,
0x7B,0x78,0x70,0x70,0x70,0x60,0x60,0x60,0x70,0x60,0x60,0x60,0x60,0x40,0x40,0x40,0x60,0x60,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x40,0x00,0x00,0x00,
0x77,0x70,0x60,0x60,0x60,0x60,0x40,0x40,0x60,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x40,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,
0x6F,0x64,0x60,0x40,0x40,0x00,0x00,0x00,0x40,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,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,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,
0x5F,0x5E,0x4C,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,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,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,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,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,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,
0x3F,0x3F,0x3E,0x00,0x1C,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,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,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,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,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,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,
0x07,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,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,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,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,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,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
};
static const unsigned char PulseSawtooth [] = {
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,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,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,0x03,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,
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,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,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,0x07,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
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,0x01,
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,0x07,0x07,0x1F,
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,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,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,0x03,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
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,0x01,
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,0x01,0x0F,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,
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,0x3D,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x0C,0x1C,0x3F,0x1E,0x3F,0x3F,0x3F,
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,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,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,0x03,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,
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,0x0A,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0x00,0x00,0x00,0x5F,0x0C,0x5F,0x5F,0x5F,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,
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,0x65,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x40,0x40,0x6F,0x40,0x6F,0x6F,0x6F,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,
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,0x40,0x61,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x40,0x40,0x70,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x70,0x40,0x60,0x60,0x77,0x60,0x77,0x77,0x77,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x60,0x00,0x40,0x40,0x60,0x40,0x60,0x60,0x79,
0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x60,0x40,0x40,0x40,0x60,0x60,0x60,0x60,0x78,0x40,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x60,0x70,0x70,0x78,0x70,0x79,0x7B,0x7B,
0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x70,0x60,0x60,0x60,0x70,0x60,0x70,0x70,0x7C,0x60,0x70,0x70,0x70,0x70,0x70,0x70,0x7C,0x70,0x78,0x78,0x7C,0x78,0x7C,0x7C,0x7D,
0x70,0x78,0x78,0x78,0x78,0x78,0x78,0x7C,0x78,0x7C,0x7C,0x7E,0x7C,0x7E,0x7E,0x7E,0x7C,0x7C,0x7C,0x7E,0x7E,0x7F,0x7F,0x7F,0x7E,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0xFF,
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,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,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,0x03,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,
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,0x80,0x8D,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x8E,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x8F,0x80,0x80,0x80,0x9F,0x80,0x9F,0x9F,0x9F,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
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,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x87,
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,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x83,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x81,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x84,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x87,0x80,0x80,0x80,0x87,0x80,0x8F,0xAF,0xAF,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,
0x00,0x00,0x00,0x80,0x00,0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x81,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xA0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xA0,0x80,0x80,0x80,0xA0,0x80,0xA3,0xB7,0xB7,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xB1,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xB0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xB0,0x80,0xA0,0xA0,0xB0,0xA0,0xB8,0xB9,0xBB,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xA0,0x80,0x80,0x80,0xA0,0x80,0xA0,0xA0,0xB8,0x80,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xB8,0xA0,0xB0,0xB0,0xB8,0xB0,0xBC,0xBC,0xBD,
0xA0,0xB0,0xB0,0xB0,0xB0,0xB8,0xB8,0xBC,0xB0,0xB8,0xB8,0xBC,0xB8,0xBC,0xBE,0xBE,0xB8,0xBC,0xBC,0xBE,0xBC,0xBE,0xBE,0xBF,0xBE,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x81,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC7,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC3,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x80,0x80,0xC0,0x80,0xC0,0xC0,0xC1,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x80,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC7,0xC0,0xC0,0xC0,0xC7,0xC0,0xCF,0xCF,0xCF,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC3,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x80,0x80,0xC0,0x80,0xC0,0xC0,0xC0,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC1,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC1,0xC7,0xD7,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xD0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xD0,0xC0,0xC0,0xC0,0xD0,0xC0,0xD0,0xD8,0xDB,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xD8,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xD8,0xC0,0xC0,0xC0,0xD8,0xD0,0xD8,0xD8,0xDD,
0xC0,0xC0,0xC0,0xD0,0xC0,0xD0,0xD0,0xDC,0xD0,0xD8,0xD8,0xDC,0xD8,0xDC,0xDC,0xDE,0xD8,0xDC,0xDC,0xDE,0xDC,0xDE,0xDE,0xDF,0xDE,0xDF,0xDF,0xDF,0xDF,0xDF,0xDF,0xDF,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE3,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xC0,0xC0,0xC0,0xE0,0xC0,0xE0,0xE0,0xE1,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xC0,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE1,0xE3,0xE7,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xC0,0xC0,0xC0,0xE0,0xC0,0xE0,0xE0,0xE0,0xC0,0xC0,0xC0,0xE0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xEB,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE8,0xE0,0xE8,0xE8,0xED,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xEC,0xE0,0xE0,0xE0,0xEC,0xE8,0xEC,0xEC,0xEE,0xE8,0xE8,0xE8,0xEC,0xEC,0xEE,0xEE,0xEF,0xEC,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,0xE0,0xE0,0xE0,0xF0,0xE0,0xF0,0xF0,0xF0,0xE0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF3,
0xE0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF5,
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF4,0xF4,0xF6,0xF0,0xF0,0xF0,0xF4,0xF0,0xF4,0xF6,0xF7,0xF4,0xF6,0xF6,0xF7,0xF7,0xF7,0xF7,0xF7,
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF8,0xF0,0xF0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF0,0xF0,0xF0,0xF8,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF9,
0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFA,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFB,0xF8,0xFA,0xFA,0xFB,0xFB,0xFB,0xFB,0xFB,
0xF8,0xF8,0xF8,0xFC,0xF8,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFD,0xFC,0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFD,
0xFC,0xFC,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
static const unsigned char PulseSawTriangle [] = {
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0x1F,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x70,0x60,0x20,0x70,0x70,0x70,0x70,0x70,0x78,0x78,0x78,0x7C,0x7C,0x7E,0x7E,0x7F,0x7F,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0x08,0x1E,0x3F,
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,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,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,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,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,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,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,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,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,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,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,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,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x8C,0x9F,
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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,
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,0x80,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x00,0x00,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xCF,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xC0,0xC0,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE3,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,
0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};

View file

@ -0,0 +1,64 @@
//VIC-II emulation
void cRSID_createVICchip (cRSID_C64instance* C64, cRSID_VICinstance* VIC, unsigned short baseaddress) {
VIC->C64 = C64;
VIC->ChipModel = 0;
VIC->BaseAddress = baseaddress;
VIC->BasePtrWR = &C64->IObankWR[baseaddress]; VIC->BasePtrRD = &C64->IObankRD[baseaddress];
cRSID_initVICchip (VIC);
}
void cRSID_initVICchip (cRSID_VICinstance* VIC) {
unsigned char i;
for (i=0; i<0x3F; ++i) VIC->BasePtrWR[i] = VIC->BasePtrRD[i] = 0x00;
VIC->RowCycleCnt=0;
}
static inline char cRSID_emulateVIC (cRSID_VICinstance* VIC, char cycles) {
unsigned short RasterRow;
enum VICregisters { CONTROL = 0x11, RASTERROWL = 0x12, INTERRUPT = 0x19, INTERRUPT_ENABLE = 0x1A };
enum ControlBitVal { RASTERROWMSB = 0x80, DISPLAY_ENABLE = 0x10, ROWS = 0x08, YSCROLL_MASK = 0x07 };
enum InterruptBitVal { VIC_IRQ = 0x80, RASTERROW_MATCH_IRQ = 0x01 };
VIC->RowCycleCnt += cycles;
if (VIC->RowCycleCnt >= VIC->RasterRowCycles) {
VIC->RowCycleCnt -= VIC->RasterRowCycles;
RasterRow = ( (VIC->BasePtrRD[CONTROL]&RASTERROWMSB) << 1 ) + VIC->BasePtrRD[RASTERROWL];
++RasterRow; if (RasterRow >= VIC->RasterLines) RasterRow = 0;
VIC->BasePtrRD[CONTROL] = ( VIC->BasePtrRD[CONTROL] & ~RASTERROWMSB ) | ((RasterRow&0x100)>>1);
VIC->BasePtrRD[RASTERROWL] = RasterRow & 0xFF;
if (VIC->BasePtrWR[INTERRUPT_ENABLE] & RASTERROW_MATCH_IRQ) {
if ( RasterRow == ( (VIC->BasePtrWR[CONTROL]&RASTERROWMSB) << 1 ) + VIC->BasePtrWR[RASTERROWL] ) {
VIC->BasePtrRD[INTERRUPT] |= VIC_IRQ | RASTERROW_MATCH_IRQ;
}
}
}
return VIC->BasePtrRD[INTERRUPT] & VIC_IRQ;
}
static inline void cRSID_acknowledgeVICrasterIRQ (cRSID_VICinstance* VIC) {
enum VICregisters { INTERRUPT = 0x19 };
enum InterruptBitVal { VIC_IRQ = 0x80, RASTERROW_MATCH_IRQ = 0x01 };
//An 1 is to be written into the IRQ-flag (bit0) of $d019 to clear it and deassert IRQ signal
//if (VIC->BasePtrWR[INTERRUPT] & RASTERROW_MATCH_IRQ) { //acknowledge raster-interrupt by writing to $d019 bit0?
//But oftentimes INC/LSR/etc. RMW commands are used to acknowledge VIC IRQ, they work on real
//CPU because it writes the unmodified original value itself to memory before writing the modified there
VIC->BasePtrWR[INTERRUPT] &= ~RASTERROW_MATCH_IRQ; //prepare for next acknowledge-detection
VIC->BasePtrRD[INTERRUPT] &= ~(VIC_IRQ | RASTERROW_MATCH_IRQ); //remove IRQ flag and state
//}
}

View file

@ -0,0 +1,39 @@
cRSID by Hermit (Mihaly Horvath) - Year 2022
--------------------------------------------
This is a serious integer-only update (rewrite) to my cSID and cSID-light
commandline SID-players, aiming for an ongoing inclusion into RockBox,
as per a request by Ninja earlier at CSDb. He will do the integration.
The name now contains the 'R' because now a RealSID-like environment-mode
(CIA, VIC, IRQ, NMI) is supported more-or-less ('RealSIDmode' in source).
There are still many RSID tunes that are not played properly, mainly
the tricky ones which use DC04 or DD0C as jump-addresses or RTI placeholders,
like for example 'Hi Fi Sky', and other modern digi tunes.
I don't feel like debugging these complex tunes now...
PSID-only playback has improved a lot since cSID-light-1.1,
and now many PlaySID-digis are supported as well if that still matters.
The CPU and ADSR went through serious timing improvements,
it's now can be called cycle-exact, and hardrestarts and delaybugs are now
simulated well, no missed notes, whatever.
This release also contains shared and static library forms for better
inclusion in other SID-playback projects (like FlexSID for example).
I completely eliminated global variables and definitions, except a
'cRSID_c64' instance which is for faster access of struct members.
(Emulated C64 memory accesses are made to this for faster operation.)
More info (the API for the library) is seen in the 'libcRSID.h' file.
It has been tried already on a SanDisk RockBox device and tunes not
containing digis are already played on it fine. Tunes with 2SID/3SID or
digis however are too much for the player (38MHz..192MHz ARM) at this form.
So maybe the code will be optimized by eliminating overheads of structs,
pointers, optimizing function-calls, inlining, and by other possible means.
Hopefully in the near future the outdated TinySID engine will be replaced
in the RockBox source-tree...
License is still WTF: Do what the fuck you want with this code, but
it would be nice mentioning me as the original author.

View file

@ -0,0 +1,62 @@
#ifdef CRSID_PLATFORM_PC
#include <SDL/SDL.h>
void cRSID_soundCallback(void* userdata, unsigned char *buf, int len) {
cRSID_generateSound( (cRSID_C64instance*)userdata, buf, len );
}
void* cRSID_initSound(cRSID_C64instance* C64, unsigned short samplerate, unsigned short buflen) {
static SDL_AudioSpec soundspec;
if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) {
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); return NULL;
}
soundspec.freq=samplerate; soundspec.channels=1; soundspec.format=AUDIO_S16;
soundspec.samples=buflen; soundspec.userdata=C64; soundspec.callback=cRSID_soundCallback;
if ( SDL_OpenAudio(&soundspec, NULL) < 0 ) {
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); return NULL;
}
return (void*)&soundspec;
}
void cRSID_closeSound (void) {
SDL_PauseAudio(1); SDL_CloseAudio();
}
void cRSID_startSound (void) {
SDL_PauseAudio(0);
}
void cRSID_stopSound (void) {
SDL_PauseAudio(1);
}
void cRSID_generateSound(cRSID_C64instance* C64instance, unsigned char *buf, unsigned short len) {
static unsigned short i;
static int Output;
for(i=0;i<len;i+=2) {
Output=cRSID_generateSample(C64instance); //cRSID_emulateC64(C64instance);
//if (Output>=32767) Output=32767; else if (Output<=-32768) Output=-32768; //saturation logic on overflow
buf[i]=Output&0xFF; buf[i+1]=Output>>8;
}
}
#endif
static inline signed short cRSID_generateSample (cRSID_C64instance* C64) { //call this from custom buffer-filler
static int Output;
Output=cRSID_emulateC64(C64);
if (C64->PSIDdigiMode) Output += cRSID_playPSIDdigi(C64);
if (Output>=32767) Output=32767; else if (Output<=-32768) Output=-32768; //saturation logic on overflow
return (signed short) Output;
}

View file

@ -0,0 +1,60 @@
#ifdef CRSID_PLATFORM_PC
int cRSID_loadSIDfile (unsigned char* SIDfileData, char* filename, int maxlen) {
static signed short Data;
static signed int SizeCnt;
static FILE *SIDfile;
if ( (SIDfile=fopen(filename,"rb")) == NULL ) return CRSID_ERROR_LOAD;
SizeCnt=0;
while ( (Data=fgetc(SIDfile)) != EOF ) {
if (SizeCnt >= maxlen) return CRSID_ERROR_LOAD;
SIDfileData[SizeCnt] = Data; SizeCnt++;
}
fclose(SIDfile);
return SizeCnt;
}
#endif
cRSID_SIDheader* cRSID_processSIDfile(cRSID_C64instance* C64, unsigned char* filedata, int filesize) {
int i;
unsigned short SIDdataOffset;
cRSID_SIDheader* SIDheader;
static const char MagicStringPSID[]="PSID";
//static const char MagicStringRSID[]="RSID";
C64->SIDheader = SIDheader = (cRSID_SIDheader*) filedata;
for (i=0x0000; i < 0xA000; ++i) C64->RAMbank[i]=0; //fresh start (maybe some bugged SIDs want 0 at certain RAM-locations)
for (i=0xC000; i < 0xD000; ++i) C64->RAMbank[i]=0;
if ( SIDheader->MagicString[0] != 'P' && SIDheader->MagicString[0] != 'R' ) return NULL;
for (i=1; i < (int)(sizeof(MagicStringPSID)-1); ++i) { if (SIDheader->MagicString[i] != MagicStringPSID[i]) return NULL; }
C64->RealSIDmode = ( SIDheader->MagicString[0] == 'R' );
if (SIDheader->LoadAddressH==0 && SIDheader->LoadAddressH==0) { //load-address taken from first 2 bytes of the C64 PRG
C64->LoadAddress = (filedata[SIDheader->HeaderSize+1]<<8) + (filedata[SIDheader->HeaderSize+0]);
SIDdataOffset = SIDheader->HeaderSize+2;
}
else { //load-adress taken from SID-header
C64->LoadAddress = (SIDheader->LoadAddressH<<8) + (SIDheader->LoadAddressL);
SIDdataOffset = SIDheader->HeaderSize;
}
for (i=SIDdataOffset; i<filesize; ++i) C64->RAMbank [ C64->LoadAddress + (i-SIDdataOffset) ] = filedata[i];
i = C64->LoadAddress + (filesize-SIDdataOffset);
C64->EndAddress = (i<0x10000) ? i : 0xFFFF;
C64->PSIDdigiMode = ( !C64->RealSIDmode && (SIDheader->ModelFormatStandard & 2) );
return C64->SIDheader;
}

View file

@ -0,0 +1,134 @@
// cRSID lightweight (integer-only) RealSID library (with API-calls) by Hermit (Mihaly Horvath), Year 2022
// License: WTF - do what the fuck you want with the code, but please mention me as the original author
#include <stdlib.h>
//#include <stdint.h>
#ifdef CRSID_PLATFORM_PC
#include <stdio.h>
#endif
#include "libcRSID.h"
#include "C64/C64.c"
#include "host/file.c"
#include "host/audio.c"
cRSID_C64instance* cRSID_init (unsigned short samplerate, unsigned short buflen) {
static cRSID_C64instance* C64 = &cRSID_C64;
C64 = cRSID_createC64 (C64, samplerate);
#ifdef CRSID_PLATFORM_PC
if ( cRSID_initSound (C64, samplerate,buflen) == NULL) return NULL;
#else
if (buflen) return C64; //this is here just to eliminate unused 'buflen' variable warning
#endif
return C64;
}
void cRSID_initSIDtune (cRSID_C64instance* C64, cRSID_SIDheader* SIDheader, char subtune) { //subtune: 1..255
static const unsigned char PowersOf2[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned int InitTimeout=10000000; //allowed instructions, value should be selected to allow for long-running memory-copiers in init-routines (e.g. Synth Sample)
if (subtune==0) subtune = 1;
else if (subtune > SIDheader->SubtuneAmount) subtune = SIDheader->SubtuneAmount;
C64->SubTune = subtune;
cRSID_setC64(C64); cRSID_initC64(C64); //cRSID_writeMemC64(C64,0xD418,0xF); //set C64 hardware and init (reset) it
//determine init-address:
C64->InitAddress = ((SIDheader->InitAddressH)<<8) + (SIDheader->InitAddressL); //get info from BASIC-startupcode for some tunes
if (C64->RAMbank[1] == 0x37) { //are there SIDs with routine under IO area? some PSIDs don't set bank-registers themselves
if ( (0xA000 <= C64->InitAddress && C64->InitAddress < 0xC000)
|| (C64->LoadAddress < 0xC000 && C64->EndAddress >= 0xA000) ) C64->RAMbank[1] = 0x36;
else if (C64->InitAddress >= 0xE000 || C64->EndAddress >=0xE000) C64->RAMbank[1] = 0x35;
}
cRSID_initCPU( &C64->CPU, C64->InitAddress ); //prepare init-routine call
C64->CPU.A = subtune - 1;
if (!C64->RealSIDmode) {
//call init-routine:
for (InitTimeout=10000000; InitTimeout>0; InitTimeout--) { if ( cRSID_emulateCPU()>=0xFE ) break; } //give error when timed out?
}
//determine timing-source, if CIA, replace FrameCycles previouisly set to VIC-timing
if (subtune>32) C64->TimerSource = C64->SIDheader->SubtuneTimeSources[0] & 0x80; //subtunes above 32 should use subtune32's timing
else C64->TimerSource = C64->SIDheader->SubtuneTimeSources[(32-subtune)>>3] & PowersOf2[(subtune-1)&7];
if (C64->TimerSource || C64->IObankWR[0xDC05]!=0x40 || C64->IObankWR[0xDC04]!=0x24) { //CIA1-timing (probably multispeed tune)
C64->FrameCycles = ( ( C64->IObankWR[0xDC04] + (C64->IObankWR[0xDC05]<<8) ) ); //<< 4) / C64->ClockRatio;
C64->TimerSource = 1; //if init-routine changed DC04 or DC05, assume CIA-timing
}
//determine playaddress:
C64->PlayAddress = (SIDheader->PlayAddressH<<8) + SIDheader->PlayAddressL;
if (C64->PlayAddress) { //normal play-address called with JSR
if (C64->RAMbank[1] == 0x37) { //are there SIDs with routine under IO area?
if (0xA000 <= C64->PlayAddress && C64->PlayAddress < 0xC000) C64->RAMbank[1] = 0x36;
}
else if (C64->PlayAddress >= 0xE000) C64->RAMbank[1] = 0x35; //player under KERNAL (e.g. Crystal Kingdom Dizzy)
}
else { //IRQ-playaddress for multispeed-tunes set by init-routine (some tunes turn off KERNAL ROM but doesn't set IRQ-vector!)
C64->PlayAddress = (C64->RAMbank[1] & 3) < 2 ? cRSID_readMemC64(C64,0xFFFE) + (cRSID_readMemC64(C64,0xFFFF)<<8) //for PSID
: cRSID_readMemC64(C64,0x314) + (cRSID_readMemC64(C64,0x315)<<8);
if (C64->PlayAddress==0) { //if 0, still try with RSID-mode fallback
cRSID_initCPU( &C64->CPU, C64->PlayAddress ); //point CPU to play-routine
C64->Finished=1; C64->Returned=1; return;
}
}
if (!C64->RealSIDmode) { //prepare (PSID) play-routine playback:
cRSID_initCPU( &C64->CPU, C64->PlayAddress ); //point CPU to play-routine
C64->FrameCycleCnt=0; C64->Finished=1; C64->SampleCycleCnt=0; //C64->CIAisSet=0;
}
else { C64->Finished=0; C64->Returned=0; }
}
#ifdef CRSID_PLATFORM_PC
char cRSID_playSIDfile(cRSID_C64instance* C64, char* filename, char subtune) {
static cRSID_SIDheader* SIDheader;
SIDheader = cRSID_loadSIDtune(C64,filename);
if (SIDheader==NULL) return CRSID_ERROR_LOAD;
cRSID_initSIDtune (C64 , SIDheader , subtune);
cRSID_playSIDtune ();
return CRSID_STATUS_OK;
}
cRSID_SIDheader* cRSID_loadSIDtune(cRSID_C64instance* C64, char* filename) {
enum SIDspecs { CRSID_FILESIZE_MAX = 100000 };
int FileSize;
static unsigned char SIDfileData [CRSID_FILESIZE_MAX]; //use memset?
FileSize = cRSID_loadSIDfile( SIDfileData, filename, CRSID_FILESIZE_MAX);
if ( FileSize == CRSID_ERROR_LOAD ) return NULL;
return cRSID_processSIDfile ( C64, SIDfileData, FileSize );
}
void cRSID_close() {
cRSID_closeSound();
}
void cRSID_playSIDtune (void) {
cRSID_startSound();
}
void cRSID_pauseSIDtune (void) {
cRSID_stopSound();
}
#endif

View file

@ -0,0 +1,221 @@
// cRSID lightweight RealSID (integer-only) library-header (with API-calls) by Hermit (Mihaly Horvath)
#ifndef LIBCRSID_HEADER
#define LIBCRSID_HEADER //used to prevent double inclusion of this header-file
enum cRSID_Specifications { CRSID_SIDCOUNT_MAX=3, CRSID_CIACOUNT=2 };
enum cRSID_StatusCodes { CRSID_STATUS_OK=0, CRSID_ERROR_INIT=-1, CRSID_ERROR_LOAD=-2 };
typedef struct cRSID_SIDheader cRSID_SIDheader;
typedef struct cRSID_C64instance cRSID_C64instance;
typedef struct cRSID_CPUinstance cRSID_CPUinstance;
typedef struct cRSID_SIDinstance cRSID_SIDinstance;
typedef struct cRSID_CIAinstance cRSID_CIAinstance;
typedef struct cRSID_VICinstance cRSID_VICinstance;
cRSID_C64instance cRSID_C64; //the only global object (for faster & simpler access than with struct-pointers, in some places)
// Main API functions (mainly in libcRSID.c)
cRSID_C64instance* cRSID_init (unsigned short samplerate, unsigned short buflen); //init emulation objects and sound
#ifdef CRSID_PLATFORM_PC
char cRSID_playSIDfile (cRSID_C64instance* C64, char* filename, char subtune); //simple single-call SID playback
cRSID_SIDheader* cRSID_loadSIDtune (cRSID_C64instance* C64, char* filename); //load and process SID-filedata to C64 memory
void cRSID_playSIDtune (void); //start/continue playback (enable playing audio-buffer)
void cRSID_pauseSIDtune (void); //pause playback (enable playing audio-buffer)
void cRSID_close (void); //close sound etc.
#endif
cRSID_SIDheader* cRSID_processSIDfile (cRSID_C64instance* C64, unsigned char* filedata, int filesize); //in host/file.c, copy SID-data to C64 memory
void cRSID_initSIDtune (cRSID_C64instance* C64, cRSID_SIDheader* SIDheader, char subtune); //init tune/subtune
static inline signed short cRSID_generateSample (cRSID_C64instance* C64); //in host/audio.c, calculate a single sample
//Internal functions
// C64/C64.c
cRSID_C64instance* cRSID_createC64 (cRSID_C64instance* C64, unsigned short samplerate);
void cRSID_setC64 (cRSID_C64instance* C64); //configure hardware (SIDs) for SID-tune
void cRSID_initC64 (cRSID_C64instance* C64); //hard-reset
int cRSID_emulateC64 (cRSID_C64instance* C64);
static inline short cRSID_playPSIDdigi (cRSID_C64instance* C64);
// C64/MEM.c
static inline unsigned char* cRSID_getMemReadPtr (register unsigned short address); //for global cSID_C64 fast-access
static inline unsigned char* cRSID_getMemReadPtrC64 (cRSID_C64instance* C64, register unsigned short address); //maybe slower
static inline unsigned char* cRSID_getMemWritePtr (register unsigned short address); //for global cSID_C64 fast-access
static inline unsigned char* cRSID_getMemWritePtrC64 (cRSID_C64instance* C64, register unsigned short address); //maybe slower
static inline unsigned char cRSID_readMem (register unsigned short address); //for global cSID_C64 fast-access
static inline unsigned char cRSID_readMemC64 (cRSID_C64instance* C64, register unsigned short address); //maybe slower
static inline void cRSID_writeMem (register unsigned short address, register unsigned char data); //for global cSID_C64 fast-access
static inline void cRSID_writeMemC64 (cRSID_C64instance* C64, register unsigned short address, register unsigned char data); //maybe slower
void cRSID_setROMcontent (cRSID_C64instance* C64); //KERNAL, BASIC
void cRSID_initMem (cRSID_C64instance* C64);
// C64/CPU.c
void cRSID_initCPU (cRSID_CPUinstance* CPU, unsigned short mempos);
unsigned char cRSID_emulateCPU (void); //direct instances inside for hopefully faster operation
static inline char cRSID_handleCPUinterrupts (cRSID_CPUinstance* CPU);
// C64/SID.c
void cRSID_createSIDchip (cRSID_C64instance* C64, cRSID_SIDinstance* SID, unsigned short model, unsigned short baseaddress);
void cRSID_initSIDchip (cRSID_SIDinstance* SID);
void cRSID_emulateADSRs (cRSID_SIDinstance *SID, char cycles);
int cRSID_emulateWaves (cRSID_SIDinstance* SID);
// C64/CIA.c
void cRSID_createCIAchip (cRSID_C64instance* C64, cRSID_CIAinstance* CIA, unsigned short baseaddress);
void cRSID_initCIAchip (cRSID_CIAinstance* CIA);
static inline char cRSID_emulateCIA (cRSID_CIAinstance* CIA, char cycles);
static inline void cRSID_writeCIAIRQmask (cRSID_CIAinstance* CIA, unsigned char value);
static inline void cRSID_acknowledgeCIAIRQ (cRSID_CIAinstance* CIA);
// C64/VIC.c
void cRSID_createVICchip (cRSID_C64instance* C64, cRSID_VICinstance* VIC, unsigned short baseaddress);
void cRSID_initVICchip (cRSID_VICinstance* VIC);
static inline char cRSID_emulateVIC (cRSID_VICinstance* VIC, char cycles);
static inline void cRSID_acknowledgeVICrasterIRQ (cRSID_VICinstance* VIC);
// host/file.c
#ifdef CRSID_PLATFORM_PC
int cRSID_loadSIDfile (unsigned char* SIDfileData, char* filename, int maxlen); //load SID-file to a memory location (and return size)
#endif
// host/audio.c
#ifdef CRSID_PLATFORM_PC
void* cRSID_initSound (cRSID_C64instance* C64, unsigned short samplerate, unsigned short buflen);
void cRSID_startSound (void);
void cRSID_stopSound (void);
void cRSID_closeSound (void);
void cRSID_generateSound (cRSID_C64instance* C64, unsigned char* buf, unsigned short len);
#endif
struct cRSID_SIDheader { //Offset: default/info:
unsigned char MagicString[4]; //$00 - "PSID" or "RSID" (RSID must provide Reset-circumstances & CIA/VIC-interrupts)
unsigned char VersionH00; //$04
unsigned char Version; //$05 - 1 for PSID v1, 2..4 for PSID v2..4 or RSID v2..4 (3/4 has 2SID/3SID support)
unsigned char HeaderSizeH00; //$06
unsigned char HeaderSize; //$07 - $76 for v1, $7C for v2..4
unsigned char LoadAddressH,LoadAddressL; //$08 - if 0 it's a PRG and its loadaddress is used (RSID: 0, PRG-loadaddress>=$07E8)
unsigned char InitAddressH,InitAddressL; //$0A - if 0 it's taken from load-address (but should be set) (RSID: don't point to ROM, 0 if BASICflag set)
unsigned char PlayAddressH,PlayAddressL; //$0C - if 0 play-routine-call is set by the initializer (always true for RSID)
unsigned char SubtuneAmountH00; //$0E
unsigned char SubtuneAmount; //$0F - 1..256
unsigned char DefaultSubtuneH00; //$10
unsigned char DefaultSubtune; //$11 - 1..256 (optional, defaults to 1)
unsigned char SubtuneTimeSources[4]; //$12 - 0:Vsync / 1:CIA1 (for PSID) (LSB is subtune1, MSB above 32) , always 0 for RSID
char Title[32]; //$16 - strings are using 1252 codepage
char Author[32]; //$36
char ReleaseInfo[32]; //$56
//SID v2 additions: (if SID2/SID3 model is set to unknown, they're set to the same model as SID1)
unsigned char ModelFormatStandardH; //$76 - bit9&8/7&6/5&4: SID3/2/1 model (00:?,01:6581,10:8580,11:both), bit3&2:VideoStandard..
unsigned char ModelFormatStandard; //$77 ..(01:PAL,10:NTSC,11:both), bit1:(0:C64,1:PlaySIDsamples/RSID_BASICflag), bit0:(0:builtin-player,1:MUS)
unsigned char RelocStartPage; //$78 - v2NG specific, if 0 the SID doesn't write outside its data-range, if $FF there's no place for driver
unsigned char RelocFreePages; //$79 - size of area from RelocStartPage for driver-relocation (RSID: must not contain ROM or 0..$3FF)
unsigned char SID2baseAddress; //$7A - (SID2BASE-$d000)/16 //SIDv3-relevant, only $42..$FE values are valid ($d420..$DFE0), else no SID2
unsigned char SID3baseAddress; //$7B - (SID3BASE-$d000)/16 //SIDv4-relevant, only $42..$FE values are valid ($d420..$DFE0), else no SID3
}; //music-program follows right after the header
struct cRSID_CPUinstance {
cRSID_C64instance* C64; //reference to the containing C64
unsigned int PC;
short int A, SP;
unsigned char X, Y, ST; //STATUS-flags: N V - B D I Z C
unsigned char PrevNMI; //used for NMI leading edge detection
};
struct cRSID_SIDinstance {
//SID-chip data:
cRSID_C64instance* C64; //reference to the containing C64
unsigned short ChipModel; //values: 8580 / 6581
unsigned short BaseAddress; //SID-baseaddress location in C64-memory (IO)
unsigned char* BasePtr; //SID-baseaddress location in host's memory
//ADSR-related:
unsigned char ADSRstate[15];
unsigned short RateCounter[15];
unsigned char EnvelopeCounter[15];
unsigned char ExponentCounter[15];
//Wave-related:
int PhaseAccu[15]; //28bit precision instead of 24bit
int PrevPhaseAccu[15]; //(integerized ClockRatio fractionals, WebSID has similar solution)
unsigned char SyncSourceMSBrise;
unsigned int RingSourceMSB;
unsigned int NoiseLFSR[15];
unsigned int PrevWavGenOut[15];
unsigned char PrevWavData[15];
//Filter-related:
int PrevLowPass;
int PrevBandPass;
//Output-stage:
signed int PrevVolume; //lowpass-filtered version of Volume-band register
};
struct cRSID_CIAinstance {
cRSID_C64instance* C64; //reference to the containing C64
char ChipModel; //old or new CIA? (have 1 cycle difference in cases)
unsigned short BaseAddress; //CIA-baseaddress location in C64-memory (IO)
unsigned char* BasePtrWR; //CIA-baseaddress location in host's memory for writing
unsigned char* BasePtrRD; //CIA-baseaddress location in host's memory for reading
};
struct cRSID_VICinstance {
cRSID_C64instance* C64; //reference to the containing C64
char ChipModel; //(timing differences between models?)
unsigned short BaseAddress; //VIC-baseaddress location in C64-memory (IO)
unsigned char* BasePtrWR; //VIC-baseaddress location in host's memory for writing
unsigned char* BasePtrRD; //VIC-baseaddress location in host's memory for reading
unsigned short RasterLines;
unsigned char RasterRowCycles;
unsigned char RowCycleCnt;
};
struct cRSID_C64instance {
//platform-related:
unsigned short SampleRate;
//C64-machine related:
unsigned char VideoStandard; //0:NTSC, 1:PAL (based on the SID-header field)
unsigned int CPUfrequency;
unsigned short SampleClockRatio; //ratio of CPU-clock and samplerate
//SID-file related:
union {
cRSID_SIDheader* SIDheader;
char* SIDfileData;
};
unsigned short Attenuation;
char RealSIDmode;
char PSIDdigiMode;
unsigned char SubTune;
unsigned short LoadAddress;
unsigned short InitAddress;
unsigned short PlayAddress;
unsigned short EndAddress;
char TimerSource; //for current subtune, 0:VIC, 1:CIA (as in SID-header)
//PSID-playback related:
//char CIAisSet; //for dynamic CIA setting from player-routine (RealSID substitution)
int FrameCycles;
int FrameCycleCnt; //this is a substitution in PSID-mode for CIA/VIC counters
short PrevRasterLine;
short SampleCycleCnt;
short TenthSecondCnt;
char Finished;
char Returned;
unsigned char IRQ; //collected IRQ line from devices
unsigned char NMI; //collected NMI line from devices
//Hardware-elements:
cRSID_CPUinstance CPU;
cRSID_SIDinstance SID[CRSID_SIDCOUNT_MAX+1];
cRSID_CIAinstance CIA[CRSID_CIACOUNT+1];
cRSID_VICinstance VIC;
//Overlapping system memories, which one is read/written in an address region depends on CPU-port bankselect-bits)
//Address $00 and $01 - data-direction and data-register of port built into CPU (used as bank-selection) (overriding RAM on C64)
unsigned char RAMbank[0x10100]; //$0000..$FFFF RAM (and RAM under IO/ROM/CPUport)
unsigned char IObankWR[0x10100]; //$D000..$DFFF IO-RAM (registers) to write (VIC/SID/CIA/ColorRAM/IOexpansion)
unsigned char IObankRD[0x10100]; //$D000..$DFFF IO-RAM (registers) to read from (VIC/SID/CIA/ColorRAM/IOexpansion)
unsigned char ROMbanks[0x10100]; //$1000..$1FFF/$9000..$9FFF (CHARGEN), $A000..$BFFF (BASIC), $E000..$FFFF (KERNAL)
};
#endif //LIBCRSID_HEADER