0

I just can't figure out how to code a simple sleep/delay cycle in gbz80 "assembly"

I must confess that my gbz80 knowledge virtually none, but I was thinking something like:

ld bc,XXX
call WaitCyclEx

WaitCyclEx:
        ld bc,(&FF05)
        dec bc
        jr nz,WaitCyclEx
   ret

The idea behind that was that by modifying the "bc" register value, once called the "WaitCyclEx" function the value would have been loaded in register FF05, which is the timer counter, and the only counter of the gbz80. Then the value is decremented and the function gets repeated until the value reaches zero.

To know if the cycle is working I've added some sound like this...

;some noise
ld a,%00010101
ld (&FF10),a
ld a,%10010110
ld (&FF11),a
ld a,%01110011
ld (&FF12),a
ld a,187
ld (&FF13),a
ld a,%10000101
ld (&FF14),a
;delay
ld bc,65535 ; loading the "wait time" value
call WaitCyclEx
;some noise again
ld a,%00010101
ld (&FF10),a
ld a,%10010110
ld (&FF11),a
ld a,%01110011
ld (&FF12),a
ld a,187
ld (&FF13),a
ld a,%10000101
ld (&FF14),a

di
halt

According to vasm everything works... but I'm hearing only one sound instead of two...

Considering the 4Mhz of the processor, repeating the cycle 65535 times should at least give me the time to notice a slight delay between the two sounds...

Any help will be really appreciated

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • According to my quick calculation that's less than 0.02 seconds. I would try some longer delay to be sure you can hear it. – Jester Feb 02 '22 at 14:45
  • 2
    Welcome to StackOverflow! You have taken the [tour], bravo! Only a few new contributors do this. However, your question lacks some sign of effort on your own. -- Since you "_confess that my gbz80 knowledge [is] virtually none_", I'm afraid that you need to gain some. Some of your ideas in the delay subroutine are wrong: 1. `ld bc,(&FF05)` _loads_ BC, if it would exist at all. 2. `dec bc` sets no flag, so you cannot check for zero. -- I suggest to read the tutorials and the documentation on the instruction set. If you keep having a problem, feel free to post another question. – the busybee Feb 02 '22 at 14:45
  • Also single-step your code in a simulator with a debugger; that's huge for learning asm and seeing what instructions do. – Peter Cordes Feb 02 '22 at 15:12
  • Just an FYI, the Game Boy has special commands just for loading from memory range `&FF00-&FFFF`. Since you're trying to delay it might not be the best option, but if your assembler doesn't optimize your syntax, you may be wasting bytes without realizing it. You might want to look at your emulator's disassembly – puppydrum64 Feb 01 '23 at 15:31

1 Answers1

2

You have a few issues, so I'll instead give some working code and hopefully you can use that to do what you want.

Unlike their 8-bit counterparts, the 16-bit increments and decrements don't affect the z flag. There are a few ways around this:

    ld bc,XXXX
WaitCyclEx:
    dec bc
    ld a,b
    or c      ; if B and C are 0, then ORed together they'll be zero, setting the Z flag
    jr nz,WaitCyclEx
   ret

Instead of just delays, you may be interested in 16-bit looping in general. For delays, size optimizations are appropriate, but general looping might warrant speed optimization. Here is a loop that has BC as a counter, but swaps the role of B and C to take advantage of djnz in the inner loop:

    ld bc,XXXX
    dec bc
    inc b
    inc c 
    ld a,b
    ld b,c
    ld c,a
loop:
    ; <do stuff>
    djnz loop
    dec c
    jr nz,loop
   ret

I can't remember if the GB Z80 has the cpi and cpd instructions, but if it does, you can use those to increment/decrement HL and use BC as a loop counter:

    ld bc,XXXX
loop:
    ; do stuff
    cpi
    jp pe,loop
    ret
Zeda
  • 382
  • 4
  • 13