DSK HASH ************************************************** * Note: * If the code looks inefficient and redundant, it is. * Lots of things that should loop are unrolled for speed. * Built with Merlin32 from Brutal Deluxe: brutaldeluxe.fr/products/crossdevtools/merlin/ * * Timing measurements include setup, hashing and printing result. * * V1: 947,063 cycles. * * Macros: converted several common subroutines to macros * for additional speed, at expense of memory size. * Currently runs 1 hash in 922,394 cycles. * * Zero page: moved some variables to zero page from Memory * Down to 916,595 cycles. * * Further optimized, more macros: 875,166 * Further optimized: 804,584 * Unrolled shift routines: 682,744 (Now, it's getting good.) * Pulled out all the stops: 671,524 (Time to hand off to Qkumba.) * What's being hashed is: version4 + previous block hash32 + merkel root32 + time4 + bits (target)4 + nonce4 = blockheader (80 bytes) * 80 bytes gets broken into two message blocks * This gets hashed twice sha256(sha256(blockheader)) * https://en.wikipedia.org/wiki/SHA-2 * http://www.yogh.io/#mine:last * https://en.bitcoin.it/wiki/Block_hashing_algorithm * https://en.bitcoin.it/wiki/Protocol_documentation * total time to run a complete hash (three SHA256 iterations total): 1,994,362 cycles * more loops to macros (LUP): 1,906,858 * 1,559,735 * Qkumba optimization, part 1: 1,248,727 * 1,238,169 * 1,218,659 * added nonce display, unrolled a couple of loops 1,210,817 * where next? PRBYTE is 255 * CROUT is 3,248 (!) * printing the result is 19,396 cycles alone! * down to 11,455 now * RORx8 into Byte 1,096,763 * more macros. 1,068,543 * * instead of CROUTx2, set cursor to top of window and print over top? 1,055,753 * whoa 929,375 * rotating Vn macro 891,692 * MAJ and CHOICE optimized 831,999 * XOR32 to combined macro 796,115 * 780,145 * unrolled HASHTOMESSAGE 779,427 = 103.765 years * who needs 1 VTAB? 779,255 * or 2 CROUTs? 778,751 * * LDVV - MACROS with parameters. 775,323 * macros with parameters? Mind. Blown. * target: 751,237 = 1 full 2^32 hashes in 100 years. * unrolled COPYCHUNK1 714,904 * replaced prbyte with my own: 708,036 * special temp/s0 macros: 662,220 * LDAW, LDWADDX, LDS, inline JSRs 627,428 * caching the result of chunk0 on pass0: 418,144 ************************************************** * Variables ************************************************** INPUT32 EQU $E0 ; DS 4 ; 32-bit Accumulator XREGISTER32 EQU $E4 ; DS 4 ; input 1 for XOR, etc (X) YREGISTER32 EQU $E8 ; DS 4 ; input 2 for MAJ, etc (Y) RESULT32 EQU $EC ; DS 4 ; temp storage for various operations CURRENTCHUNK EQU $FF ; chunk zero or one. HASHPASS EQU $FE ; pass zero or one. CURRENTMESSAGELO EQU $FC CURRENTMESSAGEHI EQU $FD S0 EQU $80 S1 EQU $84 TEMP0 EQU $88 ; temp storage for various operations TEMP1 EQU $8C ; temp storage for various operations HASHCACHED EQU $D0 ; is the first pass already done, and the result cached in CACHEDHASH? ************************************************** * Apple Standard Memory Locations ************************************************** CLRLORES EQU $F832 LORES EQU $C050 TXTSET EQU $C051 MIXCLR EQU $C052 MIXSET EQU $C053 TXTPAGE1 EQU $C054 TXTPAGE2 EQU $C055 KEY EQU $C000 C80STOREOFF EQU $C000 C80STOREON EQU $C001 STROBE EQU $C010 SPEAKER EQU $C030 VBL EQU $C02E RDVBLBAR EQU $C019 ; not VBL (VBL signal low WAIT EQU $FCA8 RAMWRTAUX EQU $C005 RAMWRTMAIN EQU $C004 SETAN3 EQU $C05E ; Set annunciator-3 output to 0 SET80VID EQU $C00D ; enable 80-column display mode (WR-only) HOME EQU $FC58 ; clear the text screen VTAB EQU $FC22 ; Sets the cursor vertical position (from CV) COUT EQU $FDED ; Calls the output routine whose address is stored in CSW, ;COUTI EQU $fbf0 ; normally COUTI CROUT EQU $FD8E ; prints CR STROUT EQU $DB3A ;Y=String ptr high, A=String ptr low PRBYTE EQU $FDDA ; print hex byte in A ALTTEXT EQU $C055 ALTTEXTOFF EQU $C054 PB0 EQU $C061 ; paddle 0 button. high bit set when pressed. PDL0 EQU $C064 ; paddle 0 value, or should I use PREAD? PREAD EQU $FB1E ROMINIT EQU $FB2F ROMSETKBD EQU $FE89 ROMSETVID EQU $FE93 ALTCHAR EQU $C00F ; enables alternative character set - mousetext CH EQU $24 ; cursor Horiz CV EQU $25 ; cursor Vert WNDWDTH EQU $21 ; Width of text window WNDTOP EQU $22 ; Top of text window ************************************************** * START - sets up various fiddly zero page bits ************************************************** ORG $2000 ; PROGRAM DATA STARTS AT $2000 JSR HOME ; clear screen STA $C050 ; rw:TXTCLR ; Set Lo-res page 1, mixed graphics + text STA $C053 ; rw:MIXSET STA $C054 ; rw:TXTPAGE1 STA $C056 ; rw:LORES JSR FILLSCREENFAST ; blanks screen to black. JSR SPLASHSCREEN ; fancy lo-res graphics LDA #$00 STA HASHCACHED ; clear cache status JSR FLIPCOIN ; set text window to last 4 lines of GR screen. LDA #$14 STA CV STA WNDTOP JSR VTAB ************************************************** * SETUP ************************************************** * * Initialize hash values: * (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): * See HTABLE * * Initialize array of round constants: * (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): * See KTABLE * * Pre-processing (Padding): * begin with the original message of length L bits (80*8 = 640bits) * append a single '1' bit (641bits) * means shifting everything over 1 bit to be 81 bytes * append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512 (640+1+K+64=1024 K=319) * append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits (append 0000000000000280) ************************************************** * Pre-processing (Padding): ************************************************** ; Start with MESSAGE padded out to 1024bits (see MESSAGE below) * Process the message in successive 512-bit chunks: * break message into 512-bit chunks * 80byte header yields 1024bit message, so chunks = 2 * Cache result of first chunk, so subsequent passes are cache then hash. PREPROCESS LDA #$00 STA HASHPASS ; pass the first = 0 STA CURRENTCHUNK ; chunk the first = 0 LDA MESSAGELO STA CURRENTMESSAGELO LDA MESSAGEHI STA CURRENTMESSAGEHI INITIALIZEHASH ; for the 32 bytes in INITIALHASH, push them into H00-H07 INITIALHASHES ]hashnumber = 31 LUP 32 LDA INITIALHASH + ]hashnumber STA H00 + ]hashnumber ]hashnumber = ]hashnumber - 1 --^ * for each chunk * create a 64-entry message schedule array w[0..63] of 32-bit words * (The initial values in w[0..63] don't matter, so many implementations zero them here) * See WTABLE * copy chunk into first 16 words w[0..15] of the message schedule array COPYCHUNKS CHECKCACHE ; if HASHCACHED == 1 ; AND chunk=0 AND pass=0 ; then read from CACHEDHASH CLC LDA HASHCACHED ; has chunk0 pass0 already done? BNE CACHEDONE JMP NOCACHE CACHEDONE LDA HASHPASS ; pass = 0 ADC CURRENTCHUNK ; chunk = 0 BEQ CACHETOHASH JMP NOCACHE CACHETOHASH ]cachebyte = 0 LUP 32 LDA CACHEDHASH + ]cachebyte STA H00 + ]cachebyte ]cachebyte = ]cachebyte+1 --^ JMP CHECKCHUNK NOCACHE LDA CURRENTCHUNK ; which chunk? BNE NEXTCHUNK ; skip chunk0 if already done LDA CURRENTMESSAGELO STA $00 ; ***** UNROLL for speedup? how, with indirect address (),Y? LDA CURRENTMESSAGEHI STA $01 LDY #$3F ; Y = 63 to 0 on chunk 0, then 64 to 127 on chunk 1 COPYCHUNK0 LDA ($0),Y STA W00,Y DEY BPL COPYCHUNK0 ; if hasn't rolled over to FF, loop to copy next byte. ***** if I'm on second pass, only do chunk0 ; HASHPASS = 1, add to CURRENTCHUNK? CLC LDA CURRENTCHUNK ADC HASHPASS STA CURRENTCHUNK ***** if I'm on second pass, only do chunk0 JMP EXTENDWORDS ; done with chunk 0 NEXTCHUNK LDA CURRENTMESSAGELO STA $00 LDA CURRENTMESSAGEHI STA $01 **** Only does this (second chunk) on first pass. So CURRENTMESSAGE always points to MESSAGE (never MESSAGE2) ]chunkbyte = 64 LUP 64 COPYCHUNK1 LDA MESSAGE + ]chunkbyte STA W00 - 64 + ]chunkbyte ; ]chunkbyte = ]chunkbyte + 1 --^ **** Only does this (second chunk) on first pass. * Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array: * for i from 16 to 63 * s0 = (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3) * s0 = (XREGISTER32) xor (YREGISTER32) xor (INPUT32) EXTENDWORDS LDA #$0F ; 15 PHA ; push to stack = 15 EXTEND PLA ; pull A from stack (15) CLC ; clear carry ADC #$01 ; increment accumulator = 16 CMP #$40 ; compare to 64 BNE EXTEND2 ; done with EXTEND step (done through 63) JMP INITIALIZE EXTEND2 PHA ; push new A to stack = 16 SEC ; set carry for subtract SBC #$0F ; -15 ASL ROL TAX ; X now = X*4 LDAW ; takes X as arg. load W[a-15] into INPUT32 RIGHTROTATE7 LUP 7 RIGHTROTATE32 ; ROR32 7 times --^ TAX32 ; should store partial result at XREGISTER32 RIGHTROTATE18 RIGHTROTATE8 LUP 3 RIGHTROTATE32 ; ROR32 11 more times --^ TAY32 ; should store partial result at YREGISTER32 ; X still = X*4 LDAW ; load W[a-15] into INPUT32 RIGHTSHIFT3 LUP 3 RIGHTSHIFT32 ; shift right, ignore carry --^ ; store partial result in INPUT32 * s0 = (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3) * s0 = (XREGISTER32) xor (YREGISTER32) xor (INPUT32) XORAXY32 ; A32 -> TEMP0 STATEMP0 * s1 := (w[i- 2] rightrotate 17) xor (w[i- 2] rightrotate 19) xor (w[i- 2] rightshift 10) PLA ; i=16 PHA ; back to stack SEC ; set carry for subtract SBC #$02 ; -02 ASL ROL TAX ; X = X*4 again LDAW ; load W14 into INPUT32 RIGHTROTATE17 RIGHTROTATE8 RIGHTROTATE8 RIGHTROTATE32 ; ROR32 17 times TAX32 ; should store partial result at XREGISTER32 RIGHTROTATE2 LUP 2 RIGHTROTATE32 ; ROR32 2 more times --^ TAY32 ; should store partial result at YREGISTER32 ; ; X = X*4 LDAW ; load W14 into INPUT32 RIGHTSHIFT10 RIGHTSHIFT8 LUP 2 RIGHTSHIFT32 ; shift right, ignore carry --^ ; store partial result in INPUT32 * s1 := (w[i- 2] rightrotate 17) xor (w[i- 2] rightrotate 19) xor (w[i- 2] rightshift 10) * s1 := (XREGISTER32) xor (YREGISTER32) xor (INPUT32) XORAXY32 * w[i] := w[i-16] + s0 + w[i-7] + s1 * w[i] := w[i-16] + TEMP0 + w[i-7] + INPUT32 TAX32 ; INPUT32 to XREGISTER32 ; TEMP0 -> A32 LDATEMP0 * w[i] := w[i-16] + INPUT32 + w[i-7] + XREGISTER32 CLC ADC32 ; add S0 and S1 TAX32 ; transfer to XREGISTER32 PLA ; copy A from stack PHA ; i=16 SEC SBC #$10 ; w[0] TAX ; load W00 into pointer, add with X32 LDWADDX ; takes X TAX32 ; transfer to XREGISTER32 PLA ; copy A from stack PHA ; i=16 SEC SBC #$07 ; w[09] TAX ; load W09 into pointer, add with X32 LDWADDX ; takes X ; store result in w[i] PLA ; copy A from stack PHA ; i=16 STOREW LDWSTA32 ; store in W16 JMP EXTEND ; repeat until i=63 INITIALIZE * Initialize working variables to current hash value: * Va := h00 * Vb := h01 * Vc := h02 * Vd := h03 * Ve := h04 * Vf := h05 * Vg := h06 * Vh := h07 HASHTOV ]bytenumber = 0 LUP 32 HTOV LDA H00 + ]bytenumber STA VA + ]bytenumber ]bytenumber = ]bytenumber + 1 --^ ************************************************** * MAIN LOOP. OPTIMIZE THIS. ************************************************** COMPRESSION * Compression function main loop: * for i from 0 to 63 LDA #$00 COMPRESS PHA ; round number to stack * S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25) LDVLDA 4 ; pointer to VE RIGHTROTATE06 LUP 6 RIGHTROTATE32 ; shift right, ignore carry --^ TAX32 ; result in XREGISTER32 RIGHTROTATE11 LUP 5 RIGHTROTATE32 ; shift right 5 more times=11, ignore carry --^ TAY32 ; result in YREGISTER32 RIGHTROTATE25 RIGHTROTATE8 LUP 6 RIGHTROTATE32 ; shift right 14 more times=25, ignore carry --^ * S1 := (XREGISTER32) xor (YREGISTER32) xor (INPUT32) XORAXY32 ;S1 STAS1 ; store INPUT32 in S1 **** CHOICE and MAJ always take the same 3 arguments - make macros * ch := (e and f) xor ((not e) and g) CHOICE32 ; CH in INPUT32 * temp1 := Vh + S1 + ch + k[i] + w[i] = TEMP0 ; S1 + CH LDSADC32 4 ; (S1 + ch) in INPUT32 ; + VH LDVHADC32 PLA ; pull i from stack PHA ; back in stack TAX LDKADC32 ; K[i] in pointer ; + K[i] PLA ; pull i from stack PHA ; back in stack TAX LDWADC ; W[i] in pointer ; + W[i] ; LDXADC32 ; (S1 + ch + VH + k[i] + w[i]) in INPUT32 ; = TEMP0 STATEMP0 ; store temp1 at TEMP0 * S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22) LDVLDA 0 ; pointer to VA RIGHTROTATE02 LUP 2 RIGHTROTATE32 ; ROR 2 times --^ TAX32 ; result in XREGISTER32 RIGHTROTATE13 RIGHTROTATE8 LUP 3 RIGHTROTATE32 ; ROR 11 more times=13 --^ TAY32 ; result in YREGISTER32 RIGHTROTATE22 RIGHTROTATE8 RIGHTROTATE32 ; ROR 9 more times=22 * S0 := (XREGISTER32) xor (YREGISTER32) xor (INPUT32) XORAXY32 ;S0 STAS0 ; store INPUT32 in S0 **** CHOICE and MAJ always take the same 3 arguments - make macros * maj := (a and b) xor (a and c) xor (b and c) ; load A,B,C into A32,X32,Y32 MAJ32 ; MAJ in INPUT32 * temp2 := S0 + maj * temp2 := S0 + INPUT32 ; load S0 into X32 ;S0 -> X32 LDA STABLELO ; takes X as argument STA $00 LDA STABLEHI STA $01 ; now word/pointer at $0+$1 points to 32bit word at STABLE,X LDX32 ; S0 in XREGISTER32 CLC ADC32 ; TEMP2 in INPUT32 ;A32 -> TEMP1 STATEMP1 ; temp2 to TEMP1 ROTATE * Vh := Vg * Vg := Vf * Vf := Ve ; Store VG in VH VXTOVY 6;7 VXTOVY 5;6 VXTOVY 4;5 * Ve := Vd + temp1 LDVLDA 3 ;TEMP0 -> X32 LDX TEMPLO STX $00 LDX TEMPHI STX $01 ; now word/pointer at $0+$1 points to TEMP0 LDXADC32 LDVSTA 4 * Vd := Vc * Vc := Vb * Vb := Va VXTOVY 2;3 VXTOVY 1;2 VXTOVY 0;1 * Va := temp1 + temp2 ;TEMP1 -> X32 LDX TEMPLO+1 STX $00 LDX TEMPHI+1 STX $01 ; now word/pointer at $0+$1 points to TEMP1 LDX32 ; load TEMP1 into XREGISTER32 ;TEMP0 -> A32 LDATEMP0 CLC ADC32 LDVSTA 0 COMPRESSLOOP PLA ; Round 0-63 from stack CLC ADC #$01 CMP #$40 BEQ ADDHASH ; checks to see if we can skip or pull from cache JMP COMPRESS ************************************************** * END MAIN LOOP. * FINALIZE HASH AND OUTPUT. ************************************************** ADDHASH * Add the compressed chunk to the current hash value: * h0 := h0 + Va * h1 := h1 + Vb * h2 := h2 + Vc * h3 := h3 + Vd * h4 := h4 + Ve * h5 := h5 + Vf * h6 := h6 + Vg * h7 := h7 + Vh ]varbyte = 0 LUP 8 CLC LDA H00+3 + ]varbyte ADC VA+3 + ]varbyte STA H00+3 + ]varbyte LDA H00+2 + ]varbyte ADC VA+2 + ]varbyte STA H00+2 + ]varbyte LDA H00+1 + ]varbyte ADC VA+1 + ]varbyte STA H00+1 + ]varbyte LDA H00 + ]varbyte ADC VA + ]varbyte STA H00 + ]varbyte ]varbyte = ]varbyte + 4 --^ ; if HASHCACHED == 0 ; AND chunk=0 AND pass=0 ; then write to CACHEDHASH CLC LDA HASHCACHED ; has chunk0 pass0 already done? ADC HASHPASS ADC CURRENTCHUNK BEQ HASHTOCACHE ; otherwise JMP CHECKCHUNK ; jump over and check which chunk we're doing HASHTOCACHE ]cachebyte = 0 LUP 32 LDA H00 + ]cachebyte STA CACHEDHASH + ]cachebyte ]cachebyte = ]cachebyte+1 --^ LDA #$01 STA HASHCACHED ; don't repeat. CHECKCHUNK LDA CURRENTCHUNK BNE CHECKPASS ; did I just do chunk 0? INC and go back and do second chunk. INC CURRENTCHUNK ; set to chunk 1 JMP COPYCHUNKS ; CHECKPASS LDA HASHPASS ; pass 0? set the message to the hash output and go again BEQ INCHASHPASS ; pass 1, skip to digest. JMP DIGEST INCHASHPASS INC HASHPASS ; HASHTOMESSAGE ; for each of 32 bytes, Y ; load byte from H00,Y ; store at MESSAGE2,Y COPYHASH ]hashbyte = 31 LUP 32 LDA H00 + ]hashbyte STA MESSAGE2 + ]hashbyte ]hashbyte = ]hashbyte - 1 --^ LDA MESSAGE2LO STA CURRENTMESSAGELO LDA MESSAGE2HI STA CURRENTMESSAGEHI ******* only need one chunk for message2 LDA #$00 STA CURRENTCHUNK JMP INITIALIZEHASH ; re-initializes the original sqrt hash values for pass 2 DIGEST ; done the thing. LDA #$14 STA CV LDA #$00 STA CH LDA #$06 ; set the memory location for line $14. STA $29 ; LDA #$50 ; STA $28 ; PRNONCE ]hashbyte = 0 LUP 4 LDA NONCE + ]hashbyte ; load from table pointer PRHEX ; PRBYTE - clobbers Y ;**** ROLL MY OWN? ]hashbyte = ]hashbyte + 1 --^ INCNONCE INC CV ; down one line INC CV ; down one line LDA #$00 STA CH ; left cursor INC $29 ; 0650 -> 0750 LDA #$50 ; STA $28 ; PRDIGEST LDA H00 BNE PRBYTE1 ; if zero, spin the coin JSR FLIPCOIN LDA H00 PRBYTE1 PRHEX ]hashbyte = 1 LUP 19 LDA H00 + ]hashbyte PRHEX ]hashbyte = ]hashbyte + 1 --^ NEXTLINE LDA #$00 STA CH INC CV LDA #$D0 STA $28 ; $0750 to $07D0 ]hashbyte = 20 LUP 12 LDA H00 + ]hashbyte PRHEX ]hashbyte = ]hashbyte + 1 --^ JMP PREPROCESS ; INC NONCE, start over. DONEWORK ; processed all the 2^32 nonce values. WTF? RTS ************************************************** * macros (expanded at assembly time) ************************************************** LDW MAC LDA WTABLELO,X ; takes X as argument STA $00 LDA WTABLEHI,X STA $01 ; now word/pointer at $0+$1 points to 32bit word at WTABLE,X <<< ; End of Macro LDK MAC LDA KTABLELO,X ; takes X as argument STA $00 LDA KTABLEHI,X STA $01 ; now word/pointer at $0+$1 points to 32bit word at KTABLE,X <<< ; End of Macro ; LDH MAC ; LDA HTABLELO,X ; takes X as argument ; STA $00 ; LDA HTABLEHI,X ; STA $01 ; now word/pointer at $0+$1 points to 32bit word at HTABLE,X ; <<< ; End of Macro LDV MAC LDA VTABLELO,X ; takes X as argument STA $00 LDA VTABLEHI,X STA $01 ; now word/pointer at $0+$1 points to 32bit word at VTABLE,X <<< ; End of Macro LDVV MAC LDA VTABLELO+]1 ; takes X as argument STA $00 LDA VTABLEHI+]1 STA $01 ; now word/pointer at $0+$1 points to 32bit word at VTABLE,X <<< ; End of Macro LDVLDA MAC LDA VA + ]1 + ]1 + ]1 + ]1 +3 ; load from table pointer STA INPUT32+3 ; store in 32 bit "accumulator" LDA VA + ]1 + ]1 + ]1 + ]1 +2 ; load from table pointer STA INPUT32+2 ; store in 32 bit "accumulator" LDA VA + ]1 + ]1 + ]1 + ]1 +1 ; load from table pointer STA INPUT32+1 ; store in 32 bit "accumulator" LDA VA + ]1 + ]1 + ]1 + ]1 ; load from table pointer STA INPUT32 ; store in 32 bit "accumulator" <<< ; End of Macro LDVLDX MAC LDA VA + ]1 + ]1 + ]1 + ]1 +3 ; load from table pointer STA XREGISTER32+3 ; store in 32 bit "accumulator" LDA VA + ]1 + ]1 + ]1 + ]1 +2 ; load from table pointer STA XREGISTER32+2 ; store in 32 bit "accumulator" LDA VA + ]1 + ]1 + ]1 + ]1 +1 ; load from table pointer STA XREGISTER32+1 ; store in 32 bit "accumulator" LDA VA + ]1 + ]1 + ]1 + ]1 ; load from table pointer STA XREGISTER32 ; store in 32 bit "accumulator" <<< ; End of Macro LDVSTA MAC LDA INPUT32+3 ; store in 32 bit "accumulator" STA VA + ]1 + ]1 + ]1 + ]1 +3 ; load from table pointer LDA INPUT32+2 ; store in 32 bit "accumulator" STA VA + ]1 + ]1 + ]1 + ]1 +2 ; load from table pointer LDA INPUT32+1 ; store in 32 bit "accumulator" STA VA + ]1 + ]1 + ]1 + ]1 +1 ; load from table pointer LDA INPUT32 ; store in 32 bit "accumulator" STA VA + ]1 + ]1 + ]1 + ]1 ; load from table pointer <<< ; End of Macro VXTOVY MAC ; rotate Vn to Vn-1 LDA VA + ]1+ ]1+ ]1+ ]1 ; load from table pointer STA VA + ]2+ ]2+ ]2+ ]2 ; store in table pointer LDA VA + ]1+ ]1+ ]1+ ]1 + 1 ; load from table pointer STA VA + ]2+ ]2+ ]2+ ]2 + 1 ; store in table pointer LDA VA + ]1+ ]1+ ]1+ ]1 + 2 ; load from table pointer STA VA + ]2+ ]2+ ]2+ ]2 + 2 ; store in table pointer LDA VA + ]1+ ]1+ ]1+ ]1 + 3 ; load from table pointer STA VA + ]2+ ]2+ ]2+ ]2 + 3 ; store in table pointer <<< ; End of Macro LDAW MAC ; X indicates which W0x word to read from LDA W00 + 3,X ; load from table pointer STA INPUT32+3 ; store in 32 bit "accumulator" LDA W00 + 2,X ; load from table pointer STA INPUT32+2 ; store in 32 bit "accumulator" LDA W00 + 1,X ; load from table pointer STA INPUT32+1 ; store in 32 bit "accumulator" LDA W00,X ; load from table pointer STA INPUT32 ; store in 32 bit "accumulator" <<< LDWSTA32 MAC ; store INPUT32 in W0x word ASL ROL TAX ;x=A*4 LDA INPUT32+3 ; load from 32 bit "accumulator" STA W00 + 3,X ; store in table pointer LDA INPUT32+2 ; load from 32 bit "accumulator" STA W00 + 2,X ; store in table pointer LDA INPUT32+1 ; load from 32 bit "accumulator" STA W00 + 1,X ; store in table pointer LDA INPUT32 ; load from 32 bit "accumulator" STA W00,X ; store in table pointer <<< STA32 MAC ; puts 4 bytes from 32 bit "accumulator" INPUT32 into ($01,$00), clobbers A,Y LDY #$03 LDA INPUT32+3 ; load from 32 bit "accumulator" STA ($0),Y ; store in table pointer LDY #$02 LDA INPUT32+2 ; load from 32 bit "accumulator" STA ($0),Y ; store in table pointer LDY #$01 LDA INPUT32+1 ; load from 32 bit "accumulator" STA ($0),Y ; store in table pointer LDY #$00 LDA INPUT32 ; load from 32 bit "accumulator" STA ($0),Y ; store in table pointer <<< ; End of Macro STAS1 MAC ; puts 4 bytes from 32 bit "accumulator" INPUT32 into S1 LDA INPUT32+3 ; load from 32 bit "accumulator" STA S1+3 ; store in table pointer LDA INPUT32+2 ; load from 32 bit "accumulator" STA S1+2 ; store in table pointer LDA INPUT32+1 ; load from 32 bit "accumulator" STA S1+1 ; store in table pointer LDA INPUT32 ; load from 32 bit "accumulator" STA S1 ; store in table pointer <<< ; End of Macro STAS0 MAC ; puts 4 bytes from 32 bit "accumulator" INPUT32 into S0 LDA INPUT32+3 ; load from 32 bit "accumulator" STA S0+3 ; store in table pointer LDA INPUT32+2 ; load from 32 bit "accumulator" STA S0+2 ; store in table pointer LDA INPUT32+1 ; load from 32 bit "accumulator" STA S0+1 ; store in table pointer LDA INPUT32 ; load from 32 bit "accumulator" STA S0 ; store in table pointer <<< ; End of Macro STATEMP1 MAC ; puts 4 bytes from 32 bit "accumulator" INPUT32 into TEMP0 LDA INPUT32+3 ; load from 32 bit "accumulator" STA TEMP1+3 ; store in table pointer LDA INPUT32+2 ; load from 32 bit "accumulator" STA TEMP1+2 ; store in table pointer LDA INPUT32+1 ; load from 32 bit "accumulator" STA TEMP1+1 ; store in table pointer LDA INPUT32 ; load from 32 bit "accumulator" STA TEMP1 ; store in table pointer <<< ; End of Macro STATEMP0 MAC ; puts 4 bytes from 32 bit "accumulator" INPUT32 into TEMP0 LDA INPUT32+3 ; load from 32 bit "accumulator" STA TEMP0+3 ; store in table pointer LDA INPUT32+2 ; load from 32 bit "accumulator" STA TEMP0+2 ; store in table pointer LDA INPUT32+1 ; load from 32 bit "accumulator" STA TEMP0+1 ; store in table pointer LDA INPUT32 ; load from 32 bit "accumulator" STA TEMP0 ; store in table pointer <<< ; End of Macro LDATEMP0 MAC ; puts 4 bytes from ($01,$00) into 32 bit "accumulator" INPUT32, clobbers A,Y LDA TEMP0+3 ; load from table pointer STA INPUT32+3 ; store in 32 bit "accumulator" LDA TEMP0+2 ; load from table pointer STA INPUT32+2 ; store in 32 bit "accumulator" LDA TEMP0+1 ; load from table pointer STA INPUT32+1 ; store in 32 bit "accumulator" LDA TEMP0 ; load from table pointer STA INPUT32 ; store in 32 bit "accumulator" <<< ; End of Macro ;/LDATEMP0 LDA32 MAC ; puts 4 bytes from ($01,$00) into 32 bit "accumulator" INPUT32, clobbers A,Y LDY #$03 LDA ($0),Y ; load from table pointer STA INPUT32+3 ; store in 32 bit "accumulator" LDY #$02 LDA ($0),Y ; load from table pointer STA INPUT32+2 ; store in 32 bit "accumulator" LDY #$01 LDA ($0),Y ; load from table pointer STA INPUT32+1 ; store in 32 bit "accumulator" LDY #$00 LDA ($0),Y ; load from table pointer STA INPUT32 ; store in 32 bit "accumulator" <<< ; End of Macro ;/LDA32 LDX32 MAC ; puts 4 bytes from ($01,$00) into 32 bit "X register" XREGISTER32 LDY #$03 LDA ($0),Y ; load from table pointer STA XREGISTER32+3 ; store in 32 bit "X register" LDY #$02 LDA ($0),Y ; load from table pointer STA XREGISTER32+2 ; store in 32 bit "X register" LDY #$01 LDA ($0),Y ; load from table pointer STA XREGISTER32+1 ; store in 32 bit "X register" LDY #$00 LDA ($0),Y ; load from table pointer STA XREGISTER32 ; store in 32 bit "X register" <<< ; End of Macro ;/LDX32 LDY32 MAC ; puts 4 bytes from ($01,$00) into 32 bit "Y register" YREGISTER32 LDY #$03 LDA ($0),Y ; load from table pointer STA YREGISTER32+3 ; store in 32 bit "Y register" LDY #$02 LDA ($0),Y ; load from table pointer STA YREGISTER32+2 ; store in 32 bit "Y register" LDY #$01 LDA ($0),Y ; load from table pointer STA YREGISTER32+1 ; store in 32 bit "Y register" LDY #$00 LDA ($0),Y ; load from table pointer STA YREGISTER32 ; store in 32 bit "Y register" <<< ; End of Macro ;/LDY32 TAX32 MAC LDA INPUT32+3 ; load from INPUT32 STA XREGISTER32+3 ; store in 32 bit "X register" LDA INPUT32+2 ; load from INPUT32 STA XREGISTER32+2 ; store in 32 bit "X register" LDA INPUT32+1 ; load from INPUT32 STA XREGISTER32+1 ; store in 32 bit "X register" LDA INPUT32 ; load from INPUT32 STA XREGISTER32 ; store in 32 bit "X register" <<< ; End of Macro ;/TAX32 TAY32 MAC LDA INPUT32+3 ; load from INPUT32 STA YREGISTER32+3 ; store in 32 bit "Y register" LDA INPUT32+2 ; load from INPUT32 STA YREGISTER32+2 ; store in 32 bit "Y register" LDA INPUT32+1 ; load from INPUT32 STA YREGISTER32+1 ; store in 32 bit "Y register" LDA INPUT32 ; load from INPUT32 STA YREGISTER32 ; store in 32 bit "Y register" <<< ; End of Macro ;/TAY32 TXA32 MAC LDA XREGISTER32+3 ; load from 32 bit "X register" STA INPUT32+3 ; store in INPUT32 LDA XREGISTER32+2 ; load from 32 bit "X register" STA INPUT32+2 ; store in INPUT32 LDA XREGISTER32+1 ; load from 32 bit "X register" STA INPUT32+1 ; store in INPUT32 LDA XREGISTER32 ; load from 32 bit "X register" STA INPUT32 ; store in INPUT32 <<< ; End of Macro ;/TXA32 TYA32 MAC LDA YREGISTER32+3 ; load from 32 bit "Y register" STA INPUT32+3 ; store in INPUT32 LDA YREGISTER32+2 ; load from 32 bit "Y register" STA INPUT32+2 ; store in INPUT32 LDA YREGISTER32+1 ; load from 32 bit "Y register" STA INPUT32+1 ; store in INPUT32 LDA YREGISTER32 ; load from 32 bit "Y register" STA INPUT32 ; store in INPUT32 <<< ; End of Macro ;/TYA32 TYX32 MAC LDA YREGISTER32+3 ; load from 32 bit "Y register" STA XREGISTER32+3 ; store in XREGISTER32 LDA YREGISTER32+2 ; load from 32 bit "Y register" STA XREGISTER32+2 ; store in XREGISTER32 LDA YREGISTER32+1 ; load from 32 bit "Y register" STA XREGISTER32+1 ; store in XREGISTER32 LDA YREGISTER32 ; load from 32 bit "Y register" STA XREGISTER32 ; store in XREGISTER32 <<< ; End of Macro ;/TYX32 RIGHTROTATE8 MAC ; rotate INPUT32 by a full byte LDY INPUT32+3 LDA INPUT32+2 STA INPUT32+3 LDA INPUT32+1 STA INPUT32+2 LDA INPUT32 STA INPUT32+1 STY INPUT32 <<< ; End of Macro ;/RIGHTROTATE8 RIGHTSHIFT8 MAC ; rotate 32 bits right, 0->BIT31, clobbers AY LDY #$00 LDA INPUT32+2 STA INPUT32+3 LDA INPUT32+1 STA INPUT32+2 LDA INPUT32 STA INPUT32+1 STY INPUT32 <<< ; End of Macro ;/RIGHTSHIFT8 RIGHTROTATE32 MAC ; rotate 32 bits right, BIT0->BIT31, clobbers AY RIGHTSHIFT32 LDA #$00 ; accumulator to 0 ROR ; CARRY into bit7 ORA INPUT32 ; acccumulator bit7 into BIT31 STA INPUT32 <<< ; End of Macro ;/RIGHTROTATE32 RIGHTSHIFT32 MAC ; rotate 32 bits right, 0->BIT31, clobbers AY LSR INPUT32 ROR INPUT32+1 ; put result into INPUT32 ROR INPUT32+2 ; put result into INPUT32 ROR INPUT32+3 ; put result into INPUT32 <<< ; End of Macro ;/RIGHTSHIFT32 ADC32 MAC ; Adds INPUT32 and XREGISTER32 with carry, if any, clobbers A,Y LDA INPUT32+3 ; LDA byte ADC XREGISTER32+3 ; ADD with CARRY with OPERAND STA INPUT32+3 ; output to INPUT32, overflow into carry LDA INPUT32+2 ; LDA byte ADC XREGISTER32+2 ; ADD with CARRY with OPERAND STA INPUT32+2 ; output to INPUT32, overflow into carry LDA INPUT32+1 ; LDA byte ADC XREGISTER32+1 ; ADD with CARRY with OPERAND STA INPUT32+1 ; output to INPUT32, overflow into carry LDA INPUT32 ; LDA byte ADC XREGISTER32 ; ADD with CARRY with OPERAND STA INPUT32 ; output to INPUT32, overflow into carry <<< ; End of Macro ;/ADC32 LDKADC32 MAC ; puts 4 bytes from K0n into 32 bit "accumulator" INPUT32, clobbers A,Y ASL ROL TAX ;x=x*4 LDA K00 + 3,X ; load from table pointer ADC INPUT32+3 ; ADD with CARRY with OPERAND STA INPUT32+3 ; output to INPUT32, overflow into carry LDA K00 + 2,X ; load from table pointer ADC INPUT32+2 ; ADD with CARRY with OPERAND STA INPUT32+2 ; output to INPUT32, overflow into carry LDA K00 + 1,X ; load from table pointer ADC INPUT32+1 ; ADD with CARRY with OPERAND STA INPUT32+1 ; output to INPUT32, overflow into carry LDA K00,X ;load from table pointer ADC INPUT32 ; ADD with CARRY with OPERAND STA INPUT32 ; output to INPUT32, overflow into carry <<< ; End of Macro ;/LDKADC32 LDVHADC32 MAC ; puts 4 bytes from K0n into 32 bit "accumulator" INPUT32, clobbers A,Y CLC LDA VH+3 ; load from table pointer ADC INPUT32+3 ; ADD with CARRY with OPERAND STA INPUT32+3 ; output to INPUT32, overflow into carry LDA VH+2 ; load from table pointer ADC INPUT32+2 ; ADD with CARRY with OPERAND STA INPUT32+2 ; output to INPUT32, overflow into carry LDA VH+1 ; load from table pointer ADC INPUT32+1 ; ADD with CARRY with OPERAND STA INPUT32+1 ; output to INPUT32, overflow into carry LDA VH ;load from table pointer ADC INPUT32 ; ADD with CARRY with OPERAND STA INPUT32 ; output to INPUT32, overflow into carry <<< ; End of Macro ;/LDVHADC32 LDWADC MAC ; puts 4 bytes from W0n into 32 bit "accumulator" INPUT32, clobbers A,Y TXA ASL ROL TAX ; x=x*4 LDA W00 + 3,X ; load from table pointer ADC INPUT32+3 ; ADD with CARRY with OPERAND STA INPUT32+3 ; output to INPUT32, overflow into carry LDA W00 + 2,X ; load from table pointer ADC INPUT32+2 ; ADD with CARRY with OPERAND STA INPUT32+2 ; output to INPUT32, overflow into carry LDA W00 + 1,X ; load from table pointer ADC INPUT32+1 ; ADD with CARRY with OPERAND STA INPUT32+1 ; output to INPUT32, overflow into carry LDA W00,X ;load from table pointer ADC INPUT32 ; ADD with CARRY with OPERAND STA INPUT32 ; output to INPUT32, overflow into carry <<< ; End of Macro ;/LDWADC LDWADDX MAC ; puts 4 bytes from W0n into 32 bit "accumulator" INPUT32, clobbers A,Y TXA ASL ROL TAX ; x=x*4 LDA W00 + 3,X ; load from table pointer ADC XREGISTER32+3 ; ADD with CARRY with OPERAND STA INPUT32+3 ; output to INPUT32, overflow into carry LDA W00 + 2,X ; load from table pointer ADC XREGISTER32+2 ; ADD with CARRY with OPERAND STA INPUT32+2 ; output to INPUT32, overflow into carry LDA W00 + 1,X ; load from table pointer ADC XREGISTER32+1 ; ADD with CARRY with OPERAND STA INPUT32+1 ; output to INPUT32, overflow into carry LDA W00,X ;load from table pointer ADC XREGISTER32 ; ADD with CARRY with OPERAND STA INPUT32 ; output to INPUT32, overflow into carry <<< ; End of Macro ;/LDWADDX LDXADC32 MAC ; adds INPUT32 with bytes from table 00,01 CLC LDY #$03 LDA INPUT32+3 ; LDA byte ADC ($0),Y ; ADD with CARRY with OPERAND STA INPUT32+3 ; output to INPUT32, overflow into carry LDY #$02 LDA INPUT32+2 ; LDA byte ADC ($0),Y ; ADD with CARRY with OPERAND STA INPUT32+2 ; output to INPUT32, overflow into carry LDY #$01 LDA INPUT32+1 ; LDA byte ADC ($0),Y ; ADD with CARRY with OPERAND STA INPUT32+1 ; output to INPUT32, overflow into carry LDY #$00 LDA INPUT32 ; LDA byte ADC ($0),Y ; ADD with CARRY with OPERAND STA INPUT32 ; output to INPUT32, overflow into carry <<< ; End of Macro ;/LDXADC32 LDSADC32 MAC ; adds INPUT32 with bytes from Stable CLC LDA INPUT32+3 ; LDA byte ADC S0 + ]1 + 3 ; ADD with CARRY with OPERAND STA INPUT32+3 ; output to INPUT32, overflow into carry LDA INPUT32+2 ; LDA byte ADC S0 + ]1 + 2 ; ADD with CARRY with OPERAND STA INPUT32+2 ; output to INPUT32, overflow into carry LDA INPUT32+1 ; LDA byte ADC S0 + ]1 + 1 ; ADD with CARRY with OPERAND STA INPUT32+1 ; output to INPUT32, overflow into carry LDA INPUT32 ; LDA byte ADC S0 + ]1 ; ADD with CARRY with OPERAND STA INPUT32 ; output to INPUT32, overflow into carry <<< ; End of Macro ;/LDSADC32 AND32 MAC ; AND function, output to INPUT32, clobbers AY LDA INPUT32+3 ; LDA byte AND XREGISTER32+3 ; AND with OPERAND STA INPUT32+3 ; output to INPUT32 LDA INPUT32+2 ; LDA byte AND XREGISTER32+2 ; AND with OPERAND STA INPUT32+2 ; output to INPUT32 LDA INPUT32+2 ; LDA byte AND XREGISTER32+1 ; AND with OPERAND STA INPUT32+1 ; output to INPUT32 LDA INPUT32 ; LDA byte AND XREGISTER32 ; AND with OPERAND STA INPUT32 ; output to INPUT32 <<< ; End of Macro ;/AND32 ; XOR32 MAC ; XOR function, output to INPUT32, clobbers AY ; LDA INPUT32+3 ; LDA byte ; EOR XREGISTER32+3 ; EOR with OPERAND ; STA INPUT32+3 ; output to INPUT32 ; ; LDA INPUT32+2 ; LDA byte ; EOR XREGISTER32+2 ; EOR with OPERAND ; STA INPUT32+2 ; output to INPUT32 ; ; LDA INPUT32+1 ; LDA byte ; EOR XREGISTER32+1 ; EOR with OPERAND ; STA INPUT32+1 ; output to INPUT32 ; ; LDA INPUT32 ; LDA byte ; EOR XREGISTER32 ; EOR with OPERAND ; STA INPUT32 ; output to INPUT32 ; ; <<< ; End of Macro ; ;/XOR32 XORAXY32 MAC LDA INPUT32+3 ; LDA byte EOR XREGISTER32+3 ; EOR with OPERAND EOR YREGISTER32+3 ; EOR with OPERAND STA INPUT32+3 ; output to INPUT32 LDA INPUT32+2 ; LDA byte EOR XREGISTER32+2 ; EOR with OPERAND EOR YREGISTER32+2 ; EOR with OPERAND STA INPUT32+2 ; output to INPUT32 LDA INPUT32+1 ; LDA byte EOR XREGISTER32+1 ; EOR with OPERAND EOR YREGISTER32+1 ; EOR with OPERAND STA INPUT32+1 ; output to INPUT32 LDA INPUT32 ; LDA byte EOR XREGISTER32 ; EOR with OPERAND EOR YREGISTER32 ; EOR with OPERAND STA INPUT32 ; output to INPUT32 <<< ; End of Macro ;/XORAXY32 * Produce the final hash value (big-endian): * digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7 * ************************************************** INCNONCE MAC INC NONCE+3 ; rolled to zero, do next byte up BNE NONCEDONE INC NONCE+2 ; rolled to zero, do next byte up BNE NONCEDONE INC NONCE+1 ; rolled to zero, do next byte up BNE NONCEDONE INC NONCE ; rolled to zero, do next byte up BNE NONCEDONE JMP DONEWORK ; done? seriously? NONCEDONE <<< ; RTS MAJ32 MAC ; majority function. Takes INPUT32, XREGISTER32 and YREGISTER32, returns with result in INPUT32, clobbers AXY ; load VA,VB,VC into AXY LDA VA + 0 LDX VB + 0 LDY VC + 0 MAJ STA INPUT32+0 LDA VA + 1 LDX VB + 1 LDY VC + 1 MAJ STA INPUT32+1 LDA VA + 2 LDX VB + 2 LDY VC + 2 MAJ STA INPUT32+2 LDA VA + 3 LDX VB + 3 LDY VC + 3 MAJ STA INPUT32+3 <<< ; End of Macro ;/MAJ32 MAJ MAC ; majority function. Takes A,X and Y, returns with A ; maj := (A and X) xor (A and Y) xor (X and Y) STA RESULT32 ; A to RESULT32,0 STX RESULT32+1 ; X to RESULT321 STY RESULT32+2 ; Y to RESULT322 AND RESULT32+1 ; A and X, result to RESULT32,3 STA RESULT32+3 LDA RESULT32 ; A and Y, result to RESULT32,4 AND RESULT32+2 STA RESULT32+4 LDA RESULT32+1 ; X and Y, result to RESULT32,5 AND RESULT32+2 STA RESULT32+5 ; RESULT32,3 xor RESULT32,4 xor RESULT32,5 LDA RESULT32+3 EOR RESULT32+4 EOR RESULT32+5 <<< ; End of Macro ;/MAJ ; choice function. Takes INPUT32 and XREGISTER32, returns with result in INPUT32, clobbers AXY CHOICE32 MAC LDA VE + 0 ; VE LDX VF + 0 ; VF LDY VG + 0 ; VG CHOICE STA INPUT32 + 0 LDA VE + 1 ; VE LDX VF + 1 ; VF LDY VG + 1 ; VG CHOICE STA INPUT32 + 1 LDA VE + 2 ; VE LDX VF + 2 ; VF LDY VG + 2 ; VG CHOICE STA INPUT32 + 2 LDA VE + 3 ; VE LDX VF + 3 ; VF LDY VG + 3 ; VG CHOICE STA INPUT32 + 3 <<< ; End of Macro ;/CHOICE32 CHOICE MAC ; choice function. Takes A,X,Y, returns with result in A, clobbers AXY ; ch := (A and X) xor ((not A) and Y) ; (RESULT32,2) EOR ((not A) AND Y) ; (RESULT32,2) EOR (RESULT32,1 AND Y) ; if bit(A)=0, then bit(Y), else bit(X) STA RESULT32 ; A to TEMP STX RESULT32+1 ; X to TEMP1 AND RESULT32+1 STA RESULT32+2 ; A AND X to TEMP LDA RESULT32 ; A back to A EOR #$FF ; NOT A STA RESULT32+1 ; NOT A to TEMP1 TYA ; Y to A AND RESULT32+1 ; AND with (NOT A) EOR RESULT32+2 ; EOR (A AND X) ; result in A <<< ; End of Macro ;/CHOICE PRHEX MAC ; replaces PRBYTE routine. still uses COUT. You're next, COUT. Watch your back. PHA ; hang onto original value for a moment AND #$F0 LSR LSR LSR LSR TAX LDA HEXTOASCII,X ; get ascii code for nibble "0"-"F" LDY CH ; 0 STA ($28),Y INC CH ; 1 PLA AND #$0F ; clear high nibble TAX LDA HEXTOASCII,X ; get ascii code for nibble "0"-"F" LDY CH ; 1 STA ($28),Y INC CH ; 2 <<< ;/PRHEX ************************************************** * subroutines ************************************************** FLIPCOIN JSR ROTATE1 LDA #$30 JSR WAIT JSR ROTATE2 LDA #$30 JSR WAIT JSR SPLASHSCREEN ; fancy lo-res graphics RTS ;/FLIPCOIN ROTATE1 LDA ROTATE1LO ; Setup pointers to move memory STA $3C ; $3C and $3D for source start LDA ROTATE1HI STA $3D LDA ROTATE1LO STA $3E ; $3E and $3F for source end LDA ROTATE1HI CLC ADC #$04 ; add $400 to start == end of graphic STA $3F ; JMP MOVEIMAGE ROTATE2 LDA ROTATE2LO ; Setup pointers to move memory STA $3C ; $3C and $3D for source start LDA ROTATE2HI STA $3D LDA ROTATE2LO STA $3E ; $3E and $3F for source end LDA ROTATE2HI CLC ADC #$04 ; add $400 to start == end of graphic STA $3F ; JMP MOVEIMAGE SPLASHSCREEN LDA SPLASHLO ; Setup pointers to move memory STA $3C ; $3C and $3D for source start LDA SPLASHHI STA $3D LDA SPLASHLO STA $3E ; $3E and $3F for source end LDA SPLASHHI CLC ADC #$04 ; add $400 to start == end of graphic STA $3F ; MOVEIMAGE LDA #$00 ; move graphic data to $8000 STA $42 ; $42 and $43 for destination LDA #$80 STA $43 LDA #$00 ; Clear ACC, X,Y for smooth operation TAX TAY JSR $FE2C ; F8ROM:MOVE ; Do the memory move ; display the data from $8000 at $400 RESETVPTR LDA #$00 ; Move titlepage from $8000 to $400 (screen) STA $FE ; pointer for where we are at vertically on screen TAY ; Y-Reg used for indexing across (horiz) screen VERTICALPTR LDA $FE ; pointer for where we are at vertically on screen JSR $F847 ; F8ROM:GBASCALC LDA $26 STA $FA ; $FA is our offset GBASL Byte (Source data titlepage) LDA $27 ; Add 04 w/ Carry to get to $8000 where graphic data is ADC #$7C STA $FB ; $FB is our offset GBASH Byte (Source data titlepage) LDY #$07 GRABSTORAGE LDA ($FA),Y ; Grab from storage STA ($26),Y ; Put to screen INY CPY #$21 ; #$28 past the width of screen? BNE GRABSTORAGE ; No? Back for another round LDA #$00 TAX TAY INC $FE ; Next line down vertically LDA #$00 TAX TAY LDA $FE CMP #$14 ; #$18 bottom of screen? BNE VERTICALPTR ; No? Go back and do next line down RTS ; We now return you to your regular programming ;/SPLASHSCREEN FILLSCREENFAST LDA #$00 LDY #$78 JSR FILL1 LDY #$50 ; #$78 for all 24 lines. JSR FILL2 RTS FILL1 DEY STA $400, Y STA $480, Y STA $500, Y STA $580, Y BNE FILL1 RTS FILL2 DEY STA $600, Y STA $680, Y STA $700, Y STA $780, Y BNE FILL2 RTS ************************************************** * MESSAGE TO BE HASHED. * ************************************************** MESSAGELO DB MESSAGE MESSAGE EQU * HEADER EQU * ; 80 bytes for header = L = 640 bits * What's being hashed is: version4 + previous block hash32 + merkel root32 + time4 + bits (target)4 + nonce4 = blockheader (80 bytes) ; 20000000e905eff72bb63f67b3abf7e0d930371814fad083000ce8640000000000000000cfbf4e0e035d175595d486a99705151b956c0a36d9febeb9ea7968ad38e54ead5d3b5f4a171f3a0800000000 ; [2019-07-26 16:15:11.585] Selecting pool 0 for work ; [2019-07-26 16:15:11.586] Generated stratum merkle cfbf4e0e035d175595d486a99705151b956c0a36d9febeb9ea7968ad38e54ead ; [2019-07-26 16:15:11.586] Generated stratum header 20000000e905eff72bb63f67b3abf7e0d930371814fad083000ce8640000000000000000cfbf4e0e035d175595d486a99705151b956c0a36d9febeb9ea7968ad38e54ead5d3b5f4a171f3a08000000000000008000000000000000000000000000000000000000000000000000000000 ; [2019-07-26 16:15:11.586] Work job_id 65e11 nonce2 5 ntime 5d3b5f4a ; [2019-07-26 16:15:11.586] Generated target 00000000000000000000000000000000000000000000000080ff7f0000000000 ; [2019-07-26 16:15:11.586] Generated stratum work VERSION HEX 20,00,00,00 ; DS 4 PREVHASH HEX e9,05,ef,f7,2b,b6,3f,67,b3,ab,f7,e0,d9,30,37,18,14,fa,d0,83,00,0c,e8,64,00,00,00,00,00,00,00,00 ; DS 32 MERKELROOT HEX cf,bf,4e,0e,03,5d,17,55,95,d4,86,a9,97,05,15,1b,95,6c,0a,36,d9,fe,be,b9,ea,79,68,ad,38,e5,4e,ad ; DS 32 TIMESTAMP HEX 5d,3b,5f,4a ; DS 4 TARGET HEX 17,1f,3a,08 ; DS 4 NONCE HEX 00,00,00,00 ; DS 4 ; then append one 1 bit APPENDBIT DB #$80 ; 10000000 - 7 extra bits = 648 bits ; append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512 ; 648 + K + 64 = 1024 PADDINGBITS DS 39 ; K = 312 bits = 39 bytes ; append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits MESSAGELENGTH HEX 00,00,00,00,00,00,02,80 ; L = 640, in 8 bytes = 0,0,0,0,0,0,02,80 ;nonce 0000 = 1A722F82830421E6F4655470C6565614144DD70202FC8C56D8E7C601060FBAD1 ;NONCELO DB NONCE JOBID ASC "65e11" ; VERSION HEX 01,00,00,00 ; DS 4 ; PREVHASH HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 ; DS 32 ; MERKELROOT HEX 3b,a3,ed,fd,7a,7b,12,b2,7a,c7,2c,3e,67,76,8f,61,7f,c8,1b,c3,88,8a,51,32,3a,9f,b8,aa,4b,1e,5e,4a ; DS 32 ; TIMESTAMP HEX 29,ab,5f,49 ; DS 4 ; TARGET HEX ff,ff,00,1d ; DS 4 ; NONCE HEX 1d,ac,2b,7c ; DS 4 ; ; then append one 1 bit ; APPENDBIT DB #$80 ; 10000000 - 7 extra bits = 648 bits ; ; append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512 ; ; 648 + K + 64 = 1024 ; PADDINGBITS DS 39 ; K = 312 bits = 39 bytes ; ; append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits ; MESSAGELENGTH HEX 00,00,00,00,00,00,02,80 ; ; L = 640, in 8 bytes = 0,0,0,0,0,0,02,80 ; JOBID ASC "0" ; GENESIS BLOCK **** Message2 only needs one chunk! **** MESSAGE2LO DB MESSAGE2 MESSAGE2 DS 32 ; new message content after first pass produces hash - 256 bits ; then append one 1 bit APPENDBIT2 DB #$80 ; 10000000 - 7 extra bits = 264 bits ; append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512 ; 264 + K + 64 = 512 !!!! 1024 PADDINGBITS2 DS 23 ; K = 184 bits = 87 bytes ; append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits MESSAGELENGTH2 HEX 00,00,00,00,00,00,01,00 ; L = 256, in 8 bytes = 0,0,0,0,0,0,01,00 ************************************************** * Data Tables * ************************************************** TEMPLO DB TEMP0,>TEMP1 RESULT32LO DB RESULT32 VA DS 4 VB DS 4 VC DS 4 VD DS 4 VE DS 4 VF DS 4 VG DS 4 VH DS 4 ; VTABLE DA VA,VB,VC,VD,VE,VF,VG,VH VTABLELO DB VA,>VB,>VC,>VD,>VE,>VF,>VG,>VH ; create a 64-entry message schedule array w[0..63] of 32-bit words ; (The initial values in w[0..63] don't matter, so many implementations zero them here) W00 DS 4 W01 DS 4 W02 DS 4 W03 DS 4 W04 DS 4 W05 DS 4 W06 DS 4 W07 DS 4 W08 DS 4 W09 DS 4 W10 DS 4 W11 DS 4 W12 DS 4 W13 DS 4 W14 DS 4 W15 DS 4 W16 DS 4 W17 DS 4 W18 DS 4 W19 DS 4 W20 DS 4 W21 DS 4 W22 DS 4 W23 DS 4 W24 DS 4 W25 DS 4 W26 DS 4 W27 DS 4 W28 DS 4 W29 DS 4 W30 DS 4 W31 DS 4 W32 DS 4 W33 DS 4 W34 DS 4 W35 DS 4 W36 DS 4 W37 DS 4 W38 DS 4 W39 DS 4 W40 DS 4 W41 DS 4 W42 DS 4 W43 DS 4 W44 DS 4 W45 DS 4 W46 DS 4 W47 DS 4 W48 DS 4 W49 DS 4 W50 DS 4 W51 DS 4 W52 DS 4 W53 DS 4 W54 DS 4 W55 DS 4 W56 DS 4 W57 DS 4 W58 DS 4 W59 DS 4 W60 DS 4 W61 DS 4 W62 DS 4 W63 DS 4 ; WTABLE DA W00,W01,W02,W03,W04,W05,W06,W07,W08,W09 ; DA W10,W11,W12,W13,W14,W15,W16,W17,W18,W19 ; DA W20,W21,W22,W23,W24,W25,W26,W27,W28,W29 ; DA W30,W31,W32,W33,W34,W35,W36,W37,W38,W39 ; DA W40,W41,W42,W43,W44,W45,W46,W47,W48,W49 ; DA W50,W51,W52,W53,W54,W55,W56,W57,W58,W59 ; DA W60,W61,W62,W63 WTABLELO DB W00,>W01,>W02,>W03,>W04,>W05,>W06,>W07,>W08,>W09 DB >W10,>W11,>W12,>W13,>W14,>W15,>W16,>W17,>W18,>W19 DB >W20,>W21,>W22,>W23,>W24,>W25,>W26,>W27,>W28,>W29 DB >W30,>W31,>W32,>W33,>W34,>W35,>W36,>W37,>W38,>W39 DB >W40,>W41,>W42,>W43,>W44,>W45,>W46,>W47,>W48,>W49 DB >W50,>W51,>W52,>W53,>W54,>W55,>W56,>W57,>W58,>W59 DB >W60,>W61,>W62,>W63 ; Initialize hash values: ; (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): CACHEDHASH DS 32 ; storage for the first chunk of first pass. Won't change between nonce changes. INITIALHASH HEX 6a,09,e6,67 ; need to keep this on hand to reset after hash pass 1. HEX bb,67,ae,85 HEX 3c,6e,f3,72 HEX a5,4f,f5,3a HEX 51,0e,52,7f HEX 9b,05,68,8c HEX 1f,83,d9,ab HEX 5b,e0,cd,19 H00 HEX 6a,09,e6,67 H01 HEX bb,67,ae,85 H02 HEX 3c,6e,f3,72 H03 HEX a5,4f,f5,3a H04 HEX 51,0e,52,7f H05 HEX 9b,05,68,8c H06 HEX 1f,83,d9,ab H07 HEX 5b,e0,cd,19 ; HTABLE DA H00,H01,H02,H03,H04,H05,H06,H07 HTABLELO DB H00,>H01,>H02,>H03,>H04,>H05,>H06,>H07 ; STABLE DA S0,S1 STABLELO DB S0,>S1 ; Initialize array of round constants: ; (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): K00 HEX 42,8a,2f,98 K01 HEX 71,37,44,91 K02 HEX b5,c0,fb,cf K03 HEX e9,b5,db,a5 K04 HEX 39,56,c2,5b K05 HEX 59,f1,11,f1 K06 HEX 92,3f,82,a4 K07 HEX ab,1c,5e,d5 K08 HEX d8,07,aa,98 K09 HEX 12,83,5b,01 K10 HEX 24,31,85,be K11 HEX 55,0c,7d,c3 K12 HEX 72,be,5d,74 K13 HEX 80,de,b1,fe K14 HEX 9b,dc,06,a7 K15 HEX c1,9b,f1,74 K16 HEX e4,9b,69,c1 K17 HEX ef,be,47,86 K18 HEX 0f,c1,9d,c6 K19 HEX 24,0c,a1,cc K20 HEX 2d,e9,2c,6f K21 HEX 4a,74,84,aa K22 HEX 5c,b0,a9,dc K23 HEX 76,f9,88,da K24 HEX 98,3e,51,52 K25 HEX a8,31,c6,6d K26 HEX b0,03,27,c8 K27 HEX bf,59,7f,c7 K28 HEX c6,e0,0b,f3 K29 HEX d5,a7,91,47 K30 HEX 06,ca,63,51 K31 HEX 14,29,29,67 K32 HEX 27,b7,0a,85 K33 HEX 2e,1b,21,38 K34 HEX 4d,2c,6d,fc K35 HEX 53,38,0d,13 K36 HEX 65,0a,73,54 K37 HEX 76,6a,0a,bb K38 HEX 81,c2,c9,2e K39 HEX 92,72,2c,85 K40 HEX a2,bf,e8,a1 K41 HEX a8,1a,66,4b K42 HEX c2,4b,8b,70 K43 HEX c7,6c,51,a3 K44 HEX d1,92,e8,19 K45 HEX d6,99,06,24 K46 HEX f4,0e,35,85 K47 HEX 10,6a,a0,70 K48 HEX 19,a4,c1,16 K49 HEX 1e,37,6c,08 K50 HEX 27,48,77,4c K51 HEX 34,b0,bc,b5 K52 HEX 39,1c,0c,b3 K53 HEX 4e,d8,aa,4a K54 HEX 5b,9c,ca,4f K55 HEX 68,2e,6f,f3 K56 HEX 74,8f,82,ee K57 HEX 78,a5,63,6f K58 HEX 84,c8,78,14 K59 HEX 8c,c7,02,08 K60 HEX 90,be,ff,fa K61 HEX a4,50,6c,eb K62 HEX be,f9,a3,f7 K63 HEX c6,71,78,f2 ; KTABLE DA K00,K01,K02,K03,K04,K05,K06,K07,K08,K09 ; DA K10,K11,K12,K13,K14,K15,K16,K17,K18,K19 ; DA K20,K21,K22,K23,K24,K25,K26,K27,K28,K29 ; DA K30,K31,K32,K33,K34,K35,K36,K37,K38,K39 ; DA K40,K41,K42,K43,K44,K45,K46,K47,K48,K49 ; DA K50,K51,K52,K53,K54,K55,K56,K57,K58,K59 ; DA K60,K61,K62,K63 KTABLELO DB K00,>K01,>K02,>K03,>K04,>K05,>K06,>K07,>K08,>K09 DB >K10,>K11,>K12,>K13,>K14,>K15,>K16,>K17,>K18,>K19 DB >K20,>K21,>K22,>K23,>K24,>K25,>K26,>K27,>K28,>K29 DB >K30,>K31,>K32,>K33,>K34,>K35,>K36,>K37,>K38,>K39 DB >K40,>K41,>K42,>K43,>K44,>K45,>K46,>K47,>K48,>K49 DB >K50,>K51,>K52,>K53,>K54,>K55,>K56,>K57,>K58,>K59 DB >K60,>K61,>K62,>K63 ; 80 ascii '0' ; 4c7f3da0386523b102328418c28d886bb9dc9c555671884e8fcc9bcba407e819 ; 4C7F3DA0386523B102328418C28D886BB9DC9C555671884E8FCC9BCBA407E819 - boom. (1 pass) ; The quick brown fox jumps over the lazy dog - len 43 ; d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592 - https://www.xorbin.com/tools/sha256-hash-calculator ; D7A8FBB307D7809469CA9ABCB0082E4F8D5651E46D3CDB762D02D0BF37C9E592 - https://docs.google.com/spreadsheets/d/1ipesRlJGtS_1Tm452lOueBEZzdgZkaH-AihtJDo55Sc/edit#gid=2107569783 ; D7A8FBB307D7809469CA9ABCB0082E4F8D5651E46D3CDB762D02D0BF37C9E592 - confirmed (1 pass) ;0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c ; GENESIS BLOCK ;af42031e805ff493a07341e2f74ff58149d22ab9ba19f61343e2c86c71c5d66d pass 1 ;6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 pass 2 ;AF42031E805FF493A07341E2F74FF58149D22AB9BA19F61343E2C86C71C5D66D - pass 1 ;6FE28C0AB6F1B372C1A6A246AE63F74F931E8365E15A089C68D6190000000000 - boom. HEXTOASCII ASC "0123456789ABCDEF" SPLASHLO db SPLASHSCREENDATA ROTATE1LO db ROTATE1DATA ROTATE2LO db ROTATE2DATA SPLASHSCREENDATA HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,D0,90,9D,99,99,99,99,99,99,99,90,90,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,99,99,99,99,99,99,99,99,DD,FF,FF,FF HEX 99,99,99,99,99,FF,FF,FF,99,99,99,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,0D HEX D9,99,99,99,9F,9F,9F,DF,FF,FF,9F,DF,FF,FF,9F,9F,9F,99,99,99,09,00,00,00,00,00,00,00,00,00 HEX FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,D0,9D,99,99,99,99,99,99,99,99 HEX 99,99,99,99,99,90,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,99,99,99,99 HEX 99,99,99,99,DD,FF,FF,FF,F9,F9,F9,F9,FD,FF,FF,9F,99,99,99,99,99,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,0D,D9,99,99,99,99,99,DD,FF,FF,99,DD,FF,FF,99,99,99,99,99,09,00,00 HEX 00,00,00,00,00,00,00,00,FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,D0,9D,99,99 HEX 99,99,99,DD,FF,FF,99,DD,FF,FF,99,99,99,99,99,90,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,DD,99,99,99,99,99,99,99,99,DD,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,99,99,99,99,99,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,0D,D9,99,99,99,9D,9F,9F,99,9D,9F,9F HEX 99,99,99,09,00,00,00,00,00,00,00,00,00,00,00,00,FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00 HEX 00,00,00,00,DD,99,99,99,99,99,99,DD,FF,FF,99,DD,FF,FF,99,99,99,99,99,99,90,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,DD,99,99,99,99,99,99,99,99,DD,FF,FF,FF,9F,9F,9F,9F,9F,DF HEX FF,FF,FF,99,99,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,0D,D9 HEX 89,99,99,99,99,99,99,99,89,09,00,00,00,00,00,00,00,00,00,00,00,00,00,00,FF,FF,FF,FF,FF,FF HEX FF,FF,00,00,00,00,00,00,00,00,00,DD,99,99,99,99,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,F9,99 HEX 99,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,99,99,99,99,99,99,99,99,DD,FF HEX FF,FF,99,99,99,99,99,99,FF,FF,FF,99,99,99,89,00,00,00,00,00,00,00,DF,DF,DF,DF,DF,DF,DF,DF HEX DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,A0,A0,A0,A0,A0 HEX A0,D5,FF,FF,FF,FF,FF,FF,FF,70,00,00,00,00,00,00,00,00,D0,9D,99,99,99,99,9F,FF,FF,FF,FF,FF HEX FF,FF,FF,FF,FF,FF,FF,F9,99,99,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,99 HEX 99,99,99,99,99,99,DD,FF,FF,FF,99,99,99,99,99,D9,FF,FF,FF,99,99,99,00,00,00,00,00,00,00,00 HEX 1F,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0 HEX A0,A0,1F,A0,A0,A0,A0,A0,A0,A0,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,DD,99,99,99 HEX 99,99,99,99,DD,FF,FF,FF,99,99,99,9D,DF,FF,FF,FF,99,99,99,99,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,DD,99,99,99,99,99,99,F9,FD,FF,FF,FF,F9,F9,F9,F9,FD,FF,FF,FF,9F,99,99,99 HEX 00,00,00,00,00,00,00,00,1F,A0,D8,BE,A0,B0,B0,A0,D9,BE,A0,B0,B0,A0,D0,EC,EF,F4,BE,A0,CF,E6 HEX E6,A0,C3,EF,EC,BE,A0,B0,B9,A0,1F,A0,A0,A0,A0,A0,A0,A0,70,FF,FF,FF,FF,FF,FF,00,00,00,00,00 HEX 00,00,00,D0,9D,99,99,99,99,99,99,99,DD,FF,FF,FF,99,99,99,99,99,FF,FF,FF,99,99,99,99,90,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,99,99,99,99,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF HEX FF,FF,FF,9F,99,99,99,00,00,00,00,00,00,00,00,00,20,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF HEX DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,20,A0,BF,AD,C8,E5,EC,F0,C7,FF,FF,FF HEX FF,FF,FF,FF ROTATE1DATA HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,D0,DD,9D,99,99,99,99,90,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD,99,99,99,99,99,DD,FF,99 HEX 99,99,DD,FF,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 0D,DD,D9,99,9D,9F,DF,FF,DF,FF,9F,99,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,FF,FF,FF,FF HEX FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD,99,99,99,99,99,99,99,99,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD,99,99,99,99 HEX 99,DD,FF,F9,F9,FD,FD,9F,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,DD,DD,99,99,99,DD,FF,DD,FF,99,99,99,09,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD,99,99,99,DD,FF,DD,FF HEX 99,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD HEX 99,99,99,99,99,DD,FF,FF,FF,FF,FF,99,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,DD,DD,99,99,9D,9F,9D,9F,99,99,09,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD,99,99,99 HEX DD,FF,DD,FF,99,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,DD,DD,99,99,99,99,99,DD,FF,9F,9F,DF,DF,FF,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,0D,DD,D9,99,99,99,99,09,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD HEX 99,99,D9,F9,FD,FF,FD,FF,F9,99,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,DD,DD,99,99,99,99,99,DD,FF,99,99,99,DD,FF,99,99,00,00,00,00,00,00,00,00,00 HEX 00,00,00,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF HEX DF,DF,DF,DF,DF,A0,A0,A0,A0,A0,A0,D5,FF,FF,FF,FF,FF,FF,FF,80,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,DD,DD,99,99,DD,FF,FF,FF,FF,FF,FF,FF,99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,0D,DD,D9,99,99,99,99,DD,FF,99,99,99,DD,FF,99,99,00,00,00,00,00 HEX 00,00,00,00,00,00,00,1F,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0 HEX A0,A0,A0,A0,A0,A0,A0,A0,1F,A0,A0,A0,A0,A0,A0,A0,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,DD,DD,99,99,99,99,DD,FF,99,99,9D,DF,F9,99,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD,99,99,D9,F9,FD,FF,F9,F9,FD,FD,FF,99,09,00 HEX 00,00,00,00,00,00,00,00,00,00,00,1F,A0,D8,BE,A0,B0,B0,A0,D9,BE,A0,B0,B0,A0,D0,EC,EF,F4,BE,A0, HEX CF,E6,E6,A0,C3,EF,EC,BE,A0,B0,C6,A0,1F,A0,A0,A0,A0,A0,A0,A0,70,FF,FF,FF,FF,FF,FF,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,DD,DD,99,99,99,99,99,DD,FF,99,99,99,DD,FF,99,99,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD,99,99,DD,FF,FF,FF,FF,FF,FF,FF HEX 99,99,00,00,00,00,00,00,00,00,00,00,00,00,00,20,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF HEX DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,20,A0,BF,AD,C8,E5,EC,F0,C7,FF,FF,FF,FF,FF,FF,FF ROTATE2DATA HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,D0,DF,DF,DF,D0,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DF,DF,DF,99 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,DD,DD,DD,DD,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,FF,FF,FF,FF HEX FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DF,DF,DF,99,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD HEX DD,DD,DD,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,DD,DF,DF,DF,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DF,DF,DF,99,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,DD,DF,DF,DF,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,DD,DF,DF,DF,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DF HEX DF,DF,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,DD,DD,DD,DD,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,0D,DF,DF,DF,0D,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,DD,FD,FD,FD,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,DD,DF,DF,DF,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF HEX DF,DF,DF,DF,DF,A0,A0,A0,A0,A0,A0,D5,FF,FF,FF,FF,FF,FF,FF,80,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,DD,DD,DD,DD,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD,DD,DD,99,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,1F,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0 HEX A0,A0,A0,A0,A0,A0,A0,A0,1F,A0,A0,A0,A0,A0,A0,A0,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,DD,DF,DF,DF,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DF,DF,DF,99,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,1F,A0,D8,BE,A0,B0,B0,A0,D9,BE,A0,B0,B0,A0,D0,EC,EF,F4,BE,A0 HEX CF,E6,E6,A0,C3,EF,EC,BE,A0,B0,C6,A0,1F,A0,A0,A0,A0,A0,A0,A0,70,FF,FF,FF,FF,FF,FF,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,DD,DD,DD,99,00,00,00,00,00,00,00,00,00,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,DD,FD,FD,FD,99,00,00,00 HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,20,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF HEX DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,20,A0,BF,AD,C8,E5,EC,F0,C7,FF,FF,FF,FF,FF,FF,FF