We just released a Feb. 5 '89 prototype of DuckTales for the NES!
If you'd like to support our preservation efforts (and this wasn't cheap), please consider donating or supporting us on Patreon. Thank you!
If you'd like to support our preservation efforts (and this wasn't cheap), please consider donating or supporting us on Patreon. Thank you!
Crystal Quest (Apple IIGS)
Jump to navigation
Jump to search
Cleanup > To do
Games > Games by content > Games with uncompiled source code
Games > Games by content > Games with unused graphics
Games > Games by developer > Games developed by Casady & Greene
Games > Games by platform > Apple IIGS games
Games > Games by publisher > Games published by Casady & Greene
Games > Games by release date > Games released in 1989
| Crystal Quest |
|---|
|
Developer:
Casady & Greene
|
Alternate Title Graphics
| Unused (MAIN.PIC.X) | Used (MAIN.PIC) |
|---|---|
![]() |
![]() |
Inside the floppy disk is a version of the title version with a different publisher logo, predating the used title screen by four days.
Uncompiled Source Code
| To do: Get the Huffman Compressor extracted out of the disk somehow. |
Scattered throughout many of the later blocks of data in the game's data is this code and executable for a Huffman compressor for the Apple IIGS, which can be found at Block 1442.
LST OFF
TR ON
XC
XC
REL
EXT LOADINPUTFILE,PARSEOUTPUT
EXT WRITEOUTPUT,SWITCHES
EXT INITEXE,KILLEXE
EXT TEXT,ALLOCMEM,PRWORD
ENT IFILENAME,OFILENAME
ENT INPUTLENGTH,INPUTPOINTER
ENT OUTPUTLENGTH,OUTPUTPOINTER
DUM $60
SCREENAD DS 4
SCREENAD2 DS 4
ENDADR DS 4
BITCOUNT DS 1
BITTEMP DS 1
LO DS 3
ZPAGEEND
DEND
HOFFSIZE = 20
*
* Load a file and pack it
*
MX %00
ENTRY
JSR INITEXE ;Do the housekeeping for an EXE file
BCS :OK ;Oops! Wrong shell!
STZ HEADERENABLE
LDA #SWITCHTABLE
JSR SWITCHES ;Check for soft switches
JSR LOADINPUTFILE ;Parse a filename and load it
BCS :ERROR ;Bad input?
LDA #APPENDSTRING ;If no filename then append this to input
;file
JSR PARSEOUTPUT ;Parse an output file.
CLC
LDA INPUTLENGTH ;Request input memory plus a 4K safety
ADC #4000
TAX
LDA INPUTLENGTH+2
ADC #^4000
TAY
LDA #$C000 ;Fixed memory
JSR ALLOCMEM ;Allocate data memory
BCS :ERROR
STX OUTPUTPOINTER ;64K data
STY OUTPUTPOINTER+2
JSR HUFFMAN ;Pack the data
JSR WRITEOUTPUT ;Write the result
BCS :ERROR
:OK JSR KILLEXE ;Kill all memory
LDA #$0000
CLC
RTL
*
* Error occured!
*
:ERROR PHA
JSR TEXT
HEX 8D
ASC "Usage : HUFFMAN Infile (.H) [Outfile]"8d
ASC "[Switchs: -N No header -W Word header "
ASC "(-L) Long word header]"8D00
JSR KILLEXE ; Kill all memory
PLA
CMP #$1
BLT :AA9
PHA
JSR PRWORD
PLA
:AA9 RTL ;Return error
APPENDSTRING STR '.H'
SWITCHTABLE ASC 'N'
DA HEADERENABLE,$FFFF
ASC 'W'
DA HEADERENABLE,$0001
ASC 'L'
DA HEADERENABLE,$0000
DB 0
*
* Do the Huffman/Repeat compaction
*
HUFFMAN SEP #$30
JSR COUNTBITS ;Count the number of repeat bytes
JSR SQUISHEM ;Compress the data
LDA BITCOUNT
CMP #7
BEQ :P
LDA #0
LDX #8
JSR PUTBITS
:P REP #$30
SEC
LDA PUTBYTE+1 ;Get the length of my data
SBC OUTPUTPOINTER
STA OUTPUTLENGTH
LDA PUTBYTE+3 ;Get the length of my data
AND #$00FF
SBC OUTPUTPOINTER+2
STA OUTPUTLENGTH+2
RTS
*
* Create a byte count table and the Hoffman tree
*
COUNTBITS
PHP
REP #$30
LDX #$3FE
]A STZ DATA,X ;Zero out the count
DEX
DEX
BPL ]A
LDA INPUTPOINTER ;Get the start address
STA SCREENAD
LDA INPUTPOINTER+2
STA SCREENAD+2
LDA INPUTLENGTH ;Get the length
STA SCREENAD2
LDA INPUTLENGTH+2
STA SCREENAD2+2
]A LDA SCREENAD2 ;Done counting?
ORA SCREENAD2+2
BEQ :MAKEHOFF
BIT SCREENAD2+2 ;High bit clear?
BMI :MAKEHOFF
LDA SCREENAD2 ;Dec count
BNE :CC
DEC SCREENAD2+2
:CC DEC SCREENAD2
SEP #$30
LDY #3
LDA [SCREENAD]
]B CMP [SCREENAD],Y
BNE :OK
DEY
BNE ]B
INY
]B CMP [SCREENAD],Y
BNE :ADDIT
INY
BNE ]B
LDA SCREENAD2+1 ;Sub $100 from length
BNE :CS
DEC SCREENAD2+2
:CS DEC SCREENAD2+1
BRA :X100 ;Add $100 to address
:ADDIT TYA
CLC
ADC SCREENAD
STA SCREENAD
BCC :XS
:X100 INC SCREENAD+1
BNE :XS
INC SCREENAD+2
:XS STY :SELF+1 ;Save length
REP #$30
SEC
LDA SCREENAD2
:SELF SBC #0
STA SCREENAD2
LDA SCREENAD2+2
SBC #0
STA SCREENAD2+2
BRA ]A
:OK REP #$30
AND #$FF ;Make word pointer
ASL
TAX
INC SCREENAD ;Next address
BNE :J
INC SCREENAD+2
:J INC DATA,X ;Count up
BNE ]A
INC DATA+$200,X
BRA ]A
:MAKEHOFF
LDY #0 ;I need 20 bytes for the tree
]A LDX #0
STZ SCREENAD2 ;Find the most used byte then work my
STZ SCREENAD2+2 ;way down
]B LDA DATA,X ;Already used?
AND DATA+$200,X
CMP #$FFFF
BEQ :SKIP ;Yep, skip
LDA DATA,X
CMP SCREENAD2 ;Bigger?
LDA DATA+$200,X
SBC SCREENAD2+2
BLT :SKIP ;Nope
STX :VALUE ;Save Byte responsible
LDA DATA,X ;Save new byte count
STA SCREENAD2
LDA DATA+$200,X
STA SCREENAD2+2
:SKIP INX
INX
CPX #$200
BLT ]B
LDA :VALUE ;Save this value into the Hoffman table
LSR
SEP #$20
STA HOFFTABLE,Y
REP #$20
LDX :VALUE
LDA #$FFFF ;Delete this byte from the count table
STA DATA,X
STA DATA+$200,X
INY
CPY #HOFFSIZE ;Table full?
BLT ]A
PLP
RTS
:VALUE DS 2
*
* Save packed data
*
SQUISHEM
PHP
SEP #$30
CLC
LDA INPUTPOINTER
STA SCREENAD
ADC INPUTLENGTH
STA ENDADR
LDA INPUTPOINTER+1
STA SCREENAD+1 ;Grab bytes here!
ADC INPUTLENGTH+1
STA ENDADR+1
LDA INPUTPOINTER+2
STA SCREENAD+2
ADC INPUTLENGTH+2
STA ENDADR+2
LDA OUTPUTPOINTER
STA PUTBYTE+1
LDA OUTPUTPOINTER+1
STA PUTBYTE+2 ;Save bytes here!
LDA OUTPUTPOINTER+2
STA PUTBYTE+3
STZ BITTEMP ;Init the Bit slice routine
LDA #7
STA BITCOUNT
LDA HEADERENABLE
BMI :NOHEADER
LDA INPUTLENGTH
LDX #8
JSR PUTBITS
LDA INPUTLENGTH+1
LDX #8
JSR PUTBITS
LDA HEADERENABLE
BNE :NOHEADER
LDA INPUTLENGTH+2
LDX #8
JSR PUTBITS
LDA INPUTLENGTH+3
LDX #8
JSR PUTBITS
:NOHEADER LDY #0
]A LDA HOFFTABLE,Y
LDX #8 ;Send the entire Hoffman table (8 Bits)
JSR PUTBITS
INY
CPY #HOFFSIZE
BLT ]A
]A
LDX #HOFFSIZE-1
LDA [SCREENAD]
]B CMP HOFFTABLE,X
BEQ :GOTIT
DEX
BPL ]B
BMI :MIN
:GOTIT LDA HOFFREPEAT,X
HEX 2C
:MIN LDA #3
STA LO
LDY #0
LDA [SCREENAD],Y ;Repeater?
]B INY
CMP [SCREENAD],Y
BNE :ASIS
CPY LO
BLT ]B
CLC
LDA SCREENAD ;Check if out of bounds
ADC LO
STA SCREENAD2
LDA SCREENAD+1
ADC #0
STA SCREENAD2+1
LDA SCREENAD+2
ADC #0
STA SCREENAD2+2
LDA SCREENAD2
CMP ENDADR
LDA SCREENAD2+1
SBC ENDADR+1
LDA SCREENAD2+2
SBC ENDADR+2
BGE :ASIS ;Too far
JSR REPEATER
BRA :CHK
:ASIS LDY #HOFFSIZE-1
LDA [SCREENAD] ;Check if byte can be Hoffman'd
]X CMP HOFFTABLE,Y
BEQ :TINY ;Yep
DEY
BPL ]X
LDA #%0 ;Save header bit
LDX #1 ;000 Means 8 bit value
JSR PUTBITS
LDA [SCREENAD]
LDX #8
JSR PUTBITS ;Save byte
JMP :NEXT
:TINY
LDX HOFFLENGTH,Y ;Save Hoffman Skew factor
LDA HOFFCODEH,Y
JSR PUTBITS
:NEXT INC SCREENAD ;Move to the next byte.
BNE :CHK
INC SCREENAD+1
BNE :CHK
INC SCREENAD+2
:CHK LDA SCREENAD ;Done Yet?
CMP ENDADR
LDA SCREENAD+1
SBC ENDADR+1
LDA SCREENAD+2
SBC ENDADR+2
BGE :PP
JMP ]A
:PP PLP
RTS ;End
REPEATER
LDA [SCREENAD]
STA :BYTE
LDY #1
]A CMP [SCREENAD],Y
BNE :GOTLEN
INY
BNE ]A
:GOTLEN TYA ;256 bytes?
BEQ :100
CLC
ADC SCREENAD
STA SCREENAD ;Move the pointer
BCC :N100
:100 INC SCREENAD+1
BNE :N100
INC SCREENAD+2
:N100 SEC
LDA SCREENAD
SBC ENDADR
STA SCREENAD2
LDA SCREENAD+1
SBC ENDADR+1
STA SCREENAD2+1
LDA SCREENAD+2
SBC ENDADR+2
STA SCREENAD2+2
BLT :FINE
; SEC
TYA
SBC SCREENAD2
TAY ;Use this length
:FINE
LDX #7
LDA #%1111111
JSR PUTBITS
TYA ;Save the count
LDX #8
JSR PUTBITS
LDA :BYTE
LDX #8
JMP PUTBITS
:BYTE DS 1
HOFFLENGTH
DFB 4,4
DFB 5,5,5,5,5,5,5
DFB 6,6,6,6,6,6,6,6
DFB 7,7,7
HOFFREPEAT DFB 6,6
DFB 5,5,5,5,5,5,5
DFB 4,4,4,4,4,4,4,4
DFB 4,4,4
HOFFCODEH
DFB %1000,%1001
DFB %10100,%10101,%10110,%10111,%11000,%11001,%11010
DFB %110110,%110111,%111000,%111001,%111010,%111011
DFB %111100,%111101
DFB %1111100,%1111101,%1111110
HOFFTABLE DS HOFFSIZE
*
* Save "X" amount of bits
*
PUTBITS
STX :COUNT
]A CPX #8
BEQ :OK
ASL
INX
BNE ]A
:OK ASL ;Shave a bit
ROL BITTEMP ;Save it
DEC BITCOUNT ;Bit bucket full?
BPL :SLICE ;Nope
PHA ;Save
LDA BITTEMP ;Empty the bit bucket
JSR PUTBYTE
STZ BITTEMP ;Reset pointers
LDA #7
STA BITCOUNT
PLA ;Restore
:SLICE DEC :COUNT ;Done yet?
BNE :OK
RTS
:COUNT DS 1
*
* Save a byte
*
PUTBYTE STAL $FFFFFF
INC PUTBYTE+1
BNE :A
INC PUTBYTE+2
BNE :A
INC PUTBYTE+3
:A RTS
HEADERENABLE DS 2
DATA DS $400
IFILENAME DS 64
OFILENAME DS 64
INPUTLENGTH DS 4
INPUTPOINTER DS 4
OUTPUTPOINTER DS 4
OUTPUTLENGTH DS 4
SAV HUFFMAN.L
Cleanup > To do
Games > Games by content > Games with uncompiled source code
Games > Games by content > Games with unused graphics
Games > Games by developer > Games developed by Casady & Greene
Games > Games by platform > Apple IIGS games
Games > Games by publisher > Games published by Casady & Greene
Games > Games by release date > Games released in 1989

