;IFF Converter ;------------- ;(C)1993 SIMON COOKE ;Copyright is reserved in this code by Simon Cooke, and ;copyright by Simon Cooke is also established in all code ;produced by modifying/altering this code. So nerr. ;Rudimentary, my dear Watson. ;Call 32768 to start... ;THIS VERSION HAS ITS OWN GFX TOOLKIT... startpage: EQU 1 iffloadpage: EQU 3 iffstart: EQU &0000 buffer.space: EQU &6000 mem_alloc: EQU &5100 sys.palette: EQU &55D8 sys.palette2: EQU &55D8+20 vmpr: EQU &FC hmpr: EQU &FB lmpr: EQU &FA ORG &8000 DUMP startpage,0 CALL initialise CALL reserve.pages CALL convert.file CALL toolbox CALL shut.down RET ;*************************************************************** ;Reserve pages for use by TOOLBOX ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ reserve.pages: LD B,&00 CALL find.pages JR Z,found.hi.2 LD HL,error.message8 JP report.error found.hi.2: LD A,&FE CALL set.pages found.hi: LD A,C LD (high.screen),A ;Find lower screen area LD B,&00 CALL find.pages JR Z,found.lo LD HL,error.message8 JP report.error found.lo: LD A,&FE CALL set.pages LD A,C LD (low.screen),A RET ;Set pages for use by TOOLBOX ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~ set.pages: LD E,C LD D,0 LD HL,mem_alloc ADD HL,DE LD (HL),A INC HL LD (HL),A RET ;Deallocate reserved pages... ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~ deallocate: LD A,(high.screen) CP &FF JR Z,not.unloc.hi ;high.screen pages unalloct'd LD E,A LD D,0 LD HL,mem_alloc ADD HL,DE LD (HL),&00 INC HL LD (HL),&00 not.unloc.hi: LD A,(low.screen) CP &FF RET Z ;low.screen pages unallocated LD E,A LD D,0 LD HL,mem_alloc ADD HL,DE LD (HL),&00 INC HL LD (HL),&00 RET ;Find pages for TOOLBOX use ;~~~~~~~~~~~~~~~~~~~~~~~~~~ ;Entered: B=requested PAGE type... ;Exits: Z if found, C=page ;NZ i find.pages: LD HL,mem_alloc+&1E ;looking for EVEN pages... LD C,&1E ;current page pager.loop: LD E,(HL) INC HL LD D,(HL) DEC HL LD A,E CP B JR NZ,not.correct XOR D RET Z ;return with Z condition... DEC C DEC C DEC HL DEC HL LD A,C CP &FF JR NZ,pager.loop OR A ;A=&FF ; RET ;TOOLBOX source code for IFF Files ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;(C) 1993 SiMoN CoOkE ;Lets you do the following: ;Set an EVEN window size for the screen to appear in ;(MAX X=1024, MAX Y=800) ;Set up interlaced screens ;Reduce screens to greyscale images ;Squish screens... ;Expand/shrink screens to fit WINDOW ;Scroll around the screen ;Save off WINDOW portions --OR-- full IFF files... video.hi.page: EQU 30+96 video.lo.page: EQU 26+96 toolbox: DI IN A,(lmpr) LD (lmpr.store),A IN A,(vmpr) LD (vmpr.store),A LD (sp.store),SP LD A,video.hi.page OUT (vmpr),A AND %00111111 OUT (lmpr),A LD SP,&C000 LD HL,error.message0 LD (error.message),HL LD HL,&0000 LD DE,&0001 LD (HL),L LD BC,24575 LDIR IN A,(lmpr) PUSH AF LD A,video.lo.page AND 63 OUT (lmpr),A LD HL,&0000 LD DE,&0001 LD (HL),L LD BC,24575 LDIR POP AF LD HL,screen.space ;1 line data space... LD DE,screen.space+1 LD BC,1023 LD (HL),&00 LDIR ;CHRIS WHITE'S ASCII KEY READ ROUTINE ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEFM "ASCII KEY READ ROUTINE : " DEFM "COPYRIGHT 1991 C.J.WHITE esq" ascii.key: fromthetop: LD C,&7F LD B,9 LD D,0 loop: LD A,C IN A,(&FE) AND &1F LD E,A LD A,C IN A,(&F9) AND &E0 OR E CP &FF JP NZ,keypressed INC D LD A,C SCF RRA LD C,A DJNZ loop XOR A ;cookie modification 1993 LD (last.key),A RET keypressed: LD B,0 keypressed2: BIT 0,A JP Z,foundkey RRA INC B JP keypressed2 foundkey: LD A,D ADD A ADD A ADD A ADD B LD L,A LD H,0 LD DE,asictable ADD HL,DE LD A,(HL) LD (last.key),A RET asictable: DEFB " ",13,"M","N","B",",",".",3 DEFB "?","L","K","J","H",";",":",2 DEFB "P","O","I","U","Y","=",34,137 DEFB "0","9","8","7","6","-","+",127 DEFB "1","2","3","4","5",27,12,1 DEFB "Q","W","E","R","T",134,135,136 DEFB "A","S","D","F","G",131,132,133 DEFB 4,"Z","X","C","V",128,129,130 DEFB 138,11,10,8,9,"*","*","*" tab.key: EQU 12 esc.key: EQU 27 caps.key: EQU 1 f0.key: EQU 137 f1.key: EQU 128 f2.key: EQU 129 f3.key: EQU 130 f4.key: EQU 131 f5.key: EQU 132 f6.key: EQU 133 f7.key: EQU 134 f8.key: EQU 135 f9.key: EQU 136 left.key: EQU 8 right.key: EQU 9 down.key: EQU 10 up.key: EQU 11 cntrl.key: EQU 138 del.key: EQU 127 inv.key: EQU 3 edit.key: EQU 2 shift.key: EQU 4 enter.key: EQU 13 ;Toolbox TEXT ;~~~~~~~~~~~~ ;0 1 2 3 ;01234567890123456789012345678901 ;-------------------------------- menu1: DEFM " IFF File Viewer/Editor  1993 Si" DEFM "on Cooke... 24/06/93 00:17 " DEFM " " DEFM "pReSs aNy kEy tO CoNtInUe!" DEFM " " DEFB 255 ;*************************************************************** ;THIS IS THE MAIN IFF FILE CONVERSION ROUTINE ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;(C) SIMON COOKE 24-06-93 11:34 v1.0b convert.file: DI IN A,(lmpr) ;store low page LD (lmpr.store),A IN A,(vmpr) LD (vmpr.store),A LD (sp.store),SP ;store stack LD SP,&C000 ;set stack to 49152 ;MAIN CONVERTER CODE ;~~~~~~~~~~~~~~~~~~~ main.start: CALL store.basic CALL start.iff CALL find.headers CALL check.missing CALL convert ;Check if CAMG segment popped up - if it did, it might not work? LD A,(camg.addr) CP &FF RET Z LD HL,error.message5 LD (error.message),HL CALL restore.basic RET ;START.IFF ROUTINE - FINDS LENGTH ETC. ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ start.iff: LD HL,form.text CALL check.head ;If returns Carry, is not FORM... JP NC,form.header ;Set error message, and exit to basic bad.form: LD HL,error.message1 ;NOT FORM MESSAGE LD (error.message),HL JP ret.to.basic ;Extract FORM length, and give FORM start address... form.header: CALL get.long CALL make.page.offs LD (form.len),A LD (form.len+1),HL EX DE,HL LD C,A LD HL,(general.pos) ADD HL,DE LD A,(general.page) ADD A,C BIT 6,H JR Z,no.carry.over INC A RES 6,H no.carry.over: LD (form2.addr),A LD (form2.addr+1),HL LD HL,ilbm.text CALL check.head JP C,not.ilbm LD HL,(general.pos) LD (form.addr+1),HL LD A,(general.page) LD (form.addr),A RET not.ilbm: LD HL,error.message2 ;NOT ILBM TYPE LD (error.message),HL JP ret.to.basic ;CHECK.MISSING: IF THERE'S ANY MISSING CHUNKS, DO AN ERROR ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ check.missing: LD HL,bmhd.text LD DE,4 LD A,(bmhd.addr) CP &FF JR Z,output.error ADD HL,DE ;move to BODY.TEXT LD A,(body.addr) CP &FF JR Z,output.error ADD HL,DE LD A,(cmap.addr) CP &FF RET NZ output.error: LD DE,error.space ;copy text to "MISSING xxxx " LD BC,4 ;"CHUNK" message LDIR LD HL,error.message3 LD (error.message),HL JP ret.to.basic ;FINDS THE DATA ADDRESSES AND LENGTHS OF THE ILBM CHUNKS ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ find.headers: LD HL,(form.addr+1) LD (general.pos),HL LD A,(form.addr) LD (general.page),A ;This section assumes that the header texts are stored as: ; "BMHDBODYCMAPCAMG" headers.loop: LD A,(form2.addr) LD C,A LD A,(general.page) CP C JR C,okay.headr LD HL,(form2.addr+1) LD DE,(general.pos) SBC HL,DE RET C okay.headr: LD HL,bmhd.text CALL check.head.n ;checks w/out moving pointer JP NC,bmhd.header CALL check.head.n JP NC,body.header CALL check.head.n JP NC,cmap.header CALL check.head.n JP NC,camg.header ;If reaches here, the header is not a recognised one... CALL skip.4 CALL get.long ;get length of "unknown head" CALL make.page.offs skipper: CALL skip.offset JP headers.loop ;Skip 4 bytes of data ;~~~~~~~~~~~~~~~~~~~~ skip.4: PUSH HL PUSH AF XOR A LD HL,4 CALL skip.offset POP AF POP HL RET ;Create start address and length for BMHD Data area ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bmhd.header: CALL skip.4 CALL get.long CALL make.page.offs LD (bmhd.len),A LD (bmhd.len+1),HL PUSH HL PUSH AF LD HL,(general.pos) LD A,(general.page) LD (bmhd.addr),A LD (bmhd.addr+1),HL POP AF POP HL JP skipper ;Create start address and length for BODY Data area ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ body.header: CALL skip.4 CALL get.long CALL make.page.offs LD (body.len),A LD (body.len+1),HL PUSH HL PUSH AF LD HL,(general.pos) LD A,(general.page) LD (body.addr),A LD (body.addr+1),HL POP AF POP HL JP skipper ;Create start address and length for camg Data area ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ camg.header: CALL skip.4 CALL get.long CALL make.page.offs LD (camg.len),A LD (camg.len+1),HL PUSH HL PUSH AF LD HL,(general.pos) LD A,(general.page) LD (camg.addr),A LD (camg.addr+1),HL POP AF POP HL JP skipper ;Create start address and length for cmap Data area ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cmap.header: CALL skip.4 CALL get.long CALL make.page.offs LD (cmap.len),A LD (cmap.len+1),HL PUSH HL PUSH AF LD HL,(general.pos) LD A,(general.page) LD (cmap.addr),A LD (cmap.addr+1),HL POP AF POP HL JP skipper ;SKIP.OFFSET: SKIPS A CERTAIN *EVEN* NUMBER OF BYTES... ;HL = no' bytes MOD 16384, A= no'bytes DIV 16384 skip.offset: PUSH BC PUSH DE BIT 0,H JR Z,not.padded INC HL not.padded: LD C,A LD A,(general.page) ADD A,C AND 31 LD C,A LD DE,(general.pos) ADD HL,DE BIT 6,H JR Z,not.increment INC C RES 6,H not.increment: LD A,C LD (general.page),A LD (general.pos),HL POP DE POP BC RET ;MAKE.PAGE.OFFS: Converts 32-bit number to pages, + offset MOD ; 16384 ;Ignores the "D" part - cannot have more than 256 pages... make.page.offs: PUSH HL RL H RL E RL H RL E LD A,E POP HL PUSH AF LD A,H AND %00111111 LD H,A POP AF RET ;Initialises the system ready to convert IFFs... ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ initialise: LD A,&FE ;Set output stream to screen CALL &112 ; LD A,&FF ;if these are &FF, they LD (low.screen),A ;have not been allocated in LD (high.screen),A;the page table... LD HL,init.message CALL send.message LD HL,(iff.offset) LD (general.pos),HL LD A,(iff.page) LD (general.page),A ;Set address space to &FFFFFF so that it can be checked for ;missing segments... LD HL,addresses LD DE,addresses+1 LD BC,address.length-1 LD (HL),&FF LDIR ;Set error message to NO ERROR LD HL,error.message0 LD (error.message),HL LD A,(stash.page) OR 32 LD (stash.low),A RET ;CHECKS FOR A SPECIFIC 4 BYTE HEADER... ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;RETURNS: NC if found, C if not found ; CORRUPTS A check.head: PUSH BC LD B,4 check.h.loop: CALL get.byte CP (HL) JR NZ,not.header INC HL DJNZ check.h.loop POP BC AND A RET not.header: CALL get.byte DJNZ not.header POP BC SCF RET ;CHECKS FOR A SPECIFIC 4 BYTE HEADER... ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;(DOES NOT ADVANCE POINTERS...) ;RETURNS: NC if found, C if not found ; CORRUPTS A check.head.n: PUSH BC LD BC,(general.pos) ;store pointer LD (temp.pos),BC LD A,(general.page) LD (temp.page),A LD B,4 check.h2.loop: CALL get.byte CP (HL) JR NZ,not.header.2 INC HL DJNZ check.h2.loop LD BC,(temp.pos) ;restore pointer LD (general.pos),BC LD A,(temp.page) LD (general.page),A POP BC AND A RET not.header.2: INC HL DJNZ not.header.2 LD BC,(temp.pos) ;restore pointer LD (general.pos),BC LD A,(temp.page) LD (general.page),A POP BC SCF RET ;GETS A BYTE FROM THE GENERAL.POS ADDRESS STORE ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ get.byte: PUSH HL EX AF,AF' PUSH AF IN A,(lmpr) EX AF,AF' LD A,(general.page) OR 32 OUT (lmpr),A LD HL,(general.pos) LD A,(HL) INC HL LD (general.pos),HL BIT 6,H JR Z,no.worries RES 6,H LD (general.pos),HL LD HL,general.page INC (HL) no.worries: EX AF,AF' OUT (lmpr),A LD A,(general.page) AND 31 LD (general.page),A POP AF EX AF,AF' POP HL RET ;GETS A WORD FROM THE GENERAL.POS ADDRESS STORE ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;returns it in DE get.word: PUSH HL PUSH AF IN A,(lmpr) PUSH AF LD A,(general.page) OR 32 OUT (lmpr),A LD HL,(general.pos) LD D,(HL) INC HL LD E,(HL) INC HL LD (general.pos),HL BIT 6,H JR Z,no.worries3 RES 6,H LD (general.pos),HL LD HL,general.page INC (HL) no.worries3: POP AF OUT (lmpr),A LD A,(general.page) AND 31 LD (general.page),A POP AF POP HL RET ;GETS A LONG FROM THE GENERAL.POS ADDRESS STORE ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;returns it in DE (HIGH), HL (LOW) get.long: PUSH AF IN A,(lmpr) PUSH AF LD A,(general.page) OR 32 OUT (lmpr),A LD HL,(general.pos) LD D,(HL) INC HL LD E,(HL) INC HL PUSH DE LD D,(HL) INC HL LD E,(HL) INC HL LD (general.pos),HL BIT 6,H JR Z,no.worries2 RES 6,H LD (general.pos),HL LD HL,general.page INC (HL) no.worries2: EX DE,HL POP DE POP AF OUT (lmpr),A LD A,(general.page) AND 31 LD (general.page),A POP AF RET ;Restores BASIC back to normal ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ret.to.basic: LD BC,&00F8 DEFB &ED,&71 LD A,(lmpr.store) OUT (lmpr),A LD A,(vmpr.store) OUT (vmpr),A LD SP,(sp.store) EI report.error: AND A LD HL,(error.message) LD DE,error.message0 SBC HL,DE LD A,H OR L JR Z,okay.then CALL shut.down ;only if an error occurs will ;this need to be called by ;ret.to.basic LD HL,(error.message) CALL send.message RET okay.then: LD HL,palette.buffer LD DE,sys.palette LD BC,16 LDIR LD HL,palette.buffer LD DE,sys.palette2 LD BC,16 LDIR RET ;Prints message to screen ;~~~~~~~~~~~~~~~~~~~~~~~~ send.message: LD A,(HL) CP 255 RET Z PUSH HL RST &10 POP HL INC HL JR send.message ;CONVERT: This does the actual conversion ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ convert: CALL get.bmhd.data CALL get.camg.data CALL convert.cmap LD A,(bit.planes) CP 5 JR C,not.many.col LD HL,error.message4 ;too many bitplanes... ;THIS ONE CAN'T HANDLE ;>4 bit planes... LD (error.message),HL JP ret.to.basic not.many.col: LD HL,(width) LD DE,15 ;no' words per line ADD HL,DE ;(rounding up) SRL H RR L SRL H RR L SRL H RR L RES 0,L LD (plane.width),HL SRL H RR L AND A EX DE,HL LD HL,64 SBC HL,DE JR NC,not.too.wide ;can't have a row greater than 128 bytes wide - ;that'd mean a screen >1024 pixels across, and ;you can go away if you think that I'm going to ;buffer that size of a screen... LD HL,error.message6 LD (error.message),HL JP ret.to.basic not.too.wide: LD HL,(body.addr+1) LD A,(body.addr) LD (general.pos),HL LD (general.page),A LD BC,(height) ;THIS BIT DECOMPRESSES (?) THE DATA LD A,(stash.low) OUT (lmpr),A XOR A LD (decomp.flag),A LD HL,(stash.offset) LD (current.line),HL length.loop: PUSH BC LD A,(bit.planes) LD B,A XOR A LD (current.plane),A ;set up for DECODE.PLANE plane.loop: PUSH BC LD HL,plane.buffer LD BC,(plane.width) width.loop: PUSH BC PUSH HL CALL decomp.byte POP HL LD (HL),A INC HL POP BC DEC BC LD A,B OR C JR NZ,width.loop CALL decode.plane POP BC LD HL,current.plane INC (HL) DJNZ plane.loop POP BC PUSH DE LD HL,(current.line) PUSH HL LD HL,(width) INC HL SRL H RR L EX DE,HL POP HL ADD HL,DE BIT 6,H JR Z,okay.dokey IN A,(lmpr) INC A OUT (lmpr),A RES 6,H okay.dokey: LD (current.line),HL POP DE LD A,(decomp.flag) OR A JR Z,fine LD HL,error.message7 LD (error.message),HL JP ret.to.basic fine: LD HL,(general.pos) LD (last.completed),HL LD A,(general.page) LD (last.page),A DEC BC LD A,B OR C JR NZ,length.loop RET ;DECODES BIT PLANE INTO SAM "CHUNKY" PEL FORMAT... ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ decode.plane: LD HL,(width) LD DE,3 ADD HL,DE SRL H RR L SRL H RR L PUSH HL POP BC ;4 pixels per plane.byte LD HL,(current.line) LD DE,plane.buffer pixel.loop: PUSH BC PUSH DE LD A,(DE) LD B,4 rotate.loop: LD DE,plane.expand ;bitplane expansion table RLCA RLCA PUSH AF AND %00000011 PUSH HL LD L,A LD H,0 ADD HL,DE EX DE,HL POP HL LD A,(DE) PUSH DE LD D,A LD A,(current.plane) OR A JR NZ,curr.rot.loop LD (HL),&00 ;blank destination byte... curr.rot.loop: OR A JR Z,ready.rot RLC D DEC A JR curr.rot.loop ready.rot: LD A,D POP DE OR (HL) LD (HL),A INC HL POP AF DJNZ rotate.loop POP DE POP BC INC DE DEC BC LD A,B OR C JR NZ,pixel.loop LD A,R ;show that it's active LD BC,&00F8 AND %01111000 OUT (C),A IN A,(lmpr) AND 30 ;and put the data onscreen, OR 96 ;too... OUT (vmpr),A RET ;DECOMP.BYTE ;~~~~~~~~~~~ ;Decompresses a bit plane... decomp.byte: LD A,(compression) CP 1 JR Z,rle.decode CALL get.byte RET rle.decode: ;if flag=1, then run of bytes ;if flag=2, then run of uncompressed ;if flag=0, then next run... LD A,(decomp.flag) OR A JR NZ,not.initial ;Sets up the decomp.flag, and counter data ;''''''''''''''''''''''''''''''''''''''''' initial.decomp: CALL get.byte CP 128 ;NOP... IGNORE & GET ANOTHER JR Z,initial.decomp JR C,uncomp.data NEG LD (decomp.count),A OR A JR Z,no.flag.2 LD A,1 LD (decomp.flag),A no.flag.2: CALL get.byte ;get replicant, and return ;with it... LD (decomp.data),A RET uncomp.data: LD (decomp.count),A OR A JR Z,no.flag.set LD A,2 LD (decomp.flag),A no.flag.set: CALL get.byte RET not.initial: CP 1 JR Z,run.of.bytes LD A,(decomp.count) DEC A LD (decomp.count),A OR A JR NZ,not.end.runm LD (decomp.flag),A not.end.runm: CALL get.byte RET run.of.bytes: LD A,(decomp.count) DEC A LD (decomp.count),A OR A JR NZ,not.end.run LD (decomp.flag),A not.end.run: LD A,(decomp.data) RET ;GET BMHD DATA ;~~~~~~~~~~~~~ get.bmhd.data: LD HL,(bmhd.addr+1) LD A,(bmhd.addr) LD (general.pos),HL LD (general.page),A CALL get.word LD (width),DE CALL get.word LD (height),DE CALL skip.4 CALL get.byte LD (bit.planes),A CALL get.byte CALL get.byte LD (compression),A RET ;GET CAMG DATA ;~~~~~~~~~~~~~ get.camg.data: LD HL,(camg.addr+1) LD A,(camg.addr) LD (general.pos),HL LD (general.page),A LD HL,camg.data LD B,4 copy.data: CALL get.byte LD (HL),A INC HL DJNZ copy.data RET ;GET & CONVERT CMAP DATA convert.cmap: LD HL,(cmap.addr+1) LD A,(cmap.addr) LD (general.pos),HL LD (general.page),A LD A,(bit.planes) LD B,A LD A,1 multiply.loop: PUSH AF LD A,B OR A JR Z,finished.mu POP AF ADD A,A DEC B JR multiply.loop finished.mu: POP AF LD B,A LD DE,palette.buffer conv.c.loop: PUSH BC PUSH DE CALL get.byte LD D,A CALL get.byte LD E,A CALL get.byte LD B,A CALL decode.rgb POP DE LD (DE),A INC DE POP BC DJNZ conv.c.loop RET ;DECODE RGB VALUES TO SAM PALETTE VALUES ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;Entered with D=R, E=G, B=B ;Exits with a value in A decode.rgb: LD C,%11100000 ;strip unusable bits... LD A,D AND C LD D,A LD A,E AND C LD E,A LD A,B AND C LD B,A LD C,&00 ;counter for BRIGHT BIT 5,B JR Z,no.blue INC C no.blue: BIT 5,D JR Z,no.red INC C no.red: BIT 5,E JR Z,no.green INC C no.green: LD A,C LD C,&00 CP 2 JR C,not.bright LD C,&08 ;if >=2 have bright, then ;bright it is... not.bright: LD A,D CALL expand.bits RLCA OR C LD C,A ;that's RED done LD A,E CALL expand.bits RLCA RLCA OR C LD C,A ;an' that's GREEN LD A,B CALL expand.bits OR C ;an' there goes BLUE RET ;FINISHED!!! ;EXPAND.BITS - converts colour as 3 bit in bits 7,6 to ; bit:xxx7xxx6 FORMAT expand.bits: RLCA RLCA PUSH BC LD C,A AND %00000001 LD B,A LD A,C AND %00000010 RLCA RLCA RLCA OR B POP BC RET ;TEXT MESSAGES/DATA ;~~~~~~~~~~~~~~~~~~ init.message: DEFB 22,0,0 ;move cursor to 0,0 DEFB 255 error.message0:DEFM "No errors occured" DEFB 255 error.message1:DEFM "This is not an IFF file" DEFB 255 error.message2:DEFM "This is not an ILBM file" DEFB 255 error.message3:DEFM "Cannot find " error.space: DEFM "XXXX" DEFM " segment" DEFB 255 error.message4:DEFM "Too many bit-planes for current " DEFM "version..." DEFB 255 error.message5:DEFM "CAMG segment in IFF file - this version " DEFM "may not have converted" DEFB 13 DEFM "it correctly. See documentation." DEFB 255 error.message6:DEFM "Picture is too wide..." DEFB &FF error.message7:DEFM "Bad DECOMPRESSION flag/data" DEFB &FF error.message8:DEFM "Not enough free pages..." DEFB &FF form.text: DEFM "FORM" ilbm.text: DEFM "ILBM" bmhd.text: DEFM "BMHD" body.text: DEFM "BODY" cmap.text: DEFM "CMAP" camg.text: DEFM "CAMG" mode3.fnt: MDAT "font.dat" ;THIS IS END OF SAVED CODE... length.of.code:EQU $-32768 ;Data storage area ;~~~~~~~~~~~~~~~~~ stash.page: DEFB &08 ;where to put the uncompressd stash.offset: DEFW &0000 ;screen... iff.page: DEFB iffloadpage ;where your IFF file sits... iff.offset: DEFW iffstart general.page: DEFB &00 general.pos: DEFW &00 temp.page: DEFB &00 temp.pos: DEFW &00 lmpr.store: DEFB &00 vmpr.store: DEFB &00 sp.store: DEFW &0000 error.message: DEFW &0000 addresses: EQU $ form.addr: DEFS 3 ;page: offset form2.addr: DEFS 3 bmhd.addr: DEFS 3 body.addr: DEFS 3 cmap.addr: DEFS 3 camg.addr: DEFS 3 form.len: DEFS 3 ;4 byte LONG bmhd.len: DEFS 3 body.len: DEFS 3 cmap.len: DEFS 3 camg.len: DEFS 3 address.length:EQU $-addresses ;DATA FOR PICTURE ;~~~~~~~~~~~~~~~~ width: DEFW &0000 height: DEFW &0000 bit.planes: DEFB &00 plane.width: DEFW &0000 compression: DEFB &00 palette.buffer:DEFS 16 plane.buffer: DEFS 128 current.plane: DEFB &00 ;MISCELLANEOUS: ;~~~~~~~~~~~~~~ stash.low: DEFB &00 current.line: DEFW &0000 camg.data: DEFS 4 decomp.flag: DEFB &00 decomp.count: DEFB &00 decomp.data: DEFB &00 ;DEBUGGING: ;~~~~~~~~~~ last.page: DEFB &00 last.completed:DEFW &0000 plane.expand: DEFB %00000000 DEFB %00000001 DEFB %00010000 DEFB %00010001 ;Toolbox ;~~~~~~~ screen.space: EQU &9C00 horiz: DEFB &00 menu: DEFB &00 last.key: DEFB &00 high.screen: DEFB &00 low.screen: DEFB &00 ;IFF load-in area ;~~~~~~~~~~~~~~~~ ORG iffstart DUMP iffloadpage,iffstart\16384 iff.address: ; MDAT "q.LBM"