Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- A1 - input - always WORD reads
- A5 - output - always WORD writes
- D1 - unused
- D2 - num bits remaining
- D3 - bits from to process. input always read into here
- D4 - used to output. Holds last word decoded? Except in write loop where lower byte overwritten from D5
- D5 - used to output. Mostly the same as D4, except 15th bit flipped occasionally.
- D6 - Has two meanings depending on inner loop or shunt loop
- inner loop: used as offset for write aheads
- shunt loop: counter for later
- Notes:
- ------
- groups of 5 bits seems to come up often
- */
- D2 = ram[F730]
- D3 = ram[F732]
- repeat all:
- D2 -= 5
- if (D2 > 0)
- {
- // top prep A
- // more than 5 bits left in registers
- rotate D3.w << 5
- D7.w = D3.w
- }
- else if (D2 == 0)
- {
- // top prep B
- // Exactly 5 bits left in registers
- D2 = 16
- rotate D3.w << 5
- D7.w = D3.w
- D3.w = input++
- }
- else
- {
- // top prep C
- // less than 5 bits left in registers
- D7 = D2
- D2 += 5
- D3 << D2
- D3.w = input++
- D7 = -D7
- D7 << D3
- D2 += 11
- D7 = D3
- swap D7
- }
- // common top prep
- D7.w &= 001F // zero all but bottom 5 bits
- D7 >> 1
- if (shunted 1)
- {
- // pre inner loop
- D4.w = D7
- output++ = D4.w
- D5.w = D4
- D5 set bit 15
- D6 = 0
- // Inner Loop
- while (true)
- {
- D2 -= 2
- if (D2 > 0)
- {
- // inner branch A
- rotate D3 << 2
- D7.w = D3
- }
- else if (D2 == 0)
- {
- // inner branch B
- D2 = 16
- rotate D3 << 2
- D7.w = D3
- D3.w = input++
- }
- else
- {
- // inner branch C
- D2 = $F
- D3 *= 2
- D3.w = input++
- ADDX.w D3, D3
- D7.w = D3
- ADDX.w D7, D7
- }
- // after inner branch
- D7 &= 0x3 // mask off all but lower two bits
- if (D7 == 0)
- {
- // inner continues
- D2--
- if (D2 == 0)
- {
- // inner reinit
- D2 = 16
- D3 *= 2
- D3 = input++
- ROXR.w D3 >> 1 // rotate-extended-right
- }
- ADDX.w D3, D3
- if (carry not set) // Branch on carry clear
- {
- // Break out of inner loop, ready for shunt loop
- // NB: Only place we can escape the inner loop
- break;
- }
- D2--
- if (D2 == 0)
- {
- // re-read before write ahead
- D2 = 16
- D3.w *= 2 // push top bit into Xtend flag?
- D3.w = input++
- ROXR D3.w >> 1
- }
- ADDX D3, D3
- if (carry set)
- {
- // write ahead method 3
- D6 += $14 // dec 20
- output[-1+D6] = D5.w
- // will restart inner loop now
- }
- else
- {
- // write ahead method 2
- D6 += $C // dec 12
- output[-2+D6] = D5.w
- // will restart inner loop now
- }
- }
- else
- {
- // write ahead method 1
- D7 += 6
- D7 *= 2
- D7 += D6
- output[-2+D6] = D5
- }
- } // end inner loop
- }
- else
- {
- // inner loop replacement
- D4.w = D7.w
- output++ = D4.w
- D5.w = D4.w
- D5 set bit 15
- }
- // Prep for shunt loop
- D7 = 0
- D6 = 1
- // Shunt loop
- while (true)
- {
- D7++
- D6 << 1
- D2--
- if (D2 > 0)
- {
- // Get more bits
- // reset D2 bit counter, read input, shunt, then exit if shunted 0
- D2 = 0x10
- D3 << 1
- D3 = input++ // nb: actually inside following if/else twice but more readable here
- if (shunted 0)
- break;
- }
- else
- {
- // has more bits
- D3 << 1
- if (shunted 0)
- break;
- }
- }
- // After shunt loop
- // Prep for write
- bool isD2Greater = (D2 > D7)
- bool isD2Equal = (D2 == D7)
- D2 -= D7
- if (isD2Greater)
- {
- // write prep A
- swap D3
- clear lower word of D3
- rotate D3 << D7
- D7.w = D3.w
- swap D3
- }
- else if (isD2Equal)
- {
- // write prep B
- D2 = 0x10
- swap D3
- clear lower word of D3
- rotate D3 << D7
- D7.w = D3.w
- D3.w = input++
- }
- else
- {
- // write prep C
- clear upper word of D3
- D2 += D7 // undo sub at top of write prep
- D3 << D2 // shift left by D2 bits
- D3.w = input++
- D7 -= D2
- D3 << D7
- D2 = 0x10
- D2 -= D7
- D7 = D3
- swap D7
- }
- // finish write prep
- D6 += D7
- D6 -= 3
- // Anything to loop?
- if (D6 > 0) // todo: check if > or >=
- {
- // Write loop
- for (int i=0; i<D6; i++)
- {
- D7 = peek output
- if (bit 31 of D7 set)
- {
- D5.w = D7.w
- D4.b = D5.b
- }
- output = D4.w
- output++
- }
- }
- // Check if buffer full?
- if output buffer not full
- jump to repeat
- // Save decompression state
- ram[F730] = D2
- ram[F732] = D3
- // nb: output pointer is maintained in register A0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement