Any fast tricks for remapping bits?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
frantik
Posts: 377
Joined: Tue Mar 03, 2009 3:56 pm

Any fast tricks for remapping bits?

Post by frantik »

Let's say I have a byte with bits in certain positions, and I would like to remap those bits to new positions. (ie lets's say I have bits 12345678 and want to remap them to 2468135, or some other order) Is there a fast/low code technique to do this? I can of course iterate through the bits and place them one at a time in the new byte but I'm wondering if there's some like trick technique that is known but maybe not easy to figure out on ones own.

The idea is to capture the input from a power pad and remap it to standard controller bits. The full input from the power pad is in two bytes so that adds on a bit of complication but it would be great if there was some trick method to remap bits vs just manually placing each bit in the proper place one by one
User avatar
Dwedit
Posts: 4924
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Any fast tricks for remapping bits?

Post by Dwedit »

256 entry lookup table?
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
frantik
Posts: 377
Joined: Tue Mar 03, 2009 3:56 pm

Re: Any fast tricks for remapping bits?

Post by frantik »

Dwedit wrote: Sat Dec 31, 2022 8:57 pm 256 entry lookup table?
yeah that would definitely be fast :mrgreen: but a bit costly in terms of space used
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: Any fast tricks for remapping bits?

Post by Oziphantom »

yeah LUT is the fastest. But if you want something that costs more but uses less space

Code: Select all

lda #0
ldx value
bpl +
ora #8
+
bvc +
ora #80
lsr value
lsr value
ldx value
bpl 
etc 
Drag
Posts: 1615
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Re: Any fast tricks for remapping bits?

Post by Drag »

Have the best of both worlds, a loop plus a LUT. :D

Code: Select all

; inputByte = The original bits you want to rearrange
; Rearranged bits are in A upon return.

 ldy #$07	; Need 8 shifts.
 lda #$00	; Initialize A.
next
 lsr inputByte	; Shift the input byte once.
 bcc skip
 ora bitsTable,y	; If the shifted bit was 1, use bitsTable to set the appropriate bit in A.
skip			; If the shifted bit was 0, skip the ORA and the bit remains a 0.
 dey
 bpl next	; Do next shift if there still are more bits.
 rts
bitsTable
 dc.b $80, $20, $08, $02, $01, $04, $10, $40
I haven't assembled and checked this code, but the way it's supposed to work is, you start with inputByte, and it shifts it right repeatedly (e.g., bit 0, bit 1, bit 2, etc), and whenever a 1 bit is present, the equivalent byte from bitsTable is OR'd to A. When this routine returns, the rearranged bits will be in register A.
Keep in mind that the table is used last-to-first, so this particular example maps 0->6, 1->4, 2->2, 3->0, and so on.
Switch the LSR to an ASL to flip the mapping around (i.e., 7->6, 6->4, 5->2, etc).
frantik
Posts: 377
Joined: Tue Mar 03, 2009 3:56 pm

Re: Any fast tricks for remapping bits?

Post by frantik »

Drag wrote: Sat Dec 31, 2022 9:37 pm Have the best of both worlds, a loop plus a LUT. :D
now you're cooking! this looks like a good solution in terms of fast and low code usage, and also makes it easy to rearrange the mapping if needed
frantik
Posts: 377
Joined: Tue Mar 03, 2009 3:56 pm

Re: Any fast tricks for remapping bits?

Post by frantik »

so instead of reading the power pad and then remapping the bits i just used the small look up table idea to assign the bits as they are read. seems fairly obvious in hindsight :beer: i can't fit reading all 12 buttons in the space where the old controller code was unfortunately

Code: Select all

PowerPadMapA:                                                                  
.hex 01 80 04 10 40 02 40 08 
                                                                                                                                                              
ReadJoypads:                                                                   
              ldy #$01               ;reset and clear strobe of joypad ports   
              sty JOYPAD_PORT                                                  
              dey                                                              
              sty JOYPAD_PORT                                                  
              sty SavedJoypadBits   ; reset joypadbits                         
              ldy #$07                                                         
PowerPadLoop:                                                                  
              lda JOYPAD_PORT2     ;read current bit on joypad port                              
              and #%00001000                                                    
              beq DoneWithPowerPad 
              lda PowerPadMapA,y                                               
              ora SavedJoypadBits                                              
              sta SavedJoypadBits                                              
DoneWithPowerPad:                                                              
              dey                                                              
              bpl PowerPadLoop                                                 
              rts 
Post Reply