Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Variable corruption?
#1
Code:
SUB FZXPrintAt(Y as uByte, X as uByte, printData as String)
DIM FZXi as uInteger=0
PRINT INK 0;FZXi: PAUSE 0
FZXPrintAChar(22) 'at
PRINT INK 1;FZXi: PAUSE 0

FZXPrintAChar(Y)
PRINT INK 2;FZXi: PAUSE 0

FZXPrintAChar(X)
PRINT INK 3;FZXi: PAUSE 0

PRINT LEN printData
FOR FZXi=0 to LEN printData-1
PRINT INK 4;FZXi: PAUSE 0
   FZXPrintAChar(CODE printData(FZXi))
PRINT INK 5;FZXi: PAUSE 0
NEXT FZXi  
END SUB

The first 3 calls to FZXPrintAChar work perfectly. Then we get to the loop part. It prints out 0 for FZXi and then prints the first letter of the string. Next time around the loop, FZXi becomes 33633!
But I'm not sure where?

Should I assume FZXPrintAChar does some stack corruption? This is just FZX from Einar Saukas (and friends) - and seems to work perfectly when called to print a single character. Even multiple times. But when looping, strange things happen.

The odd thing is it just seems to happen once. If I change the code to FZXPrintAChar(65) - it happily prints out letter A's in sequence beautifully. Except the first time through the loop, FZXi is set to 33633. It then proceeds to count upwards through 33634 33635 etc, as you'd expect for a loop variable.

Investigating as I type:
If I set the variable type to be a uByte, it gets set to 131 in the loop. (Which makes some sense, as the high byte of 33633 is 131 ) - but it isn't reset each time to 131, but is allowed to count upwards.

2 AM.

Time to quit for the night. Code dumped to <deleted> for the moment. - I fully accept the issue might be with the assembly module from someone else I've used!

EDIT: I think I see it. It's using IX in the routine. That will have to be changed!
Reply
#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


Forum Jump:


Users browsing this thread: 1 Guest(s)