Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Variable corruption?
#2
First Third pass, if you'd like to do testing:

(you'll also need an FXZ font; incbin at @FONT in asm context)

Code:
SUB FZXSetFont (FontAddress as uInteger)
POKE UINTEGER @FZXFontPointer+1,FontAddress
RETURN
END SUB


SUB FZXPrintAt(Y as uByte, X as uByte, printData as String)
DIM FZXi as uByte=0
FZXPrintAChar(22) 'at
FZXPrintAChar(Y)
FZXPrintAChar(X)

IF LEN printData > 0 THEN
   FOR FZXi=0 to LEN printData-1
      FZXPrintAChar(CODE printData(FZXi))
   NEXT FZXi  
END IF

END SUB

SUB FZXPrint(printData as String)
DIM FZXi as uInteger

IF LEN printData > 0 THEN
   FOR FZXi=0 to LEN printData-1
      FZXPrintAChar(CODE printData(FZXi))
   NEXT FZXi  
END IF

END SUB


SUB FASTCALL FZXPrintAChar (character as uByte)
ASM
PUSH IX
CALL FZX_START
POP IX
RET

; -----------------------------------------------------------------------------
; FZX driver - Copyright (c) 2013 Einar Saukas
; -----------------------------------------------------------------------------

;        org     65000           ; driver address

;FONT    EQU     60000           ; font address

MARGIN  EQU     0               ; left margin (in pixels)

;STR_NUM EQU     4               ; stream #4


; -----------------------------------------------------------------------------
; CREATE CHANNEL AND ATTACH STREAM

DRIVER:
;        ld      hl, ($5c53)     ; store system variable PROG in HL
;        dec     hl
;        ld      bc, 5           ; allocate 5 bytes for channel below BASIC area
;        push    bc
;        call    $1655           ; call routine MAKE-ROOM
;        pop     bc
;        ld      hl, CH_DATA + 4
;        lddr                    ; copy CH_DATA to new channel space
;        ld      hl, ($5c4f)     ; store system variable CHANS in HL
;        ex      de, hl
;        inc     hl
;       inc     hl              ; now HL = allocated address + 1
;        sbc     hl, de          ; calculate offset between start of channels
;                                ;   area and start of the new channel space
;                                ;   (notice the carry flag was already cleared
;                                ;   from executing CALL $1655 earlier)
;        ld      (STR_OFF), hl   ; attach stream by storing channel address
;                                ;   offset in streams table
;        ret

;STR_OFF EQU $5c10+((STR_NUM+3)*2) ; address of channel offset in streams table

;CH_DATA:
;        defw    START           ; address of the PRINT # routine
;        defw    $15c4           ; address of the INPUT # routine
;        defb    'S'             ; channel type 'S'

; -----------------------------------------------------------------------------
; PROPORTIONAL PRINT ROUTINE

FZX_START:
        ld      hl, FZX_P_FLAG      ; initial address of local variables
        dec     (hl)            ; check P_FLAG value by decrementing it
        jp      m, CHK_AT       ; expecting a regular character?
        jr      z, GET_COL      ; expecting the AT column?
GET_LIN:
        cpl
        add     a, 192          ; now A = 191 - char
        inc     hl
GET_COL:
        inc     hl
        ld      (hl), a
        ret
CHK_AT:
        cp      22              ; specified keyword 'AT'?
        jr      nz, CHK_CR
        ld      (hl), 2         ; change P_FLAG to expect line value next time
        RET
CHK_CR:
        inc     (hl)            ; increment P_FLAG to restore previous value
        inc     hl
END ASM
FZXFontPointer:
ASM
        ld      bc, FONT
        push    bc
        pop     ix
        cp      13
        jp      z, NEWLINE
CHK_CHAR:
        dec     a               ; now A = char - 1
        cp      (ix+2)          ; compare with lastchar
        jr      nc, UNDEF_CHAR
        sub     31              ; now A = char - 32
        jr      nc, PRINT_CHAR
UNDEF_CHAR:
        ld      a, '?'-32       ; print '?' instead of invalid character
PRINT_CHAR:
        inc     a               ; now A = char - 31
        ld      l, a
        ld      h, 0
        ld      d, h
        ld      e, l
        add     hl, hl
        add     hl, de          ; now HL = (char - 31) * 3
        add     hl, bc          ; now HL references offset/kern in char table
        ld      e, (hl)
        inc     hl
        ld      a, (hl)
        and     63
        ld      d, a            ; now DE = offset

        xor     (hl)
        rlca
        rlca
        ld      c, a            ; now C = kern

        push    hl
        add     hl, de
        dec     hl              ; now HL = char definition address
        ex      (sp), hl        ; now HL references offset/kern in char table
        inc     hl              ; now HL references shift/width in char table
        xor     a
        rld                     ; now A = char shift
        push    af
        rld                     ; now A = (width - 1)
        ld      (WIDTH1+1), a
        cp      8               ; check if char width is larger than 8 bits
        rld                     ; restore char shift/width

        ld      de, $000e       ; same as "LD C,0"
        jr      c, NARROW_CHAR
        ld      de, $234e       ; same as "LD C,(HL)" and "INC HL"
NARROW_CHAR:
        ld      (SMC), de       ; self-modify code to handle narrow/large chars

        inc     hl              ; now HL references next char offset
        ld      a, (hl)         ; now A = LSB of next char offset
        add     a, l
        ld      e, a            ; now E = LSB of next char definition address

        ld      hl, FZX_P_COL
        ld      a, (hl)
        sub     c               ; move left number of pixels specified by kern
        jr      nc, ON_SCREEN   ; stop moving if it would fall outside screen
        xor     a
ON_SCREEN:
        ld      (hl), a

        ld      a, (WIDTH1+1)   ; now A = (width - 1)
        add     a, (hl)         ; now A = (width - 1) + column
        call    c, NEWLINE      ; if char width won't fit then move to new line

        ld      bc, (FZX_P_COL)
        ld      a, 1
        sub     (ix+0)          ; now A = 1 - height
        add     a, b            ; now A = P_LIN - height + 1
        jp      nc, $0c86       ; call routine REPORT-5 ("Out of screen")

        pop     af              ; now A = shift

        add     a, 191          ; range 0-191
        call    $22aa + 2       ; call PIXEL-ADD + 2 to calculate screen address
        ex      af, af'
                                ; now A' = (col % 8)
        jr      CHK_LOOP

MAIN_LOOP:
        ld      d, (hl)         ; now D = 1st byte from char definition grid
        inc     hl              ; next character definition
SMC:
        ld      c, (hl)         ; now C = 2nd byte from char definition or zero
        inc     hl              ;   (either "LD C,0" or "LD C,(HL)" + "INC HL")
        xor     a               ; now A = zero (since there's no 3rd byte)
        ex      (sp), hl        ; now HL = screen address

        ex      af, af'
                                ; now A = (col % 8), A' = 0
        jr      z, NO_ROTATE
        ld      b, a            ; now B = (col % 8)
        ex      af, af'
                                ; now A = 0, A' = (col % 8)
ROTATE_PIXELS:
        srl     d               ; rotate right char definition grid in D,C,A
        rr      c
        rra
        djnz    ROTATE_PIXELS
NO_ROTATE:
        inc     l
        inc     l
        or      (hl)
        ld      (hl), a         ; put A on screen
        dec     l
        ld      a, c
        or      (hl)
        ld      (hl), a         ; put C on screen
        dec     l
        ld      a, d
        or      (hl)
        ld      (hl), a         ; put D on screen

        inc     h               ; move screen address by 1 pixel down
        ld      a, h
        and     7
        jr      nz, CHK_LOOP
        ld      a, l
        add     a, 32
        ld      l, a
        jr      c, CHK_LOOP
        ld      a, h
        sub     8
        ld      h, a
CHK_LOOP:
        ex      (sp), hl        ; now HL = char definition address
        ld      a, l
        cp      e               ; check if reached next char definition address
        jr      nz, MAIN_LOOP   ; loop otherwise

        pop     hl              ; discard screen address from stack
        ld      hl, FZX_P_COL
        ld      a, (hl)         ; now A = column
WIDTH1:
        add     a, 0            ; now A = column + (width - 1)
        scf
        adc     a, (ix+1)       ; now A = column + width + tracking
        jr      nc, EXIT        ; if didn't fall outside the screen then exit
NEWLINE:
        ld      (hl), MARGIN    ; move to initial column at left margin
        inc     hl
        ld      a, (hl)         ; now A = line
        sub     (ix+0)          ; now A = line - height
EXIT:
        ld      (hl), a         ; move down a few pixels specified by height
        RET

FZX_P_FLAG:
        defb        0
FZX_P_COL:
        defb        MARGIN
FZX_P_LIN:
        defb        191
FZX_END:

; -----------------------------------------------------------------------------
END ASM
END SUB
Reply


Messages In This Thread

Forum Jump:


Users browsing this thread: 1 Guest(s)