How do you know if your code is structured well enough?

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How do you know if your code is structured well enough?

Post by tepples »

You could use a LUT if the X register is free. But assuming that by 0, 4, 8, 16 you mean 0, 4, 8, 12, prepare to expand your mind.

You can think of asl instruction as standing for Add to SeLf. If you mask off the bits you don't want to shift, you can add the rest of the number to itself to shift only the bits you haven't masked.

Code: Select all

  ; assuming 8-bit A, we have 22 cycles
  and #$0F     ; 0000dcba
  asl a        ; 000dcba0
  asl a        ; 00dcba00
  sta tmpbits
  and #$F0     ; 00dc0000
  adc tmpbits  ; 0dc0ba00
  sta tmpbits
  and #$F0     ; 0dc00000
  adc tmpbits  ; dc00ba00
I do this in 8x16 text printing routines in some situations, shifting bits 6-4 of the character code to bits 7-5 of the tile number while preserving bits 3-0.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: How do you know if your code is structured well enough?

Post by Drew Sebastino »

tepples wrote:You could use a LUT if the X register is free
Y is free, and it's convenient here because it's already the number of the byte.

This is what I have now:

Code: Select all

VramAdress = 0
Size = 0
BankNumber = 2
TileAdress = 4



start_vram_finder:
  rep  #$30	; A=16, X/Y=16
  sep #$20	; A=8

  stz  32x32ColumnSkipperCounter
  ldx  #$0000
  ldy  #$0000
  cpx  32x32TileRequestCounter
  beq  16x16_vram_finder_start

look_for_32x32_vram:
  cpy  #$0020					;128, because there are 128 slots for sprites
  beq  vram_finder_done				;no space left for sprite
  lda  VramTable,y
  beq  32x32_slot_found
  iny
  bra  look_for_32x32_vram

32x32_slot_found:
  lda  #$FF
  sta  VramTable,y		;say that four of the slots are now taken

  rep  #$30	; A=16, X/Y=16
  lda  VramAdressConverterTable,y
  sta  32x32TileRequestTable,x
  sep  #$20	; A=8

  cpx  32x32TileRequestCounter
  beq  16x16_vram_finder_start
  inx
  inx
  inx
  inx
  inx
  inx
  bra  look_for_32x32_vram






32x32_vram_finder_start:
  ldx  #$0000
  ldy  #$0000
  cpx  32x32TileRequestCounter
  beq  16x16_vram_finder_start

look_for_16x16_vram:
  cpy  #$0020			;128, because there are 128 slots for sprites
  beq  vram_finder_done		;no space left for sprite
  lda  VramTable,y
  bit  #$11000000
  bne  16x16_slot0_found	;there is space for another sprite
  bit  #$00110000
  bne  16x16_slot1_found	;there is space for another sprite
  bit  #$00001100
  bne  16x16_slot2_found	;there is space for another sprite
  bit  #$00000011
  bne  16x16_slot3_found	;there is space for another sprite
  iny
  bra  look_for_16x16_vram	;look again if the space is already occupied


16x16_slot0_found:
  inc  VramTable,y		;say that one of the slots is now taken

  rep  #$30	; A=16, X/Y=16
  lda  VramAdressConverterTable,y
  sta  16x16TileRequestTable,x
  sep  #$20	; A=8

  cpx  16x16TileRequestCounter
  beq  vram_finder_done
  inx
  inx
  inx
  inx
  inx
  inx
  bra  look_for_16x16_vram


16x16_slot1_found:
  inc  VramTable,y		;say that one of the slots is now taken

  rep  #$30	; A=16, X/Y=16
  lda  VramAdressConverterTable,y
  clc
  adc  #$0002
  sta  16x16TileRequestTable,x
  sep  #$20	; A=8

  cpx  16x16TileRequestCounter
  beq  vram_finder_done
  inx
  inx
  inx
  inx
  inx
  inx
  bra  look_for_16x16_vram


16x16_slot2_found:
  inc  VramTable,y		;say that one of the slots is now taken

  rep  #$30	; A=16, X/Y=16
  lda  VramAdressConverterTable,y
  clc
  adc  #$0020
  sta  16x16TileRequestTable,x
  sep  #$20	; A=8

  cpx  16x16TileRequestCounter
  beq  vram_finder_done
  inx
  inx
  inx
  inx
  inx
  inx
  bra  look_for_16x16_vram


16x16_slot3_found:
  inc  VramTable,y		;say that one of the slots is now taken

  rep  #$30	; A=16, X/Y=16
  lda  VramAdressConverterTable,y
  clc
  adc  #$0022
  sta  16x16TileRequestTable,x
  sep  #$20	; A=8

  cpx  16x16TileRequestCounter
  beq  vram_finder_done
  inx
  inx
  inx
  inx
  inx
  inx
  bra  look_for_16x16_vram


vram_finder_done:
  rts



VramAdressConverterTable:
  .word 0,4,8,12,64,68,72,76,128,132,136,140,192,196,200,204
  .word 256,260,264,268,320,324,328,332,384,388,392,396,448,452,456,460
tomaitheous
Posts: 592
Joined: Thu Aug 28, 2008 1:17 am
Contact:

Re: How do you know if your code is structured well enough?

Post by tomaitheous »

Man... you guys need some macros ;>_>


Also, you could get rid of those INXs. A nice txa, clc, adc #const, tax would cut some cycles out, but it'd also make the listing more compact. I mean, doesn't look like the contents of Acc matter for the inx area.


