Jump to content
IGNORED

Fastest way to reverse a byte?


Gemintronic

Recommended Posts

In my 4 way scrolling topics I realised I needed some way to reverse a byte (i.e. turning %0100100 into %0010010)

 

Although SeaGtGruffs pfhscroll.asm keeps the correct byte order directly manipulating the screen vars does not. This means any 4 way scrolling demonstration I've made so far can only use symmetrical level data.

 

The only methods I can think of is a bunch of costly bit rearranging (i.e. this{0} = that{7}) or a very big lookup table.

 

Does anybody have any bright ideas?

Link to comment
Share on other sites

It might be. It almost seems like those ror and rol are reversing the bytes in assembly. I don't really understand enough just to pick out the bit of inline assembly needed to execute those commands.. and if they really reverse the byte in the first place (it could just be shifting the bits). At least it's a lead.

Link to comment
Share on other sites

It might be. It almost seems like those ror and rol are reversing the bytes in assembly.

 

Not almost, it is assembly. Here's an example:

__

__Scroll_Right
   asm
   lda var3
   rol
   ror var0
   rol var1
   ror var2
   rol var3
   lda var7
   rol
   ror var4
   rol var5
   ror var6
   rol var7
   lda var11
   rol
   ror var8
   rol var9
   ror var10
   rol var11
   lda var15
   rol
   ror var12
   rol var13
   ror var14
   rol var15
   
   lda var19
   rol
   ror var16
   rol var17
   ror var18
   rol var19
   
   lda var23
   rol
   ror var20
   rol var21
   ror var22
   rol var23
   
   lda var27
   rol
   ror var24
   rol var25
   ror var26
   rol var27
   
   lda var31
   rol
   ror var28
   rol var29
   ror var30
   rol var31
   
   lda var35
   rol
   ror var32
   rol var33
   ror var34
   rol var35
   
   lda var39
   rol
   ror var36
   rol var37
   ror var38
   rol var39
   
   lda var43
   rol
   ror var40
   rol var41
   ror var42
   rol var43
   
   lda var47
   rol
   ror var44
   rol var45
   ror var46
   rol var47
end

 

 

The playfield variables that are always reversed are dealt with for you in his asm code, so you don't have to worry about it, at least going left and right.

  • Like 1
Link to comment
Share on other sites

It looks like ror and rol are bit shifting and not reversing the byte.

 

Rotate Left through Carry

  2A        nzc---  2   ROL A        RCL A              ;RCL A  26 nn     nzc---  5   ROL nn       RCL [nn]           ;RCL [nn]  36 nn     nzc---  6   ROL nn,X     RCL [nn+X]         ;RCL [nn+X]  2E nn nn  nzc---  6   ROL nnnn     RCL [nnnn]         ;RCL [nnnn]  3E nn nn  nzc---  7   ROL nnnn,X   RCL [nnnn+X]       ;RCL [nnnn+X]

Rotate Right through Carry


  6A        nzc---  2   ROR A        RCR A              ;RCR A  66 nn     nzc---  5   ROR nn       RCR [nn]           ;RCR [nn]  76 nn     nzc---  6   ROR nn,X     RCR [nn+X]         ;RCR [nn+X]  6E nn nn  nzc---  6   ROR nnnn     RCR [nnnn]         ;RCR [nnnn]  7E nn nn  nzc---  7   ROR nnnn,X   RCR [nnnn+X]       ;RCR [nnnn+X]

SeaGtGruffs pfhscroll.asm takes care of shifting the playfield just fine. it's just when I must lay down playfield data into var0-47 that I need a byte reversing function.

Link to comment
Share on other sites

It looks like ror and rol are bit shifting and not reversing the byte.

 

Rotate Left through Carry

  2A        nzc---  2   ROL A        RCL A              ;RCL A  26 nn     nzc---  5   ROL nn       RCL [nn]           ;RCL [nn]  36 nn     nzc---  6   ROL nn,X     RCL [nn+X]         ;RCL [nn+X]  2E nn nn  nzc---  6   ROL nnnn     RCL [nnnn]         ;RCL [nnnn]  3E nn nn  nzc---  7   ROL nnnn,X   RCL [nnnn+X]       ;RCL [nnnn+X]

