3

I'm new to ASM and I trying to workout how to create a delay for the following code:

org $1000

loop: inc $d021
    jmp loop
Michael
  • 57,169
  • 9
  • 80
  • 125
icodenosleep
  • 49
  • 1
  • 5

4 Answers4

7

Comments are clear enough i guess.

Code sample for changing color each frame (1/50 of a second)

        sei       ; enable interrupts

loop1:  lda #$fb  ; wait for vertical retrace
loop2:  cmp $d012 ; until it reaches 251th raster line ($fb)
        bne loop2 ; which is out of the inner screen area

        inc $d021 ; increase background color

        lda $d012 ; make sure we reached
loop3:  cmp $d012 ; the next raster line so next time we
        beq loop3 ; should catch the same line next frame

        jmp loop1 ; jump to main loop

Code sample for changing color each second

counter = $fa ; a zeropage address to be used as a counter

        lda #$00    ; reset
        sta counter ; counter

        sei       ; enable interrupts

loop1:  lda #$fb  ; wait for vertical retrace
loop2:  cmp $d012 ; until it reaches 251th raster line ($fb)
        bne loop2 ; which is out of the inner screen area

        inc counter ; increase frame counter
        lda counter ; check if counter
        cmp #$32    ; reached 50
        bne out     ; if not, pass the color changing routine

        lda #$00    ; reset
        sta counter ; counter

        inc $d021 ; increase background color
out:
        lda $d012 ; make sure we reached
loop3:  cmp $d012 ; the next raster line so next time we
        beq loop3 ; should catch the same line next frame

        jmp loop1 ; jump to main loop
Emir Akaydın
  • 5,708
  • 1
  • 29
  • 57
  • You can use Y instead of zero page and A. And instead of incrementing the counter, decrement it, so you can implicitly BNE on Y. Shorter, faster, more idiomatic. See my edit request. – youri Aug 29 '14 at 19:16
  • Since i love to code 256 bytes intros, i use many more tricks like self modifying code, illegal opcodes, shared register values etc. But this code sample is specially written for someone who said "I'm new to ASM". So, this is neither size nor cycle optimized source code. This is a code sample for beginners and i believe reversed loops may confuse them. – Emir Akaydın Sep 02 '14 at 15:41
  • I'd argue using zero-page makes is more complicated than using the Y register, regardless of how you loop (reverse or forward), specially if A is used for 2 purposes. My suggestion was not to reduce code size or the number of cycles (that's a side effect) but rather to increase readability. Maybe using the Y register forward, with an explicit CPY, would have made an even nicer beginner solution. – youri Sep 03 '14 at 08:41
0

for example:

loop: ldx $d021
      inx
      stx $d021
      cpx #100
      bne loop
user2699113
  • 4,262
  • 3
  • 25
  • 43
  • This doesn't change $d021 once per second, it changes it once every 15 cycles until its' value is #100 (which is entirely variable since we don't know what is in $d021 to start with). – Eight-Bit Guru Feb 09 '14 at 12:49
  • On the very beginning user3049038 wrote only about loop so I wrote a loop for him. There were nothing more info about that $d021 is HW register - so my answer is correct. – user2699113 Feb 10 '14 at 05:03
  • $D020/01 are very well known adresses for us dinosaurs. Especially in conjunction with a 6502/10. ;) – Devolus Feb 10 '14 at 06:47
  • Maybe for C64 dinos. I have Atari 800xl so I don't know this register :) – user2699113 Feb 10 '14 at 06:50
0

How about this? This should change the background, wait 4 seconds, then change it again. Repeat forever.

Note, you can change the number of seconds to anything from 0 to 255.

This is for NTSC machines but you can change the 60 to 50 for PAL.

main:
    inc $D021

    ldx #4          //  Wait 4 seconds
loop1:
    ldy #60
loop2:

waitvb:
    bit $D011
    bpl waitvb
waitvb2:
    bit $D011
    bmi waitvb2

    dey
    bne loop2
    dex
    bne loop1

    jmp main
cbmeeks
  • 11,248
  • 22
  • 85
  • 136
0

If you can ensure that the code doesn't cross a page boundary, a useful approach is to have a pair of bytes somewhere in RAM which will hold a computed jump address, and use an indirect jump into something like the following:

TableStart:
    cmp #$C9
    cmp #$C9
    cmp #$C9
    cmp #$C9
    cmp #$C9
    ...
TableEnd:
    nop

If the jump vector points to tableEnd, code will reach the instruction after the NOP after seven cycles. If it points one byte earlier, eight cycles. Two bytes earlier, nine cycles, etc. Setting up the jump vector may take a little while, but the delay itself will be smoothly adjustable from seven cycles to any higher value in single-cycle increments. Flags will be trashed, but no registers will be affected.

supercat
  • 77,689
  • 9
  • 166
  • 211