Jump to content
IGNORED

Accessing DATA as binary array?


Gemintronic

Recommended Posts

So, RevEng thinks that inline pfread may be broken (for multi-sprite kernel). In that case I'd have to make a collision map of the playfield. Unfortunatly, SDATA statement appear to be broken in the latest bB 1.1. A multi-sprite playfield would have 32x40 elements. The normal DATA statement can only hold 256 values. It would make sense to use an array of binary values to represent either empty space (0) or a playfield pixel (1).

 

How does one use DATA as a binary array? Is there an easy way to access, say, the 107th binary element from a DATA statement?

 

Batari himself uses a binary array in his RallyB example but it's indecipherable to me.

http://www.atariage....e/#entry2566587

Edited by theloon
Link to comment
Share on other sites

Normally I'd think that one would make a function that returns a binary value from a DATA statement like so:

(assuming the DATA statement is named "leveldata")

function levelarray
rem The first argument is the x value wanted from the level data
rem The second argument is the y value wanted
levelx = temp1
levely = temp2
rem Figure out what 8-bit value that has the bit we need
whatcell = levelx * levely
rem Divide that value by 10 to get the position of the bit we want from that 8-bit value
whatbit = whatcell / 10
rem Read the 8-bit cell we want to a variable
thecell = leveldata[whatcell]
rem Return the bit we want from the 8-bit value
return thecell[whatbit]
end

 

Is this how it works?

Edited by theloon
Link to comment
Share on other sites

How does one use DATA as a binary array? Is there an easy way to access, say, the 107th binary element from a DATA statement?

 

Loon,

yes you could turn your 107th bit offset into a byte offset plus a bit offset:

Divide by 8 and grab the remainder - the 107th binary element is the 3rd bit in the 14th byte; you can check to see if the 3rd bit is on by ANDing just the third bit (%00000100). If the result is >0 the bit is set :)

 

And only keeps the bits turned on that are both turned on; since you're masking every other bit as off you will only get a zero result if the target bit you are checking for is off - if your byte was %10101010 and you AND %000000100 the results would be zero, showing the third bit was off.

Edited by Mr SQL
  • Like 1
Link to comment
Share on other sites

So, er, umm..

 

Given that you want the 251th row, 253rd column in a binary array (made out of 8-bit values) you would:

 

You divide the x value in a binary map data array by 8

You divide the y value wanted by 8

You multiply the new x and y values to get the 8-bit cell you want (DATA statements are one dimensional arrays - we're just using them as 2d)

Then you extract the bit in that cell by the remainder of y?

 

Help Mr. SQL! I feel like I'm doing an outer join with my math skills and BASIC commands :P

Edited by theloon
Link to comment
Share on other sites

LOL! I like your SQL humour Loon! :)

Aha you want x and y, not just the nth element of the binary array.

You're right about the data being a 1D array but we can change that conceptually by picking a row length. Say we want to turn this 1D array into a table (2D array) of 16x3 (X and Y) elements:

 

.byte 01010101, 01010101, 0001111, 1110111, 0000011,1111101

 

becomes:

 

byte. 10101010, 01010101

byte. 01101010, 01010101

byte. 00000011, 11111110

 

Now we can calculate X and Y coordinates with ease from our table construct.

Say you want to find the bit at the X and Y coordinates 12,2 (where 0,0 is in the upper left):

Multiply your row size (in bytes, not bits) by your Y value: 2x2 bytes=4

 

This is your offset that turns that 1D array into a 2D table :)

 

You can see that it brings us down to the start of the 3rd line; now just add the math we talked about previously to walk to the target bit - 8 goes into 12 once with 4 left over so the target bit is the 4th bit of the next byte (2nd byte in the row). Technically it is the 5th bit of that byte but we are using 0,0 offset coordinates and reading all the bits in the row from left to right :)

 

Now do an AND against that byte with a bit mask like we talked about above, masking all of the bits in the comparison except the target bit you want to check is on or off.

Edited by Mr SQL
Link to comment
Share on other sites

