Page 2 of 2
Re: posting code in hopes of peer reviews.
Posted: Fri May 10, 2019 1:39 pm
by FrankenGraphics
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.
Re: posting code in hopes of peer reviews.
Posted: Fri May 10, 2019 2:54 pm
by nocash
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.
Re: posting code in hopes of peer reviews.
Posted: Fri May 10, 2019 4:18 pm
by FrankenGraphics
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.
Re: posting code in hopes of peer reviews.
Posted: Fri May 10, 2019 11:17 pm
by nocash
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)
Re: posting code in hopes of peer reviews.
Posted: Sat May 11, 2019 12:33 am
by FrankenGraphics
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.
Re: posting code in hopes of peer reviews.
Posted: Sat May 11, 2019 1:50 am
by nocash
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 : )
Re: posting code in hopes of peer reviews.
Posted: Sat May 11, 2019 9:57 am
by supercat
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:
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:
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:
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.