I'm trying to conver this ACME asm script to Kick Assembler syntax.
This is what i've made:
.macro Wait (v) {
ldy #v
dey
bne *-1
}
* = $0801
.byte $0c, $08, $00, $00, $9e, $32, $30, $36, $31, $00, $00, $00
* = $080d
lda #$01
sta $3fff
sei
start:
lda #$30
cmp $d012
bne *-3
lda #$00
sta $d011
Wait(24)
lda #$0b
sta $d011
lda #$31
cmp $d012
bne *-3
lda #$1b
sta $d011
Wait(8)
bit $ea
ldx #$00
loop1:
txa
sta $d020
sta $d021
Wait(9)
inx
cpx #254
bne loop1
asl $3fff
bne start
inc $3fff
jmp start
Unfortunately it displays:
I dont' understand actually 2 things:
Lastly: I've tried out of curiosity to remove the macro, and it shows screen without border, but in the upper part i got rasterlines:
Hope it helps to clearify my question. Thanks for any advice!
EDIT - as per Emir advices:
this is my new code attempt, mixed with your first snippet, it's useful since the sprite can be moved with joystick to test (horizonthal on the right i still didn't fixed the 255 limit, so it will reapper on the left in case moving on the far right...). Actually tried to follow your suggestion but probably did something wrong so end up with this "almost" working result:
* = $0801
BasicUpstart($080d);
.label JOYSTICK_2 = $dc00
.label UP = %00000001
.label DOWN = %00000010
.label LEFT = %00000100
.label RIGHT = %00001000
.label FIRE = %00010000
.label JOYSTICK_2_IDLE = %01111111
.label SCREEN_RAM = $0400
.label SCREEN_CLEAR = $e544
.label SCREEN_BORDER_COLOR = $d020
.macro WAIT(duration) {
ldy #duration
dey
bne *-1
}
* = $080d
lda #150
sta $d000 // X position of sprite 0
lda #230
sta $d001 // Y position of sprite 0
lda #LIGHT_RED
sta $d027 // Sprite 0 color
lda #BLACK
sta $d025 // Sprite extra color 1
lda #WHITE
sta $d026 // Sprite extra color 2
lda #$80
sta $07f8 // Sprite 0 sprite pointer index
lda #%00000001 // Enable multicolor for sprite 0
sta $d01c
lda #%00000001 // Enable sprite 0
sta $d015
lda #$01
sta $3fff
sei
start:
lda #$fa
cmp $d012
bne *-3
lda #$00
sta $d011
WAIT(22)
lda #$1b
sta $d011
jsr gameLoop
/*
loop1:
txa
sta $d020
sta $d021
WAIT(9)
inx
cpx #254
bne loop1
asl $3fff
bne start
inc $3fff
jmp start*/
gameLoop:
ldx #0
slowDownLoop:
nop
nop
nop
nop
nop
nop
nop
nop
inx
cpx #255
bne slowDownLoop
jsr readJoystick_2
//jmp gameLoop
//
jsr start
readJoystick_2:
lda JOYSTICK_2 // $dc00
cmp #JOYSTICK_2_IDLE // %01111111
beq joy2_IDLE
jmp checkJoy2_UP
joy2_IDLE:
checkJoy2_UP:
lda JOYSTICK_2
and #UP
beq joy2_UP
jmp checkJoy2_DOWN
joy2_UP:
dec $d001
checkJoy2_DOWN:
lda JOYSTICK_2
and #DOWN
beq joy2_DOWN
jmp checkJoy2_LEFT
joy2_DOWN:
inc $d001
checkJoy2_LEFT:
lda JOYSTICK_2
and #LEFT
beq joy2_LEFT
jmp checkJoy2_RIGHT
joy2_LEFT:
dec $d000
checkJoy2_RIGHT:
lda JOYSTICK_2
and #RIGHT
beq joy2_RIGHT
jmp checkJoy2_FIRE
joy2_RIGHT:
inc $d000
checkJoy2_FIRE:
lda JOYSTICK_2
and #FIRE
beq joy2_FIRE
jmp doneReadJoystick_2
joy2_FIRE:
inc SCREEN_BORDER_COLOR
doneReadJoystick_2:
rts
*=$2000
.import binary "testGuy.bin"
The "testGuy.bin" is a trivial sprite (i'll link here for complete test anyways).
Anyways the sprite is capable to overlap upper\lower borders, but there are black vertical lines artifacts:
Can u help me solve this? Regards!
EDIT 2: this finally did the trick!
lda #$00
sta $3fff
Case closed!
The script you are trying disables the screen without opening the borders. Benefit is having stable timing and not dealing with DMA lines. You can use border/screen colors, sprites and ghost byte ($3fff in this code example) to draw things even if screen seems to be disabled.
If you want to open borders, the code you need is very similar (you can find it below the answers). I removed unnecessary parts to have stable raster timings since raster timings are harder to deal with when the screen is open. You will notice raster flickering. They are easy to avoid using timing tables and stable raster IRQ tricks. But i'll focus on your questions.
There is nothing to fix. It's supposed to work like this. The version i shared below opens upper/lower borders with a very similar method but at bottom border position instead of top border (which are top=$32, bottom=$fa). You'll notice that ghost byte is now shown in upper and lower borders only. Since we don't disable the inner screen now (we still could), inner screen doesn't show ghost byte. You can put sprites to upper/lower borders or inner screen area if you want.
$080d is your code entry point. You can of course change it to any address, use labels for start address etc. Only static address in this case is $0801, which is default basic startup address. You don't need $0801 at all. You can load the PRG file and run your code with a SYS command. $0801 is only there to make things easier and serves you as an autorun mechanism, nothing else.
What that macro does is just to wait, spend cycles while screen is being drawn. When you skip waiting, code runs as fast as it can and you see shorter splitted raster colors. Every 8 pixel character area equivalent to a CPU cycle. So, let's say we started changing colors using back to back STA/STX opcodes like STA $d021, STX $d021, STA $d021, STX $d021 while A and X registers are having two different color codes. Screen color will change every four character wide area, in other words every 32 pixels. This is why STA/STX opcodes take 4 cycles to operate. This is how things work. That WAIT macro waits for correct raster positions to operate things at the right place.
That WAIT macro is not required. You can simply inline the same code (LDY, DEY, BNE opcodes) to the places where macro is used. Macros just helps us with repeating codes, very similar to inlined functions. If it's a distraction for you, just ignore them, inline the codes, get rid of macro usage.
Here is the modified code which opens the upper/lower borders and doesn't disable inner screen.
* = $0801
BasicUpstart($080d);
.macro WAIT(duration) {
ldy #duration
dey
bne *-1
}
* = $080d
lda #$01
sta $3fff
sei
start:
lda #$fa
cmp $d012
bne *-3
lda #$00
sta $d011
WAIT(22)
lda #$1b
sta $d011
loop1:
txa
sta $d020
sta $d021
WAIT(9)
inx
cpx #254
bne loop1
asl $3fff
bne start
inc $3fff
jmp start
Here is another alternative version with open borders and closed inner screen with stable timings.
* = $0801
BasicUpstart($080d);
.macro WAIT(duration) {
ldy #duration
dey
bne *-1
}
* = $080d
lda #$01
sta $3fff
sei
start:
lda #$fa
cmp $d012
bne *-3
lda #$00
sta $d011
WAIT(22)
lda #$0b
sta $d011
loop1:
txa
sta $d020
sta $d021
WAIT(9)
inx
cpx #254
bne loop1
asl $3fff
bne start
inc $3fff
jmp start