6809 assembly request: make this more better?

Updates:

  • 2021-9-17 – Added revisions suggested by William “Lost Wizard” Astle.

Hello, folks who actually know how to program 6809 assembly.

Can you make this more better?

The idea is to look at each byte on the 32-column VDG screen (from 1024 to 1535) and if the high bit is set (>128, thus a semigraphics block character), add 16 to it. That moves it to the next color. If it rolls over, adjust it back to the proper range.

i.e., if the block is 250, and it adds 16, you end up with 10. Setting the high bit again bumps it back to the 128-255 range. Initially, I did this using a compare to #128, then using ADDA of #128. Then I looked up the BIT test. Rather than compare to decide if I need to do something, I just do the OR to set that high bit back. Seems to work. Maybe faster than checking each byte?

Does this make sense?

Please and thank you.

William Astle Updates

William Astle immediately left these comments:

I’d use “BPL” instead of “BITA/BEQ”. (Bit 7 is the sign bit and LD and ST set flags.) Also, I’d do “LDA ,X+” and then if updating the screen, do “STA -1,X”. That removes the need for the “LEAX”.

William Astle

BPL is “Branch if PLus”. When a register value is used to represent values that can be negative (-127 to 128 versus 0 to 255), the high bit is used to indicate negative. I expect BPL is basically “branch if the high bit is not set.”

When I “LDA ,X”, I am loading register A with whatever is pointed to by X. Adding the plus “LDA ,X” will load A then increment X. Since STA allows an offset, so you can do things like “STA 5,X” to start the value in register A 5 locations past wherever X points. Doing a -1 stores it one byte earlier. That eliminates me needing to use “LEAX” to add one to X.

Here is the update:

References

References I used:

