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:
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”.
BPL – branch if plus. Is this basically a branch if the high bit is not set?
I assume STA -1,X is faster than LEAX?
Added your updates. Neat! Thanks!
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
I see now that William already suggested the same thing…
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.
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.
You mean doing multiple bytes at a time rather than one at a time
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.
Is SYNC what I’m looking for to make the screen not tear during updates? Or am o just seeing that from emulation?
Is this function to rotate the attract screen border in the last post?
Why, yes it is. It is indeed.
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.
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.
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
What is the purpose of sync?
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
Ah, sync for delay. Gotcha. I’ll compile all of these various tips and suggestions in to a follow up. Can’t wait to try them out.
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+3214
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]
And this, people and other people (I do miss “ladies and gentlemen”) is how we slowly build the ultimate attract border screen.
Pingback: Color BASIC Attract Screen – part 5 | Sub-Etha Software