	;;
	;; Sample image viewer, shows how to interface to jpeg decoder
	;; and displays image in a few different modes, also has output
	;; of data to file option
	;;
	;; Raphael Espino
	;; last updated 22-Dec-00
	;; 

	
;; ---------- renderer zero page addresses, 192 and up are available
	
rendpt = 192			; pointer to image data - 2 bytes
filtpt = 194			; filter pointer - 2 bytes
drawtemp = 196			; 2 temporary storage bytes
devpt = 198			; 2 byte pointer to device name
	
;; ---------- end of renderer zero page addresses

;; ------------- decoder information addresses ------------------
	
DISPCOLS = $600 	    ; (# of columns to display)/8 must be <= 40
DISPROWS = $601 	    ; (# of rows to display)/8
coloff   = $602             ; Coloumn offset to display image from
rowoff   = $603             ; Row offset to display image from
numcols  = $604		    ; image width, 1 column = 8 pixels (pixels/8)
numrows  = $605	  	    ; image height 1 row = 8 pixels (pixels/8)

IOCBNUM  = $606		    ; IOCB to read jpeg data from
STACKPT  = $607		    ; stack pointer at program start, use to return
			    ; to DOS at any point
ERROR    = $608		    ; non 0 if error ocurred decoding jpeg
			    ; error codes are as defined in decoder
RERUN    = $609		    ; 2 bytes - restart address, use to rerun decoder
VERSION  = $60B	   	    ; decoder version number
	
	;; page 6 addresses from $630 up are available to renderer
	
;; ------------- end of decoder info addresses ----------------------

LODCHN = 2		; IOCB to use for loading file
SAVECHN = 3		; IOCB to use for saving to file

ABORTCD = 128		; code to tell decoder to abort

ROWCRS = 84
COLCRS = 85
SAVMSC = 88
VKEYBD = 520			; keyboard IRQ vector
SDLSTL = 560
GPRIOR = 623			; priority register, enable GR.9
SDMCTL = 559			; shadow DMA control address
COLOR0 = 708			; colour shadow addresses
COLOR1 = 709
COLOR2 = 710
COLOR3 = 711
COLOR4 = 712

CH     = 764			; last keypress shadow address
	
	;; IOCB addresses
ICCOM  = 834
ICSTA  = 835
ICBAL  = 836
ICBAH  = 837
ICBLL  = 840
ICBLH  = 841
ICAX1  = 842
ICAX2  = 843

	
MAXLEN = 64                 ; max file name length		
RDBUF  = $630		    ; use page 6 for file name buffer


KBCODE = 53769		    ; hardware keyboard code address
PORTB  = 54017		    ; OS RAM control on XL/XE
DMACTL = 54272		    ; DMA control
NMIEN  = 54286		    ; NMI enable
CIOV   = 58454		    ; CIO vector
SETVBV = 58460		    ; Set VBI vector
EXITIM = 58463		    ; Exit Immediate VBI vector


	;; ICCOM values
OPEN   = 3   ; open channel
GETLNE = 5   ; get line
GETBUF = 7
PUTLNE = 9
PUTBUF = 11  ;  put buffer
CLOSE  = 12  ; close channel

	;; IOCB open modes
READ   = 4   ; open for read
READDIR= 6   ; open for directory read
WRITE  = 8   ; open for write


		;; set up viewer jmp vectors
	.ADDR segvector
	.ADDR segvectorend-1
	
 	.ORG $0620
	
segvector:
	
	;; next 12 bytes should be JMP's to renderer's init, start, draw
	;; and end code
	
	JMP RafRendInit		; init renderer
	JMP RafRendStart	; image data about to arrive
	JMP RafRendDraw		; 8 lines of image data available
	JMP RafRendEnd		; image completed
	JMP UnusedVec		; unused for now, point at an RTS
	
segvectorend:	

		;; header for viewer
	.ADDR segcode
	.ADDR segcodeend-1

		;; renderer has area from $8C00 upwards for itself and screen
	
	 	.ORG $8C00
	;;
	;; init code, this will be called when decoder starts or
	;; when it is re-run.  Renderer should display start up information,
	;; open an IOCB for the decoder to read the jpeg data from
	;; and store the (IOCB number * 16) in IOCBNUM ($606)
	;; The rowoff and coloff values can optionally be set here
	;; or in RendDraw.  If they are not set they will default to 0
	;; DISPCOLS and DISPROWS can also optionally be set here or in
	;; RendDraw.  If not set they default to DISPCOLS = 40 (320 pixels) 
	;; DISPROWS = 24 (192 pixels)
	;; *** DISPCOLS should NEVER be set to > 40 ***
	;;
	
segcode:
	
RafRendInit:

	 ;;  display rendered information
	 jsr strout
	 .BYTE "RafRender v0.4 (22Dec00)",155,155,0
	 lda repeat		; don't ask for filename if we are redisplaying
	 beq @newfn
	 jsr RestFN		; restore the previous one instead
	 jsr strout
	 .BYTE "Redisplaying ",0
	 jsr DispFN		; display filename too
	 lda #0
	 sta repeat
	 sta wild
	 beq @openfl		; forced branch
	
@newfn:
	 jsr strout
	 .BYTE "Use wildcards (D:*) for directory",155
         .BYTE "file name:D:",0
	
	 JSR RDLINE		;  get filename from user
	 lda RDBUF+2		; return to environment if no
	 cmp #155		; filename entered
	 bne @cont
	 LDX STACKPT
	 TXS
@rts:
	 RTS
	
@cont:	
	
	 ;;  make sure IOCB is available
	 JSR CloseInFile
         ; BMI @error

	 ;;  now open the file
  	 STX IOCBNUM		; tell decoder what IOCB to use
	 JSR CheckExt		; check if extension needs to be added to name

	 JSR CheckWild		; check if there is a wild card in the name
	 lda wild
	 bne @dirop
@openfl:
	 LDA #READ
 	 .BYTE $2C		; ignore next 2 bytes
@dirop:	
	 LDA #READDIR

	 LDX #(LODCHN*16)
	 
	 JSR OpenFile
	 BMI @error

	 lda wild
	 beq @savefn		; don't do a directory listing
	 jsr DispDir
	 jsr CloseInFile
	 jmp WaitandRun
	
@savefn:
	 jmp SaveFN		; save file name and return to decoder


	;; an error occured, display error code and restart
@error:
	 LDX #(LODCHN*16)
  	 LDA ICSTA,X		; read status value
	 pha			; remember error code
	 jsr CloseInFile	; close file
         jsr strout
         .BYTE "load error ",0
	 pla
         jsr DecOut		; display error code
				; display file name too
	 jsr strout
	 .BYTE " ",0
	
         jsr DispFN		; display file name
	 jmp WaitandRun


	;;
	;; renderer start code, will be called immediately before
	;; the image data is about to start arriving.  Renderer
	;; should open graphics mode, open output file, etc. here.
	;; This is the first point that numcols and numrows information
	;; is valid.  Renderer can optionally setup DISPCOLS, DISPROWS,
	;; coloff, rowoff information here.
	;; *** DISPCOLS should NEVER be set to > 40 ***
	;;
	
RafRendStart:
	lda #25
	sta DISPROWS

	jsr strout		; display image size
	.BYTE 155,"Image: cols wide=",0
	lda numcols
	jsr DecOut

	jsr strout
	.BYTE " rows high=",0
	lda numrows
	jsr DecOut
	
	;; get column and row offsets from user
	jsr strout
	.BYTE 155,"offset col:0",30, 0
        jsr getnum		; get number from user
        sta coloff
        jsr strout
        .BYTE "offset row:0",30,0
        jsr getnum		; get number from user
        sta rowoff

askagain:
	;; display menu
	jsr strout
	.BYTE 155,"S KEY TOGGLES SCREEN WHILE DECODING",155
        .BYTE 155,"1) 40x25x2 (GR.8)",155
	.BYTE "2) 20x25x4 (GR.15)",155
	.BYTE "3) 40x25x4 (GR.15) 1/1",155
	.BYTE "4) 10x25x16 (GR.9)",155
	.BYTE "5) 20x25x16 (GR.9) 2/1", 155
	.BYTE "6) 20x12x16 (GR.9) 1/1", 155
	.BYTE 0

	lda #9			; 10 options available on 48K machines
	sta optlen

	jsr CKOSRAM		; is there any RAM under the OS?
	lda OSRAM
	bne @doram		; if so then display 64K options too
	jmp @noram
@doram:
	jsr strout
	.BYTE "7) 40x25x2x2 (GR.8) Needs 64K", 155
	.BYTE "8) 20x25x4x2 (GR.15) Needs 64K", 155
	.BYTE "9) 40x25x4x2 (GR.15) 1/1, 64K", 155
	.BYTE "A) 10x25x16x2 (GR.9) Needs 64K", 155
	.BYTE "B) 20x25x16x2 (GR.9) 2/1, 64K", 155
	.BYTE "C) 20x12x16x2 (GR.9) 1/1, 64K", 155
	.BYTE 0
	lda #15			; 16 options available on 64K machines
	sta optlen
@noram:
	
	jsr strout
	.BYTE "M) Save Micropainter format",155
	.BYTE "N) Save Micropainter format 1/1",155
	.BYTE "R) Rerun",155
	.BYTE "S) Save 40x25x256 to disk",155
	.BYTE "Choice?"
	.BYTE 0
	lda #0
	sta USE2SCR
	sta USEFILT
	jsr getmenu		; get user selection
	sta RENDMODE		; remember user selection

	jsr getaddr
	bcs @optfnd
	jmp askagain

@optfnd:
	cpy #20		; options >= 7-9 and A-C 2 screens
 	rol USE2SCR

	lda @optadr,y
	pha
	dey
	lda @optadr,y
	pha
	rts
	

@optadr: .WORD @gr8-1, @gr15-1, @gr15a-1, @gr9-1, @gr9a-1, @gr9a-1
	.WORD @savetofile-1, @savetofile-1, @runagain-1, @savetofile-1
	.WORD @gr8-1, @gr15-1, @gr15a-1, @gr9-1, @gr9a-1, @gr9a-1

		
@runagain:
	jsr CloseInFile		; close opened file
	jmp (RERUN)		; and rerun
	
@gr9:
	lda #10			; 80/8 = 10 columns
	sta DISPCOLS
	bne @skipfl9

@gr9a:
	inc USEFILT
@skipfl9:
	lda #15			; Graphics 9
	jsr OpenGr

	lda #<SCR2TMP		; save 2nd screen of gr.9 data temp area
	sta gr9scr22+1
	lda #>SCR2TMP
	sta gr9scr22+2

	ldx SAVMSC		; set up gr.9 screen address
	stx gr9scr+1
	stx gr9scr2+1
	ldy SAVMSC+1
	sty gr9scr+2
	sty gr9scr2+2

	lda RENDMODE		; check if image is to be doubled vertically
	cmp #'6'			; modes 6 and 13 are
	beq @dogrd
	cmp #'C'
	bne @skgrd
@dogrd:	
	txa
	clc
	adc #40
	sta gr9scrd+1		; set up addresses for doubled data
	sta gr9scr2d+1
	bcc @noiny
	iny
@noiny:	
	sty gr9scrd+2
	sty gr9scr2d+2
	ldy gr9scr22+2
	lda gr9scr22+1
	clc
	adc #40
	sta gr9scr22d+1
	bcc @no92d
	iny
@no92d:
	sty gr9scr22d+2
	
	lda #$9D		; enable doubling of data
	sta gr9scrd
	sta gr9scr2d
	sta gr9scr22d
	lda #80
	sta LINEBYTES
	lda #12
	sta DISPROWS
	bne @sknop
@skgrd:
        lda #$EA		; NOP operation
	sta gr9scrd		; disable doubling of data
	sta gr9scrd+1
	sta gr9scrd+2
	sta gr9scr2d
	sta gr9scr2d+1
	sta gr9scr2d+2
	sta gr9scr22d
	sta gr9scr22d+1
	sta gr9scr22d+2
	lda #40
	sta LINEBYTES

@sknop:	
	lda #64
	sta GPRIOR		; enable gr.9
	bne @exit	

@gr8:
	lda #15			; Graphics 8 -> DL mode 15
	jsr OpenGr		; open graphics mode
	lda SAVMSC
	sta gr8scr+1
	lda SAVMSC+1
	sta gr8scr+2
	lda #<SCR2TMP		; save 2nd screen of gr.8 data temp area
	sta gr8scr2+1
	lda #>SCR2TMP
	sta gr8scr2+2

	;; graphics 8 colours are 0 and 1
	lda #0
	sta COLOR2
	lda #8
	sta COLOR1
	bne @exit
@gr15:
	lda #20			; 160/8 = 20 columns
	sta DISPCOLS
	bne @skipfl
@gr15a:				; leave DISPCOLS at default
	inc USEFILT
@skipfl:
	lda #14			; Graphics 15 -> DL mode 14
	jsr OpenGr		; open graphics mode
	lda SAVMSC
	sta gr15scr+1
	sta gr15scr2+1
	lda SAVMSC+1
	sta gr15scr+2
	sta gr15scr2+2
	lda #<SCR2TMP		; save 2nd screen of gr.15 data temp area
	sta gr15scr2b+1
	lda #>SCR2TMP
	sta gr15scr2b+2

		;; graphics 15 colours are 0, 1, and 2 + background (4)
	lda #4
	sta COLOR0
	lda #8
	sta COLOR1
	lda #12
	sta COLOR2

@exit:

	;; set up our own keyboard IRQ to toggle DMA if key pressed
	lda #0
	sta SAVEDM
	lda VKEYBD		; save current keyboard IRQ for later
	sta OSKEYBIRQ+1
	lda VKEYBD+1
	sta OSKEYBIRQ+2

	sei			; inhibit interrupts
	lda #<dmatoggle		; set up keyboard IRQ to toggle DMA on/off
	sta VKEYBD
	lda #>dmatoggle
	sta VKEYBD+1
	cli			; renable interrupts
	rts


	;; save the data to a file
@savetofile:
	jsr strout
	.BYTE 125,"Save file name:D:",0
        JSR RDLINE		;  get filename from user

	;;  make sure IOCB is available
	JSR CloseOutFile
        BMI @error
	
	;;  now open the file
	LDA #WRITE
	jsr OpenFile
	BMI @error
	
	lda #40			; 320/8 = 40 columns
	sta DISPCOLS

	lda RENDMODE
	cmp #'M'
	beq @savmic
	cmp #'N'
	bne @exit
	inc USEFILT
@savmic:
	;; if saving in micropainter format, then save header
	lda #20			; 160/8 = 20 columns
	sta DISPCOLS
	lda #24
	sta DISPROWS
	sta savecount		; need to save 24 blocks worth

	lda #<SCRADR		; use screen area as temp storage area
	sta gr15scr+1
	lda #>SCRADR
	sta gr15scr+2
	jmp @exit
	
@error:
  	LDA ICSTA,X		; read status value
	pha
	jsr CloseOutFile	; close channel
        jsr strout		; display error message
        .BYTE "error ",0
	pla
        jsr DecOut		; display error code
        jsr strout
        .BYTE " opening file",155,0
	jmp askagain		; display menu again

	
	;; toggle DMA to speed processing up
dmatoggle:
	lda KBCODE
	and #%00111111		; ignore Shift and Control keys
	cmp #40			; 'r' aborts and reruns with same file
	bne @ckesc
	inc repeat
	bne @abort		; forced branch
@ckesc:
	cmp #28			; ESC key aborts
	bne @ckdma
@abort:
	lda #ABORTCD		; tell decoder to abort
	sta ERROR
	bne OSKEYBIRQ
@ckdma:	
	cmp #62			; toggle DMA if 's' key is pressed
	bne OSKEYBIRQ		; pass key press to OS
	
	txa
	pha
	lda SDMCTL		; toggle DMA value
	ldx SAVEDM
	stx SDMCTL
	stx DMACTL
	sta SAVEDM
	pla
	tax
OSKEYBIRQ:
	jmp 30000		; gets changed - jump to previous keyb IRQ
		

SAVEDM:	.BYTE 0			; save previous DMA value
RENDMODE: .BYTE 0		; graphics mode menu selection
USE2SCR: .BYTE 0		; use 2 screens?
USEFILT: .BYTE 0		; use filter?
LINEBYTES: .BYTE 0		; number of bytes to skip for next GR.9 line
savecount: .BYTE 0		; number of blocks saved so far

	;;
	;; draw image data.  This gets called when 8 lines of image
	;; data have been read and decoded from jpeg image.  Renderer
	;; should display/save/etc the 8 lines as it sees fit.  Address
	;; of data is in Acc (lo) and Y (hi).  Data is 256 levels of
	;; greyscale (8 bit luminance), 1 byte per pixel.  Data is arranged
	;; as 8 lines of 320 pixels ($A00 consecutive bytes).
	;; If DISPCOLS < 40 then remaining data in line will be empty, i.e.
	;; if DISPCOLS = 10 then each line will be 80 (10*8) bytes of image
	;; data followed by 240 (30*8) bytes that should be ignored
	;; *** DISPCOLS should NEVER be set to > 40 ***
	;; 


RafRendDraw:
  	sta rendpt		; save data buffer address
  	sty rendpt+1
        ldy #8			; draw 8 lines
	sty rendline
	lda RENDMODE

	jsr getaddr
	
	lda @optadr2,y
	pha
	dey
	lda @optadr2,y
	pha
	rts

@optadr2: .WORD rendgr8-1, rendgr15-1, rendgr15-1, rendgr9-1, rendgr9-1
	 .WORD rendgr9-1, rendgr15-1, rendgr15-1, 0, savefile-1
	.WORD rendgr8-1, rendgr152-1, rendgr152-1
	.WORD rendgr92-1, rendgr92-1, rendgr92-1


	;; save data to file
savefile:
 	ldx #(SAVECHN*16)	; IOCB should already be open
	lda #PUTBUF		; so just dump all data to file
	sta ICCOM,X
	lda rendpt
	sta ICBAL,X
	lda rendpt+1
	sta ICBAH,X
 	lda #<(320*8)		; save 8 lines worth of data
	sta ICBLL,X
	lda #>(320*8)
	sta ICBLH,X
 	JSR CIOV
	bpl @rts
	jmp saveerr		; error saving data
@rts:
UnusedVec:
	rts


	;; draw data in gr.9 mode
rendgr9:

	lda USEFILT
	beq @nofilt
 	jsr filter		; reduce pixels horizontally
@nofilt:

	ldy #0
	ldx #0
gr9loop:
	lda (rendpt),y		; get 1st pixel
	and #%11110000		; use top 4 bits for grey level
	sta drawtemp
	iny
	lda (rendpt),y		; get 2nd pixel
	lsr			; shift top 4 bits to the low 4 bits
	lsr			; of pixel data
	lsr
	lsr
	ora drawtemp
gr9scr:	
	sta 30000,x		; put pixel on screen
gr9scrd:
	sta 30000,x		; double pixel vertically
	iny
	inx
	cpx #40			; do 40 bytes worth of data at a time
	bcc gr9loop		; 40 bytes = 80 pixels
	
	lda gr9scr+1		; move screen pointer onto next line
	clc
	adc LINEBYTES
	sta gr9scr+1
	bcc @nogr9hi
	inc gr9scr+2
@nogr9hi:
	lda RENDMODE
	cmp #'6'
	bne @nogr9hi2

	lda gr9scrd+1		; move screen pointer onto next line
	clc
	adc #80
	sta gr9scrd+1
	bcc @nogr9hi2
	inc gr9scrd+2
@nogr9hi2:

	lda rendpt		; move data pointer onto next line
	clc
	adc #<320		; skip the other 240 bytes as they
	sta rendpt		; are empty
	lda rendpt+1
	adc #>320
	sta rendpt+1
	
	dec rendline		; have all 8 lines been drawn?
	bne rendgr9		; no, go back and do the rest

        rts

	;; 
	;; draw data in gr.15 mode
	;; 
rendgr15:

	lda USEFILT
	beq @nofilt
 	jsr filter
@nofilt:
	
	ldy #0
	ldx #0
gr15loop:
	lda (rendpt),y		; get 1st pixel
	and #%11000000		; use top 2 bits for grey level
	sta drawtemp
	iny
	lda (rendpt),y		; get 2nd pixel
	and #%11000000		; use top 2 bits and shift into position
	lsr
	lsr
	ora drawtemp
	sta drawtemp
	iny
	lda (rendpt),y		; get 3rd pixel
	and #%11000000
	lsr
	lsr
	lsr
	lsr
	ora drawtemp
	sta drawtemp
	iny
	lda (rendpt),y		; get 4th pixel
	rol
	rol
	rol
	and #%00000011
        ora drawtemp
gr15scr:	
	sta 30000,x		; display on screen
	iny
	inx
	cpx #40			; do 40 bytes worth of data
	bcc gr15loop
	lda USE2SCR
	beq @nogr152
 	jsr rendgr152		; save data for 2nd GR.15 screen
@nogr152:	
	lda gr15scr+1		; move screen pointer onto next line
	clc
	adc #40
	sta gr15scr+1
	bcc @nogr15hi
	inc gr15scr+2
@nogr15hi:
	lda rendpt		; move data pointer onto next line
	clc
	adc #<320
	sta rendpt
	lda rendpt+1
	adc #>320
	sta rendpt+1
	
	dec rendline		; have we done 8 lines yet?
	bne rendgr15		; if not then go do the rest

@chksv:
	lda RENDMODE
	cmp #'M'		; if we are saving to file then
	beq @dosav
	cmp #'N'
	bne @rts
@dosav:
 	dec savecount
 	lda #<SCRADR
 	sta gr15scr+1		; reset screen pointer too
 	lda #>SCRADR
 	sta gr15scr+2
  	jsr saveblock		; dump 8 lines of data to disk
  	bpl @rts
  	jmp saveerr
@rts:
	rts
	
	
	;; draw data in gr.8 mode
rendgr8:
	lda USE2SCR		; are we using 2 screens?
	beq dogr8
	sei			; yes so disable interrupts
	LDA NMIEN
	PHA
	LDA #0
	STA NMIEN
	lda PORTB
	pha
	and #%11111110		; enable OS RAM
	sta PORTB
dogr8:	
	ldy #0
	ldx #0
gr8loop:
	lda #0
	sta drawtemp
	sta drawtemp+1
	lda (rendpt),y		; get 1st pixel
	rol			; set GR.8 pixel if value >= 128
	rol drawtemp
	rol
	rol drawtemp+1
	iny	
	lda (rendpt),y		; get 2nd pixel
	rol
	rol drawtemp
	rol
	rol drawtemp+1
	iny	
	lda (rendpt),y		; get 3rd pixel
	rol
	rol drawtemp
	rol
	rol drawtemp+1
	iny	
	lda (rendpt),y		; get 4th pixel
	rol
	rol drawtemp
	rol
	rol drawtemp+1
	iny	
	lda (rendpt),y		; get 5th pixel
	rol
	rol drawtemp
	rol
	rol drawtemp+1
	iny	
	lda (rendpt),y		; get 6th pixel
	rol
	rol drawtemp
	rol
	rol drawtemp+1
	iny	
	lda (rendpt),y		; get 7th pixel
	rol
	rol drawtemp
	rol
	rol drawtemp+1
	iny	
	lda (rendpt),y		; get 8th pixel
	rol
	rol drawtemp
	rol
	rol drawtemp+1
        lda drawtemp
	
gr8scr:	
	sta 30000,x
	iny
	bne @noinchi
	inc rendpt+1
@noinchi:
	lda USE2SCR
	beq gr8noram
	lda drawtemp+1
gr8scr2:
	sta 30000,x
gr8noram:	
	inx
	cpx #40			; do 40 bytes worth of data
	bcc gr8loop
	lda gr8scr+1		; move screen pointer onto next line
	clc
	adc #40
	sta gr8scr+1
	bcc @nogr8hi
	inc gr8scr+2
@nogr8hi:
	lda gr8scr2+1		; move screen pointer onto next line
	clc
	adc #40
	sta gr8scr2+1
	bcc @nogr8hi2
	inc gr8scr2+2
@nogr8hi2:

 	lda rendpt		; move data pointer onto next line
 	clc
 	adc #64
 	sta rendpt
	bcc @noincp1
	inc rendpt+1
@noincp1:
	
	dec rendline
	beq @exit
	jmp dogr8
@exit:
	lda USE2SCR		; are we using 2 screens?
	beq @rts
	PLA			; yes, so reenable interrupts
	STA PORTB
        PLA
	STA NMIEN
	cli
@rts:
        rts

saveerr:
	jsr reset		; restore DMA + IRQ
	jsr strout
	.BYTE "error ",0
	ldx #(SAVECHN*16)
	lda ICSTA,x
	jsr DecOut
	jsr strout
	.BYTE " writing to file",155,0
	jsr CloseOutFile	; close output file
	jsr CloseInFile		; close input file
	jmp WaitandRun		; wait for key press and rerun

	
	;; do a 1-2-1 filter on pixels to keep aspect ration in gr.15 
filter:
	lda rendpt
	sta filtpt
	sta @destadr+1
	lda rendpt+1
	sta filtpt+1
	sta @destadr+2
	ldx #0
@filtlp:
	ldy #0
	lda (filtpt),y		; get 1st pixel
	lsr			; divide it by 4
	lsr
	sta drawtemp+1
	iny
	lda (filtpt),y		; get 2nd pixel
	lsr			; divide it by 2
	clc
	adc drawtemp+1		; and add to pixel 2
	cpx #159		; make sure we don't go over right edge
	beq @destadr
	sta drawtemp+1
	iny
	lda (filtpt),y		; get 3rd pixel
	lsr			; divide it by 4
	lsr
	clc
	adc drawtemp+1		; and add to pixel 1 + pixel 2
@destadr:
	sta 30000,x		; store result back at original pos
	clc
	lda filtpt		; and skip a pixel
	adc #2
	sta filtpt
	bcc @noinchi
	inc filtpt+1
@noinchi:
	inx
	cpx #160
	bcc @filtlp
	rts
		

	;; 
	;; copy the second gr.15 screen to under the OS
	;; 
rendgr152:
	sei
	LDA NMIEN
	PHA
	LDA #0
	STA NMIEN		; disable interrupts
	lda PORTB
	pha
	and #%11111110		; enable OS RAM
	sta PORTB
	
dogr152:
	lda USEFILT
	beq @nofilt
 	jsr filter
@nofilt:

	ldy #0
	sty index
gr152loop:
	jsr getpixel
	clc
	ror
	ror
	ror
	sta drawtemp
	txa
	clc
	ror
	ror
	ror
	sta drawtemp+1
	
	jsr getpixel
	asl
	asl
	asl
	asl
	ora drawtemp
	sta drawtemp
	txa
	asl
	asl
	asl
	asl
	ora drawtemp+1
	sta drawtemp+1
	
	jsr getpixel
	asl
	asl
	ora drawtemp
	sta drawtemp
	txa
	asl
	asl
	ora drawtemp+1
	sta drawtemp+1

	jsr getpixel
	ora drawtemp
	pha
	txa
	ora drawtemp+1
	ldx index
	
gr15scr2b:
	sta 30000,x		; display on screen
	pla
gr15scr2:	
	sta 30000,x

	inx
	stx index
	cpx #40			; do 40 bytes worth of data
	bcc gr152loop
	lda gr15scr2+1		; move screen pointer onto next line
	clc
	adc #40
	sta gr15scr2+1
	bcc @nogr152hi
	inc gr15scr2+2
@nogr152hi:
	lda gr15scr2b+1		; move screen pointer onto next line
	clc
	adc #40
	sta gr15scr2b+1
	bcc @nogr152bhi
	inc gr15scr2b+2
@nogr152bhi:
	lda rendpt		; move data pointer onto next line
	clc
	adc #<320
	sta rendpt
	lda rendpt+1
	adc #>320
	sta rendpt+1

	dec rendline		; have we done 8 lines yet?
	beq @skpjmp
	jmp dogr152		; if not then go do the rest
@skpjmp:

	PLA
	STA PORTB
        PLA
	STA NMIEN
	cli			; renable them
@rts:	
	rts
	 

index:	.BYTE 0
	

getpixel:		
	lda (rendpt),y		; get 1st pixel
	iny
	and #%11110000
	lsr
	lsr
	lsr
	lsr
	tax
	lda @lowclrtab,x
	pha
	lda @hiclrtab,x
	tax
	pla
	rts

@lowclrtab:	.BYTE 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 2, 3
@hiclrtab:	.BYTE 0, 0, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3

	;; 
	;; copy the second gr.9 screen to under the OS
	;; 
rendgr92:

	sei			; disable interrupts
	LDA NMIEN
	PHA
	LDA #0
	STA NMIEN
	lda PORTB
	pha
	and #%11111110		; enable OS RAM
	sta PORTB
dogr92:

	lda USEFILT
	beq @nofilt
 	jsr filter
@nofilt:

	ldy #0
	ldx #0
gr9loop2:
	lda #0
	sta drawtemp
	sta drawtemp+1
	lda (rendpt),y
	and #%11110000
	sta drawtemp
	sta drawtemp+1

	lda (rendpt),y		; get 1st pixel
	and #%00001000
	beq @noinc
	lda drawtemp+1
	cmp #240
	beq @noinc
	clc
	adc #16
	sta drawtemp+1
@noinc:
	iny
	lda (rendpt),y
	
	lsr
	lsr
	lsr
	lsr
	pha
	ora drawtemp
	sta drawtemp
	pla
	pha
	ora drawtemp+1
	sta drawtemp+1
	pla
        bcc @noinc2
	and #%00001111
	cmp #15
	bcs @noinc2
	inc drawtemp+1
	
@noinc2:
        lda drawtemp
gr9scr2:	
	sta 30000,x		; put pixel on screen
gr9scr2d:
	sta 30000,x		; double pixel vertically
	
	lda drawtemp+1
gr9scr22:	
	sta 30000,x		; put second pixel into temp memory
gr9scr22d:	
	sta 30000,x		; double pixel vertically
	
	iny
	inx
	cpx #40			; do 40 bytes worth of data at a time
	bcc gr9loop2		; 40 bytes = 80 pixels

	lda gr9scr2+1		; move screen pointer onto next line
	clc
	adc LINEBYTES
	sta gr9scr2+1
	bcc @nogr92hi
	inc gr9scr2+2
@nogr92hi:
	lda gr9scr22+1		; move screen pointer onto next line
	clc
	adc LINEBYTES
	sta gr9scr22+1
	bcc @nogr92hi2
	inc gr9scr22+2
@nogr92hi2:

	lda RENDMODE
	cmp #'C'
	bne @nogr92hi4
@doscr2d:
	lda gr9scr2d+1		; move screen pointer onto next line
	clc
	adc #80
	sta gr9scr2d+1
	bcc @nogr92hi3
	inc gr9scr2d+2
@nogr92hi3:
	lda gr9scr22d+1		; move screen pointer onto next line
	clc
	adc #80
	sta gr9scr22d+1
	bcc @nogr92hi4
	inc gr9scr22d+2
@nogr92hi4:

	lda rendpt		; move data pointer onto next line
	clc
	adc #<320		; skip the other 240 bytes as they
	sta rendpt		; are empty
	lda rendpt+1
	adc #>320
	sta rendpt+1
	
	dec rendline		; have all 8 lines been drawn?
	beq @exit
	jmp dogr92		; no, go back and do the rest
@exit:
	
	PLA			; renable interrupts
	STA PORTB
        PLA
	STA NMIEN
	cli
	rts
	
rendline: .BYTE 0

	
	;;
	;; end of data.  Gets called when image has finished.  Renderer
	;; should close files, restore system back to original state,
	;; wait for user to press a key and then return.  After returning
	;; decoder will exit back to environment (DOS).  To restart decoder
	;; instead do JMP (RERUN) instead of RTS.  If decoder failed to
	;; decode image then this will be called with ERROR > 0
	;;
	
RafRendEnd:
        jsr reset		; reset IRQ and DMA

	;; close input file
	jsr CloseInFile

	ldx #255		; clear last key press
	stx CH
	inx
	stx COLOR4		; set background colour to black
	
	lda RENDMODE
	cmp #'7'
	bne @notgr82
	lda #2
	sta COLOR2
	bne notsave
@notgr82:
	cmp #'S'
	beq @save

	cmp #'M'
	beq @issav
	cmp #'N'
	bne notsave		; we're not saving to disk
@issav:	
	lda savecount		; make sure we've saved enough data
	beq @endsave
	lda #>SCRADR
	ldx #2			; clear 2 pages worth
 	jsr clrarea		; clear temporary data area for save

@savlp:	
	jsr saveblock
	bpl @ok
	jmp saveerr
	
@micclrs: .BYTE 0, 4, 8, 12

@ok:
	dec savecount
	bne @savlp
	
@endsave:
	ldx #(SAVECHN*16)
	lda #<@micclrs		; save colour (grey levels) for image
	sta ICBAL,X
	lda #>@micclrs
	sta ICBAH,X
	lda #4
	sta ICBLL,x
	lda #0
	sta ICBLH,X
	lda #PUTBUF
	sta ICCOM,X
	jsr CIOV

@save:
	;; we are saving to disk, so close file
	jsr CloseOutFile

	lda ERROR
	bne waitmsg
	jsr strout
	.BYTE 155,"Save complete",0
waitmsg:
	lda ERROR
	cmp #ABORTCD
	beq rerun
WaitandRun:
	jsr WAITKEYP		; wait for key press
rerun:	
	jmp (RERUN)		; and rerun decoder

notsave:
	ldx ERROR		; did decoder complete successfully?
	bne waitmsg

	lda USE2SCR
	beq @waitkp		; if we copied data to OS RAM
	jsr copyscr		; then copy it back down again

	LDY #<IMVBI		; set up immediate VBI to switch screens
	LDX #>IMVBI
	LDA #6
 	JSR SETVBV

	;; get key press
@waitkp:
	lda #0
	lda CH
	and #%00111111		; ignore Shift and Control keys
	cmp #28			; ESC key - return to environment
	beq @exit
	cmp #12			; RETURN key - rerun decoder
	beq @exit
	cmp #33			; SPACE BAR - rerun decode
	beq @exit
	cmp #40			; 'R' key repeats same image again
	beq @repeat
	cmp #6			; + key
	beq @incclr
	cmp #14			; - key
	bne @waitkp
				; decrease colour number used
				; leave luminance unchanged
	lda COLOR4
	and #%11110000
	sec
	sbc #16
	jmp @dorest
	
@repeat:
	inc repeat		; redisplay current image
	bne @exit
	
@incclr:			; increase colour number used
				; leave luminance unchanged
	lda COLOR4
	and #%11110000
	clc
	adc #16
@dorest:	
	sta COLOR4
	ldx #2
	;; update other colour registers based on colour in COLOR4
	;; leave luminance values unchanged
@clrloop:	
	lda COLOR0,x
	and #%00001111
	ora COLOR4
	sta COLOR0,x
	dex
	bpl @clrloop
	lda #255
	sta CH
        bne @waitkp
@exit:
	pha
	LDY #<EXITIM		; disable our VBI
	LDX #>EXITIM
	LDA #6
 	JSR SETVBV

	;; clear key press and return
	lda #255
	sta CH
	pla
	cmp #28			; if this was ESC key, then go do to DOS
	beq @rts
	jmp (RERUN)
	
@rts:
	rts
	
	;; reset IRQ and DMA
reset:
	lda VKEYBD+1
	cmp #>dmatoggle
	bne @rts		; IRQ was not put in place, so Init not called
	lda VKEYBD
	cmp #<dmatoggle		; just wait for keypress and exit then
	bne @rts
	
	;;  undo keyboard IRQ
	sei
	lda OSKEYBIRQ+1
	sta VKEYBD
	lda OSKEYBIRQ+2
	sta VKEYBD+1
	cli
	
	;; is DMA disabled, then re-enable it
	lda SAVEDM
	beq @rts		; DMA already enabled
	sta SDMCTL		; enable DMA
	sta DMACTL
@rts:	
	rts

 ;
 ; immediate VBI code to switch between 2 screens
 ;

IMVBI:
	lda #>SCRADR		; if currently on screen 1, switch to 2
	cmp DLADR+5
	beq @swscr2
	sta DLADR+5			; otherwise switch to 1
	lda #(>SCRADR)+16
	sta DLADR+109
	lda RENDMODE
	cmp #'7'
	bne @ck9
	lda #6			; its a GR.8 screen
	sta COLOR1
@exit:	
	jmp EXITIM
@ck9:
	cmp #11
	bcs @exit
	lda COLOR1
	and #%11110000
	ora #6
	sta COLOR1
	lda COLOR2
	and #%11110000
	ora #8
	sta COLOR2
	jmp EXITIM
	
@swscr2:			; switch to screen 2
	lda #>SCR2ADR
	sta DLADR+5
	lda #(>SCR2ADR)+16
	sta DLADR+109
	lda RENDMODE
	cmp #'7'		; is this a GR.8 mode screen?
	bne @ck92
	lda #4
	sta COLOR1
	jmp EXITIM
@ck92:
	cmp #11
	bcs @exit
	lda COLOR0
	and #%11110000
	ora #2			; its a GR.15 screen
	sta COLOR0
	lda COLOR1
	and #%11110000
	ora #4
	sta COLOR1
	lda COLOR2
	and #%11110000
	ora #10
	sta COLOR2
	jmp EXITIM

vbinum:	.BYTE 0

 
	;; **********************************************************
	;; library routines, these may be useful in your own renderer
	;; or they may be too lame for you to use =)
	;; **********************************************************

	; display embeded string on screen
	; string data should follow strout call and be terminated
	; with a 0
strout:
	 PLA			; get string address from stack
	 TAY
	 PLA
	 TAX
	 INY
	 BNE @NIN2
	 INX
@NIN2:
	 STY ICBAL		; point at start of string
	 STX @loop+2
	 STX ICBAH
	 LDX #0			; no data yet
	 STX ICBLL	
	 STX ICBLH
@loop:   lda $c000,y		; - this address gets modified
         beq @exit		; continue until we find terminating 0
	 INC ICBLL		; increase length count
	 bne @skplh
	 inc ICBLH
@skplh:
	 iny
         bne @loop
         inc @loop+2		; bump up to next page
         bne @loop
@exit:
	 LDA #PUTBUF		; found end of string
	 STA ICCOM
	 TYA
	 PHA

	 JSR CIOV		; let CIO display it
         PLA
	 TAY			; modify return address to 
	 lda @loop+2		; return immediately after
         pha			; terminating 0
         tya
         pha
         rts

	;; 
	;; use CIO to read a line of input from user
	;; 
RDLINE:
 	 lda COLCRS		; remember current cursor pos - 2
 	 sec
 	 sbc #2
 	 sta @hpos
	 lda ROWCRS
	 sta @vpos
	 jsr GetLine
	 PHP

	 lda SAVMSC
	 sta devpt
	 lda SAVMSC+1
	 sta devpt+1
	 
	 ldy @vpos
 	 lda devpt
@dvloop:
	 dey			; calculate position on screen of
	 bmi @vdone		; device name
	 clc
	 adc #40
	 bcc @dvloop
	 inc devpt+1
	 bne @dvloop
@vdone:
	 sta devpt
	 lda @hpos
	 clc
	 adc devpt
	 sta devpt
	 bcc @nopt1
	 inc devpt+1
@nopt1:
	 ldy #1
@cpdev:
	 lda (devpt),y		; get device name from screen
	 jsr int2asc		; convert char to ASCII
	 sta RDBUF,y		; add device name to buffer
	 dey
	 bpl @cpdev

	 PLP
	 BPL @EXTOK

@EOL:
	;; make sure there is a return char at end of line
	 LDA #<RDBUF
	 CLC
	 ADC ICBLL,X
	 STA @STA01+1
	 LDA #>RDBUF
	 ADC ICBLH,X
	 STA @STA01+2
	 LDA #155
@STA01:
	 STA 30000 ; GETS CHANGED
@EXTOK:
	 LDY #0
	 RTS
	
@hpos:  .BYTE 0
@vpos:	.BYTE 0

	;; 
	;; get a line worth of data
	;; 
GetLine:	
	 LDX #0
GetLineX:
	 LDA #GETLNE		; read line of data into buffer
	 STA ICCOM,X
	 LDA #<(RDBUF+2)
	 STA ICBAL,X
	 LDA #>(RDBUF+2)
	 STA ICBAH,X
	 LDA #<(MAXLEN-6)  ; leave 2 bytes for dev. name and 6 for extension
	 STA ICBLL,X
	 LDA #>(MAXLEN-6)
	 STA ICBLH,X
	 JMP CIOV
	
	;; 
	;;  convert a number from internal screen code to ASCII
	;; 
int2asc:
	cmp #96
	bcs @rts		; if >= 96 then don't change
	cmp #64
	bcs @bit6
				; carry already clear
	adc #32			; bit 6 not set, < 64, so add 32
	rts

@bit6:
        and #%10111111		; if  >= 64 and < 96 then clear bit 6
@rts:
	rts

	
	;; 
	;; close IOCB
	;; 
CloseInFile:
	 ldx #(LODCHN*16)
	 .BYTE $2C
CloseOutFile:
	 ldx #(SAVECHN*16)
	 LDA #CLOSE
	 STA ICCOM,X
	 JMP CIOV

	;;
	;; wait for key press
	;; 
WAITKEYP:
	jsr strout
	.BYTE 155,"press a key to continue",0
        lda #255
        sta CH
@waitkpd:
	lda CH
	cmp #255
	beq @waitkpd
	lda #255
	sta CH
	rts

	
DLADR = $9F00			; display list address
SCRADR = $A010			; 1st screen address
SCR2ADR = $5010 		; 2nd screen address
SCR2TMP = $E000			; temporary storage for screen 2 until
				; decoder finishes
	;; 
	;; open screen in appropriate graphics mode
	;; graphics mode in y register
	;;

OpenGr:
	STA @mode
	ldy #2
	lda #96
@blnk3:	
	sta DLADR,y		; do 21 blank scan lines
	dey
	bpl @blnk3
	ldy #3
	lda #64			; LMS
	clc
	adc @mode		; add in LMS screen mode
	sta DLADR,y
	iny
	lda #<SCRADR		; set up screen start address
	sta DLADR,y
	iny
	lda #>SCRADR
	sta DLADR,y
	ldy #100		; do 101 lines
	lda @mode
@filgr1:
	sta DLADR+6,y
	dey
	bpl @filgr1
	ldy #107
	lda #64			; LMS
	clc
	adc @mode		; add in LMS screen mode
	sta DLADR,y
	iny
	lda #0
	sta DLADR,y		; set up data address for LMS
	iny
	lda #(>SCRADR)+16
	sta DLADR,y
	ldy #96			; do 97 lines
	lda @mode
@filgr2:
	sta DLADR+110,y
	dey
	bpl @filgr2

	ldy #207
	lda #65			; end the DL
	sta DLADR,y
	iny
	lda #<DLADR		; point back at start of DL
	sta DLADR,y
	iny
	lda #>DLADR
	sta DLADR,y
	 
	lda #<SCRADR		; clear screen memory area
	sta SAVMSC
	
	lda #>SCRADR
	sta SAVMSC+1
	jsr clrscr		; clear 8k of ram

	lda USE2SCR		; check if temp scr area needs cleaning too
	beq @notmp
	
	sei
	LDA NMIEN		; disable all interrupt
	PHA
	LDA #0
	STA NMIEN		; disable interrupts
	lda PORTB
	pha
        and #%11111110
	sta PORTB		; enable OS RAM
	lda #>SCR2TMP		; clear temp area too
	jsr clrscr
	PLA
	STA PORTB		; enable OS ROM
        PLA
	STA NMIEN		; enable interrupts
	cli
	
@notmp:
	lda #<DLADR		; set up display list
	sta SDLSTL
	lda #>DLADR
	sta SDLSTL+1

	RTS
	
@mode:	.BYTE 0

	;; clear 8K worth of RAM for screen
clrscr:
	ldx #32			; 8K worth of screen data
clrarea:
	sta filtpt+1		; screen starting page
	ldy #0
	tya
	sta filtpt
@clrlp1:
	dey
  	sta (filtpt),y
	bne @clrlp1
	inc filtpt+1
	dex
	bne @clrlp1
	rts


	;;
	;;  Print 1 byte decimal number on screen
	;; 

DecOut:
	ldx #'0'		; initialise to ASCII char 0
	stx @reslt
	stx @reslt+1
	ldx #0
@numlp:
	cmp @numtbl,X
	bcc @endb1
	sbc @numtbl,X		; carry already set
	inc @reslt,X
	bne @numlp
@endb1:
	inx
	cpx #2
	bcc @numlp

	clc
	adc #'0'
	sta @reslt+2
 	ldx #0
 	ldy #2
 	lda #'0'

@fndst:
 	cmp @reslt,X
 	bne @endlp
 	inx
 	dey
 	bne @fndst
@endlp:
 	iny
@disp:
 	sty ICBLL
 	lda #>@reslt
 	sta ICBAH
 	txa
 	clc
 	adc #<@reslt
 	sta ICBAL
 	bcc @noinc
 	inc ICBAH
 @noinc:
	lda #PUTBUF
	sta ICCOM
	ldx #0
	stx ICBLH
	jmp CIOV

@reslt:	.RES 3
@numtbl:
 .BYTE 100
 .BYTE 10
	
	;; 
	;; get keypress for menu selection
	;; 
getmenu:
	ldx #0
	stx ICBLL
	stx ICBLH
	lda #GETLNE
	sta ICCOM
	jsr CIOV		; get single key press
	cmp #155
	beq @rts
	pha
 	jsr CIOV		; ignore return key press
        pla
@rts:
 	rts

	;; 
	;; get number from from user
	;; 
getnum:			   
 	 JSR GetLine		; read input data from user
         lda #0
         TAY
@loop2:  sta @temp
@loop:   LDA RDBUF+2,Y
 	 cmp #155		; finished if return key press found
         beq @done
         INY
         sec
         sbc #'0'		; convert from ASCII to number
         sta @temp+1
         ldx #10
         lda #0
         clc
@l2:	 adc @temp		; multiply by 10
         dex
         bne @l2
         adc @temp+1
         jmp @loop2
@done:  
         lda @temp
         rts

@temp:	 .WORD 0


	;;
	;; open an IOCB
	;; Acc = 4 -> open file for read
	;; Acc = 6 -> open for directory read
	;; Acc = 8 -> open file for write
	;; 
OpenFile:
	 STA ICAX1,X
	 LDA #<RDBUF		; use new file name
	 STA ICBAL,X
	 LDA #>RDBUF
	 STA ICBAH,X
	 LDA #OPEN
	 STA ICCOM,X
	 LDA #0
	 STA ICAX2,X
	 JMP CIOV

	
OSRTST = 52224 ; check this address to see if it is RAM or not

	;; check if there is any RAM under the OS
CKOSRAM:
	 PHP
	 SEI
	 LDA NMIEN
	 PHA
	 LDA #0
	 STA NMIEN		; disable interrupts

	 LDY OSRTST		; PICK LOC. IN OS TO TEST
	 LDA PORTB		; save current PORTB state
         PHA
	 AND #%11111110		; try enabling OS RAM
	 STA PORTB
	 LDX #255
	 STX OSRTST		; store $FF to test if it is RAM
	 CPX OSRTST
	 BNE @NTRAM		; not RAM
	 INX
	 STX OSRTST		; store 0 to test if it is RAM
	 CPX OSRTST
	 BNE @NTRAM		; not RAM
	 STY OSRTST		; restore original value
	 LDY #1			; 1 FLAGS IT IS RAM 
	 BNE @ISRAM

@NTRAM:
	 STY OSRTST		; RESTORE JUST IN CASE
	 LDY #0

@ISRAM:
	 STY OSRAM
	 PLA
	 STA PORTB
	 PLA
	 STA NMIEN
	 PLP			; restore status register including irq bit
 
	 RTS

OSRAM:	 .BYTE 0
	
	;; copy screen data back down again from OS RAM
copyscr:	
	sei
	LDA NMIEN
	PHA
	LDA #0
	STA NMIEN		; disable interrupts
	lda PORTB
	pha
	and #%11111110		; enable OS RAM
	sta PORTB

	lda #<SCR2TMP
	sta rendpt
	lda #>SCR2TMP
	sta rendpt+1

	lda #<SCR2ADR
	sta filtpt
	lda #>SCR2ADR
	sta filtpt+1

	LDY #0
@CPCD1:
	LDA (rendpt),Y
	STA (filtpt),Y
	INY
	BNE @CPCD1
	INC filtpt+1
	INC rendpt+1		; copy data up to $FFFF
	BNE @CPCD1
	
	PLA
	STA PORTB
        PLA
	STA NMIEN
	cli

	rts

;; 
;; check if extension needs to be added to filename
;; 
CheckExt:
 	ldx ICBLL
	dex
	dex
	lda #'.'
	cmp RDBUF+2,x		; if last char is '.' no extension needed
	bne @skpdt
        lda #155		; so replace that '.' with a return
	sta RDBUF+2,x
	rts
@skpdt:
	ldy #4			; check last 4 characters
@extlp:
	dex
	beq @addext		; end of name, add extension
	cmp RDBUF+2,x
	beq @rts		; extension is already there, ignore
	dey
	bne @extlp
@addext:
 	ldx ICBLL
	ldy #0
	dex
@cpextlp:
	lda @extname,y		; add extension to filename buffer
	beq @rts
	sta RDBUF+2,x
	inx
	iny
	bne @cpextlp
@rts:		
	rts	

@extname: .BYTE ".JPG",155,0

	;; 
	;; check for a wild card in the file name, C set if wild card found
	;; C clear if wild card not found
	;; 
CheckWild:
	lda #0
	sta wild		; no wild card found yet
 	ldx ICBLL
	dex
@wldloop:
	dex
	bmi @rts
	lda RDBUF+2,x
	cmp #'*'
	beq @wldcard		; wild card found
	cmp #'?'
	bne @wldloop		; not found, go look at next character
@wldcard:
	inc wild		; wild card found
@rts:
	rts
	
wild:	 .BYTE 0

	;;
	;; display the disk directory using an open IOCB
	;; 
DispDir:
	ldx #(LODCHN*16)
	jsr GetLineX		; get next line of input from dir
	bmi @rts
	LDX #0
	LDA #PUTLNE		; write out file name to screen
	STA ICCOM,X
	LDA #<(RDBUF+2)
	STA ICBAL,X
	LDA #>(RDBUF+2)
	STA ICBAH,X
	LDA #<MAXLEN  ; MAX BYTES PER LINE (INCLUDING RETURN)
	STA ICBLL,X
	LDA #>MAXLEN  ; MAX BYTES PER LINE (INCLUDING RETURN)
	STA ICBLH,X
	JSR CIOV
	jmp DispDir
@rts:
	rts

	;; 
	;; save filename for later
	;;
	
lastfn:	.RES MAXLEN-2

SaveFN:
	ldx #MAXLEN
	dex
@cpflnam:
	lda RDBUF,x		; copy filename from buffer to storage area
	sta lastfn,x
	dex
	bpl @cpflnam
	rts

	;;
	;; restore previously saved file name
	;; 
RestFN:
	ldx #MAXLEN
	dex
@cpflnam:
	lda lastfn,x		; copy filename from buffer to storage area
	sta RDBUF,x
	dex
	bpl @cpflnam
	rts
	
repeat:	 .BYTE 0


	;;
	;; display file name
	;;
DispFN:
	 LDA #PUTLNE		; write out file name
	 STA ICCOM
	
	 LDA #<MAXLEN  ; MAX BYTES PER LINE (INCLUDING RETURN)
	 STA ICBLL
	 LDX #0
	 STX ICBLH

	 LDA #<RDBUF
	 STA ICBAL
	 LDA #>RDBUF
	 STA ICBAH
	 JMP CIOV

	;; 
	;;  save one block of data for Micropainter format
	;;  X = IOCB number * 16
	;;  A = data address low byte
	;;  Y = data address high byte
	;; 
saveblock:
	LDX #(SAVECHN*16)
	lda #<SCRADR
	sta ICBAL,X
	lda #>SCRADR
	sta ICBAH,X
	lda #<(40*8)
	sta ICBLL,X
	lda #>(40*8)
	sta ICBLH,X
	lda #PUTBUF
	sta ICCOM,X
	jmp CIOV

	
getaddr:
	ldy optlen
@optloop:	
	cmp @menuopts,y		; check if key is on menu
	beq @optfnd
	dey
	bpl @optloop
        clc
	rts
@optfnd:
	tya
	asl
	tay
	iny
	sec
	rts
	
@menuopts: .BYTE "1", "2", "3", "4", "5", "6", "M", "N", "R", "S"
	.BYTE "7", "8", "9", "A", "B", "C"

optlen: .BYTE 0

	

segcodeend:
	;; end of renderer code