21 thoughts on “6809 assembly request: make this more better?

  1. William Astle

    I’d use “BPL” instead of “BITA/BEQ”. (Bit 7 is the sign bit and LD and ST set flags.) Also, I’d do “LDA ,X+” and then if updating the screen, do “STA -1,X”. That removes the need for the “LEAX”.

    Reply
  2. Dave Philipsen

    Line 120 could be LDA ,X+
    Line 130 could be eliminated
    Line 140 could be BPL SKIP
    Line 170 could be STA -1,X
    Line 180 could be eliminated

    Reply
  3. L. Curtis Boyle

    If speed is/was of the utmost importance, you could do a ldd ,x++ (grab 2 bytes at a time & auto double increments, which is faster than doing two lda ,x+ in the loop)). Doing that, you would change sta -1,x to sta -2,x (same speed/size as before), and after the sta -2,x, add: tstb / bpl skip / addb #16 / orb #$80 / stb -1,x. This does make the code a little longer, though.

    Reply
  4. Dave Philipsen

    And to add to what Curtis said, if speed was important and size is not an issue, you can unroll the loop as much as you want. Think of it this way, a loop isn’t even needed if you’re willing to unroll it far enough. But you probably don’t want to go that far. You could unroll it by 2, 4, 8, 16 iterations though.

    Reply
      1. Dave Philipsen

        Yes, or multiple LDDs (as Curtis suggested). If you walked through all 512 bytes you wouldn’t need a loop. Increasing the number of bytes handled per loop will speed it up a wee bit. But unless you really need the speed, don’t bother.

        Reply
      1. craig allsop

        In that case, there are number of things you could do depending on how far you want to go.

        Nothing. Its pretty good already for its ‘size’ and has the benefit that you could have multiple borders going in any direction using this function since it doesn’t matter where on the screen they are.
        If you want it to go faster, make it only look at the edge bytes rather than the whole screen as the loop is spending more time just spinning than doing real work. This should make it about 5x faster.
        Using 2 – just paint the border in, starting from a color, eliminates reading the screen. Also, regarding the OCD version, if you want to fill the corners, when you change direction add an extra 1 (i.e. skip 1 color), this gives you a total of 96 which is divisible by 8. When its animating nobody will notice the temporary delay of one color. Or if you really wanted a ‘square’ then move the left/right edges in 1 character.

        3a. Simplify, make this a ‘paint colors’ function, i.e. X = address, Y = increment, A = color, B = count. Then call it once per ‘edge’. You can also use it to draw smaller boxes or horizontal bars if you want. Could be a usrdef.

        Just ‘move’ the actual bytes and eliminate the bit math.

        Reply
        1. Allen Huffman Post author

          I am not sure how to approach a routine that would just do the outline of the screen. But drawing the border itself seems to be similar to how I would have done it in BASIC.

          Reply
          1. craig allsop

            Here is one in 15 loops. It does 15×2 characters top and bottom and left/right edge. That leaves 1 character in the top right and 1 in the bottom corner done last. Of course at the expense of size. But to be honest I think just painting them is a better idea as its easier to understand and use.

            screen equ $400

            repeat:

            sync
            sync
            sync
            sync
            sync
            sync
            sync
            sync
            sync
            sync

            ldx #screen ; for top/bottom edge
            ldy #screen+31 ; for left/right edge

            loop:
            ; top edge
            ldd ,x++
            andb #$7F
            addd #$1010
            ora #$80
            orb #$80
            std -2,x

            ; bottom edge
            ldd 32*15,x
            andb #$7F
            addd #$1010
            ora #$80
            orb #$80
            std 32*15,x

            ; do left and right edge (b/a)
            ldd ,y
            andb #$7F
            addd #$1010
            ora #$80
            orb #$80
            std ,y
            leay 32,y ; next line

            cmpx #screen+30
            bne loop ; loop 15x

            ; 30th char top line (x=30)
            lda ,x
            adda #$10
            ora #$80
            sta ,x

            ; 2nd char bottom line (x=30)
            lda 32*15+1-30,x
            adda #$10
            ora #$80
            sta 32*15+1-30,x

            jmp repeat ; for fun

          2. craig allsop

            Just paint it, OCD version:

            opt c,cd,ct,cc
            org $4000

            screen equ $400
            color fcb 143

            start:
            lda color ; starting color

            repeat:
            ldx #screen+1
            ldy #30
            ldb #1
            bsr paint ; top edge

            ldx #screen+31+32
            ldy #14
            ldb #32
            bsr paint ; right edge

            ldx #screen+32*16-2
            ldb #-1
            ldy #30
            bsr paint ; bottom edge

            ldx #screen+32*14
            ldb #-32
            ldy #14
            bsr paint ; left edge

            lda color
            adda #$10
            ora #$80
            sta color

            sync ; slow it down
            sync
            sync
            sync
            sync
            sync
            sync
            sync

            jmp repeat ; for fun

            rts

            opt cc

            paint:
            sta ,x
            adda #$10
            ora #$80
            leax b,x
            leay -1,y
            bne paint
            rts

            end start

          3. craig allsop

            Paint with a table is probably the best way, like you did in basic.

            [php]

            opt c,cd,ct,cc
            org $4000

            screen equ $400
            color fcb 143
            table fdb screen+1
            fcb 30
            fcb 1
            fdb screen+31+32
            fcb 14
            fcb 32
            fdb screen+3216-2
            fcb 30
            fcb -1
            fdb screen+32
            14
            fcb 14
            fcb -32
            start:
            lda #128
            bsr clear
            lda color
            repeat:
            ldy #table
            bsr paint
            bsr paint
            bsr paint
            bsr paint
            lda color
            adda #$10
            ora #$80
            sta color
            sync ; slow it down
            sync
            sync
            sync
            jmp repeat ; keep doing it for fun
            ; rts

            clear:
            ldx #screen
            loop@:
            sta ,x+
            cmpx #screen+32*16
            bne loop@

            opt cc

            ;
            ; paint:
            ; y table: address, count, offset
            ;
            paint:
            ldx ,y++ ; address
            ldb ,y+ ; count
            pshs b
            ldb ,y+ ; offset
            opt cc
            loop@:
            sta ,x
            adda #$10
            ora #$80
            leax b,x
            dec ,s
            bne loop@
            puls b,pc

            end start

            [/php]

  5. Pingback: Color BASIC Attract Screen – part 5 | Sub-Etha Software

Leave a Reply to Allen HuffmanCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.