Rotate Right through Carry

  6A        nzc---  2   ROR A        RCR A              ;RCR A  66 nn     nzc---  5   ROR nn       RCR [nn]           ;RCR [nn]  76 nn     nzc---  6   ROR nn,X     RCR [nn+X]         ;RCR [nn+X]  6E nn nn  nzc---  6   ROR nnnn     RCR [nnnn]         ;RCR [nnnn]  7E nn nn  nzc---  7   ROR nnnn,X   RCR [nnnn+X]       ;RCR [nnnn+X]

SeaGtGruffs pfhscroll.asm takes care of shifting the playfield just fine. it's just when I must lay down playfield data into var0-47 that I need a byte reversing function.

 

Right, it's shifting bits from normal bytes into reversed bytes and also doing the reverse of that. If you want to plop down the whole screen with data and not feed it from one of the edges, VbB can already create data from a playfield that you draw which will contain the reversed data.

Link to comment
Share on other sites

In my 4 way scrolling topics I realised I needed some way to reverse a byte (i.e. turning %0100100 into %0010010)

 

Although SeaGtGruffs pfhscroll.asm keeps the correct byte order directly manipulating the screen vars does not. This means any 4 way scrolling demonstration I've made so far can only use symmetrical level data.

 

The only methods I can think of is a bunch of costly bit rearranging (i.e. this{0} = that{7}) or a very big lookup table.

 

Does anybody have any bright ideas?

Loon,

here is a reflection routine from the ASDK with another approach. To optimise it for speed I would use registers for argument REVBT and variable b, and use BIT to process the two most significant bits with fewer operations.

 

;---------------------------------------------------------

; Reverse Byte Routine 1100000 in REVBT becomes 00000011

;---------------------------------------------------------

; Note: This routine is not used, comment it out if you need the space:

;;ReverseB ; REVBT holds byte to be reversed

;; lda #0

;; sta b

;; lda REVBT

;; and #%10000000 ; keep just the 8th bit

;;;is the 8th bit set?

;; beq skip1

;; ; reflect it to set bit 1

;; lda b

;; ora #%00000001

;; sta b ; put it back in b

;;skip1

;;

;; lda REVBT

;; and #%0100000 ; keep just the 7th bit

;;; is the 7th bit set?

;; beq skip2

;; ;reflect it to set bit 2

;; lda b

;; ora #%00000010

;; sta b

;;skip2

;;

;; lda REVBT

;; and #%00100000 ;keep just the 6th bit

;; beq skip3 ; is the 6th bit set?

;; lda b

;; ora #%00000100; reflect to set bit 3

;; sta b

;;skip3

;;

;; lda REVBT

;; and #%00010000 ; keep just the 5th bit

;; beq skip4; is the 5th bit set?

;; lda b

;; ora #%00001000; reflect to set bit 4

;; sta b

;;skip4

;;

;; lda REVBT

;; and #%00001000 ; keep just the 4th bit

;; beq skip5; is the 4th bit set?

;; lda b

;; ora #%00010000; reflect to set bit 5

;; sta b

;;skip5

;;

;; lda REVBT

;; and #%00000100 ; keep just the 3rd bit

;; beq skip6; is the 3rd bit set?

;; lda b

;; ora #%00100000; reflect to set bit 6

;; sta b

;;skip6

;;

;; lda REVBT

;; and #%00000010 ; keep just the 2nd bit

;; beq skip7; is the 2nd bit set?

;; lda b

;; ora #%0100000; reflect to set bit 7

;; sta b

;;skip7

;;

;; lda REVBT

;; and #%00000001 ; keep just the 1st bit

;; beq skip8

;; lda b

;; ora #%10000000; reflect to set bit 8

;; sta b

;;skip8

;;

;; lda b

;; sta REVBT ; put the reversed byte in REVBT and return

;;

;; rts

;;

  • Like 1
Link to comment
Share on other sites

It looks like ror and rol are bit shifting and not reversing the byte.

 

If you shift the bits out one direction and shift them in

in the other direction they end up reversed.

 

That will give you the shortest code but it's slow

 

 

sec
rol
LOOP
ror temp
asl
bne LOOP

 

Fastest would be a straight table look up.

but takes a big table.

 

A reasonable compromise is to do a nybble at a time.

 

A bB function (from the smooth 4 way scrolling thread)

 

 

