Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > ACME macro for delaying X cycles
2017-10-24 13:02
Frantic

Registered: Mar 2003
Posts: 1627
ACME macro for delaying X cycles

Anybody got an macro handy for the ACME assembler for delaying X number of cycles? It is OK if it kills the A or X register.
 
... 21 posts hidden. Click here to view all posts....
 
2017-10-24 13:13
Frantic

Registered: Mar 2003
Posts: 1627
Thanks!
2017-10-24 14:35
ChristopherJam

Registered: Aug 2004
Posts: 1378
np.

Also this:
#define wait_min24(x) lda#88-x:jsr waitN

waitN
	sta *+4
	bne *+2
	.dsb 64,$a9
	lda $ea
	rts
2017-10-24 15:54
TWW

Registered: Jul 2009
Posts: 541
And this (part of my delay pseudo) ;-)

  .if(cycles.getValue()==15) {
    pha         // 3
    nop         // 2
    nop         // 2
    nop         // 2
    nop         // 2
    pla         // 4 <- 15 cycles | 6 bytes
  }

  .if(cycles.getValue()==16) {
    pha         // 3
    pha         // 3
    nop         // 2
    pla         // 4
    pla         // 4 <- 16 cycles | 5 bytes
  }

  .if(cycles.getValue()==17) {
    pha         // 3
    pha         // 3
    bit $00     // 3
    pla         // 4
    pla         // 4 <- 17 cycles | 6 bytes
  }

  .if(cycles.getValue()==18) {
    pha         // 3
    pha         // 3
    nop         // 2
    nop         // 2
    pla         // 4
    pla         // 4 <- 18 cycles | 6 bytes
  }

  .if(cycles.getValue()==19) {
    pha         // 3
    pha         // 3
    nop         // 2
    bit $00     // 3
    pla         // 4
    pla         // 4 <- 19 cycles | 7 bytes
  }

  .if(cycles.getValue()==20) {
    pha         // 3
    pha         // 3
    nop         // 2
    nop         // 2
    nop         // 2
    pla         // 4
    pla         // 4 <- 20 cycles | 7 bytes
  }

  .if(cycles.getValue()==21) {
    pha         // 3
    pha         // 3
    pha         // 3
    pla         // 4
    pla         // 4
    pla         // 4 <- 21 cycles | 6 bytes
  }

  .if(cycles.getValue()==22) {
    pha             // 3
    lda #%00000010  // 2
    lsr             // 2 2
    nop             // 2 2
    bcc *-2         // 3 2
    pla             //   4 <- 22 cycles | 8 bytes
  }

  .if(cycles.getValue()==23) {
    pha             // 3
    lda #%00000100  // 2
    lsr             // 2 2 2
    bcc *-1         // 3 3 2
    pla             //     4 <- 23 cycles | 7 bytes
  }

  .if(cycles.getValue()==24) {
    pha         // 3
    pha         // 3
    pha         // 3
    bit $00     // 3
    pla         // 4
    pla         // 4
    pla         // 4 <- 24 cycles | 8 bytes
  }

  .if(cycles.getValue()==25) {
    pha             // 3
    lda #%00000100  // 2
    lsr             // 2 2 2
    bcc *-1         // 3 3 2
    nop             //     2
    pla             //     4 <- 25 cycles | 8 bytes
  }

  .if(cycles.getValue()==26) {
    pha         // 3
    pha         // 3
    pha         // 3
    nop         // 2
    bit $00     // 3
    pla         // 4
    pla         // 4
    pla         // 4 <- 26 cycles | 9 bytes
  }

  .if(cycles.getValue()==27) {
    pha         // 3
    pha         // 3
    pha         // 3
    nop         // 2
    nop         // 2
    nop         // 2
    pla         // 4
    pla         // 4
    pla         // 4 <- 27 cycles | 9 bytes
  }

  .if(cycles.getValue()==28) {
    pha             // 3
    lda #%00001000  // 2
    lsr             // 2 2 2 2
    bcc *-1         // 3 3 3 2
    pla             //       4 <- 28 cycles | 7 bytes
  }

  .if(cycles.getValue()==29) {
    pha             // 3
    lda #%00000100  // 2
    lsr             // 2 2 2
    nop             // 2 2 2
    bcc *-2         // 3 3 2
    pla             //     4 <- 29 cycles | 8 bytes
  }

  .if(cycles.getValue()==30) {
    pha             // 3
    lda #%00001000  // 2
    lsr             // 2 2 2 2
    bcc *-1         // 3 3 3 2
    nop             //       2
    pla             //       4 <- 30 cycles | 8 bytes
  }

  .if(cycles.getValue()==31) {
    pha             // 3
    lda #%00001000  // 2
    lsr             // 2 2 2 2
    bcc *-1         // 3 3 3 2
    bit $00         //       3
    pla             //       4 <- 31 cycles | 9 bytes
  }

  .if(cycles.getValue()==32) {
    pha             // 3
    lda #%00001000  // 2
    lsr             // 2 2 2 2
    bcc *-1         // 3 3 3 2
    nop             //       2
    nop             //       2
    pla             //       4 <- 32 cycles | 9 bytes
  }

  .if(cycles.getValue()==33) {
    pha             // 3
    lda #%00010000  // 2
    lsr             // 2 2 2 2 2
    bcc *-1         // 3 3 3 3 2
    pla             //         4 <- 33 cycles | 7 bytes
  }

  .if(cycles.getValue()==34) {
    pha             // 3
    lda #%00001000  // 2
    lsr             // 2 2 2 2
    bcc *-1         // 3 3 3 2
    nop             //       2
    nop             //       2
    nop             //       2
    pla             //       4 <- 34 cycles | 10 bytes
  }

  .if(cycles.getValue()==35) {
    pha             // 3
    lda #%00010000  // 2
    lsr             // 2 2 2 2 2
    bcc *-1         // 3 3 3 3 2
    nop             //         2
    pla             //         4 <- 35 cycles | 8 bytes
  }

  .if(cycles.getValue()==36) {
    pha             // 3
    lda #%00001000  // 2
    lsr             // 2 2 2 2
    nop             // 2 2 2 2
    bcc *-2         // 3 3 3 2
    pla             //       4 <- 36 cycles | 8 bytes
  }
