Jump to content

Grebnedlog

Members
  • Posts

    31
  • Joined

  • Last visited

Everything posted by Grebnedlog

  1. Ah, sorry. I actually did have 3.7.2 installed, but the for some reason the Visual bB devkit program I was using was mapped to an archived version when I took the screenshot. In any case, the ARM error still seems to occur when I run it with Stella 3.7.2 (see attached JPEG). Also, sorry to be a pest, but what would the syntax be to turn off the trap? Thanks.
  2. I agree, it would be nice to think of other applications for this. My application was very specific and limited (loading hi-res playfields for DPC+ games without using the graphics bank). I guess that bit arrays might also work pretty well for storing a bunch of scrollable playfield data too, but not using the specific pf-drawing routine I wrote. That works fine for drawing a static playfield before UI starts, but it's too cycle intensive to nest in any sort of looping gameplay. In general, I guess the application would be that storage of any binary data that requires >256 values. But I'm thinking binary values would probably be most useful for storing playfield and sprite pixel states -- and, as far as I know, there is no "playerpixel" command for writing to player sprites, so storage of playfield data is probably the most applicable thing for most kinds of Atari games. As for including this on Random Terrain's bB page, what exactly is it that needs to be up there? Is it just a brief explanation of how to structure a bit array and read values from it? If that's the case, are we sure that the method we've come up with on this thread is the simplest/most-efficient one? It works well, but I'm just wondering about other ways to do it (and other ways to demonstrate it).
  3. Does anyone here know enough about how ARM emulation works in Stella to explain what this recurring crash message means (attached JPEG), and how one might go about troubleshooting it in a program? Are there instructions or methods that other programmers have found to generally cause these kinds of errors?
  4. Yeah, that's what I meant. You could do it with cases or conditionals. It was sort of a broad question (whether this could be adapted for random mazes). The short answer is "of course it can", but it can be done in almost too many ways to describe. In addition to randomizing the pointer, you could also assign another byte of RAM that points to different IF statements. For instance: 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 dim maze_ref = h ... 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 on maze_ref goto MazeData1 MazeData2 MazeData3 MazeData4 MazeData1 if mazes1[current_byte] & setbits[current_bit] then pfpixel current_col print_row goto Continue WritePFChunk MazeData2 if mazes2[current_byte] & setbits[current_bit] then pfpixel current_col print_row on goto Continue WritePFChunk MazeData3 if mazes3[current_byte] & setbits[current_bit] then pfpixel current_col print_row on goto Continue WritePFChunk MazeData4 if mazes3[current_byte] & setbits[current_bit] then pfpixel current_col print_row on Continue WritePFChunk next next How he arrives at the value of "maze_ref" is completely up to the programmer, of course. It could perhaps increment with the levels or stages that a player advances through, or could itself be randomly assigned. EDIT: Boy, this forum software really messes up the spacing inside CODE tags.
  5. I see no reason why it couldn't be used with any kernel version. The routine isn't doing anything that's specific to the DPC+ kernel. The only reason I picked that one is because that's the kernel I'm working with at the moment, and because I think it's greatest usefulness would be with drawing hi-res playfields that eat up a lot of ROM space. Again, I don't see why not. For instance, you could just define offsets that point to the various regions of the maze, then randomize which segment of the array it reads during the pfpixel routine. For instance, when using this method each row of playfield pixels is defined by 4 bytes, meaning that each data statement can contain 64 playfield rows (or one 64 row x 32 column playfield). So, if you were using the optional superchip 23 visible rows (23 x 32) display, you could maybe break each maze down into 4 segments of 16 rows (or 8 segments of 8 rows, etc), then do a rand command in conjunction with "current_row" to pick the starting point of the segment you want to draw. And that's just one of many ways to do it. I see no reason to even be limited to a single data statement to draw a semi-random "maze-style" playfield. You could always look up data segments in multiple arrays for your maze pieces, in whatever way you see fit. All this routine does is draw whatever binary image is fed into it.
  6. Is what a typo? Not sure I understand your question, but I'm using bB version 1.1d.
  7. I'm sure you would have spotted it eventually.
  8. @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
  9. Oh, okay. Got it now. 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. 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.)
  10. 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.
  11. 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). 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. 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.
  12. 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?
  13. 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.
  14. 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). 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. 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 Oh, OK. Is that because the assembled code auto-labels the jump tables during compilation? 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.
  15. 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
  16. 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
  17. Thank you. I read your routine and it makes sense to me. I've been able to use it to copy player0 to a virtual sprite, but I'm wondering if it is possible to dynamically copy one virtual p1's data to another, without using the static labels bB assigns to the low pointers (i.e. "playerL0xxx_1") ?
  18. Yes, that's what I was thinking of as a workaround, too; flickering the ball under each sprites and then testing for those collisions for the gaps. If that was the case, the native Y-temp4 return would probably work okay if limited to the wall detection (turned off when within range of the ladder objects). It would be nicer to have sprite collisions and preserve the ball object, obviously, but that method would probably mimic the effect pretty well.
  19. Interesting thread! That would be a good workaround for the absence of pfread, but I think it might be a bit of overkill for the types of games I'm imagining here. For example, in my demo I don't need the to id the state of every drawn pixel on the screen, just the ones that will trigger certain events. Although that problem would also be solved with a binary array, I think it's possible to solve with byte arrays, too, depending o the complexity of the hitzone shape. For example, I might have a craggy, mountainous shape on the screen composed of 264 playfield pixels, but for the purposes of in-game collision detection my x-y collision map for it might be far simpler. I might only have to check a few rectangles, or a simple square/line. Hmm... I can't get this one to compile (I'm using 1.1d).
  20. Thanks for the advice and insights on assembly outputs. Works like a charm! I think I grok you here. I guess that could work for a handful of repeating screens that repeats the same collision areas (something like "Donkey Kong" springs to mind). If I grok you right, that's already in the demo program, in a limited way (the sprites shift direction when the reach a minimum/maximum X near the screen edge. I just get the feeling that might be a bit much to store in RAM. For instance, even the very sparsely populated demo program has six such collision zones -- it wouldn't be the ladders that would need to be checked, but the pits and walls. I was wondering if there could be a more general approach. Still, I guess that technique could work fine for certain games. Maybe instead of tracking all the collision zones constantly, we could loop some pointers through an array that contains all the x-y collision zones for that "game screen." The pointer would advance one frame at a time, then check to see if any of the virtual sprites is overlapping that particular collision zone. It might look a little visually sloppy maybe, with sprites constantly "overstepping" gap zones and clipping into wall zones that haven't come up in the pointer queue yet, but I guess it might save some precious RAM. But gosh-golly, this still seems like it be a whole lot simpler with pfread implemented! I wonder if there are any plans to do eventually so (or if it's even possible, given all that's going on already in this kernel). Thanks again.
  21. No, not at all. I was just worried I wasn't explaining my questions right (and still am, sort of). Thank you very much for the detailed reply. That's kind of what I thought. For instance, in the program I was using them to draw the hit zones for the ladders (what I assume theloon meant by "soft collisions), and it seemed to work as expected. That's why I was asking about temp4, since I wasn't sure at what point bB was returning the value. Ah, okay. I noticed this was a little unpredictable as well, so just decided to track a hit zone the covers the full vertical range of the sprite with a top buffer of one pixel: temp2 = sprite1y + sprite1height : temp3 = sprite1y - 1 if temp4 < temp2 && temp4 >= temp3 then sprite1pf = 1 I wonder what accounts for the slight variance? Also, how do you see the assembly listing for a compiled bB program? Does DASM spit it out in a default directory? Oh, okay. Again, I'm not sure I'm thinking about this the right way... but when you put it that way, the problem with my program seems to be unsolvable in bB. I can't do a manual check to see whether I should clear the player1 collision register or not, because it always begins its loop in a cleared state, starts drawing the screen, and sets the register whenever the first collision scanline is reached? I wonder if it would be possible to revise the drawscreen function to use more temp variables to store multiple collisions, with each variable assigned a certain vertical range (which sounds well above my pay grade, skill-wise). Yeah, I was wondering too whether a solution could be generalized to store multiple lines of collision, or if the display would have to be divided into the sort of vertical bands you describe. Either way, it sounds like a new kernel would have to be written from scratch -- which is beyond my abilities, and I suppose it sort of defeats the purpose of using bB. Still, if a feasible general solution exists I wonder if this might be something batari might consider incorporating into the new version. It seems to me like that, in the absence of a pfread, it would be a very useful feature in all sorts of games that use the DPC+ kernel and virtual sprites.
  22. I didn't say they were used in drawscreen, just that they were cleared after one (at least, that's what seems to be going on). I've done that in my test program, but it doesn't change the result. I honestly don't think this is the issue here, anyway. There's not much going on in my program itself, besides a scenario that favors multiple simultaneous p1 collisions with the playfield. The problem seems to be (and, I'm not sure, which is why I'm asking) that only the collision on the highest scanline is returned in temp4, and while collisions on other scanlines are ignored. I'm just asking if anyone here can explain why this is the case, and if there's any known workaround. Sorry if I've broken some sort of protocol in asking this sort of question, I am just a novice trying to understand the result I'm seeing.
  23. That kind of why I asked question #2. It's not clear to me when the value is returned in temp4. I'm not sure what you mean by the temp variables being unreliable, though. It seems to me that while they are obliterated on a drawscreen, they work as expected as temporary variables. That's why I am interested in precisely when the Y is returned. If temp4 is reset on a drawscreen command like the other temps, then I gather that the value is being returned outside of the drawscreen (i.e., you don't have to actively test for player1/playfield collisions before retrieving the current value; you can just issue the conditional "if temp4 =.... then" whenever you want). As far as storing the values to permanent RAM, if you look at my program I think you'll see that's exactly what I'm tring to do, by trying to turn on a collision bit whenever temp4 corresponds to a given sprite's Y range. I assume by "soft collisions" you are talking about bounding boxes/hit zones, but unfortunately that isn't going to cut it for playfield collisions, which normally don't neatly correspond to rectangular hit zones like sprites do. The ability to read the state of pfpixels would sidestep the problem completely, but unfortunately from what I can tell playfield reading is not implemented yet in bB 1.1d.
×
×
  • Create New...