This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

ASM indentation style

ASM indentation style
by on (#231119)
Hi.

I hate how I indent my assembly code. I helps readability, but I am very inconsistent.
Basically I tend to increase the indent when it feels like a proper branch or a loop (as if it would be one in higher level languages like C) but I tend not to indent when it is simply a random jump target.
I don't want to use unnamed labels. I like how I see my labels in the debugger, it is very useful to me.

This is what it looks like, and I dont like it!

Code:
some_loop: ; this is a loop, so i tend to indent here.

   lda test
   bmi test_is_negative

   test_is_positive: ; feels like a legit branch, so both if/else are indented.
      inc test_is_minus
      jmp resume
   test_is_negative:
      dec test_is_minus

   resume: ; this label feels ugly.
   dec count
   bne some_loop


How do you guys do it? Again, i dont want unamed labels.

-Mat
Re: ASM indentation style
by on (#231121)
What about it in particular that you don't like? That's there indenting at all? or that the indenting dosn't intuitively hint at execution structures (like if else, while etc)?

From what I seen, what you have is how other people indent their code, if they indent 6502 asm at all.

The most common style is essentially unindented:
Code:
subroutine:
some_loop:
    lda test
    bmi test_is_negative
    inc test_is_minus
    jmp end_test
test_is_negative:
    dec test_is_minus
end_test:
    dec count
    bne some_loop
    rts


As for myself here's how I go about indenting things (you can adopt as much or as little of this as you want)
Code:
; two spaces for each intent level due to me sometimes being in 3 or 4 levels deep in IF and LOOPS
subroutine:  ; top level for global label intended to be called by outside code
  pha  ; pha and pla introduces a indent level
    lda test1
    beq skip_everything  ; forward branches inside a subroutine indents forward until the label
      ldy count
      loop:  ; labels from backward branches indents until the branch
        lda test3
        bmi else_is_negative  ; this is a if else structure which has a somewhat special way of indenting
        is_positive:  ; A label to remind me what the condition was to get here, also makes it easier to reorder blocks of code
          inc sum
        jmp endif  ; outside of the if else structure I generally unindent jmp and rts. Even if it's in the middle of the code.
        else_is_negative:
          dec sum
        endif:
        dey
      beq loop
      lda sum
      beq no_save
        sta saved_sum
      no_save:  ;  all branches goes to unique labels, even if they are at the same PC.
    skip_everything:
  pla
rts  ; rts ends the subroutine block so I unindent.


From then I occasionally add a blank line between sections of code that otherwise don't have branches.

There are exceptions of course, especially when I optimize branch ordering for speed.

Edit: Spelling corrections
Re: ASM indentation style
by on (#231123)
I usually don't indent since this is something I'm used for high level language like c, java etc. For asm, I tend to put blank lines to separate group of action of if it refer to a specific processing.

Here an example of a helper function (that is a little long) used while fading the palette at a specific step. The reason a take a longer one is to show what I mean by blank lines:

Code:

;->BEGIN----------------------------------------------------------------------
;
; Helper function that apply a value on the palette for a specific range
;
; note:
; - most locals are set from calling function
; - 'A' contains decrement
;
.proc subFadeStep
;---------------- Parameters definitions ----------------
.scope local
    paletteAdr  = zpTemp     ; adress of source palette
    steps       = zpTemp+2   ; how many color to change
    start       = zpTemp+3   ; where to start in palette
    decrement   = zpTemp+4   ; to remove by how much
    waitFrames  = zpTemp+5   ; How many frame to wait at the end of 1 step
    useVBlank   = zpTemp+6   ; use vblank instead of nmi for waiting   
.endscope
;---------------------------------------------------------

    sta local::decrement            ; save decrement from calling function

    ldx local::steps                ; load counter
    ldy local::start                ; load target start position

    lda #$00
    sta zpPaletteUpdateFlag         ; set flag to disable palette update

loop:
    lda (local::paletteAdr),y       ; load color from buffer
    sec
    sbc local::decrement            ; if carry clear, out of bound
    bcs colorNotOutsideBound        ; no, was not, use new color value
   
    lda #$0F                        ; when outside bound, set to black by default

colorNotOutsideBound:
    cmp #$0D                        ; Edge case: check if blacker than black
    bne notBlackerThanBlack         ; no it's not, skip that step
    lda #$0F                        ; it is, use $0F instead

notBlackerThanBlack:   
   
    sta palBuffer, y                ; store in buffer for nmi
    iny                             ; go next step in buffer
    dex                             ; reduce counter
    bne loop                        ; not end of counter? do next color

    inc zpPaletteUpdateFlag         ; set flag to update palette

    ldx local::waitFrames           ; load frames to wait

    lda local::useVBlank            ; check which way to wait
    bne whileWaitVBlank             ; use vblank intead

whileWaitNmiFrame:
    jsr subWaitNmi                  ; Use NMI to wait frame

    dex
    bne whileWaitNmiFrame           ; If not 0, still some frames to wait

    rts

whileWaitVBlank:
    jsr subWaitVBlank               ; Use vblank instead

    dex
    bne whileWaitVBlank             ; If not 0, still some frames to wait

    rts

.endproc
;-<END------------------------------------------------------------------------


But formatting code is something personal and that you define with time. The only time you will want everyone to make it all the same is while working at a company: if you don't, trying to read other people code and managing it will be quite hell ^^;;
Re: ASM indentation style
by on (#231124)
I generally use what amounts to the same style as bleubleu, with 2 spaces, without dedenting jump/branch the way JRoatch does. I even built a preprocessor for RGBASM (Game Boy assembler), which expects all labels to start in column 1, to be able to keep this indent style.

Indentation is slightly more important in assembly than in C, as I'm not aware of any automated way to determine block structure in assembly. In C, on the other hand, there exist numerous indent filters.
Re: ASM indentation style
by on (#231125)
The whole concept of indenting feels misguided. Assembly doesn't nest, and the control flow it produces often jumps around in a way that can't be represented with indentations (i.e. the control flow is irreducible). The moment you break the indentation rules for an unusual jump, the advantage of indenting goes out the window because it's not consistent anymore.
Re: ASM indentation style
by on (#231126)
Indentation resembling that associated with block-structured languages at least shows readers of your code that you're trying to adhere to the principles of structured programming with early exit to the extent possible in assembly language.
Re: ASM indentation style
by on (#231127)
bleubleu wrote:
How do you guys do it?

Simple: I don't.
Re: ASM indentation style
by on (#231128)
pubby wrote:
Assembly doesn't nest, and the control flow it produces often jumps around in a way that can't be represented with indentations (i.e. the control flow is irreducible). The moment you break the indentation rules for an unusual jump, the advantage of indenting goes out the window because it's not consistent anymore.

I don't believe there is a way to indent assembly in any 100% consistent way.

However, I feel there's a lot of value in visual information from indentation, and just because some cases won't fit a structure exactly doesn't mean that it can't be helpful to indicate cases that do, and can even apply in a useful way to cases that don't quite.

In most cases, I add an indent after a branch, and that indent will end at the end of the code it jumps to. For "if, else" style, there's a brief break in the indent at the else. This makes the length of the branch and its structure instantly readable visually, and I can quickly skim to the end of the structure without having to read the code in between. These two cases covers probably 95% of indents in my assembly code. Especially when nesting simple decision branches within a larger if/else, this make it very easy to see the hierarchy and extent of what's happening there. (typical example)

Sometimes it gets weird, and I'll make a decision whether to indent or not. It's not necessarily consistent with the rest of my code, but this is because assembly code structures are not consistent. I simply make a decision about how I think I would best read the indent when I'm trying to come back to this code in the future, and leave it that way. Sometime that means a flat/unindented style. Sometimes that means indents that don't match other uses quite. Sometimes that means an extra comment or two to clarify.

The bottom line is that the indents are there to make something easy to read. They're not information for a computer or a compiler, so they don't need to fit some formal and absolute definition of structure. The tabs are merely a visual tool.


If I was writing code that was part of a library for a company that is selling the code itself as the product, however, and not something for my own use, most likely a non-indented style would be mandated for assembly, partly for the consistency, but mostly for traditional practice. It is simply the "standard" appearance of assembly code, and probably worth using as a lowest-common-denominator that nobody would be able to say is an unexpected or irregular practice. This usage case is very different than anything I've done for the NES though.
Re: ASM indentation style
by on (#231129)
Yeah, I don't indent ASM code either. One of the advantages of using assembly is that you're not bound to the constructs of higher-level languages, so you can optimize your code in ways that are not possible in other languages. Not that I'm suggesting everyone starts writing messy spaghetti code, you should definitely try to adhere to some sort of programming style that makes sense to you, so that if you're coherent enough, your own code will always make sense to you, it's just that imposing formatting limitations that weren't even invented for this type of language can't really end well, can it?

What makes assembly particularly hard to indent is the fact that there are often several paths to a given set of instructions. In higher-level languages you have to nest all the different decisions and each one will select whether to go deeper or not, but in assembly you can move freely to any depth, different paths can merge later, it's a completely different story.

Instead of using indentation and trying to artificially make my program look like it has a structure it doesn't, what I do is write comments at the top of each block of related instructions explaining the conditions that lead to the execution of that block. I always start a new block with instructions that are the target of significant jumps/branches, so I can easily tell the paths that the logic can take. This means that I still have easily discernible blocks of logic, the difference is that they're not nested, I can move freely from block to block.
Re: ASM indentation style
by on (#231130)
Without writing a huge essay, I'll just summarize my asm style as:
I use vertical whitespace instead of horizontal whitespace to signal semantics.
Re: ASM indentation style
by on (#231132)
Code:
-   
   jsr inter_waitRaster
   jsr inter_moveOthersLeft
   jsr inter_movePlayerLeft
   jsr inter_animateSpritesNotPlayer
   dec IMZ_SpriteTimer
   bne +
   _BREAK
      lda screenSprID0   
      cmp #149+kSprBase   
      beq _doneTrample   
         lda $d001
         clc
         adc #2
         sta $d001
         inc screenSprID0               
   _doneTrample               
      lda #7         
      sta IMZ_SpriteTimer            
+  ldy #3*2
   jsr inter_compareSpriteYXLessThan
   bcs -
Is the normal way I do it. Once you get into the
A -> C,D
B -> C
C -> E,F
E -> G
F -> B
kind of chains it starts to become meaningless to do the indents for all of it. Putting an empty line after a hard jmp, effective jmp or rts is also normal for me. Sometimes you can fix it by making some parts of the code into a macro/segment and using that to keep the structure clearer, but then its obfuscated by having code hidden behind macros.

Getting into this discussion on the C64 forums usually gets heated. With people declaring the C64 doesn't have a TAB key for a reason.. to which one can shoot back with the more evolved C128 does ;)
Re: ASM indentation style
by on (#231143)
Like Oziphantom said, it becomes quite "religious" to some degree so its better to not go to deep into it ^^;; There is no perfect way but the one you feel comfortable with it. The only time you need to adhere to a style is when you work with a group of individual.
Re: ASM indentation style
by on (#231150)
I do like Rainwarrior - I indent when it helps readability. I'm not consistent with any rule, I just do whatever makes that chunk of code easier for me to read later. Sometimes that means indenting like C. Sometimes it just means lots of comments and vertical spacing.
Re: ASM indentation style
by on (#231169)
I agree with many of the points above (although not all). I indent to make conditionals and loops obvious, and also things like what's between a PHA and PLA for example. I always indent at least three spaces. One or two spaces are just enough to make it look like you just got really sloppy at vertical alignment, whereas three is pretty clear; or if the indented portion is pretty long, I might go for four, rarely five.

Blank lines are also important to readability. I hate trying to read code from the 1970's and early 80's where all the mnemonics start in the same column and there are no blank lines to visually group sets of instructions like punctuation and paragraphs do in prose.

Several years ago I realized there's a way to do nestable program flow-control structures in assembly macros without labels, even if the assembler does not provide a way to have variable arrays in the assembler itself and index into them in order to have the needed stack in the assembler itself. Since then, I've been enjoying assembly language a lot more and I've become more productive and gotten fewer bugs. In most cases, the macros assemble exactly the same thing you would do by hand, but they make the source code more readable and maintainable. In some cases you'll actually get better efficiency from the macros, just because there's greater visibility of what you're doing, which helps you spot inefficiencies in your approach. Use of the structure macros still allows the use of labels so you can jump into the middle of a program structure; but I don't do that without a really good reason. My article on it is at http://wilsonminesco.com/StructureMacros/ . There are some longer usage examples in the last 40% of my page on multitasking at http://wilsonminesco.com/multitask/, and more explanation of how the assembler does them in the program-structure chapter of my 6502 stacks treatise, at http://wilsonminesco.com/stacks/pgmstruc.html .

For your original routine above, I might write it this way:
Code:
    BEGIN
        LDA  test
        IF_POS
            INC  test_is_minus
        ELSE_
            DEC  test_is_minus
        END_IF
        DEC  count
    UNTIL_ZERO

The assembler's output would be the same. (Is "test" an input port? Or perhaps interrupts could be changing it while this loop is running?)
Re: ASM indentation style
by on (#231332)
I sort of follow what I'm used to from other languages just because it makes things easier for me to read and wrap my head around. I'm not super consistent with it but for me that's not really the point. I just want to be able to read and understand what I'm doing with the code, so with that I usually do a lot of comments and little "TODO" notes.

I'll follow Banshaku's example and show you my take on the same task. :)

Code:
BufferOffsetBackgroundPalette:

   ; a = how much to subtract from currently loaded palette.
   
   ; TODO: if the palette pointers have not been set yet, do something to handle that.
   
   ldx palette_bkg_ptr_lo
   ldy palette_bkg_ptr_hi
   
   stx curr_pointer_lo
   sty curr_pointer_hi
   
   ldx #15
   
   jmp BufferOffsetPalette
   
BufferOffsetSpritePalette:
   
   ; a = how much to subtract from currently loaded palette.
   
   ldx palette_sprites_ptr_lo
   ldy palette_sprites_ptr_hi
   
   stx curr_pointer_lo
   sty curr_pointer_hi
   
   ldx #31
   
BufferOffsetPalette:
   
   ; x = palette_buffer end index
   
   pha   ; how much to subtract
   
   lda nmi_flags
   and #NMI_UPDATE_PALETTE_CLEAR
   sta nmi_flags
   
   ldy #15
   @offsetloop:
      
      pla
      pha      ; push this for next loop iteration
      clc
      adc (curr_pointer_lo), y   ; offset palette value with a
      pha                     ; push this so we can use a for some logic
      
      ; first, lets knock down all $xE and $xF to $xD
      and #%00001111
      cmp #$0e
      bcc @no_xE
         ; we've determined that the value must be $xE or $xF
         
         ; knock it down to $xD
         pla            ; retrieve offset palette value
         and #%11110000
         ora #%00001101
         jmp @xEset
      
      @no_xE:
         pla            ; retrieve offset palette value
      @xEset:
      
      
      ; TODO: determine if the offset was positive or negative.
      ; we could do that by temporarily storing a in the buffer and digging out the initial offset by pla
      sta palette_buffer, x
      
      pla      ; retrieve original offset value
      pha      ; and push it again for next loop itteration.
      bpl @offsetispositive
         
      @offsetisnegative:
      
         lda palette_buffer, x
         cmp #$20
         bne @not20
            lda #$10
            sta palette_buffer, x
            ;jmp @offset_adjusted_by_direction
         @not20:
         
         jmp @offset_adjusted_by_direction
         
      @offsetispositive:
      
         lda palette_buffer, x
         cmp #$1d
         bne @not1d
            lda #$2d
            sta palette_buffer, x
            jmp @offset_adjusted_by_direction
         @not1d:
         cmp #$2d
         bne @not2d
            lda #$00
            sta palette_buffer, x
            ;jmp @offset_adjusted_by_direction
         @not2d:
         
         
      @offset_adjusted_by_direction:
      
      lda palette_buffer, x
      cmp #$3d+1            ; so now we check if any value goes above 3d (out of range) and cap it to either 30 or 0d
      bcc @nocap            ; is the value above 127?
         cmp #0
         bpl @nocap1
            ; if the offset was negative, this is our stop
            lda #$0d
            jmp @nocap
         @nocap1
            ; this is where we end up if the offset was positive
            lda #$30
      @nocap
      
      sta palette_buffer, x
      
      dex
      dey
      cpy #$ff
      bne @offsetloop
   
   pla      ; clean stack from original a value
   
   ; TODO: patch all sprite opacity buffers with that of the background palette buffer
   lda palette_buffer
   sta palette_buffer+16   ; seems just patching the first entry of the sprite palette buffer is enough..
   
   lda nmi_flags
   ora #NMI_UPDATE_PALETTE
   sta nmi_flags
   
   rts

I'm surprised so many people seem to not do indentation! :) For me that simply wouldn't work. My mind needs some visual aide even to just help my eye find it's way back to the right spot on the screen when going back and forth between all my source files.
Re: ASM indentation style
by on (#231343)
I don't indent code, and it barely ever caused any problems. Basically I use vertical spacing when apropriate to make up for the lack of indentation. Also I use local labels such as _loop in order to make things clearer, and sometimes _loop2 for an outer loop, etc.... I use _next when it's the equivalent to a "break" instruction in a higher level language.

One of the point of coding in assembly is not being bound by structures of higher level langusages. For example you can have two loops crossing eachother, a subroutine calling it's own end, or particular cases or stufflike that. This defeats the purpose of indenting completely.

EDIT : Sometimes I label loops according to what they do, such as _wordloop for a loop decoding words in a text, the inner loop decoding letters and the outer loop decoding the entiere line :)
Re: ASM indentation style
by on (#231379)
@pwnskar

For the lack of use of indentation, I guess it must be because I started to write assembler this way and saw code formatted this way ~25 years ago. It is possible that maybe the assembler was forcing it but I cannot tell since I was barely copying how other people were doing it in those days and my knowledge of programming was still in its infancy ^^;;;
Re: ASM indentation style
by on (#231386)
oh to be clear

ldx #8
L1
lda thing,x
sta place,x
dex
bne L1
..

Is the standard and only way it was done back in the day. Its all well and good to have modern sensibilities but when you are coding on a C64 with no TAB key, 40 columns and every character uses precious precious RAM and CPU cycles. Or a 5K 22column VIC20 or a 4K PET or APPLE ][. You keep label as short as possible <6 is the "standard"(if you are using a C64, on a 4/5K machine there is no room for labels.) Using Line editors while giving you more cpu power, makes typing painful. And when you have a 4~30mins Assemble you do everything you can to make it faster. Whitespace slows you down.

So even when we got to 80 column screens we used it as 2 40 col screens as there was no mouse, F12, PgUp PGDown, Bookmarks, autocomplete, other handy documents etc so being able to keep 1 half of the screen on variable names was very handy.

See also C
K&R style is
Code:
void myFunction(bool var) {
    some code here
}
which is nice as it cuts down the number of lines and the number of lines you need to edit and the number of lines the code need to parse etc.
These days Stroustrup style is more popular
Code:
void myFunction(bool var)
{
    some code here
}
Re: ASM indentation style
by on (#231388)
pwnskar wrote:
I sort of follow what I'm used to from other languages just because it makes things easier for me to read and wrap my head around. I'm not super consistent with it but for me that's not really the point. I just want to be able to read and understand what I'm doing with the code, so with that I usually do a lot of comments and little "TODO" notes.

I'll follow Banshaku's example and show you my take on the same task. :)

Code:
BufferOffsetBackgroundPalette:

   ; a = how much to subtract from currently loaded palette.
   
   ; TODO: if the palette pointers have not been set yet, do something to handle that.
   
   ldx palette_bkg_ptr_lo
   ldy palette_bkg_ptr_hi
   
   stx curr_pointer_lo
   sty curr_pointer_hi
   
   ldx #15
   
   jmp BufferOffsetPalette
   
BufferOffsetSpritePalette:
   
   ; a = how much to subtract from currently loaded palette.
   
   ldx palette_sprites_ptr_lo
   ldy palette_sprites_ptr_hi
   
   stx curr_pointer_lo
   sty curr_pointer_hi
   
   ldx #31
   
BufferOffsetPalette:
   
   ; x = palette_buffer end index
   
   pha   ; how much to subtract
   
   lda nmi_flags
   and #NMI_UPDATE_PALETTE_CLEAR
   sta nmi_flags
   
   ldy #15
   @offsetloop:
      
      pla
      pha      ; push this for next loop iteration
      clc
      adc (curr_pointer_lo), y   ; offset palette value with a
      pha                     ; push this so we can use a for some logic
      
      ; first, lets knock down all $xE and $xF to $xD
      and #%00001111
      cmp #$0e
      bcc @no_xE
         ; we've determined that the value must be $xE or $xF
         
         ; knock it down to $xD
         pla            ; retrieve offset palette value
         and #%11110000
         ora #%00001101
         jmp @xEset
      
      @no_xE:
         pla            ; retrieve offset palette value
      @xEset:
      
      
      ; TODO: determine if the offset was positive or negative.
      ; we could do that by temporarily storing a in the buffer and digging out the initial offset by pla
      sta palette_buffer, x
      
      pla      ; retrieve original offset value
      pha      ; and push it again for next loop itteration.
      bpl @offsetispositive
         
      @offsetisnegative:
      
         lda palette_buffer, x
         cmp #$20
         bne @not20
            lda #$10
            sta palette_buffer, x
            ;jmp @offset_adjusted_by_direction
         @not20:
         
         jmp @offset_adjusted_by_direction
         
      @offsetispositive:
      
         lda palette_buffer, x
         cmp #$1d
         bne @not1d
            lda #$2d
            sta palette_buffer, x
            jmp @offset_adjusted_by_direction
         @not1d:
         cmp #$2d
         bne @not2d
            lda #$00
            sta palette_buffer, x
            ;jmp @offset_adjusted_by_direction
         @not2d:
         
         
      @offset_adjusted_by_direction:
      
      lda palette_buffer, x
      cmp #$3d+1            ; so now we check if any value goes above 3d (out of range) and cap it to either 30 or 0d
      bcc @nocap            ; is the value above 127?
         cmp #0
         bpl @nocap1
            ; if the offset was negative, this is our stop
            lda #$0d
            jmp @nocap
         @nocap1
            ; this is where we end up if the offset was positive
            lda #$30
      @nocap
      
      sta palette_buffer, x
      
      dex
      dey
      cpy #$ff
      bne @offsetloop
   
   pla      ; clean stack from original a value
   
   ; TODO: patch all sprite opacity buffers with that of the background palette buffer
   lda palette_buffer
   sta palette_buffer+16   ; seems just patching the first entry of the sprite palette buffer is enough..
   
   lda nmi_flags
   ora #NMI_UPDATE_PALETTE
   sta nmi_flags
   
   rts

I'm surprised so many people seem to not do indentation! :) For me that simply wouldn't work. My mind needs some visual aide even to just help my eye find it's way back to the right spot on the screen when going back and forth between all my source files.

That's excellent! Probably the best that could be done without program-structure macros. With them, I might modify it to the following. Note that no labels are needed except the two I left at and near the top as entry points. Hopefully I didn't make any mistakes, as I was quickly converting the form without focusing much on the bigger picture of what the program is doing. The section of triple-nested IF's could stand some more comments.

Code:
BufferOffsetSpritePalette:       ; a = how much to subtract from currently loaded palette.

   LDX  palette_sprites_ptr_lo
   LDY  palette_sprites_ptr_hi
   
   STX  curr_pointer_lo
   STY  curr_pointer_hi
   
   LDX  #31
   
BufferOffsetPalette:             ; x = palette_buffer end index

   PHA                           ; how much to subtract
   
   LDA  nmi_flags
   AND  #NMI_UPDATE_PALETTE_CLEAR
   STA  nmi_flags
   
   FOR_Y  15, UP_TO, $FF         ; (offset loop)
      PLA
      PHA                        ; Copy TOS into A.
      CLC
      ADC  (curr_pointer_lo), Y  ; Offset palette value with A.

      PHA                        ; Push this so we can use A for some logic.
      AND  #%00001111            ; Knock down all $xE and $xF to $xD.
      CMP  #$0E
      IF_CARRY_SET               ; We've determined that the value must be $xE or $xF; so
         PLA                     ; knock it down to $xD.  First retrieve offset palette value.
         AND  #%11110000
         ORA  #%00001101
      ELSE_
         PLA                     ; Retrieve offset palette value.
      END_IF
     
     
                                 ; TODO: determine if the offset was positive or negative.  We could do that by
                                 ; temporarily storing A in the buffer and digging out the initial offset by PLA
      STA  palette_buffer, X
     
      PLA                               ; Copy offset from TOS into A.
      PHA
      IF_NEG                            ; If it's negative:
         LDA  palette_buffer, X
         CMP  #$20
         IF_EQ
            LDA  #$10
            STA  palette_buffer, X
         END_IF
      ELSE_                             ; But if it's positive:
         LDA  palette_buffer, X
         CMP  #$1d
         IF_EQ
            LDA  #$2d
            STA  palette_buffer, X
         ELSE_
            CMP  #$2d
            IF_EQ
               LDA  #$00
               STA  palette_buffer, X
            END_IF
         END_IF
      END_IF         
     
      LDA  palette_buffer, X     ; Continue now for offset adjusted by direction:
      CMP  #$3d+1                ; Now we check if any value goes >3d (out of range) and cap it to either 30 or 0d.
      IF_GE                      ; Is the value above 127?  [Shouldn't that say "above 61"?]
         CMP  #0
         IF_LT
            LDA  #$0d            ; If the offset was negative, this is our stop.
         ELSE_
            LDA  #$30            ; This is where we end up if the offset was positive.
         END_IF
      END_IF
     
      STA  palette_buffer, X
     
      DEX
   NEXT_Y                        ; (back to top of offset loop)
   
   PLA                           ; clean stack from original a value
                                 ; TODO: patch all sprite opacity buffers w/ that of the background palette buffer.
   LDA  palette_buffer
   STA  palette_buffer+16        ; Seems just patching the first entry of the sprite palette buffer is enough.
   
   LDA  nmi_flags
   ORA  #NMI_UPDATE_PALETTE
   STA  nmi_flags
   
   RTS
 ;-------------

To answer Bregalad's objection, you can still use labels and explicit branches and jumps if desired; but I try to minimize them. A main reason for using assembly language is performance; and if I didn't make any mistakes in my quick conversion above, the assembled code will be identical to the earlier version.
Re: ASM indentation style
by on (#231395)
Garth wrote:
Code:
      IF_GE                      ; Is the value above 127?  [Shouldn't that say "above 61"?]

I think my reasoning was that at that place in the code we don't know which direction we've offset in. It could probably be reworked a bit, since I'm checking for direction twice, but I've left it that way for now since it works... :P

I've yet to use macros, but I probably will once I feel more comfortable with regular assembly. I can definitely see how they would make life a little easier. Thanks for the example!
Re: ASM indentation style
by on (#231411)
pwnskar wrote:
Garth wrote:
Code:
      IF_GE                      ; Is the value above 127?  [Shouldn't that say "above 61"?]

I think my reasoning was that at that place in the code we don't know which direction we've offset in. It could probably be reworked a bit, since I'm checking for direction twice, but I've left it that way for now since it works... :P

This line was immediately following a comparison to $3D+1 which is 62; so branching on the carry flag splits 61, 60, 59,... from 62, 63, 64...

Quote:
I've yet to use macros, but I probably will once I feel more comfortable with regular assembly. I can definitely see how they would make life a little easier. Thanks for the example!

I used macros for three decades before I realized there was a way to use them for nestable program structures. Next I need to figure out a way to use them to automatically create and destroy local variables.
Re: ASM indentation style
by on (#231424)
Oziphantom wrote:
See also C
K&R style is
Code:
void myFunction(bool var) {
    some code here
}

No, its the Java-style.

Oziphantom wrote:
These days Stroustrup style is more popular
Code:
void myFunction(bool var)
{
    some code here
}

Or better known as K&R style :)
Re: ASM indentation style
by on (#231426)
cyc wrote:
Or better known as K&R style :)


K&R is an awful mix, where braces for functions are on their own lines, but braces in control blocks are on the same line
https://en.wikipedia.org/wiki/Indentation_style#K&R_style