Newbie simple (ha!) assembler question

harper

New Member
Nov 12, 2019
9
2
3
Hi

I'm looking at implementing a couple of simple demos on the X16 in assembler. Just trying to find my feet.

I've looked at the memory maps etc. and I can't see how I write to screen memory in assembler. I don't want to do anything fancy, just write to the "standard" 80x60 screen in the ROM font, much like what the BASIC VPOKE will do.

The assembler demos all seem to be much more complex than this.

Sorry if it's stupidly simple and I've just overlooked some documentation somewhere.

Ultimately, I'll want to read from, and write to, individual 80x60 character positions

edit: I think I understand I can't do this without going through vera , I have done a screen clear 80x60 in basic, VPOKEing one char at a time, and it wasn't all that quick.

I guess that's what I want to start with in ASM

Cheers folks :)
 
Last edited:

BruceMcF

Active Member
May 19, 2019
150
49
28
You definitely can't do this without going "to" Vera, the "Video RAM" is sitting INSIDE the Vera FPGA.

I am also hoping to see answers to this. If the Vera reference at GitHub is correct, then if you have the current foreground and background color byte at "color", and the target location encoded as (Vera address/2) is at "current", and the character code is in A, then with auto-increment set to 1 for the following color byte:

VPORT_SEL = $9F25
VPORTA = $9F23
VPORTB = $9F24
VADDRLO = $9F20
VADDRMID = $9F21
VADDRHI = $9F22 ; also increment in high four bits

TAY
LDA #0
STA VPORT_SEL ; set Port to PortA
LDA current
ASL A
STA VADDRLO
LDA current+1
ROL A
STA VADDRMID
LDA #0
ADC #$10 ; add in high bit from current if set
STA VADDRHI ; also puts $1 in increment nybble
STY VPORTA
LDA color
STA VPORTA

Based on the Vera Programmer Guide and untested, so critique from people experienced with the current emulator welcomed.
 

harper

New Member
Nov 12, 2019
9
2
3
Okay, based on your help, and some web pages, and some demos, I come up with this so far.

Code:
zr = $20          ;get zome zero page vars to work with

z_hl = zr         ;hl Pair
z_l  = zr
z_h  = zr+1

z_de = zr+4       ;de pair
z_e  = zr+4
z_d  = zr+5

z_as = zr+6       ;hold a

CursorX = zr+7
CursorY = zr+8


!src "vera.inc"
*=$0801            ; Assembled code should start at $0801
            ; (where BASIC programs start)
            ; The real program starts at $0810 = 2064
!byte $0C,$08        ; $080C - pointer to next line of BASIC code
!byte $0A,$00        ; 2-byte line number ($000A = 10)
!byte $9E        ; SYS BASIC token
!byte $20        ; [space]
!byte $32,$30,$36,$34    ; $32="2",$30="0",$36="6",$34="4"
            ; (ASCII encoded nums for dec starting addr)
!byte $00        ; End of Line
!byte $00,$00        ; This is address $080C containing
            ; 2-byte pointer to next line of BASIC code
            ; ($0000 = end of program)
*=$0810            ; Here starts the real program
+video_init
+vset $00000 | AUTO_INC_1 ; VRAM bank 0

