; -----------------------------------------------
; PShell - a runtime environment for    
; sharp pocket computers                 
; file     : display.asm                   
; author   : puehringer edgar           
; date     : 09.05.2005                 
; version  : 1.0.0                      
; assembler: as61860                    
;                                       
; All display related funtions for pshell
; -----------------------------------------------

.area pshell (REL)
        
.include "pshell.h"
.include "internal.h"


; -----------------------------------------------
; Writes a character in A to the display
; label prefix 01
; Used Registers: A,B,X,Y
; -----------------------------------------------

ps_putchar_con::

.if __PC_IS_BANKSWITCHED__
; if this is a bankswiched pocket, we
; switch to the rom with the character table
        PUSH
        LIDP  MEM_BANKSWITCH
        LIA   MEM_BS_IND_CHARTAB
        STD
        POP
.endif

        CALL  ps_ctabadr
        CALL  ps_xcur2xgcur

        LP    REG_K
        EXAM

        LIA  LCD_CHAR_WIDTH-1
        PUSH
lb0101:                       ; copy the 5 (or 6) pixmaps
        LIDP  ps_cur_y        ; y cursor into B
        LDD
        EXAB

        LP    REG_K
        LDM
        INCK
        CALL  ps_dispadr
.if __INVERS_CHARTAB__
        DXL
.else
        IXL
.endif
        DY
        IYS 
        LOOP lb0101

        LIDP  ps_cur_x        ; increase x cursor
        LDD
        ADIA  1
        STD

        CPIA  LCD_COLS        ; if not max. column + 1,
        JRNZP lb0102          ; then go on

        RA                    ; else: set to zero
        STD

        LIDP  ps_cur_y        ; ... and increase y
        LDD
        ADIA  1
        STD
        
        CPIA  LCD_ROWS        ; if not max. row + 1,
        JRNZP  lb0102         ; then go on

        NOPW
        ;CALL  ps_scroll       ; else: scroll!

lb0102:

        RTN


