posting code in hopes of peer reviews.

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2032
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: posting code in hopes of peer reviews.

Post by FrankenGraphics » Fri May 10, 2019 1:39 pm

except that at the top of each loop, we check for y to be 0, in that case: we escape the loop to @skip. but if myTemp1 sets carry before that, i think we end up with an empty bitmask.

so to correct myself, it's its the cpy / beq that makes it work, seemingly, and it seems to me the bcc messes this up.


edit. i might be wrong abut the chicken-egg condition.

this seems to work identically. but it's simpler to read. thanks everybody.

@loop
asl myTemp1
dey
bpl @loop

it seems my troubles are elsewhere:

-certain items respawn on certain screens when they ought to be permanently collected, but it seems more related to a specific item type that misbehaves occasionally.
-when altering a bit related to a certain room, revisiting that room teleports the player to a wholly different screen and position unintentionally. - more likely something is looking for a var in the wrong place. maybe even a missed bank switch or something. i'll keep searching.
http://www.frankengraphics.com - personal NES blog

nocash
Posts: 1211
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: posting code in hopes of peer reviews.

Post by nocash » Fri May 10, 2019 2:54 pm

Are you sure about the BPL? That will jump when Y is positive (=including 00). The code in your pre-previous post looked more as if you wanted to stop looping when Y=00, if yes, then better use BNE.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2032
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: posting code in hopes of peer reviews.

Post by FrankenGraphics » Fri May 10, 2019 4:18 pm

hm... for all intents and purposes it doesn't seem to matter? watching RAM in the hex editor, the same bit in the same byte gets picked.
http://www.frankengraphics.com - personal NES blog

nocash
Posts: 1211
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: posting code in hopes of peer reviews.

Post by nocash » Fri May 10, 2019 11:17 pm

No, BPL loops once more than BNE. Unless you still have the CPY+@skip inside of the loop (as in your old code version)?
Then yes, then the @skip would exit upon Y=00 no matter of BPL or BNE (or then you could even use non-conditional JMP @loop).
I would move the @skip stuff outside of the loop, and use BNE at loop end:

Code: Select all

Prepare_32byteBitwise:
 sta  myTemp    ;-memorize value with lower 3bit
 lsr            ;\
 lsr            ; get the 5 most significant bits
 lsr            ;
 tax            ;/
 ldy  #1        ;\init bitmask
 sty  myTemp1   ;/
 lda  myTemp    ;\
 and  #$7       ; isolate lower 3bit and skip if zero
 beq  @skip     ;/
 tay            ;\
@loop:          ;
 asl  myTemp1   ; shifts bitmask up
 dey            ;
 bne  @loop     ;/
@skip:
 rts
Or, replace the whole loop by a single table look-up:

Code: Select all

Prepare_32byteBitwise:
 sta  myTemp    ;-memorize value with lower 3bit
 lsr            ;\
 lsr            ; get the 5 most significant bits
 lsr            ;
 tax            ;/
 lda  myTemp    ;\
 and  #$7       ; isolate lower 3bit and skip if zero
 tay            ; and look-up bitmask table
 lda  @table,y  ;
 sta  myTemp1   ;/
 rts
@table:
 db   1,2,4,8,16,32,64,128   ;(or "dcb" or "defb" or whatever your assembler wants for defining data bytes)
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2032
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: posting code in hopes of peer reviews.

Post by FrankenGraphics » Sat May 11, 2019 12:33 am

i think if the incoming ID to the subroutine is #0 or otherwise has no modulo left from AND #7, a BNE would have the Y-loop wrap around for 255 more iterations.

on the other hand, using bpl, an incoming ID of #7 can push the bitmask into carry, missing every 8th trigger bit.

so this:
@loop:
beq @skip ;true conditional
asl myTemp1
dey
bne @loop ;could be jmp since beq will get us out either way
@skip

seems necessary, after all, short of using the LUT.

edit: Nope, that pushes the problem forward. Not sure what i do wrong here and will try to examine it more carefully at some point, but i think i'll simply resign to using the LUT for now.


All screen triggers + item triggers seem to work just fine now, except for the few rooms that have the teleporting bug which seems to be an isolated issue.
http://www.frankengraphics.com - personal NES blog

nocash
Posts: 1211
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: posting code in hopes of peer reviews.

Post by nocash » Sat May 11, 2019 1:50 am

FrankenGraphics wrote:i think if the incoming ID to the subroutine is #0 or otherwise has no modulo left from AND #7, a BNE would have the Y-loop wrap around for 255 more iterations.
Yes. But to prevent that you do have the CPY+BEQ @skip in your code.
Looking at your current example, you have only BEQ, without CPY? That looks wrong!
Or alternately, use the AND+BEQ @skip from my example (AND affects zeroflag too, so you don't need CPY).

You need to pre-check for Y=00 only once before the loop.
Doing it inside of the loop would be useless and slow (instead you can just rely on DEY+BNE at the loop end).

If the table method works is fine, too. And it's faster. Though you'll probably need to get familar with loops sooner or later, too : )
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

supercat
Posts: 161
Joined: Thu Apr 18, 2019 9:13 am

Re: posting code in hopes of peer reviews.

Post by supercat » Sat May 11, 2019 9:57 am

FrankenGraphics wrote:i think if the incoming ID to the subroutine is #0 or otherwise has no modulo left from AND #7, a BNE would have the Y-loop wrap around for 255 more iterations. [
There are two approaches one can take here: plan on the loop running 1-8 times, or handle the zero-case specially and then have it loop 1-7 if the value wasn't zero.

Unless code space is at an absolute premium, the approach of putting a value 0-7 into X and the value with the bit to be tested in A, and then doing:

Code: Select all

    and bitTable,x
will offer an excellent size/speed trade-off since the table will only be eight bytes, and the code to access it three, for a total of 11. If one wants to test the value of bit X of the accumulator without a table, the loop:

Code: Select all

@lp:
    lsr
    dex
    bpl @lp
will do the job in four bytes, leaving the result in C. The result could be moved into the Z and N flags via "ror" instruction if desired. If one wants to convert a value 0-7 into a bit mask in A, the table approach would be 11 bytes, or one could use:

Code: Select all

    lda #0
    sec
@lp:
    rol
    dex
    bpl @lp
If one wanted the bit mask in a location which had been initialized to 1, without disturbing A, one could use:

Code: Select all

    dex
    bmi @done
@lp:
    asl temp
    dex
    bpl @lp
@done:
noting that "dex" is a byte cheaper than "cpx #0". If it's neccessary to have X end up at zero, one could use:

Code: Select all

    cpx #0
    beq @done
@lp:
    asl temp
    dex
    bne @lp
@done:
but note that the code there is 8-9 bytes (depending upon whether "tmp" is in zero page) and unless "temp" needed to be initialized to 1 for some other reason, the 11-byte table approach could be more efficient.

Post Reply