Okay, this is my attempt to integrate the hints Mr SQL gave me. I couldn't get div_mul16.asm to compile so I couldn't use a remainder value. I don't think I'm doing it right yet.. Since SDATA is broke I can only use 256 values per DATA statement. This means 128x128 binary values or 16x16 8-bit values.

include div_mul.asm

rem Kernel options
set smartbranching on
set romsize 4k

dim mapx = a
dim mapy = b
dim cell = c
dim cellx = d
dim celly = e
dim bit = f
dim result = g


player0:
%11000011
%10000001
%00000000
%00000000
%00000000
%00000000
%10000001
%11000011
end

playfield:
XX............................XX
X..............................X
................................
................................
................................
................................
................................
................................
................................
X..............................X
XX............................XX
end

init
COLUPF=$4E
scorecolor = $0E

rem We want to get the binary value 5 rows by 5 columns into the map data.
mapx = 5
mapy = 5
rem Convert the binary x and y into 8 bit values
rem Multiply the y value by 16 as the data array is 16 8-bit values wide
celly = (mapy * 16)
rem Divide the binary x value by 8 as each binary value is stored in an 8 bit data entry
cellx = (mapx / 
rem Add the two values to get the 8 bit cell with our binary data
cell = (mapx + celly)
rem Grab the 8 bit value from the map data
result = map[cell]
rem Grab the binary x value we want from the 8 bit value we extracted from the data
rem and show it as the score
if result[cellx] then score = 1 else score = 0
goto main

main

gosub draw_event

goto main

draw_event

drawscreen
return

data map
%11111101, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111
%10000001, %00000011, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000111, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00011000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000001, %00000010, %00000011, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00011100, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111
end

binarr.bas

Edited by theloon
Link to comment
Share on other sites

Excellent progress Loon!

 

I see you've calculated the row offset to get your Y value and then add in your x byte off set: cellx = (mapx/8)

But you need the remainder to check the bit; in this case 5/8 is zero remainder 5, or the 5th bit (reading left to right, 4th bit really) of the 1st byte in the row.

 

One way to get the byte offset and the bit offset is with a subtract loop:

 

xbyteoffset=0

subloop

if mapx<= 8 then jumparound

mapx = mapx-8

xbyteoffset=xbyteoffset+1

goto subloop

jumparound

cell = (xbyteoffset + celly)

rem mapx now holds the remainder or target bit in the cell (0-7)

rem you could use 8 handlers like these to check the status of the target bit:

rem if mapx = 0 then result = cell and %1000000 rem this will check the 1st bit reading left to right

if mapx = 1 then result = cell and %01000000

...

I'm not sure if that's the correct syntax for using AND but I know it's supported, check RT's command reference on AND'ing if it throws an error :)

Link to comment
Share on other sites

  • 2 weeks later...

Things will be easiest if you can keep one dimension

in powers of 2

 

Then you can use simple shifts and bitwise logical ops

for composing the cell and bit addresses, there by

avoiding expensive multiplys/divides

Bb will use shifts for multiplying and dividing by

low powers of two, much faster than full blown

mutiplications and divisions (I think a low power

of 2 means 8, 4, or 2)

 

 

Near as I can tell, Bb wants a constant for bit ops

so to use a variable you'll have to do it yourself

 

If you have 256 bytes that's 2048 bits

 

So say you have 128 (x coordinate) x 16 (y coordinate)

x will be 16 (bytes) * 8 (bits)

You can get the bit address (ie the bit you want in

the selected cell) by simply masking for the

lower 3 bits of x

dim mapx = a
dim mapy = b
dim cell = c
dim cellx = d

rem x mod 8
cellx = mapx & 7

rem ORing instead of addition saves a clc so it's slightly
rem faster and is possible since mapx / 8 is an integral
rem power of 2 bytes per row (ie per y)
rem mapy * 16 is done as mapy * 4 * 4 so that Bb will use
rem shifts rather than invoking a mutilplication subroutine
cell = mapy * 4 * 4 | mapx / 8

if map[cell] & setbits[cellx] then score = 1 else score = 0


rem use an adressable set of masks so you can point
rem to them with a variable
data setbits
%10000000, %01000000, %00100000, %00010000
%00001000, %00000100, %00000010, %00000001
end

data clearbits
%01111111, %10111111, %11011111, %11101111
%11110111, %11111011, %11111101, %11111110
end


data map
%11111101, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111
%10000001, %00000011, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000111, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00011000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000001, %00000010, %00000011, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00011100, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000001
%11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111
end

 

If you want your map to be something closer to square, say, 40 x 51

You could use a look up table for the mutiplication or hard code it

ie write a dedicated mutiply routine (or just use the built in

multiplication routine which would be slower).

I think I'd go with a look up table (if there's room), it'd only cost