; -----------------------------------------------
; Scrolls the display one line.
; for pockets with only on line it is 
; simple - just delete the display
; (procedure isn't assembled then and
; ps_scroll is the same as ps_clrscr
; label prefix 02
; -----------------------------------------------
ps_scroll::
.if PC_HAS_MULTI_LINE_LCD

.if __PC_1350__
 
        CALL  EXT_ROM_SCROLL

        LIDP  ps_cur_x        
        RA
        STD
        LIDP  ps_cur_y
        LIA  LCD_ROWS - 1
        STD

.else
.if __PC_1262__

        LIDP  MEM_LCD_L2C1
	LII  12*LCD_CHAR_WIDTH-1
        RA
        FILD

        LIDP <MEM_LCD_L2C2
	LII  12*LCD_CHAR_WIDTH-1
        FILD

.else

; other modells are not implemented yet
.error 1

.endif
.endif

        RTN

.endif


; -----------------------------------------------
; Deletes all lines of the display
; Used Registers: Various, for models which
;   provide a suitable ROM call
; label prefix 02
; -----------------------------------------------
ps_clrscr::

.if __PC_1403__

; ensure, that LIDL can be uses instead of LIDP one time
.assume >MEM_LCD_PART1 - >MEM_LCD_PART2

        LIDP  MEM_LCD_PART1
	LII  12*LCD_CHAR_WIDTH-1
        RA
        FILD

        LIDL <MEM_LCD_PART2
	LII  12*LCD_CHAR_WIDTH-1
        FILD
        
.else
.if __PC_1350__

        CAL INT_ROM_CLRSCR 
        CAL INT_ROM_DISP
.else
.if __PC_1262__

; ensure, that LIDL can be uses instead of LIDP two times
.assume >MEM_LCD_L1C1 - >MEM_LCD_L2C1
.assume >MEM_LCD_L1C2 - >MEM_LCD_L2C2

        LIDP  MEM_LCD_L1C1
	LII  12*LCD_CHAR_WIDTH-1
        RA
        FILD

        LIDL <MEM_LCD_L2C1
	LII  12*LCD_CHAR_WIDTH-1
        FILD

        LIDP  MEM_LCD_L1C2
	LII  12*LCD_CHAR_WIDTH-1
        FILD

        LIDL <MEM_LCD_L2C2
	LII  12*LCD_CHAR_WIDTH-1
        FILD

.else

; other modells are not implemented yet
.error 1

.endif
.endif
.endif

	; now reset the cursors
        LIDP  ps_cur_x        
        RA
        STD
        LIDP  ps_cur_y
        STD

        RTN


; -----------------------------------------------
; Converts x cursor position to graphics
; cursor position
;
; Used Registers: A,B
; Input value: A
; Return value: A
; label prefix 03
; -----------------------------------------------
ps_xcur2xgcur::	

.if __PC_1262__ | __PC_1403__        
        LIDP ps_cur_x          ; Load x cursor position
        LDD                    ; into A and B
	EXAB
	LP   REG_B
        LDM
	SL                     ; Shift A two times and
	SL                     ; add B, this equals
	ADM                    ; multiply by five
	EXAB

.else

.if __PC_1350__ | __PC_1360__

        LIDP ps_cur_x          ; Load left shifted x cursor
        LDD                    ; position into A and B
        SL
	EXAB
	LP   REG_B
        LDM
	SL                     ; Shift A one times and
	ADM                    ; add B, this equals
	EXAB                   ; multiply by six

.else

; other modells are not implemented yet
.error 1

.endif
.endif

        RTN


; -----------------------------------------------
; Calculates the display adress of a
; given graphics cursor location.

; Positions that are to big to fit in
; the display return the adress of the
; most right display column if __RANGE_CHECK__
; is on, otherwise the behaviour is undefined
; (most likely crash).

; Used Registers: A,B,Y
; Input A (graph. cur. x), B (graph. cur. y)
; Return value: Y
; label prefix 04
; -----------------------------------------------
ps_dispadr:

.if __PC_1403__

; -----------------------------------------------

        EXAB                    ; copy A to B
        LP  REG_B
        LDM        
        CPIA 60			; Char 1-12 ?
        JRCP lb0402		; Jump to positive offset calculation

; Calculate negative offsets

.if __RANGE_CHECK__
        CPIA 120		; Valid char range ( < 25) ?
	JRCP lb0403
        LIA  119                ; default: most right x position
lb0403: 
.endif

        CPIA 90			; If not char 19-24, jump ahead
	JRCP lb0404
        LIB  0xB7               ; LSB is 0xB7 - REG_A
        JRP  lb0406		; "break"
lb0404: CPIA 75			; If not char 16-18, jump ahead
	JRCP lb0405
        LIB  0xC6               ; LSB is &C6 - REG_A
        JRP  lb0406		; "break"
; Assert char position is in the range 13-15 
lb0405: LIB  0xA8               ; LSB is 0xA8 - REG_A

lb0406: LP   REG_B
	RC
        SBM

        JRP  lb0409		; Jump over positive offset calculation

; Calculate positive offsets

lb0402: CPIA 45			; If not char 10-12, jump ahead
	JRCP lb0407
        LP   REG_B              ; LSB is REG_B - 0x0F
        SBIM 0x0F              
        JRP  lb0409		; "break"
lb0407:	CPIA 30			; If not char 7-9, jump ahead
	JRCP lb0408
        LP   REG_B              ; LSB is REG_B + 0x0F
        ADIM 0x0F              
; Next line not nessesary, because handling of range 1-6
;  does nothing
;       JRP  lb0409		; "break"

; Assert char position is in the range 1-6 
lb0408:				; LSB is REG_B - do nothing !

; Write result to memory

lb0409:	EXAB		        ; Copy B to YL
        LP REG_YL
        EXAM

.assume >MEM_LCD_PART1 - >MEM_LCD_PART2

        LIA >MEM_LCD_PART1      ; Copy constant hi byte to YH
        LP REG_YH
        EXAM
; -----------------------------------------------

.else
.if __PC_1350__ | __PC_1360__

; -----------------------------------------------

; First we handle the row
        PUSH
        RA
        LP   REG_B
        TSIM 0x02               ; Test for line 3 and 4
        JRZP lb0406
        LIA  0x1E
lb0406: TSIM 0x01               ; Test for line 2 and 4
        JRZP lb0407
        ORIA 0x40        
lb0407: LP   REG_YL
	EXAM
        POP

; Now we handle the column block address
        PUSH

        CPIA 120		; If not char 21-25, jump ahead
	JRCP lb0401
	LIA  >MEM_LCD_L1C5
        LIB  120
        JRP  lb0405		; "break"

lb0401:	CPIA 90			; If not char 16-20, jump ahead
	JRCP lb0402
	LIA  >MEM_LCD_L1C4
        LIB  90
        JRP  lb0405		; "break"

lb0402:	CPIA 60			; If not char 11-15, jump ahead
	JRCP lb0403
	LIA  >MEM_LCD_L1C3
        LIB  60
        JRP  lb0405		; "break"

lb0403:	CPIA 30			; If not char 6-10, jump ahead
	JRCP lb0404
	LIA  >MEM_LCD_L1C2
        LIB  30
        JRP  lb0405		; "break"

; Assert char position is in the range 1-5 
lb0404:	LIA  >MEM_LCD_L1C1
        LIB  0

; Write result to YH
lb0405:	LP REG_YH
        EXAM

; Calculate graph x cur - block offset
        POP
        EXAB
        LP   REG_B
        SBM
        RA
        EXAB

; Add it to Y
        LP   REG_YL
	ADB			; 16 bit add

; -----------------------------------------------

.else
.if __PC_1262__

; -----------------------------------------------

; First we handle the row
        PUSH
        RA
        LP   REG_B
        TSIM 0x01               ; Test for line 1
        JRZP lb0407
        ORIA 0x40        
lb0407: LP   REG_YL
	EXAM
        POP

; Now we handle the column block address
        PUSH

        CPIA 60			; If not char 13-24, jump ahead
	JRCP lb0401
	LIA  >MEM_LCD_L1C2
        LIB  60
        JRP  lb0402		; "break"

; Assert char position is in the range 1-12 
lb0401:	LIA  >MEM_LCD_L1C1
        LIB  0

; Write result to YH
lb0402:	LP REG_YH
        EXAM

; Calculate graph x cur - block offset
        POP
        EXAB
        LP   REG_B
        SBM
        RA
        EXAB

; Add it to Y
        LP   REG_YL
	ADB			; 16 bit add

; -----------------------------------------------

.else

; other modells are not implemented yet
.error 1

.endif
.endif
.endif

        RTN


; -----------------------------------------------
; Calculates the address of a given character
; (Register A) in the character table
; The character stays in A
;
; Used Registers: A,B,X
; Return value: X
; label prefix 06
; -----------------------------------------------
ps_ctabadr:
	LIB  1			; Default table offset: 0, plus on for IXL mnemonic

.if __PC_1403__        
        TSIA 0x80               ; Not greater than 127 ?
	JRZP lb0601		; Jump ahead
	LIB MEM_CHARTAB_OFF+1	; Offset to alternative table, plus on for IXL mnemonic
lb0601:
.endif

	PUSH			; Save A (= ascii code)

	LIA  >MEM_CHARTAB       ; Table address -> X
	LP   REG_XH
	EXAM
	LIA  <MEM_CHARTAB
	LP   REG_XL
	EXAM
	
	RA			; (00 B) -> BA = Table offset 
	EXAB

	SBB			; 16 bit sub
	DECP

	POP			; (00 ascii) -> BA			
	
	ADB			; 16 bit add
	DECP

	ADB			; 16 bit add
	DECP

	ADB			; 16 bit add
	DECP

	ADB			; 16 bit add
	DECP

	ADB			; 16 bit add
	DECP

        RTN


; -----------------------------------------------
; Display a byte pattern with address given in 
; X+1, length in A and x pos in B
; label prefix 14
; -----------------------------------------------
ps_gprint::
	PUSH
        CALL  ps_xcur2xgcur
	EXAB
	POP
ps_gdraw::
	TSIA  0xff
	JRZP  lb1402

	DECA
	PUSH			; counter for loop on stack

        EXAB			; x pos in K
	LP    REG_K
        EXAM

lb1401:                       ; copy n pixmaps
        LIDP  ps_cur_y        ; y cursor into B
        LDD
        EXAB

        LP    REG_K
        LDM
        INCK
        CALL  ps_dispadr
        IXL
        DY
        IYS 
        LOOP lb1401
lb1402:	RTN

	
ps_bitbltr:
        IXL
        DY
        IYS 
	RTN

ps_bitbltp:
        IXL
        DY
        IYS 
	RTN
