Page 2 of 2
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 10:05 pm
by cbmeeks
Well, that's not quite the same thing
HA! Yeah. After rotating the bits correctly and observing the numbers, I noticed my error. It's one of those situations where I got exactly what I asked for...just asked the wrong question. lol
I would take a different approach. As there's only 16 bit combinations to a nibble, you can simply use a 16-byte lookup table with the rotated values. You can mask off the upper 4-bits (to retain the lower 4 bits), xfer to an index register and load the accumulator indexed from the lookup table.
For the upper nibble, you would need to do 4 LSR A instructions and again xfer it to an index register. To save time, you could use a different 16-byte table where the rotated values are in the upper 4 bits. Once you have both values, you just OR them together for the twin-shifted nibbles.
That's exactly what I'm going to do. I was trying to be fancy by containing everything in one byte and rotating. But proves to be more trouble.
Thanks for all the suggestions. At the very least, I know have a better rotation function.

Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 10:15 pm
by cbmeeks
Wait...
What if I used two bytes?
One byte for the facing direction and one byte for the moving direction?
Then, just make both nybbles the same. Wouldn't the rotate then work out OK?
Code: Select all
// Facing Byte
%1000 1000
// Moving Byte
%0100 0100
Then, I can just rotate as normal and mask off either nybble.
I may try that next. If it doesn't work, use some lookup tables.
Thanks!
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 10:32 pm
by BigEd
I reckon you can still do the nibble rotate, with a bit of care. There are two checks and corrections to be made, one for each nibble. But I'm not quite smart enough right now to just write the code!
Re: Rotate bits when you don't care about carry.
Posted: Wed Nov 11, 2020 2:53 am
by barrym95838
In order to transform the current facing value to the new facing value without affecting the movement direction, you only need four different EOR operands (#$30, #$60, #$C0, #$90) for clockwise or counterclockwise. The trick is in calculating the desired operand as efficiently as possible. Are you more interested in fastest execution or smallest code footprint? Because the solutions will probably end up evolving differently. One intermediate possibility might look like:
Code: Select all
rotcw:
lda status
lsr
lsr
lsr
lsr
tax
lda cwtable-2,x
bne rotzzz
rotccw:
lda status
lsr
lsr
lsr
lsr
tax
lda ccwtable-1,x
rotzzz:
eor status
sta status
rts
ccwtable:
dcb $30,$60,0,$C0,0,0,0,$90
cwtable:
dcb $30,0,$60,0,0,0,$C0
[UNTESTED!]
I truncated and slightly overlapped the tables to save space, but this will blindly provide nonsense values for invalid inputs ... garbage in, garbage out.
I know someone here can do better, perhaps much better, but I'm just throwing this out there as an example. If status happens to reside at address $30 or address $30xx, I know how to save two more bytes of ccwtable!

Re: Rotate bits when you don't care about carry.
Posted: Wed Nov 11, 2020 3:22 am
by cbmeeks
The EOR idea sounds interesting as well!
My idea of using two bytes seems to be working. The sprite is rotating correctly on screen now.
The numbers I am getting are:
Code: Select all
$88 // N
$44 // E
$22 // S
$11 // W
Which translates perfectly to:
Code: Select all
.label FACING_DIR_N = %10001000
.label FACING_DIR_E = %01000100
.label FACING_DIR_S = %00100010
.label FACING_DIR_W = %00010001
Same for moving.
Thanks again everyone for your help.
Re: Rotate bits when you don't care about carry.
Posted: Wed Nov 11, 2020 8:31 am
by BigEd
Just a thought: you want to maintain two pieces of information, each of which has four possible states. You've chosen a one-hot encoding, and now you're looking for ways to manipulate it.
But four states can be encoded in two bits. The whole story fits in a nibble. And a nibble-sized lookup table is only 16 bytes: you can have one table for left rotation and one for right rotation.
If at some point you need a one-hot representation of this packed encoding, again a nibble-sized lookup table, with another 16 bytes, can give you what you want - or a pair of lookups, one to give you the movement part and the other to give you the orientation part.
(I have just spent 64 bytes on lookup tables! But the speed should be good.)
Re: Rotate bits when you don't care about carry.
Posted: Wed Nov 11, 2020 4:28 pm
by barrym95838
Yeah, my suggested solution was constrained by the structure it was trying to update. In a clean-sheet design, I would probably just use the two low bits of two separate bytes for each attribute and just INC and DEC to rotate.
Re: Rotate bits when you don't care about carry.
Posted: Thu Nov 12, 2020 12:43 pm
by MagerValp
Re: Rotate bits when you don't care about carry.
Posted: Fri Nov 13, 2020 2:04 am
by Chromatix
For rotating left:
And for rotating right:
Barrel shifts by more than one bit are a little more involved - here's one way to do a nybble swap:
Code: Select all
STZ tmp
ASL A
ROL tmp
ASL A
ROL tmp
ASL A
ROL tmp
ASL A
ROL tmp
ORA tmp
Re: Rotate bits when you don't care about carry.
Posted: Fri Nov 13, 2020 3:10 am
by GARTHWILSON
here's one way to do a nybble swap: <snip>
http://6502.org/source/general/SWN.html has a 6-instruction, 8-byte, 12-cycle nybble swap.
Re: Rotate bits when you don't care about carry.
Posted: Thu Jun 17, 2021 8:05 am
by TobyLobster
To rotate the bits in each each nibble to the left, how about this:
Code: Select all
asl
bit sixteen
beq +
and #$ef
ora #1
+
bcc +
sixteen = * + 1
ora #16
+
Re: Rotate bits when you don't care about carry.
Posted: Thu Jun 17, 2021 10:53 am
by BigEd
(welcome Toby! I've seen you over on stardot...)
Re: Rotate bits when you don't care about carry.
Posted: Sun Jun 27, 2021 7:30 pm
by TobyLobster
(thanks, I've seen you in stardot-land too...)