2017-10-24 17:04
lft

Registered: Jul 2007
Posts: 369
Quoting ChristopherJam

;minimal bytes

...
; 6 cycles (3 bytes)
    nop
    nop
    nop


The following is more minimal. =)

; 6 cycles (2 bytes)
    cmp (0,x)


The routines for 8, 12 and 13 cycles can be shortened with the same technique.
2017-10-24 21:22
Frantic

Registered: Mar 2003
Posts: 1627
Thanks all!

@lft: cool. Wasn't aware of that one.
2017-10-25 00:23
chatGPZ

Registered: Dec 2001
Posts: 11108
i'd refrain from using branches in those macros... or atleast have guards that give warnings (or even adjust the macro accordingly) when the branch crosses a page boundary. without you will get nice heisenbugs that appear and disappear randomly when you add/remove code :)
2017-10-25 01:35
Kruthers

Registered: Jul 2016
Posts: 21
Can't help posting my "stable" delay macro, though it's 64tass not ACME. Maybe somebody will find it useful. It allows you to tweak the delay without causing code to shift around because it always uses 8 bytes. Alas, it can't do 2 or 4 cycles...

Only real regret is that it sometimes needs to trash a ZP location. And branching is not optional of course. Liberal use of ".option allow_branch_across_page" helps. :)