function rev()
temp2 = temp1 & $0F
temp1 = temp1 / 16
temp1 = revhi[temp2] | revlo[temp1]
return

data revhi
$00, $80, $40, $C0, $20, $A0, $60, $E0
$10, $90, $50, $D0, $30, $B0, $70, $F0
end

data revlo
$00, $08, $04, $0C, $02, $0A, $06, $0E
$01, $09, $05, $0D, $03, $0B, $07, $0F
end

 

a variation in asm (tables not shown. start,end with the byte in a)

 

 

tax
and #$0F
tay
txa
lsr
lsr
lsr
lsr
tax
lda hi_tbl,y
ora lo_tbl,x
  • Like 1
Link to comment
Share on other sites

I also found what I *think* is the nasty big lookup table on the Internets. here is the "ready for bB" version:

 data reverse
 $00, $80, $40, $c0, $20, $a0, $60, $e0
 $10, $90, $50, $d0, $30, $b0, $70, $f0
 $08, $88, $48, $c8, $28, $a8, $68, $e8
 $18, $98, $58, $d8, $38, $b8, $78, $f8
 $04, $84, $44, $c4, $24, $a4, $64, $e4
 $14, $94, $54, $d4, $34, $b4, $74, $f4
 $0c, $8c, $4c, $cc, $2c, $ac, $6c, $ec
 $1c, $9c, $5c, $dc, $3c, $bc, $7c, $fc
 $02, $82, $42, $c2, $22, $a2, $62, $e2
 $12, $92, $52, $d2, $32, $b2, $72, $f2
 $0a, $8a, $4a, $ca, $2a, $aa, $6a, $ea
 $1a, $9a, $5a, $da, $3a, $ba, $7a, $fa
 $06, $86, $46, $c6, $26, $a6, $66, $e6
 $16, $96, $56, $d6, $36, $b6, $76, $f6
 $0e, $8e, $4e, $ce, $2e, $ae, $6e, $ee
 $1e, $9e, $5e, $de, $3e, $be, $7e, $fe
 $01, $81, $41, $c1, $21, $a1, $61, $e1
 $11, $91, $51, $d1, $31, $b1, $71, $f1
 $09, $89, $49, $c9, $29, $a9, $69, $e9
 $19, $99, $59, $d9, $39, $b9, $79, $f9
 $05, $85, $45, $c5, $25, $a5, $65, $e5
 $15, $95, $55, $d5, $35, $b5, $75, $f5
 $0d, $8d, $4d, $cd, $2d, $ad, $6d, $ed
 $1d, $9d, $5d, $dd, $3d, $bd, $7d, $fd
 $03, $83, $43, $c3, $23, $a3, $63, $e3
 $13, $93, $53, $d3, $33, $b3, $73, $f3
 $0b, $8b, $4b, $cb, $2b, $ab, $6b, $eb
 $1b, $9b, $5b, $db, $3b, $bb, $7b, $fb
 $07, $87, $47, $c7, $27, $a7, $67, $e7
 $17, $97, $57, $d7, $37, $b7, $77, $f7
 $0f, $8f, $4f, $cf, $2f, $af, $6f, $ef
 $1f, $9f, $5f, $df, $3f, $bf, $7f, $ff
end
Link to comment
Share on other sites

The routines presented here have been REALLY useful. Even though I've seen these floating around I guess it's all about context and sometimes a kind soul to repeat what they tried to explain before :)

 

How would I use these assembly routines in a bB program? My hunch is using the asm .. end

 asm
 ldx #47
 lda #0
playfieldclear
 sta playfield,x 
 dex
 bne playfieldclear
end

But how do I feed a routine the proper variables? Mr SQLs code uses something called REVBT but I don't know how that maps to bB variables.

Link to comment
Share on other sites

The routines presented here have been REALLY useful. Even though I've seen these floating around I guess it's all about context and sometimes a kind soul to repeat what they tried to explain before :)

 

How would I use these assembly routines in a bB program? My hunch is using the asm .. end

 asm
 ldx #47
 lda #0
playfieldclear
 sta playfield,x 
 dex
 bne playfieldclear
end

But how do I feed a routine the proper variables? Mr SQLs code uses something called REVBT but I don't know how that maps to bB variables.

Loon,

you could alias a variable in bB to REVBT:

dim REVBT = i

 

Aliasing makes both variables point to the same memory location.

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...