CHROUT=$FFD2        ; CHROUT outputs a character (C64 Kernal API)
CHRIN=$FFCF        ; CHRIN read from default input
CLS=$e544        ; sadly this did not work
CURRENT=$0

    jsr    CLS    ; clear the screen (sadly this didn't work)
    ldx    #0    ; X register is used to index the string
loop:
    lda    .string,x ; Load character from string into A reg
    beq    end    ; If the character was 0, jump to end label
    jsr    CHROUT    ; Output character stored in A register
    inx        ; Increment X register
    jmp    loop    ; Jump back to loop label to print next char
end:
    jsr    CHRIN    ; Read input until Enter/Return is pressed

    ; test the X Y addressing  -- using Y to store char value
    lda #0
    sta CursorX
    lda #0
    sta CursorY
    ldy $50
    jsr    veraprint
    jsr    CHRIN
    lda #1
    sta CursorX
    lda #1
    sta CursorY
    ldy $50
    jsr    veraprint
    jsr    CHRIN
    lda #2
    sta CursorX
    lda #2
    ldy $50
    sta CursorY
    jsr    veraprint
    jsr    CHRIN
    rts        ; Return to caller

veraprint:
    ; save our char
    phy
    ; set the memory addr
    jsr sexy
    ; get our char back
    ply
    ; send the char to VERA at x y
    sty veradat
    rts

SetVeraADDR:             
                        
        ; A contains vera Hi addr,
        ; Y contains vera mid
        ; X contains vera lo

        ; -- comment - could I use X and Y regs directly
        ; -- instead of my Zero page surrogates? Hmm

                sta verahi
                sty veramid
                stx veralo
        rts

sexy:

                stz z_d                     
                lda CursorY     
                clc
                adc z_e                         ;Add carry to M byte
                tay
                lda z_d
                adc #0                          ;Add carry to H byte
                sta z_d
                stz z_e
                lda CursorX     
                asl
                rol z_e
                tax                       
                tya                       
                adc z_e
                tay                     
                lda z_d                 
                adc #$10               

                jsr SetVeraADDR       
        rts

.string !pet    "testing x y coords - waiting for enter...",13,0
This seems to work in that I get a staggered line of @ symbols in my co-ordinates

(I'm using the vera.inc from the assembler demo in the github project).

I always get an @ though, no matter what I store into Y before calling my routine, lol. Why would that be?

Can I clear the screen from ASM?

I found mention of a C64 Kernal routine for clearing the screen but jsr'ing it did nothing
 

harper

New Member
Nov 12, 2019
9
2
3
I've changed this to fill the screen with @ characters one at a time in a loop!

Code:
    ; test the X Y addressing  -- using Y to store char value
    ldy $50
    lda #79
    sta CursorX
    lda #59
    sta CursorY
goleft:
    jsr column
    dec CursorX
    bne goleft
    jsr column
    rts        ; Return to caller

column:
    jsr veraprint
    dec CursorY
    bne column
    jsr veraprint
    lda #59
    sta CursorY
    rts
 

harper

New Member
Nov 12, 2019
9
2
3
Ah I fixed the character issue. now I can fill the screen with whatever character I want.

I know this isn't the most efficient way to do this, but I'm building up techniques to address characters.


Code:
zr = $20          ;get zome zero page vars to work with

z_hl = zr         ;hl Pair
z_l  = zr
z_h  = zr+1

z_de = zr+4       ;de pair
z_e  = zr+4
z_d  = zr+5

z_as = zr+6       ;hold a

CursorX = zr+7
CursorY = zr+8
Character = zr+9


!src "vera.inc"
*=$0801            ; Assembled code should start at $0801
            ; (where BASIC programs start)
            ; The real program starts at $0810 = 2064
!byte $0C,$08        ; $080C - pointer to next line of BASIC code
!byte $0A,$00        ; 2-byte line number ($000A = 10)
!byte $9E        ; SYS BASIC token
!byte $20        ; [space]
!byte $32,$30,$36,$34    ; $32="2",$30="0",$36="6",$34="4"
            ; (ASCII encoded nums for dec starting addr)
!byte $00        ; End of Line
!byte $00,$00        ; This is address $080C containing
            ; 2-byte pointer to next line of BASIC code
            ; ($0000 = end of program)
*=$0810            ; Here starts the real program
+video_init
+vset $00000 | AUTO_INC_1 ; VRAM bank 0

CHROUT=$FFD2        ; CHROUT outputs a character (C64 Kernal API)
CHRIN=$FFCF        ; CHRIN read from default input
CLS=$e544        ; sadly this did not work
CURRENT=$0

    jsr    CLS    ; clear the screen (sadly this didn't work)
    ldx    #0    ; X register is used to index the string
loop:
    lda    .string,x ; Load character from string into A reg
    beq    end    ; If the character was 0, jump to end label
    jsr    CHROUT    ; Output character stored in A register
    inx        ; Increment X register
    jmp    loop    ; Jump back to loop label to print next char
end:
    jsr    CHRIN    ; Read input until Enter/Return is pressed

    ; test the X Y addressing  -- using Y to store char value
    lda #32
    sta Character
    jsr fullscreen

    lda #166
    sta Character
    jsr fullscreen

    lda #32
    sta Character
    jsr fullscreen

    rts

fullscreen:
    lda #79
    sta CursorX
    lda #59
    sta CursorY
goleft:
    jsr column
    dec CursorX
    bne goleft
    jsr column
    rts        ; Return to caller

column:
    jsr veraprint
    dec CursorY
    bne column
    jsr veraprint
    lda #59
    sta CursorY
    rts
    

veraprint:
    ; set the memory addr
    jsr sexy
    ; send the char to VERA at x y
    ldy Character
    sty veradat
    rts

SetVeraADDR:             
                        
        ; A contains vera Hi addr,
        ; Y contains vera mid
        ; X contains vera lo

        ; -- comment - could I use X and Y regs directly
        ; -- instead of my Zero page surrogates? Hmm

                sta verahi
                sty veramid
                stx veralo
        rts

sexy:

                stz z_d                     
                lda CursorY     
                clc
                adc z_e                         ;Add carry to M byte
                tay
                lda z_d
                adc #0                          ;Add carry to H byte
                sta z_d
                stz z_e
                lda CursorX     
                asl
                rol z_e
                tax                       
                tya                       
                adc z_e
                tay                     
                lda z_d                 
                adc #$10               

                jsr SetVeraADDR       
        rts

.string !pet    "testing x y coords - waiting for enter...",13,0
 
  • Like
Reactions: BruceMcF