When you start writing tens of thousands of lines of asm code per "include" bank/file/whatever, things get messy to read or scroll through. Macros are great for code clarity, a compact the listing, and usually proves to be less work for making changes. I also do a lot more leading white space now for asm, as well as different levels of indents to keep track of certain instructions (makes them easier to see/pick up); the more to the right de-emphasizes the instruction, and more to the left emphasizes it. I usually add a lot of title bars (different kinds) to help separate code segments as well as ending lines (usually dots/segments). Some are more pronounced than others.
__________________________
http://pcedev.wordpress.com
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: How do you know if your code is structured well enough?

Post by Drew Sebastino »

tomaitheous wrote:Also, you could get rid of those INXs. A nice txa, clc, adc #const, tax would cut some cycles out, but it'd also make the listing more compact.
Yeah, I really don't know what I was doing there...

Edit: Actually, wait, I know what I was doing there. I didn't want to have to change the accumulator size to 16 bit just for that, because it would really be:

rep #$30, txa, clc, adc #const, tax, sep #$20

Anyway, I don't really want to deal with the hassle of setting up macros though.
User avatar
nicklausw
Posts: 376
Joined: Sat Jan 03, 2015 5:58 pm
Location: ...
Contact:

Re: How do you know if your code is structured well enough?

Post by nicklausw »

Am I the only one with a weird habit of intentionally avoiding macros? I just don't like them, because when first starting out with assembly people got onto me for being too macro-heavy (since it made my code have no subroutines and therefore be redundant).
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: How do you know if your code is structured well enough?

Post by Drew Sebastino »

nicklausw wrote:Am I the only one with a weird habit of intentionally avoiding macros?
I just about try to avoid them too.
KungFuFurby
Posts: 264
Joined: Wed Jul 09, 2008 8:46 pm

Re: How do you know if your code is structured well enough?

Post by KungFuFurby »

I actually attempted macros on WLA DX. I partially abandoned them as a result of me attempting some magic that ended up failing quite horribly.
User avatar
nicklausw
Posts: 376
Joined: Sat Jan 03, 2015 5:58 pm
Location: ...
Contact:

Re: How do you know if your code is structured well enough?

Post by nicklausw »

KungFuFurby wrote:I actually attempted macros on WLA DX.
Eeyup. Not the greatest idea.
93143
Posts: 1371
Joined: Fri Jul 04, 2014 9:31 pm

Re: How do you know if your code is structured well enough?

Post by 93143 »

nicklausw wrote:when first starting out with assembly people got onto me for being too macro-heavy (since it made my code have no subroutines and therefore be redundant).
I'd have thought that would only be bad if you cared about code size. Macros are faster and just as easy to maintain.

Unrolled loops are by no means as easy to maintain as regular loops, yet they're still considered good practice if speed is important...
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: How do you know if your code is structured well enough?

Post by Drew Sebastino »

What exactly is an "unrolled loop"? :oops: I've probably done them several times, but I just don't know what it is and I've heard it several times.
User avatar
darryl.revok
Posts: 520
Joined: Sat Jul 25, 2015 1:22 pm

Re: How do you know if your code is structured well enough?

Post by darryl.revok »

Hopefully somebody will correct me if I'm wrong, but I believe it's when, instead of creating a loop that performs a repeated task multiple times for multiple pieces of data, you essentially lay out each cycle of the loop as it's own step. This takes a lot more space, is a lot less maintainable, is uglier, but ultimately it can save you a few CPU cycles by not performing excess tests for the exit conditions of your loop.
lidnariq
Posts: 10677
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: How do you know if your code is structured well enough?

Post by lidnariq »

If you're willing to use macros or other assembler help, unrolled loops are only "takes a lot more space".

For example, ca65 supports the ".repeat / .endrep" command:

Code: Select all

 .repeat 16, count
  lda $0200+count
  sta $2007
 .endrep
User avatar
dougeff
Posts: 2876
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: How do you know if your code is structured well enough?

Post by dougeff »

Here's two examples...unrolled loops

Code: Select all

LDA buffer
Sta $2007
LDA buffer + 1
Sta $2007
LDA buffer + 2
Sta $2007
Etc... until all PPU updates done
Or the more efficient...

Code: Select all

Pla
Sta $2007
Pla
Sta $2007
Pla
Sta $2007
Etc... until all PPU updates done
Edit. They use the same # of cycles.
Last edited by dougeff on Sun Aug 16, 2015 3:51 pm, edited 1 time in total.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: How do you know if your code is structured well enough?

Post by Drew Sebastino »

How is "PLA" a substitute for "LDA buffer", unless you said "LDA buffer, PHA" a bunch of times, which is even slower?
User avatar
darryl.revok
Posts: 520
Joined: Sat Jul 25, 2015 1:22 pm

Re: How do you know if your code is structured well enough?

Post by darryl.revok »

PLA means pull value from stack into accumulator, so I'm guessing that example would have involved pushing (PHA) the values onto the stack first.

I just have to ask because this example made me wonder. You're pulling values from the stack and writing them to the PPU, so you're inside of NMI, however, when you go into NMI it pushes the return address to the stack, so do you then pull that back and store it and then push it before RTI, or something else?

I'm wondering because I know it's nonsense example code but I got the sense that you do something like it because you chose that example. I've considered using the stack for things like preloading background tiles, but just the fact that I'd have to pull the return address off and store it made me reconsider trying the stack route on that.
Post Reply