; macro to generate delay in cycles, always using 8 bytes
; requires the x or y register and one zeropage location which may be trashed
;
; usage: #delay8b 1282, y, $02
;        #delay8b 23, x, $ff
delay8b     .macro cycles, reg, zp
                ; validation
                .cerror (\cycles < 3 || \cycles == 4), "8-byte-delay cannot be 1, 2 or 4 cycles"
                .cerror (\cycles > 1282), "8-byte-delay must be less than 1283 cycles"
                .cerror (\reg != "x" && \reg != "y"), "Unknown register", \reg
                .cerror (\zp < $00 || \zp > $ff), "Zeropage argument is required"
                ; 3 to 10 cycles are hard coded
                .switch \cycles
                .case 3
                    jmp *+8
                    bit \zp
                    bit \zp
                    nop
                .case 5
                    nop
                    jmp *+7
                    bit \zp
                    bit \zp
                .case 6
                    bit \zp
                    jmp *+6
                    bit \zp
                    nop
                .case 7
                    nop
                    nop
                    jmp *+6
                    bit \zp
                    nop
                .case 8
                    nop
                    bit \zp
                    jmp *+5
                    bit \zp
                .case 9
                    bit \zp
                    bit \zp
                    jmp *+4
                    nop
                .case 10
                    nop
                    nop
                    bit \zp
                    jmp *+4
                    nop
                ; 11 or more cycles follows a repeating pattern
                .default
                    ; determine number of each operation
                    loop := (\cycles - 4) / 5
                    n_nop := 1
                    n_bit := 0
                    n_ldy := 0
                    n_jmp := 0
                    n_inc := 0
                    .if (\cycles % 5) == 0
                        n_ldy := 1
                    .elsif ((\cycles - 1) % 5) == 0
                        n_bit := 1
                    .elsif ((\cycles - 2) % 5) == 0
                        n_nop := 3
                    .elsif ((\cycles - 3) % 5) == 0
                        n_inc := 1
                    .elsif ((\cycles - 4) % 5) == 0
                        n_nop := 0
                        n_jmp := 1
                    .endif
                    ; write out the code
                    ; extra ldy (or ldx)
                    .if n_ldy > 0
                        .if \reg == "y"
                            ldy #($100-loop)
                        .else
                            ldx #($100-loop)
                        .endif
                    .endif
                    ; loop
                    .if \reg == "y"
                        ldy #($100-loop)
                        iny
                    .else
                        ldx #($100-loop)
                        inx
                    .endif
                    bne *-1
                    ; bit
                    .if n_bit
                        bit \zp
                    .endif
                    ; nops
                    .rept n_nop
                        nop
                    .next
                    ; inc
                    .if n_inc
                        inc \zp
                    .endif
                    ; jmps
                    .if n_jmp
                        jmp *+3
                    .endif
                .endswitch
            .endm
2017-10-25 05:29
TWW

Registered: Jul 2009
Posts: 541
@ GPZ: That is a good point. Straight fwd. to add an assertion based on .pc.

@lft: Nice one. Will shamelessly update my routines with this one, saving a byte where I can ;-)

Forgot to say the other criteria for me was to leave the registers untouched and used simply as :DELAY 5
2017-10-25 07:13
ChristopherJam

Registered: Aug 2004
Posts: 1378
Actually, no one should ever use my wait_min24 from above on a 6510, unless they have ideological objections to unintended opcodes.

This is better; covers shorter delays and doesn't clobber any registers or flags. Still requires two bytes of stack.
#define wait_min14(x) jsr wait14+14-(x)

    .dsb 64,$80   ; NOP#nn
    .byt $04      ; NOP zp
wait14
    nop
wait12
    rts


(if you don't like illegals, replace the NOPs with BITs, and you get one that preserves registers but not flags..)

oh, and lft, thanks for the cmp (0,x)!
2017-10-25 21:58
doynax
Account closed

Registered: Oct 2004
Posts: 212
@lft: Cute, but beware of inadvertently touching I/O register with side-effects on read (i.e. $DC0D or $DD0D).
Previous - 1 | 2 | 3 | 4 - Next
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Matt
iAN CooG/HVSC
Freeze/Blazon
kbs/Pht/Lxt
Guests online: 126
Top Demos
1 Next Level  (9.8)
2 Mojo  (9.7)
3 Coma Light 13  (9.7)
4 Edge of Disgrace  (9.6)
5 Comaland 100%  (9.6)
6 No Bounds  (9.6)
7 Uncensored  (9.6)
8 Wonderland XIV  (9.6)
9 Bromance  (9.6)
10 Memento Mori  (9.6)
Top onefile Demos
1 It's More Fun to Com..  (9.7)
2 Party Elk 2  (9.7)
3 Cubic Dream  (9.6)
4 Copper Booze  (9.5)
5 Rainbow Connection  (9.5)
6 TRSAC, Gabber & Pebe..  (9.5)
7 Onscreen 5k  (9.5)
8 Wafer Demo  (9.5)
9 Dawnfall V1.1  (9.5)
10 Quadrants  (9.5)
Top Groups
1 Oxyron  (9.3)
2 Nostalgia  (9.3)
3 Booze Design  (9.3)
4 Censor Design  (9.3)
5 Crest  (9.3)
Top Organizers
1 Burglar  (9.9)
2 Sixx  (9.8)
3 hedning  (9.7)
4 Irata  (9.7)
5 MWS  (9.6)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.054 sec.