bogax
Members-
Content Count
902 -
Joined
-
Last visited
Content Type
Profiles
Member Map
Forums
Blogs
Gallery
Calendar
Store
Everything posted by bogax
-
yes you want to scroll one part of the sprite while the other stays (more or less) constant the obvious thing is to use two sprites if you can you could flicker the a single sprite ie multiplex the sprite in bB, display the two parts seperately on alternate frames you could put the sprite in ram not sure you could find 40 bytes you wouldn't have room for much else I can't think of any other way to do it with the standard kernel
-
I'm not sure what you are trying to achieve (why scroll ?) you can scroll through the sprite data or you can just point at different data here's some sprite-pointer-animation stuff might give you some ideas
-
there's some stuff with tables here the last one (that notes that it's not very accurate) could be made accurate without too much trouble I should have done an accurate one and one not so accurate for comparison, but I was in a hurry I doubt the difference would be obvious edit: there's also this thread I know I've seen 6502 CORDIC code but I can't remember where
-
Programming a game and when I run it, it doesn't work.
bogax replied to tuckrix7865's topic in batari Basic
works for me with bB.1.1d.reveng37 and Stella 4.5 -
it looks to me like the multisprite kernel doesn't have the paddle code there may not be time to do both sprite multiplexing and paddle reading
-
I don't know about VBB but bB its self doesn't have any trouble with if x = 1 then if b = 4 then score = score + 1 however if x = 1 && b = 4 then score = score + 1 produces exactly the same code for a random number between 16..124 you need a random number 0..108 + 16 108 = 12 * 9 rand produces numbers 0..255 and you are limited to numbers 0..255 in a byte and you'd like to keep as many bits as possible for accuracy 9 is 8 + 1 12 is 1.5 * 8 temp1 = rand & 127 will give you (approximately) 1 * 128 then temp1 = temp1/2 + temp1 will give you (approximately) 0..192 = 1.5 * 128 = 12 * 16 16 = 2 * 8 so now temp1 = (temp1/8 + temp1) = ((12 * 16 / + 12 * 16) = 12 * (16 / 8 + 16) = 12 * (1 + * 2 = 12 * 9 * 2 = 108 * 2 so temp1 = rand & 127 : temp1 = temp1/2 + temp1 : temp1 = (temp1/8 + temp1)/2 + 17 due to starting with 127 instead of 128 (max) and rounding, the numbers will be 17..123 due to the limited accuracy the distribution may not be as nice as you'd like if you realy want 16..124 then its 127 * 109/127 which would be something like this temp1 = rand/2 : temp1 = ((((temp1/4 + temp1)/2 + temp1)/4 + temp1)/2 + temp1)/2 + 16 in this case rand/2 gives you essentially the same as rand & 127 you've got redundant if statements eg if pfscore1 = 0 then AUDV0 = 0 if pfscore1 = 0 then AUDV1 = 0 could be done this way if pfscore1 = 0 then AUDV0 = 0 : AUDV1 = 0 and doing assignments to the same value consecutively on the same line saves you something it loads 0 into the accumulator and then stores it to AUDV0, if it's done consecutively on the same line bB won't load 0 again for the store to AUDV1 since 0 is already in the accumulator. it'll just store to AUDV1 it could also be written like this if !pfscore1 then AUDV0 = 0 : AUDV1 = 0 which also saves you something. because of the way bB and the processor work it doesn't do an explicit compare to zero you still didn't show your paddle code I suspect the scoring is not working the way you'd like
-
at first glance line 973 temp5 = (_PEEK_Frame_Counter) + 1 : _POKE_Frame_Counter temp5 : on temp5 goto donef1 donef1 f1 f22 f33 f44 unless you're limiting frame counter to 4 somewhere I didn't see yet, temp5 could go up to 16 and you've only got 6 target labels
-
Can someone explain pointers to me?
bogax replied to Electrk's topic in 2600 Programming For Newbies
um, notice one of those is even and one is odd? -
the sine table is built on the (possibly) spurious theory that it's good to start with the best accuracy and then throw away what you don't need so the sines are 0..255 and which would give you sines -255..255 the sine function immediately throws some of that away and returns sines that range 0..255 those values are scaled to fit by multiplying by the reciprocal of the scale factor that's what the scl function does if you just want a different radius that can be baked into the sine table dim angle = a.c dim tangle = temp1 angle = 0 gosub su loop temp1 = angle/4 player0x = sinetbl[temp1] + 42 temp1 = (angle - 64)/4 player0y = sinetbl[temp1] + 7 angle = angle + 0.5 COLUP0 = $3A COLUP1 = $14 drawscreen goto loop data sinetbl 38, 42, 45, 49, 53, 56, 59, 62 65, 67, 70, 72, 73, 74, 75, 76 76, 76, 75, 74, 73, 72, 70, 67 65, 62, 59, 56, 53, 49, 45, 42 38, 34, 31, 27, 23, 20, 17, 14 11, 9, 6, 4, 3, 2, 1, 0 0, 0, 1, 2, 3, 4, 6, 9 11, 14, 17, 20, 23, 27, 31, 34 end su player0: %00000000 %00000000 %00011000 %00111100 %00111100 %00011000 %00000000 %00000000 end player1: %00111100 %01111110 %11111111 %11111111 %11111111 %11111111 %01111110 %00111100 end COLUPF = $48 player1x = 80 player1y = 48 return if you want to vary the radius on the fly probably the easiest way is to scale the sines to suit here the sines are scaled using an approximate reciprocal calulated from the radius you can vary the radius from 4..40 using joy0 up-down none of it is very accurate the sine table is not very accurate the scl function is not very accurate and the reciprocal approximation is not very accurate dim angle = a.c dim tangle = temp1 angle = 0 gosub su dim num = temp1 dim mul = temp2 r = 20 loop f = (SWCHA ^ $FF) & f if f{4} then r = r + 1 : if r > 40 then r = 4 if f{5} then r = r - 1 : if r < 4 then r = 40 f = SWCHA temp1 = angle/4 temp1 = sinetbl[temp1] temp2 = r * 2 temp1 = scl(temp1,temp2) player0x = temp1 + 80 - r temp1 = (angle - 64)/4 temp1 = sinetbl[temp1] temp2 = r * 2 temp1 = scl(temp1,temp2) player0y = temp1 + 48 - r angle = angle + 0.5 COLUP0 = $3A COLUP1 = $14 drawscreen goto loop ; multiply by .328125 so scales 255 -> 83 function scl asm lda #$00 sec ror mul loop bcc shift adc num shift ror enter lsr mul bne loop rts end data sinetbl 127, 139, 151, 163, 175, 186, 197, 207 216, 225, 232, 239, 244, 248, 251, 253 253, 253, 251, 248, 244, 239, 232, 225 216, 207, 197, 186, 175, 163, 151, 139 126, 114, 102, 90, 78, 67, 56, 46 37, 28, 21, 14, 9, 5, 2, 0 0, 0, 2, 5, 9, 14, 21, 28 37, 46, 56, 67, 78, 90, 102, 114 end su player0: %00000000 %00000000 %00011000 %00111100 %00111100 %00011000 %00000000 %00000000 end player1: %00111100 %01111110 %11111111 %11111111 %11111111 %11111111 %01111110 %00111100 end COLUPF = $48 player1x = 80 player1y = 48 return circle64_baked.bas circle64_baked.bin circle64_scaled.bas circle64_scaled.bin
-
I forgot to mention that in the case of the line segment circle the table is matched to the number of steps in the circle so if you change the number of steps the circle changes it will get larger or smaller and if things don't add up just right it will probably wobble
-
here's one that uses a sine table dim angle = a.c dim tangle = temp1 angle = 0 gosub su loop temp3 = sine(angle) temp3 = scl(temp3) player0x = temp3 + 37 temp3 = angle - 64 temp3 = sine(temp3) temp3 = scl(temp3) player0y = temp3 + 7 angle = angle + 1.0 COLUP0 = $3A COLUP1 = $14 drawscreen goto loop ; multiply by .328125 so scales 255 -> 83 function scl asm lda temp1 lsr lsr adc temp1 ror lsr adc temp1 ror lsr rts end function sine temp2 = tangle if tangle{6} then temp2 = temp2 ^ %00111111 ; if its an odd quadrant complement the angle in 64 (64 is one quadrant) temp2 = (temp2 & %00111111) ; scale to index table 0..63 /2 for 32 elements /4 for 16 elements temp2 = sinetbl[temp2]/2 if tangle{7} then temp2 = 255 - temp2 ; if the angle is greater than 128 then complement the sine in 128 temp2 = temp2 + 128 ; add an offset so the sine is 0..255 no negatives return ; data sinetbl ; 0, 50, 74, 98, 121, 142, 162, 181 ; 198, 213, 226, 237, 245, 251, 255, 255 ;end ; data sinetbl ; 0, 25, 37, 50, 62, 74, 86, 98 ; 109, 120, 131, 142, 152, 162, 171, 180 ; 189, 197, 205, 212, 219, 225, 231, 236 ; 240, 244, 247, 250, 252, 254, 255, 255 ;end data sinetbl 0, 13, 19, 25, 31, 38, 44, 50 56, 62, 68, 74, 80, 86, 92, 98 104, 109, 115, 121, 126, 132, 137, 142 147, 152, 157, 162, 167, 172, 177, 181 185, 190, 194, 198, 202, 206, 209, 213 216, 220, 223, 226, 229, 231, 234, 237 238, 241, 243, 245, 247, 248, 250, 251 252, 253, 254, 255, 255, 255, 255, 255 end su player0: %00000000 %00000000 %00011000 %00111100 %00111100 %00011000 %00000000 %00000000 end player1: %00111100 %01111110 %11111111 %11111111 %11111111 %11111111 %01111110 %00111100 end COLUPF = $48 player1x = 80 player1y = 48 return here's one that uses a smaller sine table to form a circle from a set of line segments dim angle = a.c dim tangle = temp1 angle = 0 gosub su loop temp3 = sine(angle) x = x + temp3 player0x = scl(x) player0x = player0x + 39 temp3 = angle + 64 temp3 = sine(temp3) y = y + temp3 player0y = scl(y) player0y = player0y + 6 angle = angle + 1.0 COLUP0 = $3A COLUP1 = $14 drawscreen goto loop ; multiply by .328125 so scales 255 -> 83 function scl asm lda temp1 lsr lsr adc temp1 ror lsr adc temp1 ror lsr rts end function sine temp2 = tangle & %00111111 if tangle{6} then temp2 = 64 - temp2 ; if its an odd quadrant complement the angle in 64 (64 is one quadrant) temp2 = (temp2 & %00111111)/8 ; scale to index table 0..63 -> 0..7 temp2 = sinetbl[temp2] if tangle{7} then temp2 = 0 - temp2 ; if the angle is greater than 128 then negate temp2 = temp2 return data sinetbl 0, 1, 1, 2, 2, 3, 3, 3 end su player0: %00000000 %00000000 %00011000 %00111100 %00111100 %00011000 %00000000 %00000000 end player1: %00111100 %01111110 %11111111 %11111111 %11111111 %11111111 %01111110 %00111100 end COLUPF = $48 x = 0 : y = 128 : angle = 0 player1x = 80 player1y = 48 return here's one that uses a parabolic aproximation of sines-cosines if you look closely you'll see it's actually sort of elliptical dim dx = v dim dy = w gosub su loop c = c + 1 if c & 7 then skip if x{7} then dx = dx - 1 else dx = dx + 1 x = x + dx player0x = scl(x) player0x = player0x + 34 if y{7} then dy = dy - 1 else dy = dy + 1 y = y + dy player0y = scl(y) player0y = player0y + 2 skip COLUP0 = $3A COLUP1 = $14 drawscreen goto loop ; multiply by .34375 so scales 247 -> 84 function scl asm lda temp1 lsr adc temp1 ror lsr adc temp1 ror lsr rts end su player0: %00000000 %00000000 %00011000 %00111100 %00111100 %00011000 %00000000 %00000000 end player1: %00111100 %01111110 %11111111 %11111111 %11111111 %11111111 %01111110 %00111100 end COLUPF = $48 dx = $0E : x = $7F dy = $00 : y = $F7 player1x = 80 player1y = 46 return circle.bas circle.bas.bin circle2.bas circle2.bas.bin circle3.bas circle3.bas.bin
-
indexes are limited to 8 bits so it's definetely best to limit your tables to 256 bytes when possible to that end I wrote a bit of javascript that transposes data so that each column goes into it's own table for those instances where you need two levels of indirection and still need to compute an index into a table of tables so to speak I wouldn't use if statements it's probably smaller and faster to use a lookup table if you can't fit your table of tables in to 256 bytes you can still do it with microscopic amounts of asm using RevEng's example if roomIndex=0 then roomNumber=room0Data[level] if roomIndex=1 then roomNumber=room1Data[level] if roomIndex=2 then roomNumber=room2Data[level] I'd do it like this (there may be pathological cases where it would be better to use if statments though) index = roomOffset[roomIndex] ; room_offset is an LUT for number of rooms x number of levels, zero based roomNumber = roomData[level] ; so if your room index ranges to 0..14 and there are 10 levels your roomOffset table is data roomOffset 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140 end ; and your roomData table will be 150 bytes if the table is more than 256 bytes it'd be something like this dim indexLo = temp3 dim indexHi = temp4 def load_indirect = callmcro ldin ; looks up a byte from a 16 bit address, lo byte in temp3 hi byte in temp4 ; indexed by the value in the variable specified by the first parameter ; and puts it in to the second parameter variable macro ldin asm ldy {1} lda (temp3),y sta {2} end end indexLo = roomOffsetLo[roomIndex] ; roomOffsetLo is a table of the lo bytes of the offset indexHi = roomOffsetHi[roomIndex] ; roomOffsetHi is a table of the hi bytes of the offset load_indirect level roomNumber ; "<" signifies the lo byte ">" is the hi byte ; these values/expressions are asm not bB data roomOffsetLo <(roomData + 0), <(roomData + 10), <(roomData + 20), <(roomData + 30), <(roomData + 40), <(roomData + 50), <(roomData + 60), <(roomData + 70) <(roomData + 80), <(roomData + 90), <(roomData + 100), <(roomData + 110), <(roomData + 120), <(roomData + 130), <(roomData + 140) end data roomOffsetHi >(roomData + 0), >(roomData + 10), >(roomData + 20), >(roomData + 30), >(roomData + 40), >(roomData + 50), >(roomData + 60), >(roomData + 70) >(roomData + 80), >(roomData + 90), >(roomData + 100), >(roomData + 110), >(roomData + 120), >(roomData + 130), >(roomData + 140) end you break even somwhere around three or four if statements it would also be possible to calculate the offsets at run time and if your offsets are a power of 2 that could be fairly fast (eg in this case, if the number of levels were a power of 2) you could also do something in between like group them into tables <= 256 bytes and use if statements to choose a table
-
I don't know if this would work given the problem you're having but you don't need a labyrinthine system of gotos you'd put a single instance of the screenrefresh routine in some bank and return otherbank then in each bank you'd put a single goto screenrefresh bankx then when you want to refresh you'd gosub to the goto edit I don't know how it works with DPC+ if you're just bank switching and if you're in the appropriate bank you can use asm jsr drawscreen end and save the bank switch for the drawscreen at least that works in stella
-
Again I'm no expert but I think that's not going to work with DPC+ Thats for a different sort of RAM expansion I think what you want is here I think iesposta is correct I think it should be possible to poke the player colors edit OK maybe not at least I haven't been able to get it to work (I thought maybe you could point the player color pointers at the stack)
-
Yes but it's read only only because it's in ROM the variables are in sequence in memory so a[0] = 3 a[1] = 4 sets a to 3 and b to 4
-
Here is something similar in bB with the tables the tables have redundancies and symmetries that could be exploited to make them smaller but it would be slower I should have mentioned that this assumes that directions is limited to 0..31 dim tmp88 = temp4.temp3 if !joy0up then skip temp3 = Vx_lo[direction] : temp4 = Vx_hi[direction] : xVel = xVel + tmp88 temp3 = Vy_lo[direction] : temp4 = Vy_hi[direction] : yVel = yVel + tmp88 skip data Vx_lo 8, 7, 6, 5, 4, 3, 2, 1 248, 255, 254, 253, 252, 251, 250, 249 248, 249, 250, 251, 252, 253, 254, 255 8, 1, 2, 3, 4, 5, 6, 7 end data Vx_hi 0, 0, 0, 0, 0, 0, 0, 0 255, 255, 255, 255, 255, 255, 255, 255 255, 255, 255, 255, 255, 255, 255, 255 0, 0, 0, 0, 0, 0, 0, 0 end data Vy_lo 0, 255, 254, 253, 252, 251, 250, 249 0, 249, 250, 251, 252, 253, 254, 255 0, 1, 2, 3, 4, 5, 6, 7 0, 7, 6, 5, 4, 3, 2, 1 end data Vy_hi 0, 255, 255, 255, 255, 255, 255, 255 0, 255, 255, 255, 255, 255, 255, 255 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0 end I may have gotten the tables right edit: oops nope (fixed now) (I hope )
-
first you consolidate the redundant predicates then use a lookup table here's a macro to lookup 8.8 values you'll have to figure out the table(s) yourself untested but it should give you the idea dim tmp88 = temp4.temp3 ; lookup an 8.8 constant from a table ; the table is in two data statements one for hi bytes and one for lo bytes ; takes three parameters ; a variable to take the looked up value it must be in consecutive locations ; eg variable a for the lo byte and b for the hi byte b.a or temp4.temp3 etc ; an 8 bit index ; the name of the table if the name supplied is "table" then the data statements ; must be named tablelo, tablehi macro lu88 asm ldx {2} lda {3}lo,x sta {1}-1 lda {3}hi,x sta {1} end end if joy0up then callmacro lu88 tmp88 direction Vx_table : xVel = xVel + tmp88 : callmacro lu88 tmp88 direction Vy_table : yVel = yVel + tmp88
-
a pointer is a location in memory that contains the location (memory address) of something else I suppose by that definition a pointer could be a constant but they're always variables technically I misspoke I should have said that it passes a reference since I was talking about the value the pointer would contain (which in this case would be the address of the playercolor table)
-
I'm not all that familiar with the DPC+ kernel It looks to me like it just passes a pointer to the color table to the ARM code. so short of modifying the kernel you could have a routine that passed a pointer from a variable, but the colors themselves would have to be in a ROM table and they'd have to be in the graphics bank and I think the only way to get them there is with a player color statement it might be possible to have all the colors in one big playercolor statement though
-
draw a line then poke a hole in it
-
functions are pretty much useless (or worse) in bB about the only thing you can do is assign it to a variable use a subroutine you don't need (or want) an end statement, just return whatever is in the accumulator is what the functiion returns a function always passes two values and puts them in temp1 and temp2 whether you supply parameters or not function dummy b = 3 return c = dummy() c contains 3 function void return l = 5 d = void() temp1 and d contain 5
-
Assuming you mean you want something to happen once when the fire button is pressed and not happen again until the fire but is (released and) pressed again check the state of the fire button and if it wasn't pressed last time and is pressed this time do whatever save the current state for the next check something like if joy0fire && previous_state = 0 then do_something = 1 previous_state = 0 if joy0fire then previous_state = 1 if do_something then go_do_it ; or temp1 = previous_state previous_state = 0 if joy0fire then previous_state = 1 if temp1 = 0 && previous_state = 1 then go_do_something
-
I don't quite follow you so maybe I'm missing something why don't you just do something like schnooga=0 for temp1=0 to 17 if shnooga = 2 then skip_schnooga if ooga-2=booga[temp1] then schnooga=1 if ooga-1=booga[temp1] then schnooga=2 skip_schnooga next you can do somthing like modulo for powers of 2 in binary using AND (ie "&" in bB) 15 mod 8 is 15 & 7 7 being 8 - 1 in binary %00001000 (8 ) and %00000111 (7) bB does a bitwise AND bits in the result are the ANDing of corresponding bits in the operands AND is 0 AND 0 = 0 0 AND 1 = 0 1 AND 0 = 0 1 AND 1 = 1 %00001111 (15) & %00000111 (7) = %00000111 (7) %00001110 (14) & %00001101 (13) = %00001100 (12) the player 1..9 variables are in order in memory so you should be able to eg address player3x as player1x[2] but I haven't tryed it
-
room_shape[room] is in ROM, you can't add 1 to it
-
Heck! Darn! (other obscenities as required) After actually thinking about it for two seconds it occured to me that, since rand16 goes through every number 1..65535, 0 must come up(since there are certainly combinations of bytes that will produce a 0 when XORed). use rand in an if statement and it just tests the rand variable, it doesn't actually call the rand routine dim rand16 = aux1 scorecolor = $1E COLUPF = $76 for i = 0 to 255 for j = 0 to 255 temp1 = rand if temp1 = 0 then score = score + 1 if !(j & $1F) then drawscreen next score = score + 1000 next scorecolor = $3A loop drawscreen goto loop