an extra 40 bytes or so and be a lot faster.

 

Here's hard coded for 40 ie rows of 5 bytes of 8 bits

Each row is 5 bytes so you need to mutiply y by 5

(still uses the same map data, but I'm sure it doesn't make

sense here)

 

dim mapx = a
dim mapy = b
dim cell = c
dim cellx = d

rem x mod 8
cellx = mapx & 7

rem have to use addition this time
rem 5 = 1 + 4
cell = mapy + mapy * 4 + mapx / 8

if map[cell] & setbits[cellx] then score = 1 else score = 0


rem use an adressable set of masks so you can point
rem to them with a variable
data setbits
%10000000, %01000000, %00100000, %00010000
%00001000, %00000100, %00000010, %00000001
end

data clearbits
%01111111, %10111111, %11011111, %11101111
%11110111, %11111011, %11111101, %11111110
end


data map
%11111101, %11111111, %11111111, %11111111, %11111111
%11111111, %11111111, %11111111, %11111111, %11111111
%11111111, %11111111, %11111111, %11111111, %11111111
%11111111, %10000001, %00000011, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000001, %10000000, %00000000, %00000111
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000001, %10000000, %00000000
%00000000, %00011000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000001, %10000000
%00000000, %00000000, %00000001, %00000010, %00000011
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000
%00011100, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000001, %10000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000001, %10000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000001, %10000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000001, %10000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000001
%10000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000001, %10000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000001, %10000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000001, %10000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000001, %10000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000000
%00000000, %00000000, %00000000, %00000000, %00000001
%11111111, %11111111, %11111111, %11111111, %11111111
%11111111, %11111111, %11111111, %11111111, %11111111
%11111111, %11111111, %11111111, %11111111, %11111111
end

 

edit: actually

cell = mapy * 4 + mapy + mapx / 8

is faster because Bb doesn't stash mapy

on the stack while it computes mapy * 4

 

edit some more:

I suppose you all know this already.

 

It's better to avoid the stack altogether

cell = mapx / 8
cell = mapy * 4 + mapy + cell

saves 2 bytes and 7 cycles

 

yet more edit: fixed setbits and clearbits

which were good for bit variables but not screen

stuff

Edited by bogax
Link to comment
Share on other sites

  • 3 weeks later...

.

.

edit some more:

I suppose you all know this already.

 

It's better to avoid the stack altogether

cell = mapx / 8
cell = mapy * 4 + mapy + cell

saves 2 bytes and 7 cycles

 

This part doesn't compile, claiming there are duplicate labels. So, do I need to dimension a new "cell"? I tried changing it to cellx, but that causes more problems.

Link to comment
Share on other sites

.

.

edit some more:

I suppose you all know this already.

 

It's better to avoid the stack altogether

cell = mapx / 8
cell = mapy * 4 + mapy + cell

saves 2 bytes and 7 cycles

 

This part doesn't compile, claiming there are duplicate labels. So, do I need to dimension a new "cell"? I tried changing it to cellx, but that causes more problems.

 

I can't explain that.

 

All I can say is it worked for me.

 

This was the result:

.L08 ; cell = mapx / 8

LDA mapx
lsr
lsr
lsr
STA cell
.L09 ; cell = mapy * 4 + mapy + cell

; complex statement detected
LDA mapy
asl
asl
CLC
ADC mapy
CLC
ADC cell
STA cell
.
; 

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...