Jump to content

bogax

Members
  • Posts

    942
  • Joined

  • Last visited

Everything posted by bogax

  1. There are things I wish you could do (more directly) in bB And there are common idioms that I think it would be useful to have built in Things that are not hard to do now but could be more convenient Karl G suggested in another thread some facility for multidefinition sprites for animations and such Ranged random numbers is another that comes up frequently Computed bit indexes Maybe transposed tables so you could specify values in sets for eg the sound registers and have them go into seperate tables Perhaps some built in division-by-a-constant routines similar to mutiplication by a constant My wish list is more nuts and bolts I'd like more direct access to the CPU registers and flags It would be nice if the registers were more fully integrated in to the syntax But even a few assembly instructions would help ACC = [expression] do the normal thing but suppress the assignment just leave the result in the accumulator var = mem[XREG] do the normal thing but suppress the loading of x TAX, TXA, LDX, STX so you could do something like ACC = [expression] : TAX : Px = tablex[XREG] : Py = tabley[XREG] without generating a lot of extranious load and store instructions (of course XREG = [expression] would be nicer) Some dedicated if constructs for testing flags would be nice if CARRY then ... or if !CARRY then ... no predicate expression, just test the carry flag (likewise for the z, n, v flags) I generally like the way macros work, although I like to hide the callmacro key word with a def statement But using macros gets messy when trying to let the assembler know what it needs to know about what bB knows Perhaps I need a preprocessor ... I'd be curious to see other's wish lists
  2. heh heh I think they ought to just bite the bullet and learn enough about what's going on under the hood to know what they're doing Its not THAT complicated. I think it would be useful to have some lowest-common-denominator way of choosing among multiple sprite definitions for animations and such built in to bB Something more stream-lined than the usual clumsy, wasteful string of if-thens Given the variety of ways it might be done and the possible tradeoffs it might be better to have a utility that generated bB or assembly and could be more general (in addition to whatever got included in bB) Besides, if bB is going to be augmented I'd rather see the effort go in to other things.
  3. hmm You shouldn't need to align the table as a whole. Freshbrood didn't post his code so it's hard to know what's going on there. As far as aligning the table goes, what's wrong with the align directive you were using? bB sometimes includes some assembly to generate the correct padding. (15 is the length of the table -1) 2511 f730 - if (<*) > (<(*+15)) 2512 f730 - repeat ($100-<*) 2513 f730 - .byte 0 2514 f730 - repend 2515 f730 endif
  4. correct and as needed so eg in the example I pointed to the height never changes so it's set once A slight elucidation of Karl G's point, the table can span a page boundary but an individual sprite definition should not cross a page boundary If all the definitions are in a single page then you'll only need to change the lo byte
  5. This does something like what you want I think.
  6. Functions are gosubs with additional overhead They always pass two parameters whether you specify them or not (but bB is likely to complain if you don't pass any parameters) You can sometimes sort of use them in place of an operand or an expression But I'd just use a subroutine. More predicable. Functions are so finicky they're almost (but not quite) useless Subroutines have overhead, but not much. A gosub uses 12 cycles and two bytes of the stack a = b + c uses 11 cycles Depending on the kernel, the stack might be only 6 bytes so you could only go 3 levels deep provided you don't use any expressions that use stack (and I think drawscreen goes 3 deep) And the way bB uses the stack in expressions is all kinds of goofy
  7. If like Karl G you find tables and indexes and sprite timing and addition and subtraction and stuff painful, assembly will be pure agony Best stick with writing out multiple copies of your sprite data and strings of redundant if then spaghetti going "is this it? is this it?" Any way you don't need any assembly for your sprite tables tl;dr "loading player graphics from data tables is a pain, so avoid it if you can." is an exceptionally silly sentiment
  8. That's kinda like asking "why does this clock keep ticking when I'm not looking at the time" That's pretty much all the TIA does The 12th row is for scrolling I assume Here's 12 rows (well, more actually)
  9. I avoid using the forum to edit replys as much as possible I use a text editor and then just paste it wholesale then maybe fix it in the forum editor if I think it relly needs it Seems like it always messes something up Your colors are not a multiple of 24 (or 23, your player defintion is 23 lines) You avoid division if possible because it takes a long time and quite often there's something else you can do to avoid or minimize the use of division It occurs to me that you may be getting confused by the way the names are used So here's a bit of a ramble throught some of the intricacies First the processor deals in bytes and, generally, so does bB A byte is 8 bits and can represent values 0..255 That's not enough for some stuff, memory addresses in particular So two bytes are used which gives you 0..65535 But they still only get dealt with one byte at a time It's kinda like a two digit decimal number has a ones place and a tens place except we have a ones place and a 256 place Each of the 256 place is a "page" of 256 bytes With indexing you start with a 16 bit number and add a 8 bit number to it ie you start with a value 0..65535 and add a value 0..255 to it Kinda like (in decimal) taking a 0..99 number and adding a number 0..9 If the result of adding the ones places is more than the ones place can "hold" you need to do a carry. That takes extra time and that messes up the kernel timing (Its only going to matter for stuff used in the kernel where timing is tight, not for ordinary data in bB) So you need to be sure that the result of adding your index to your base location doesn't result in a location in the next page, ie doesn't cause a carry into the 256's byte of your 16 bit address For example, in the case of the your color table with 24 colors, if the player0colors is a two byte, 16 bit memory location which specifies a memory location (of the color table) then if the ones byte ie the value contained in player0colorslo is within 24 of 256 ie if it's greater than 255 - 24, then the kernel will try to reach into the next page and that will mess up the timing Mind you the complete table of colors can cross the page boundary as long as there's a whole group of 24 on this side of the page boundary and a whole group on the other side Assuming they're contiguous then the one in the next page must start at zero in the page As long as they're wholly contained in a page it doesn't matter where they are in the page and normally that's how it works with individual color defintions Putting them all in one table means they have to align with a page boundary (if the overall table straddles the page boundary) Player0pointerlo is the name for the memory address for the first byte of the 16 bit address in memory of the table that contains the player definition To the assembler its a constant, $8A as defined in 2600basic.h In the kernel it's the first byte of the two bytes of memory that contain the address (location) in memory of the player definition table bB take it as an alias for the value it contains, the lo byte of that address So player0pointerlo is also the constant $8A If I define a constant as player0pointerlo + 1 that constant name will be an alias for the same value as player0pointerhi, $8B which will be the address of the location in memory after (the location specified by) player0pointerlo, ie it will be location $8B In bB if I say a = player0pointer + 1 it will get the contents of memory location $8A add one to it and put the result in memory location $D4 (the location in memory of variable a, also specified in 2600basic.h) (of course, it actually compiles code to do that) Now back to the decimal anology Suppose memory is 100 locations 00..99 Each "byte" (location) can hold a single digit Our player height is 3 and we want 5 possible color schemes of 3 bytes each Our color table will be 15 bytes Say the colors table just happens to begin at location 65 Player0colors will contain 5 and the location after player0colors will contain 6 the kernel will look at player0colors find 65, add 2 to it and look into the table at location 67 for the first color For three lines (the player height) with three colors the index values will be 0..2. The locations in the table will be 65..67 The high byte, ie the "page" will be 6 for each of those locations and doesn't change. No carry. The second set of colors will start after the first set beginning at location 68 We choose it by setting (the location in memory refered to by) player0colors to 8 and the following location to 6 Now when the kernel looks for line one it gets 68 adds 2 and gets 70. The page has changed, that needs a carry to the page digit, that takes extra time, that screws up the kernel timing. The second set of colors straddles the page boundary at locations 68..70. To fix it we can add padding, two zeros to align the colors boundary with the page boundary 65..66 will contain 0 the colors table will start at 67 the individual color sets will be at locations 67..69, 70..72, 73..75 etc Each set is wholly contained within a page. You won't be able to do that if the whole table straddles more than one page boundary and the color sets are not an integral divisor of the page length ie (in this decimal anology with "pages" of 10 "bytes") it cant be done for two pages if the player height is 3 but a player height of 5 will work You could add padding to the middle of the table or something like that but it would screw up the regularity of the table in which case a look up table would definitely work better than multiplying Also the individual color tables don't have to be in one big table, even if you're multiplying to get the index You would want them to be contiguous if you're multiplying
  10. I realized I should be doing an increment or a reset of seconds/minutes, not both since I'm going for speed And now the table needs padding to page align Shaves 36 cycles so worst case is ~80 cycles set optimization noinlinedata dim frames = t.s dim seconds_lo = player0pointerlo dim seconds_hi = player0pointerhi dim minutes_lo = player1pointerlo dim minutes_hi = player1pointerhi dim seconds = seconds_hi.seconds_lo dim minutes = minutes_hi.minutes_lo def frame_time = 4.274 def reset_seconds = seconds_lo = Pxtlo : seconds_hi = Pxthi def reset_minutes = minutes_lo = Pxtlo : minutes_hi = Pxthi def inc_seconds = seconds = seconds + 0.02 def inc_minutes = minutes = minutes + 0.02 const max = 59 * 5 const rollover = Pxtbl + max const Pxthi = >Pxtbl const Pxtlo = <Pxtbl const rollover_hi = >rollover const rollover_lo = <rollover player0x = 79 : player1x = 70 player0y = 40 : player1y = 40 player0height = 4 : player1height = 4 reset_seconds reset_minutes loop COLUP0 = $1C : COLUP1 = $1C drawscreen temp1 = t frames = frames + frame_time if t > temp1 then loop if seconds_lo <> rollover_lo then inc_seconds : goto loop ; the player height and the bytes per page are coprime ; so rollover_lo only occurs once per cycle reset_seconds if minutes_lo <> rollover_lo then inc_minutes : goto loop reset_minutes goto loop data table_padding ; padding to align player definitions with a page boundary $00 end data Pxtbl $77, $55, $55, $55, $77, $71, $51, $51, $51, $71 $77, $54, $57, $51, $77, $77, $51, $57, $51, $77 $71, $51, $57, $55, $75, $77, $51, $57, $54, $77 $77, $55, $57, $54, $77, $71, $51, $51, $51, $77 $77, $55, $57, $55, $77, $77, $51, $57, $55, $77 $17, $15, $15, $15, $17, $11, $11, $11, $11, $11 $17, $14, $17, $11, $17, $17, $11, $17, $11, $17 $11, $11, $17, $15, $15, $17, $11, $17, $14, $17 $17, $15, $17, $14, $17, $11, $11, $11, $11, $17 $17, $15, $17, $15, $17, $17, $11, $17, $15, $17 $77, $45, $75, $15, $77, $71, $41, $71, $11, $71 $77, $44, $77, $11, $77, $77, $41, $77, $11, $77 $71, $41, $77, $15, $75, $77, $41, $77, $14, $77 $77, $45, $77, $14, $77, $71, $41, $71, $11, $77 $77, $45, $77, $15, $77, $77, $41, $77, $15, $77 $77, $15, $75, $15, $77, $71, $11, $71, $11, $71 $77, $14, $77, $11, $77, $77, $11, $77, $11, $77 $71, $11, $77, $15, $75, $77, $11, $77, $14, $77 $77, $15, $77, $14, $77, $71, $11, $71, $11, $77 $77, $15, $77, $15, $77, $77, $11, $77, $15, $77 $17, $15, $75, $55, $57, $11, $11, $71, $51, $51 $17, $14, $77, $51, $57, $17, $11, $77, $51, $57 $11, $11, $77, $55, $55, $17, $11, $77, $54, $57 $17, $15, $77, $54, $57, $11, $11, $71, $51, $57 $17, $15, $77, $55, $57, $17, $11, $77, $55, $57 $77, $15, $75, $45, $77, $71, $11, $71, $41, $71 $77, $14, $77, $41, $77, $77, $11, $77, $41, $77 $71, $11, $77, $45, $75, $77, $11, $77, $44, $77 $77, $15, $77, $44, $77, $71, $11, $71, $41, $77 $77, $15, $77, $45, $77, $77, $11, $77, $45, $77 end hour_clock_02.bas hour_clock_02.bas.bin
  11. Here is another clock It counts up seconds to one hour It uses a brute force approach with every thing in 300 bytes of tables/ROM It's more accurate and uses 16 fractional bits (of a second) for the increment it takes about 110 cycles (not counting drawscreen) for the loop in the worst case, ie rollover to 00 00 set optimization noinlinedata dim frames = t.s dim seconds_lo = player0pointerlo dim seconds_hi = player0pointerhi dim minutes_lo = player1pointerlo dim minutes_hi = player1pointerhi dim seconds = seconds_hi.seconds_lo dim minutes = minutes_hi.minutes_lo def frame_time = 4.274 def reset_seconds = seconds_lo = Pxtlo : seconds_hi = Pxthi def reset_minutes = minutes_lo = Pxtlo : minutes_hi = Pxthi const max = 60 * 5 const rollover = Pxtbl + max const Pxthi = >Pxtbl const Pxtlo = <Pxtbl const rollover_hi = >rollover const rollover_lo = <rollover player0x = 79 : player1x = 70 player0y = 40 : player1y = 40 player0height = 4 : player1height = 4 reset_seconds reset_minutes loop COLUP0 = $1C : COLUP1 = $1C drawscreen temp1 = t frames = frames + frame_time if t > temp1 then loop seconds = seconds + 0.02 if seconds_lo <> rollover_lo then loop ; the player height and the bytes per page are coprime ; so rollover_lo only occurs once per cycle reset_seconds minutes = minutes + 0.02 if minutes_lo <> rollover_lo then loop reset_minutes goto loop data Pxtbl $77, $55, $55, $55, $77, $71, $51, $51, $51, $71 $77, $54, $57, $51, $77, $77, $51, $57, $51, $77 $71, $51, $57, $55, $75, $77, $51, $57, $54, $77 $77, $55, $57, $54, $77, $71, $51, $51, $51, $77 $77, $55, $57, $55, $77, $77, $51, $57, $55, $77 $17, $15, $15, $15, $17, $11, $11, $11, $11, $11 $17, $14, $17, $11, $17, $17, $11, $17, $11, $17 $11, $11, $17, $15, $15, $17, $11, $17, $14, $17 $17, $15, $17, $14, $17, $11, $11, $11, $11, $17 $17, $15, $17, $15, $17, $17, $11, $17, $15, $17 $77, $45, $75, $15, $77, $71, $41, $71, $11, $71 $77, $44, $77, $11, $77, $77, $41, $77, $11, $77 $71, $41, $77, $15, $75, $77, $41, $77, $14, $77 $77, $45, $77, $14, $77, $71, $41, $71, $11, $77 $77, $45, $77, $15, $77, $77, $41, $77, $15, $77 $77, $15, $75, $15, $77, $71, $11, $71, $11, $71 $77, $14, $77, $11, $77, $77, $11, $77, $11, $77 $71, $11, $77, $15, $75, $77, $11, $77, $14, $77 $77, $15, $77, $14, $77, $71, $11, $71, $11, $77 $77, $15, $77, $15, $77, $77, $11, $77, $15, $77 $17, $15, $75, $55, $57, $11, $11, $71, $51, $51 $17, $14, $77, $51, $57, $17, $11, $77, $51, $57 $11, $11, $77, $55, $55, $17, $11, $77, $54, $57 $17, $15, $77, $54, $57, $11, $11, $71, $51, $57 $17, $15, $77, $55, $57, $17, $11, $77, $55, $57 $77, $15, $75, $45, $77, $71, $11, $71, $41, $71 $77, $14, $77, $41, $77, $77, $11, $77, $41, $77 $71, $11, $77, $45, $75, $77, $11, $77, $44, $77 $77, $15, $77, $44, $77, $71, $11, $71, $41, $77 $77, $15, $77, $45, $77, $77, $11, $77, $45, $77 end hour_clock.bas hour_clock.bas.bin
  12. I guess the answer then is that every thing is precalculated and kept in ROM In the case of a player you just set a pointer to a table in ROM In the case of the playfield the table in ROM gets copied to RAM But you don't have to do it that way According to RT's page you get 1675 cycles in vblank If your clock needed to update every frame and you used 4 digits of 8 bytes each ie 128 pixels, probably not enough time to do a pixel at a time. If your clock only needs to update once a second it probably is enough time. The code I posted takes around 150 cycles to compose the two 3 x 4 digits but it doesn't do a pixel at a time as for accuracy I don't think glitching would be a problem but crystals aren't all that accurate to begin with a really good crystal would be like +-1 second a day I calculate the code I posted at 106 seconds for the 100 second count down I measured it to be 105 in Stella
  13. I don't think you're describing what you want very well Here's a 2 digit count down timer that uses player0 in RAM Pressing joy0fire resets the counter to 100 and it proceeds to count down by seconds to 00 You could put the numbers in ROM and it would be faster and save the four variables it uses It would be 400 bytes of ROM for 100 numbers dim time = t.s dim d0 = temp2 dim d1 = temp3 COLUPF = $2C player0x = 80 : player0y = 44 player0height = 4 player0pointerlo = $EA : player0pointerhi = $00 ; set player0pointer to point to variable w COLUP0 = $1C gosub update_player loop COLUP0 = $1C drawscreen if joy0fire && !f then t = 100 : s = 0 ; set time to 99 if joy0fire then f = 255 else f = 0 if !(t | s) then loop ; if time = 0 skip decremting the timer temp1 = time time = time - 0.017 ; decrement time by ~1/60 if time > 99 then t = 0 : s = 0 ; if underflow, set time to 0 if temp1 = time then loop ; if the decrement didn't change the integer part of time skip updating the display temp1 = time / 16 dec temp1 = (time & $0F) + 0 + dnib[temp1] ; convert to bcd gosub update_player goto loop update_player d0 = temp1 & 15 d1 = temp1 / 16 z = l0[d1] & $F0 : z = (l0[d0] & $0F) | z y = l1[d1] & $F0 : y = (l1[d0] & $0F) | y x = l2[d1] & $F0 : x = (l2[d0] & $0F) | x w = l3[d1] & $F0 : w = (l3[d0] & $0F) | w return data l0 $77, $22, $77, $77, $55, $77, $33, $77, $77, $77 end data l1 $55, $66, $33, $33, $77, $66, $66, $11, $77, $55 end data l2 $55, $22, $66, $11, $11, $11, $55, $22, $55, $33 end data l3 $77, $22, $77, $77, $11, $66, $77, $22, $77, $66 end data dnib $00, $16, $32, $48, $64, $80, $96 end count_down_timer.bas count_down_timer.bas.bin
  14. Your color tables are not multiples of 24 I guess what you want would best be done with a look up table for the multiplication dim tmp88 = temp2.temp1 temp2 = 0 : temp1 = mpy24[o] P0c_pointer = P0c_pointer + tmp88 data mpy24 0, 24, 48, 72, 96, 120, 144 etc end Or you could do the multiplication in bB temp1 = ((o * 2) + o) * 8
  15. If you're going to do it that way you'll have to use 16 bit math something like const P0cphi = player0color + 1 ; name the hi byte of the player0color pointer ; so you can use it to define a bB 8.8 player0color pointer 16 bit variable dim P0c_pointer = P0cptr.player0color ; so you can use it to do 16 bit math in bB P0c_pointer = P0c_pointer + 0.094 ; then you'd do your math something like this (24/256 = ~.094)
  16. I'm not really sure I understand what you're doing I'd just asign a room number so that it can be used as an index then use tables untested proom = rand & 15 ; pit room droom = rand & 15 ; dragon room hrow = hroom / 4 ; hero row hcol = hroom & 3 ; hero column prow = proom / 4 pcol = proom & 3 ; if same row and if adjacent columns if hrow = prow && af[hcol] & rc[pcol] then COLUBK = $A0 : goto BK_color_done ; if same column and if adjacent rows if hcol = pcol && af[hrow] & rc[prow] then COLUBK = $A0 : goto BK_color_done drow = droom / 4 dcol = droom & 3 ; etc if hrow = drow && af[hcol] & rc[dcol] then COLUBK = $34 : goto BK_color_done if hcol = dcol && af[hrow] & rc[drow] then COLUBK = $34 BK_color_done ; row or column position flag data rc %00000001, %00000010, %00000100, %00001000 end ; adjacent position flags data af %00000010, %00000101, %00001010, %00000100 end
  17. Show your code My first guess would be that your color table is straddling a page bounary presumably at 45 bytes in So if that's the case The pointers are 16 bits so you need 16 bit math for the carry to the next page The individual player color frames need to be page boundary aligned That is to say each color frame must be wholey contained in a page The table over all does not The boundary from this page to the next page must align with a boundary between color frames So if the color frames are 0 based your color frames 0,1 are contained in in the first page but color frame 2 straddles the page boundary I think the simplest and probably fastest and least code (in ROM not necessarily the source)) way would be use a look up table and get the assembler to do the 16 bit math at compile time in the data statements And add 5 (or remove 15) bytes of padding to the color frames table data cf_lo <Pxc_data, <Pxc_data+20, <Pxc_data+40, <Pxc_data+60, <Pxc_data+80 end data cf_hi >Pxc_data, >Pxc_data+20, >Pxc_data+40, >Pxc_data+60, >Pxc_data+80 end Then you'd choose your color_frame something like player0color = cf_lo[cf_no] : player0color[1] = cf_hi[cf_no]
  18. You could put rand into a bB function either as bB code or as a bit of asm You don't absolutely need a temp variable to copy data from a data statement to the playfield But you only need it long enough for the actual copying Not a good idea to expect temp variables to be persistent Drawscreen and some of the built in functions use them
  19. See if this is something like what you want I had to add some padding (the zpad table) to get the Pxc data into the next page Your code as copied and pasted was sort of munged Maybe the forum code is corrupting it I only fixed it enough so it would compile for me I don't know what's going on with the playfield declaration bB still complains about a missing end statement so I just loaded it from a table I added the noinline data optimization FBs_share_01.bas FBs_share_01.bas.bin
  20. the color table has to be in the graphics bank (the last bank I think) bank 8 in this case same as the other sprite data
  21. I forgot to mention presumably the color table needs to be wholey contained within a page and not straddle a page boundary if it does it'll probably mess up the kernel timing so you may need to add you own padding or page align the table or just move it
  22. Hmm Should change P0_c_pointer_lo = Px_color_data_lo P0_c_pointer_hi = Px_color_data_hi P1_c_pointer_lo = Px_color_data_lo P1_c_pointer_hi = Px_color_data_hi to P0_c_pointer_lo = Px_color_data_lo : P1_c_pointer_lo = Px_color_data_lo P0_c_pointer_hi = Px_color_data_hi : P1_c_pointer_hi = Px_color_data_hi That should save 4 bytes and 4 cycles
  23. The way it's done there it costs 4 bytes and 8 cycles (or something like that) for the indexing bB reports the same ROM remaining so I assume it gets lost in the padding for the tables This should be the same as normal code I think and so save the full color table, in this case, 8 bytes instead of four. Same cycles It's just a little more convoluted set kernel_options player1colors playercolors pfcolors const Px_color_data_lo = <Pxc_data const Px_color_data_hi = >Pxc_data dim P0_c_pointer_lo = player0color dim P0_c_pointer_hi = player0color + 1 dim P1_c_pointer_lo = player1color dim P1_c_pointer_hi = player1color + 1 gosub init_PF player0: %11111111 %01111110 %00111100 %00011000 %00011000 %00111100 %01111110 %11111111 end player1: %00011000 %00111100 %01111110 %11111111 %11111111 %01111110 %00111100 %00011000 end P0_c_pointer_lo = Px_color_data_lo P0_c_pointer_hi = Px_color_data_hi P1_c_pointer_lo = Px_color_data_lo P1_c_pointer_hi = Px_color_data_hi player0x = 80 : player1x = 104 player0y = 35 : player1y = 35 COLUBK = 0 mainloop COLUPF = $94 drawscreen goto mainloop data Pxc_data $02, $0A, $12, $1A, $22, $2A, $32, $3A end init_PF playfield: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X X..............................X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX end pfcolors: $94 $96 $98 $9A $9C $9E $A8 $A6 $A4 $A2 $A0 end return
×
×
  • Create New...