Sogona wrote:You can gan go 129 bytes forward and 126 bytes backward. It should be -127 - 128 but for whatever reason the people who designed the 6502 fucked up with the microcode. I believe this is also responsible why the address pushed onto the stack when jumping to a subroutine is off by 1.
The 6502 does not use microcode, but rather a program logic array. It does a lot of small-scale pipelining, and I suspect what's happening here is that the program counter is already advanced to the first byte of the next instruction when the branch calculation is being done, so a branch with a distance of 0 is a do-nothing instruction. Since the branch-taken scenario takes one more cycle than the branch-not-taken scenario, this may actually be useful for timing, using a flag to determine whether to take two or three clocks. (Be aware that a branch will take four clocks if it crosses a page boundary; but most branches won't cross a page boundary.)
The pipelining is not deep, but does allow the 6502 to make better use of clock cycles than its contemporaries. Take ADC # for example. There are five distinct steps, but it only takes two cycles, finishing up while the next op code is being fetched. An interrupt's operation is different from that of JSR in more ways than just pushing the status and setting the interrupt-disable flag (plus clearing the D flag on the 65c02); and I'm sure the pipelining worked out better for performance and silicon real estate the way the designers did it.
BioMechanical Dude wrote:
Code: Select all
NOTE: I'm typing this from memory, so there might be some errors, unrelated to the problem itself.
LDA $0203, X
STA $0203, X
Execute the rest of the code
Since you're trying to shorten the code so the branches reach better, take the four lines starting with LDA $0203, X and replace them with the one instruction DEC $0203, X. You'll save six bytes, and it will take 6 cycles to execute instead of 12. The only reason not
to do this is if you need it in decimal, since increment and decrement instructions are always in hex, regardless of the state of the D flag. The next four lines can be replaced with four INX's. It will run the same speed, but save a byte. You apparently have a table starting at $203. If there's no need to go up
in the indexing, ie, if it would work just as well to start at the top and go down
instead, that will remove the need for the CPX #$10, because coming down, you can take advantage of the automatic, implied compare-to-0 in DEX before the BNE loop. If you really do need to go in ascending order, you can start with a different value of X (make it $F0) and a different base (start with $113) such than INX will get you up
to 0 instead of down
to zero. Now it becomes:
Code: Select all
DEC $0113, X
I'm not familiar with your hardware; but if you can put whatever the "1" in your AND# instruction represents into bit 6 or 7, then you can use BIT Buttons and you can get rid of the AND# instruction too. Regardless of what was in the accumulator, bit 7 of whatever is read by BIT goes into the N flag, and bit 6 goes into the V flag, and you can branch on those with BPL, BMI, BVC, or BVS. Now the accumulator goes undisturbed for the entire routine.