Grebnedlog Posted October 4, 2012 Share Posted October 4, 2012 (edited) I've been trying to write an elegant loop statement that can rewrite chunks of longer playfields from data statements, but I've been failing a lot more than I planned to. Basically, the attached program writes 256 consecutive bytes of the playfield using the pfpixel command and a data statement (the idea here was to conserve some romspace in the graphics bank of DPC+ programs by defining some playfield data in other banks, and I'm assuming - maybe wrongly - this is the best way to do it.) The write-routine works, but it's too expensive in ROM to be useful right now (705 bytes): data objectdata 0,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0 end WritePFChunk for temp1 = 0 to 31 if objectdata[temp1] = 1 then pfpixel temp1 current_row on temp2 = temp1 + 32 : temp3 = current_row + 1 if objectdata[temp2] = 1 then pfpixel temp1 temp3 on temp2 = temp1 + 64 : temp3 = current_row + 2 if objectdata[temp2] = 1 then pfpixel temp1 temp3 on temp2 = temp1 + 96 : temp3 = current_row + 3 if objectdata[temp2] = 1 then pfpixel temp1 temp3 on temp2 = temp1 + 128 : temp3 = current_row + 4 if objectdata[temp2] = 1 then pfpixel temp1 temp3 on temp2 = temp1 + 160 : temp3 = current_row + 5 if objectdata[temp2] = 1 then pfpixel temp1 temp3 on temp2 = temp1 + 192 : temp3 = current_row + 6 if objectdata[temp2] = 1 then pfpixel temp1 temp3 on temp2 = temp1 + 224 : temp3 = current_row + 7 if objectdata[temp2] = 1 then pfpixel temp1 temp3 on next I might have some sort of basic brain problem here... this doesn't seem like such a complex task. I've tried to do it with nested for-loops and pointers, but these approaches either don't work as expected or cause a fatal ARM exception. Essentially, I need to advance the data pointer by 32 elements eight times using the fewest bytes possible, and I know the above method is pretty dumb. Can anyone help out? draw_pf_from_array.bas.bin draw_pf_from_array.bas Edited October 4, 2012 by Grebnedlog Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 4, 2012 Share Posted October 4, 2012 pfpixel and similar functions obliterate temp1, temp2, and temp3, which is probably why you're having trouble with the looping and getting ARM exceptions. Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted October 4, 2012 Share Posted October 4, 2012 (edited) As I understand it Batari's stated plan is to only allow graphic data like playfields access the extra storage space. He said maybe on allowing use for SDATA and was even less enthusiastic about normal DATA statements (which is what I'd want it for most). So, if I got my info right, just using normal playfield statements sounds like the way forward. That being said, why not just use consecutive pfpixel statements and call it a day? Also, what RevEng said. My opinion is that temp vars are too unpredictable for normal use. i actually "waste" one or two normal vars for temp usage. Also, once more, are you using each 8-bit data statement element as one playfield pixel? I didn't have time to figure out if you were. If so, I'd suggest using each of the 8 bits in an element as playfield pixels. Edited October 4, 2012 by theloon Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 4, 2012 Author Share Posted October 4, 2012 (edited) pfpixel and similar functions obliterate temp1, temp2, and temp3, which is probably why you're having trouble with the looping and getting ARM exceptions. Aha! Thanks so much, that indeed seems to be the trouble. With that in mind, this version already looking a lot more streamlined, and saving some precious bytes: dim current_row = a dim current_col = b dim lo_pointer = c dim current_pixel = d dim print_row = e dim chunk_start = f chunk_start = 20 PROGRAMLOOP DF0FRACINC=128 DF1FRACINC=128 DF2FRACINC=128 DF3FRACINC=128 DF4FRACINC=255 DF6FRACINC=24 if joy0fire then z{0} = 1 if !joy0fire && z{0} then gosub WritePFChunk drawscreen goto PROGRAMLOOP data hellodata 0,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,1,1,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0 end WritePFChunk for current_row = 0 to 8 for current_col = 0 to 31 current_pixel = lo_pointer + current_col print_row = chunk_start + current_row if hellodata[current_pixel] = 1 then pfpixel current_col print_row on next lo_pointer = current_row * 32 next z{0} = 0 return thisbank That said, I'm wondering if there's a way to slim it down even more? Also, now I'm starting to wonder in general if there's a way to reuse the same routine with variable data statements in bB, but without hard coding the name of the set each time. In other words, could the line: if hellodata[current_pixel] = 1 then pfpixel current_col print_row on be expressed such that "hellodata" is replaced with a variable that points to one of 256-byte several tables in ROM (i.e. "goodbyedata", "endofdata", etc.)? Or would that line have to be repeated for each table name? EDIT: Ugh, the site screwed up my code formatting a bit, so I attached the new BAS and BIN draw_pf_from_array_v2.bas draw_pf_from_array_v2.bas.bin Edited October 4, 2012 by Grebnedlog Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 4, 2012 Share Posted October 4, 2012 Aha! Thanks so much, that indeed seems to be the trouble. Not a problem. I only nudged you in the right direction. ... That said, I'm wondering if there's a way to slim it down even more? Also, now I'm starting to wonder in general if there's a way to reuse the same routine with variable data statements in bB, but without hard coding the name of the set each time. The best way to slim it down (as theloon suggested) is to convert your data to use binary representation instead of setting bytes to 0's and 1's. (eg. %11001101 would replace 1,1,0,0,1,1,0,1,...) Each screen will go from using 256 bytes to using 32 bytes. There isn't a way in pure bB to pass on a reference to an array. (or any variable) How many screens worth of data are we talking about? If you convert to binary representation and it's 8 or less you could fit them all into a single data statement, and just offset which row you begin with to access them individually. If it's more, then you need to convert to using sdata. Quote Link to comment Share on other sites More sharing options...
bogax Posted October 4, 2012 Share Posted October 4, 2012 possibly I misunderstand your intent. On your first pass through the inner for loop current_col will be 0 and lo_pointer will be whatever you haven't set lo_pointer yet At the end of the first pass through the loop you'll set lo_pointer to current_col * 0 and lo_pointer will be 0 while current_col is 1 (second pass). etc also you'll make 9 passes through the loop (0-8 inclusive) If you multiply by a power of two that's 8 or less Bb will use shifts so * 8 * 4 compiles as shifts * 32 calls the mutiplication routine Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 4, 2012 Author Share Posted October 4, 2012 As I understand it Batari's stated plan is to only allow graphic data like playfields access the extra storage space. He said maybe on allowing use for SDATA and was even less enthusiastic about normal DATA statements (which is what I'd want it for most). So, if I got my info right, just using normal playfield statements sounds like the way forward. That being said, why not just use consecutive pfpixel statements and call it a day? Well, I guess the point of the experiment is to maximize the graphic storage space for something other than playfield data (for instance, the project I'm working on requires the use of a lot of sprite data, and uses 88 rows of playfield pixels. So dynamically drawing certain portions of the playfield without storing that data in the graphics bank is actually pretty helpful to me. Not sure what you mean by "consecutive pfpixel statements" (from what I can tell, that's what I'm doing with my for-loop in the post above). Also, what RevEng said. My opinion is that temp vars are too unpredictable for normal use. i actually "waste" one or two normal vars for temp usage. Again, I'm not really sure what you mean by "normal use" here. They can't be used to store persistent data, but I wasn't trying to use them that way in my example. They do seem to have a few quirks that weren't readily apparent. For instance, I'm still not sure why the temp vars are obliterated after a pfpixel, but I know that I haven't had any problem using them to draw pixels in an un-nested for-next loop... well, not so far, at least. The problem only seemed to arise when I included them in a nested loop. Perhaps RevEng could explain why that is. Also, once more, are you using each 8-bit data statement element as one playfield pixel? I didn't have time to figure out if you were. If so, I'd suggest using each of the 8 bits in an element as playfield pixels. The best way to slim it down (as theloon suggested) is to convert your data to use binary representation instead of setting bytes to 0's and 1's. (eg. %11001101 would replace 1,1,0,0,1,1,0,1,...) Each screen will go from using 256 bytes to using 32 bytes. You know, I tried following the example in this post, but I confess I got a bit lost (Get it? A bit lost? ). I guess part of the reason is that I'm not sure what the binary posted there is supposed to be doing. Maybe one of you can edit my v2 BAS to demonstrate how it would be converted to a binary array and drawn from my routine? I took the liberty of comma-separating the "hellodata" statement, to remove some of the grunt work for you: %00000010,%01011101,%00010001,%11000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01011101,%11011101,%11000000 There isn't a way in pure bB to pass on a reference to an array. (or any variable) Oh, OK. Is that because the assembled code auto-labels the jump tables during compilation? How many screens worth of data are we talking about? If you convert to binary representation and it's 8 or less you could fit them all into a single data statement, and just offset which row you begin with to access them individually. If it's more, then you need to convert to using sdata. Well, I suppose I was only thinking of about twelve (partial) screens for the particular project I was working on, but obviously more (and smaller) is always better, and drawing the pf using a bit array with offsets would be useful for all sorts of projects, I would think. Thanks to both of you for your help. Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 4, 2012 Author Share Posted October 4, 2012 (edited) possibly I misunderstand your intent. On your first pass through the inner for loop current_col will be 0 and lo_pointer will be whatever you haven't set lo_pointer yet At the end of the first pass through the loop you'll set lo_pointer to current_col * 0 and lo_pointer will be 0 while current_col is 1 (second pass). etc also you'll make 9 passes through the loop (0-8 inclusive) If you multiply by a power of two that's 8 or less Bb will use shifts so * 8 * 4 compiles as shifts * 32 calls the mutiplication routine When lo_pointer is zero, the routine is searching the array values representing the first row in the "playfield chunk" (i.e. the segment of the playfield being drawn). The lo_pointer advances by 32 on each iteration to draw the next playfield row, starting with playfield position 0 and advancing to position 31. The routine checks the value, then draws a pixel if it reads a "1". As RevEng and theloon pointed out above, this routine would obviously be a lot better (and more useful) if the array data could be read as a binary array, since only on/off states are needed. I'm fighting my way through the binary array examples you provided on that other thread, but I'm not sure how to adapt it to this purpose. Any help would be much appreciated. Edited October 4, 2012 by Grebnedlog Quote Link to comment Share on other sites More sharing options...
bogax Posted October 4, 2012 Share Posted October 4, 2012 I phrased that poorly Suppose you set lo_pointer = 15 (some arbitrary value) then call WritePFChunk then the first time you run the current_col loop current_row = 0 and lo_pointer = 15 at the end of the first pass through the current_row loop lo_pointer will get set to 0 ie 0 * 32 so your passes would go like this current row = 0, lo_pointer = 15 current row = 1, lo_pointer = 0 current row = 2, lo_pointer = 32 current row = 3, lo_pointer = 64 current row = 4, lo_pointer = 96 current row = 5, lo_pointer = 128 current row = 6, lo_pointer = 160 current row = 7, lo_pointer = 192 current row = 8, lo_pointer = 224 9 iterations of the current row loop the first one with what ever lo_pointer is when you call WritePFChunk Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 4, 2012 Author Share Posted October 4, 2012 (edited) I phrased that poorly Suppose you set lo_pointer = 15 (some arbitrary value) then call WritePFChunk then the first time you run the current_col loop current_row = 0 and lo_pointer = 15 at the end of the first pass through the current_row loop lo_pointer will get set to 0 ie 0 * 32 so your passes would go like this current row = 0, lo_pointer = 15 current row = 1, lo_pointer = 0 current row = 2, lo_pointer = 32 current row = 3, lo_pointer = 64 current row = 4, lo_pointer = 96 current row = 5, lo_pointer = 128 current row = 6, lo_pointer = 160 current row = 7, lo_pointer = 192 current row = 8, lo_pointer = 224 9 iterations of the current row loop the first one with what ever lo_pointer is when you call WritePFChunk Okay, I think I see what you mean. If so, then yes you are right that it is the wrong number of iterations. I changed it to "for current_row 1 to 8." Thanks! Is there any chance you can help with converting this to a binary bitmap routine? Edited October 4, 2012 by Grebnedlog Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted October 4, 2012 Share Posted October 4, 2012 (edited) You could straight up use code to avoid DATA statements and complicated for next loops. pfpixel 1 1 on : pfpixel 2 1 on : pfpixel 3 1 on : pfpixel 4 1 on : pfpixel 5 1 on : pfpixel 3 2 on : pfpixel 3 3 on : pfpixel 8 3 on : pfpixel 9 3 on : pfpixel 10 3 on : pfpixel 11 3 on : pfpixel 3 4 on pfpixel 8 4 on : pfpixel 27 4 on : pfpixel 28 4 on : pfpixel 3 5 on : pfpixel 8 5 on : pfpixel 9 5 on : pfpixel 15 5 on : pfpixel 16 5 on : pfpixel 17 5 on : pfpixel 27 5 on : pfpixel 28 5 on : pfpixel 8 6 on pfpixel 14 6 on : pfpixel 20 6 on : pfpixel 21 6 on : pfpixel 22 6 on : pfpixel 23 6 on : pfpixel 24 6 on : pfpixel 27 6 on : pfpixel 28 6 on : pfpixel 8 7 on : pfpixel 9 7 on : pfpixel 10 7 on : pfpixel 11 7 on pfpixel 15 7 on : pfpixel 16 7 on : pfpixel 22 7 on : pfpixel 27 7 on : pfpixel 28 7 on : pfpixel 17 8 on : pfpixel 22 8 on : pfpixel 14 9 on : pfpixel 15 9 on : pfpixel 16 9 on : pfpixel 22 9 on : pfpixel 27 9 on pfpixel 28 9 on : pfpixel 22 10 on If that code is run the playfield should look like this: ................................ .XXXXX.......................... ...X............................ ...X....XXXX.................... ...X....X..................XX... ...X....XX.....XXX.........XX... ........X.....X.....XXXXX..XX... ........XXXX...XX.....X....XX... .................X....X......... ..............XXX.....X....XX... ......................X......... The only thing to watch out for is going over your CPU cycles so the screen starts to roll. The easy way out is to break up your pfpixel commands with an appropriate DRAWSCREEN somewhere. Also, normal use means expecting temp vars to look, feel and taste like normal vars. You can't expect the values to hold. You can't expect the calculations to actually happen. Just don't use them. Trust me. Edited October 4, 2012 by theloon Quote Link to comment Share on other sites More sharing options...
bogax Posted October 4, 2012 Share Posted October 4, 2012 (edited) Okay, I think I see what you mean. If so, then yes you are right that it is the wrong number of iterations. I changed it to "for current_row 1 to 8." Thanks! That might do it but then you need to intialize lo_pointer Your rows are going to be addressed as 0-7 Is there any chance you can help with converting this to a binary bitmap routine? I can try but you probably want someone who knows what they're doing ;P I'd imagine it something like this: dim current_row = a dim current_col = b dim current_byte = c dim current_bit = d dim print_row = e dim chunk_start = f chunk_start = 20 PROGRAMLOOP DF0FRACINC=128 DF1FRACINC=128 DF2FRACINC=128 DF3FRACINC=128 DF4FRACINC=255 DF6FRACINC=24 if joy0fire then z{0} = 1 if !joy0fire && z{0} then gosub WritePFChunk drawscreen goto PROGRAMLOOP WritePFChunk for current_row = 0 to 7 for current_col = 0 to 31 current_byte = current_col / 8 + lo_pointer[current_row] current_bit = current_col & 7 print_row = chunk_start + current_row if hellodata[current_byte] & setbits[current_bit] then pfpixel current_col print_row on next next z{0} = 0 return thisbank bank 3 bank 4 bank 5 bank 6 data lo_pointer 0, 4, 8, 12, 16, 20, 24, 28 end data hellodata %00000010,%01011101,%00010001,%11000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01011101,%11011101,%11000000 end data setbits %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001 end I used a look up table for lo_pointer because it only costs a couple bytes, doesn't use a variable and is faster edit: ack! wrong! it's significantly slower (forgot that moves it into the inner loop) so using a variable: dim current_row = a dim current_col = b dim current_byte = c dim current_bit = d dim lo_pointer = e dim print_row = f dim chunk_start = g chunk_start = 20 PROGRAMLOOP DF0FRACINC=128 DF1FRACINC=128 DF2FRACINC=128 DF3FRACINC=128 DF4FRACINC=255 DF6FRACINC=24 if joy0fire then z{0} = 1 if !joy0fire && z{0} then gosub WritePFChunk drawscreen goto PROGRAMLOOP WritePFChunk for current_row = 0 to 7 lo_pointer = current_row * 4 for current_col = 0 to 31 current_byte = current_col / 8 + lo_pointer current_bit = current_col & 7 print_row = chunk_start + current_row if hellodata[current_byte] & setbits[current_bit] then pfpixel current_col print_row on next next z{0} = 0 return thisbank bank 3 bank 4 bank 5 bank 6 data hellodata %00000010,%01011101,%00010001,%11000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01011101,%11011101,%11000000 end data setbits %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001 end damn! more edits: should be current_byte = current_col / 8 + lo_pointer even more editing: fixed the setbits (see below) Edited October 5, 2012 by bogax Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 4, 2012 Author Share Posted October 4, 2012 You could straight up use code to avoid DATA statements and complicated for next loops. pfpixel 1 1 on : pfpixel 2 1 on : pfpixel 3 1 on : pfpixel 4 1 on : pfpixel 5 1 on : pfpixel 3 2 on : pfpixel 3 3 on : pfpixel 8 3 on : pfpixel 9 3 on : pfpixel 10 3 on : pfpixel 11 3 on : pfpixel 3 4 on pfpixel 8 4 on : pfpixel 27 4 on : pfpixel 28 4 on : pfpixel 3 5 on : pfpixel 8 5 on : pfpixel 9 5 on : pfpixel 15 5 on : pfpixel 16 5 on : pfpixel 17 5 on : pfpixel 27 5 on : pfpixel 28 5 on : pfpixel 8 6 on pfpixel 14 6 on : pfpixel 20 6 on : pfpixel 21 6 on : pfpixel 22 6 on : pfpixel 23 6 on : pfpixel 24 6 on : pfpixel 27 6 on : pfpixel 28 6 on : pfpixel 8 7 on : pfpixel 9 7 on : pfpixel 10 7 on : pfpixel 11 7 on pfpixel 15 7 on : pfpixel 16 7 on : pfpixel 22 7 on : pfpixel 27 7 on : pfpixel 28 7 on : pfpixel 17 8 on : pfpixel 22 8 on : pfpixel 14 9 on : pfpixel 15 9 on : pfpixel 16 9 on : pfpixel 22 9 on : pfpixel 27 9 on pfpixel 28 9 on : pfpixel 22 10 on No offense intended, but I'm not sure why would that be better than my nested loop statement. I mean, both our versions work, but your version seems like it would be a nightmare for drawing lots of pictures with. Design workflow for my version would just involve drawing a playfield in the ordinary way (either by using tools or typing it out ASCII style), using find-replace to comma separate, copying it into a data array (in the bank of my choosing), and having the program run the routine whenever I need to draw or redraw a section of the playfield. Also, my version allows the programmer to vary the position (vertical only, right now, but probably easily adaptable for horizontal) of the playfield graphic being drawn. For instance, with my V2 version, you can change the message from "HELLO WORLD" to "WORLD HELLO" simply by changing "chunk_start = 20" to "chunk_start=70", whereas your static version would require recoding all the pfpixel statements to achieve the same effect (essentially doubling the ROM space used, too). The only thing to watch out for is going over your CPU cycles so the screen starts to roll. The easy way out is to break up your pfpixel commands with an appropriate DRAWSCREEN somewhere. Actually, for the particular project I had in mind this wouldn't be a problem, since the drawing routine doesn't happen during gameplay, but rather before a new game level starts (i.e. setting up the game map, obstacles, etc). I essentially shut off the display while this is going on by reducing the screen resolution to 1 until the process is finishes, meaning the screen won't appear to roll even if the improper number of scanlines are drawn (which, they most definitely will be). I've tested this on real hardware and it works pretty much as expected. The screen goes black for a second while the drawing is done, and then I increase the screen res just before the level starts. Also, normal use means expecting temp vars to look, feel and taste like normal vars. You can't expect the values to hold. You can't expect the calculations to actually happen. Just don't use them. Trust me. Well, I guess we'll have to agree to disagree on that one. I personally am finding the temp vars indispensable for certain in-game routines (particularly for things like soft collisions, where a temp can act as a second "edge" for a sprite coordinate during an overlap test). It's true they aren't useful as general purpose variables (seing as they are temporary), but not using them at all seems a little extreme. Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted October 4, 2012 Share Posted October 4, 2012 No offence taken. But, I'm still not sure how the extra cycles needed for loops and taking the more indirect approach of DATA statements help. For editing you can use this utility: http://www.alienbill.com/2600/basic/bbpf.cgi Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 4, 2012 Author Share Posted October 4, 2012 (edited) No offence taken. But, I'm still not sure how the extra cycles needed for loops and taking the more indirect approach of DATA statements help. Well, I guess the idea is a based on a tradeoff. In this case, the tradeoff is between hi-res playfield definitions and hi-res sprite definitions. Both share the same bank in the DPC+ framework, so if you want more of one, you'll necessarily have less of the other. If I wanted to have 88-row multicolored playfields (which I do) and had to rely solely on using the static playfield definitions, I wouldn't be able to include very many of them, and won't be able to include lots of sprite data either. Live playfield drawing seems far more useful in general for hi-res screens, but particularly if you want to have lots of varying kinds of sprites. From what I can see, the loop statement I used isn't really using that many more cycles than a string of successive static pfpixel commands would (and the screen would roll for either version, if you don't take precautions). Also, your version uses 1650 bytes of ROM, and to draw only 11 rows in one static position. My version draws 8 rows wherever I want them, and only uses 373 bytes (256 of which is the data array itself, and the other 117 of which can be reused to draw multiple screens) and it will use far less still if we can get binary arrays working. Actually, that would be really exciting... if that was the case, a single data statement could draw a full, fairly high resolution screen without sacrificing any space for sprite data. Edited October 4, 2012 by Grebnedlog Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 4, 2012 Author Share Posted October 4, 2012 (edited) That might do it but then you need to intialize lo_pointer Your rows are going to be addressed as 0-7 Oh, okay. Got it now. I can try but you probably want someone who knows what they're doing ;P Ha! Based on that other thread, I'm fairly sure you know what you're doing. Now I just want to be sure that I know what you're doing. I'd imagine it something like this: dim current_row = a dim current_col = b dim current_byte = c dim current_bit = d dim print_row = e dim chunk_start = f chunk_start = 20 PROGRAMLOOP DF0FRACINC=128 DF1FRACINC=128 DF2FRACINC=128 DF3FRACINC=128 DF4FRACINC=255 DF6FRACINC=24 if joy0fire then z{0} = 1 if !joy0fire && z{0} then gosub WritePFChunk drawscreen goto PROGRAMLOOP WritePFChunk for current_row = 0 to 7 for current_col = 0 to 31 current_byte = current_col / 8 + lo_pointer[current_row] current_bit = current_col & 7 print_row = chunk_start + current_row if hellodata[current_byte] & setbits[current_bit] then pfpixel current_col print_row on next next z{0} = 0 return thisbank bank 3 bank 4 bank 5 bank 6 data lo_pointer 0, 4, 8, 12, 16, 20, 24, 28 end data hellodata %00000010,%01011101,%00010001,%11000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01011101,%11011101,%11000000 end data setbits %00000001, %00000010, %00000100, %00001000 %00010000, %00100000, %01000000, %10000000 end I used a look up table for lo_pointer because it only costs a couple bytes, doesn't use a variable and is faster edit: ack! wrong! it's significantly slower (forgot that moves it into the inner loop) so using a variable: dim current_row = a dim current_col = b dim current_byte = c dim current_bit = d dim lo_pointer = e dim print_row = f dim chunk_start = g chunk_start = 20 PROGRAMLOOP DF0FRACINC=128 DF1FRACINC=128 DF2FRACINC=128 DF3FRACINC=128 DF4FRACINC=255 DF6FRACINC=24 if joy0fire then z{0} = 1 if !joy0fire && z{0} then gosub WritePFChunk drawscreen goto PROGRAMLOOP WritePFChunk for current_row = 0 to 7 lo_pointer = current_row * 4 for current_col = 0 to 31 current_byte = current_col / 8 + lo_pointer current_bit = current_col & 7 print_row = chunk_start + current_row if hellodata[current_byte] & setbits[current_bit] then pfpixel current_col print_row on next next z{0} = 0 return thisbank bank 3 bank 4 bank 5 bank 6 data hellodata %00000010,%01011101,%00010001,%11000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000011,%11011101,%00010001,%01000000 %00000010,%01010001,%00010001,%01000000 %00000010,%01011101,%00010001,%01000000 %00000010,%01011101,%11011101,%11000000 end data setbits %00000001, %00000010, %00000100, %00001000 %00010000, %00100000, %01000000, %10000000 end damn! more edits: should be current_byte = current_col / 8 + lo_pointer Thanks! The resulting binary looks close to correct. However, instead of saying "HELLO", my screen looks like this: I believe that's Klingon for "Destroy all humans" Seriously, though, I guess it looks like it's reading some of the data in backwards, and starting to write it in the middle of the screen. Any ideas? EDIT: Oh, I also forgot to mention that bB cannot see data in different banks from the one that is reading them, so I cut and pasted the arrays back into bank 2 with the WritePFChunk routine (though, I suppose, you could alternately stick the routine in bank 6, and then bankswitch to it from the main loop.) Edited October 4, 2012 by Grebnedlog Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 5, 2012 Author Share Posted October 5, 2012 (edited) @bogax Okay, I see the problem. The elements in your setbits array were just in reverse order. Changed it to this and it works fine now: data setbits %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001 end Thanks again! I think this could be very useful for hi-def playfield drawing. EDIT: Attached a BAS file combining all edits and corrections. draw_pf_from_binary_array.bas Edited October 5, 2012 by Grebnedlog Quote Link to comment Share on other sites More sharing options...
bogax Posted October 5, 2012 Share Posted October 5, 2012 Another thought. Looks like you could pull the print_row assignment out of the inner loop for current_row = 0 to 7 lo_pointer = current_row * 4 print_row = chunk_start + current_row for current_col = 0 to 31 current_byte = current_col / 8 + lo_pointer current_bit = current_col & 7 if hellodata[current_byte] & setbits[current_bit] then pfpixel current_col print_row on next next Quote Link to comment Share on other sites More sharing options...
bogax Posted October 5, 2012 Share Posted October 5, 2012 (edited) @bogax Okay, I see the problem. The elements in your setbits array were just in reverse order. Changed it to this and it works fine now: data setbits %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001 end Heck! Darn! Other obscenities as required! And since the binary array thread is talking about screen stuff and not bit variables they're backwards there too. Ha! Based on that other thread, I'm fairly sure you know what you're doing. How sure are you now . Edited October 5, 2012 by bogax Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 5, 2012 Author Share Posted October 5, 2012 Heck! Darn! Other obscenities as required! And since the binary array thread is talking about screen stuff and not bit variables they're backwards there too. How sure are you now . I'm sure you would have spotted it eventually. Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted October 5, 2012 Share Posted October 5, 2012 Waitasec.. did this topic just render a working "use DATA statements as a binary array" function? Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 5, 2012 Author Share Posted October 5, 2012 (edited) Waitasec.. did this topic just render a working "use DATA statements as a binary array" function? Yep. I posted the BAS above. Edited October 5, 2012 by Grebnedlog Quote Link to comment Share on other sites More sharing options...
Gateway Posted October 5, 2012 Share Posted October 5, 2012 What release number of the DPC+ kernel are you using? I am using the version from January 2011. set kernel DPC+ set kernel_options collision(playfield,player1) set optimization inlinerand set smartbranching on set tv ntsc Above is what the first few lines of your code say in both BAS files. Is that a typo? I am still new to using DPC+ ,so I don't know. I tried both of the BAS files posted but the compilation fails. I changed around the kernel options but then it was looking for pfcolors, then bkcolors.. Any help to get it to compile is welcome. Quote Link to comment Share on other sites More sharing options...
Grebnedlog Posted October 5, 2012 Author Share Posted October 5, 2012 What release number of the DPC+ kernel are you using? I am using the version from January 2011. set kernel DPC+ set kernel_options collision(playfield,player1) set optimization inlinerand set smartbranching on set tv ntsc Above is what the first few lines of your code say in both BAS files. Is that a typo? I am still new to using DPC+ ,so I don't know. I tried both of the BAS files posted but the compilation fails. I changed around the kernel options but then it was looking for pfcolors, then bkcolors.. Any help to get it to compile is welcome. Is what a typo? Not sure I understand your question, but I'm using bB version 1.1d. Quote Link to comment Share on other sites More sharing options...
Gateway Posted October 5, 2012 Share Posted October 5, 2012 Is what a typo? Not sure I understand your question, but I'm using bB version 1.1d. I didn't recognize this kernel option: set kernel_options collision(playfield,player1) But then, it looks like I need to update my DPC+ files. I have been focused on using the multisprite kernel, so I probably missed a few updates to DPC+. K, thanks, I will try it out again and post if I have any further issues. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.