Cybearg Posted February 2, 2014 Share Posted February 2, 2014 (edited) From what I understand, the reason sdata is able to hold so much more than a normal data set is because it is essentially a 2d array, while a data set is more like a 1d array. Therefore, an sdata set can hold 256^2, or 65536 bytes of data, far more than a single bank making it as large as one could use it. According to the link posted, two sequential bytes are set aside, but do those two bytes work together to create a 16-bit register to address the sdata's data, like a superlong 1d array, or do they work separately to create a 2d array, as mentioned? I ask in the interest of creating a scrollable playfield. Evidently, the only way to read data from an sdata array is using var = sread(_SData_Set), so it will read from whatever the bytes aside from the sdata depict, but how would one then move along the sdata set, say to read playfield data? For instance, if I have 4 x 11 = 44 bytes per full room and wanted nine rooms in a square of 3x3, which would take 396 bytes of ROM, how would I need to address that data in order to account for both horizontal and vertical shifts? My guess would be that an sdata set is a very long 1d array using the two bytes as a 16-bit register to reference them. If I had the aforementioned data set as: sdata _Playfield = a ... end ... and the player started in the center-most of the 9 screens, I would do something like: a = 4 * 44 ... for temp1 = 0 to 47 temp2 = a + temp1 var0[temp2] = sread(_Playfield) next And, if so, then I suppose that shifting would all come down to how the playfield data was arranged, correct? For instance, if the 12 bytes of the first row of the top-most 3 rooms would come first, followed by the 12 bytes of the second row of the top-most three rooms, etc. moving down, how would one accomplish shifts left/right and up/down? In this particular data configuration, up/down shifts should be as easy as adding or subtracting 12 from a for each vertical shift, but how would one account for horizontal shifts? This would be much simpler if a and b were treated as a 2d array, with one specifically being rows and the other columns, rather than an upper and lower byte of a 16-bit register. So, in conclusion (after that speculative ramble), how do the two bytes of an sdata set work, how should playfield data be organized in an sdata set, and how can directional shifts for playfield data in an sdata set be accomplished? Edited February 2, 2014 by Cybearg Quote Link to comment Share on other sites More sharing options...
bogax Posted February 2, 2014 Share Posted February 2, 2014 It's a 1d array you could check this threadhow the data is organized dependson how you want to approach it Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted February 2, 2014 Share Posted February 2, 2014 I think the best reference is still R.T.s http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#dataarrays I rather like normal DATA statements. Doesn't use up 2 variables and you can use them like a normal array. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted February 2, 2014 Author Share Posted February 2, 2014 I think the best reference is still R.T.s http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#dataarrays I rather like normal DATA statements. Doesn't use up 2 variables and you can use them like a normal array. But a normal array can only hold up to 256 bytes of data. If (like I plan) I'm using the superchip to get a 4x22 grid, that's 88 bytes per screen, limiting me to 2 full screens that can fit in an array. It's not enough. Quote Link to comment Share on other sites More sharing options...
bogax Posted February 2, 2014 Share Posted February 2, 2014 I don't think bB cares how big you makea data statement it's just that you wontbe able to address more than the first256 bytes with the normal syntax withoutgoing through some gyrationsIf you want random access to more than256 bytes you're going to have to gothrough those gyrations in bB byselecting amongst data referencesI think sdata has no particularadvantage unless you're going toaddress the data serially.A little asm would help, it wouldn'tbe too hard to write peek and pokemacros (which would suck. One of thethings I really like about bB is thatyou can reference memory as an array) Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted February 2, 2014 Share Posted February 2, 2014 But a normal array can only hold up to 256 bytes of data. That's because the data is read from the array using an index, and an index is a 1-byte register that can have a value of only 0 through 255. So the data you're reading must be at Array+X, where Array is the starting address of the data and X is the 1-byte index (the 6507's X register, not bB's X variable), therefore the range is Array+0 through Array+255. The disadvantage of using indexed data is that (normally) the data can't exceed 256 bytes, but the advantage is that it can be read randomly. To get around the 256-byte limitation you can break the data into 256-byte pages, each page having its own address, and read from the desired page-- e.g., ArrayPage3[138]. With sdata there's no index per se, because the entire address is stored as a 2-byte pointer. Note that bB's instructions about using sdata stress that your program must run over the sdata itself before you try to use it (I didn't look up the exact wording, but it's something like that). That's because when bB encounters the sdata it stores the starting address in the 2-byte pointer. Then as you read from the sdata the address of the pointer is updated so that it always points to the next unread byte of data. You aren't reading from an indexed position per se, but from a 2-byte address. The range is 256*Hi+Lo, where Hi is the hi-byte of the address and Lo is the lo-byte. Since Hi and Lo both have ranges of 0 through 255, the range for the sdata is 256*0+0 through 256*255+255, or 0 through 65535. The advantage of sdata is that the data can exceed 256 bytes, but the disadvantage is that (normally) it can't be read randomly. You can get around the non-random limitation by setting the 2-byte pointer yourself-- e.g., if you want to randomly access the data at offset 1624, you'd need to set the pointer to the address Array+1624. Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted February 2, 2014 Share Posted February 2, 2014 For instance, if I have 4 x 11 = 44 bytes per full room and wanted nine rooms in a square of 3x3, which would take 396 bytes of ROM, how would I need to address that data in order to account for both horizontal and vertical shifts? Let's assume the sdata looks something like this: sdata roomdata=a ; room 1's data ; room 2's data ; room 3's data ; room 4's data ; room 5's data ; room 6's data ; room 7's data ; room 8's data ; room 9's data end To start reading from a given location within the sdata, either you're going to have to calculate the desired address yourself-- which would be a bit of a hassle-- or you can define some constants and let the assembler do all of the hard work for you: const room1lo = <roomdata const room1hi = >roomdata const room2lo = <(roomdata+44) const room2hi = >(roomdata+44) const room3lo = <(roomdata+88) const room3hi = >(roomdata+88) ; ... const room9lo = <(roomdata+352) const room9hi = >(roomdata+352) Then when you want to read the data for a particular room you just set the sdata pointer and start reading: ; to read the data for room 6 a = room6lo : b = room6hi ; we defined the sdata to be variable a, so the lo-byte is in a and the hi-byte is in b ; now read the 44 bytes of data sequentially: var0 = sread(roomdata) var1 = sread(roomdata) var2 = sread(roomdata) ; etc. var47 = sread(roomdata) You could also use a for loop or nested for loop. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted February 2, 2014 Author Share Posted February 2, 2014 (edited) That's because the data is read from the array using an index, and an index is a 1-byte register that can have a value of only 0 through 255. So the data you're reading must be at Array+X, where Array is the starting address of the data and X is the 1-byte index (the 6507's X register, not bB's X variable), therefore the range is Array+0 through Array+255. The disadvantage of using indexed data is that (normally) the data can't exceed 256 bytes, but the advantage is that it can be read randomly. To get around the 256-byte limitation you can break the data into 256-byte pages, each page having its own address, and read from the desired page-- e.g., ArrayPage3[138].That would be fine, except that it would require code to jump between the pages, which could be clumsy if a room was half of one page and half of another page, wouldn't it? It'd need some sort of on..goto statement to switch between data sets, as I don't know of any way to do so elegantly without on..goto With sdata there's no index per se, because the entire address is stored as a 2-byte pointer. Note that bB's instructions about using sdata stress that your program must run over the sdata itself before you try to use it (I didn't look up the exact wording, but it's something like that). That's because when bB encounters the sdata it stores the starting address in the 2-byte pointer. Then as you read from the sdata the address of the pointer is updated so that it always points to the next unread byte of data. You aren't reading from an indexed position per se, but from a 2-byte address. The range is 256*Hi+Lo, where Hi is the hi-byte of the address and Lo is the lo-byte. Since Hi and Lo both have ranges of 0 through 255, the range for the sdata is 256*0+0 through 256*255+255, or 0 through 65535. The advantage of sdata is that the data can exceed 256 bytes, but the disadvantage is that (normally) it can't be read randomly. You can get around the non-random limitation by setting the 2-byte pointer yourself-- e.g., if you want to randomly access the data at offset 1624, you'd need to set the pointer to the address Array+1624.But to read the address Array+1624, you'd actually be setting Hi = (1624 / 255) : Lo = (1624 & 255), right? I suppose that, in the end then, sdata may be the most difficult way of indexing the data because of the need to shift where the data is being read from in order to account for rows and columns. For instance, if I had a set of data for 10 rooms (480 bytes), arranged like so: column0-row0, column1-row0, column2-row0... column39-row0, column0-row1, column1-row1, ... column39-row11 ... then code that reads from the array would be like: for i = 0 to 11 k = 0 loopjump if k > 3 then goto skiptonext temp1 = (i * 4) + k temp2 = indexposition + (i * ARRAYWIDTH) + k var0[temp1] = _DataArray[temp2] k = k + 1: goto loopjump skiptonext next ... Right? I mean, forgetting for a moment that the above code wouldn't work on a 2600, that's essentially what I'm doing, yes? And to facilitate a shift up, I would subtract ARRAYWIDTH from indexposition and add ARRAYWIDTH to indexposition to shift down, while horizontal shifts would just be a matter of adding or subtracting 1 from indexposition. So then what would actually be the best way to do this for large, 4-directional scrolling playfield data? Then when you want to read the data for a particular room you just set the sdata pointer and start reading: ; to read the data for room 6 a = room6lo : b = room6hi ; we defined the sdata to be variable a, so the lo-byte is in a and the hi-byte is in b ; now read the 44 bytes of data sequentially: var0 = sread(roomdata) var1 = sread(roomdata) var2 = sread(roomdata) ; etc. var47 = sread(roomdata) You could also use a for loop or nested for loop. That sounds great if I wanted a bunch of individual rooms stored together in a single large sdata set, but how would I index half one room and half of another room? 1/4 of one room, 1/4 of another room, 1/4 of yet another room, and 1/4 of a fourth room, in the case that the player was standing right on the intersection of the corners of four rooms? How would I handle horizontal/vertical playfield scrolling with this? Edited February 2, 2014 by Cybearg Quote Link to comment Share on other sites More sharing options...
RevEng Posted February 2, 2014 Share Posted February 2, 2014 If you want the flexibility of data with the larger sizes of sdata, the usual solution is to break up the data into smaller chunks and keep them in different data statements. e.g. if you want 9 3x3 rooms, just store the strips of data in different data structures. data roomrow1 [data here] end data roomrow2 [data here] end data roomrow3 [data here] end The format is split up and less easy for you to read and edit, but that's the cost of a less resource intensive solution. The difference between data and sdata boils down to limitations in 6502/7 indexed mode and complexity of its indirect mode. If bB were to be enhanced to allow random access to sdata, you'd be blowing a bunch of rom and cycles on 16-bit math every single time you tried to access an element. No bueno. Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted February 2, 2014 Share Posted February 2, 2014 The disadvantage of using indexed data is that (normally) the data can't exceed 256 bytes, but the advantage is that it can be read randomly. To get around the 256-byte limitation you can break the data into 256-byte pages, each page having its own address, and read from the desired page-- e.g., ArrayPage3[138]. That would be fine, except that it would require code to jump between the pages, which could be clumsy if a room was half of one page and half of another page, wouldn't it? It'd need some sort of on..goto statement to switch between data sets, as I don't know of any way to do so elegantly without on..goto In this particular case, I'm inclined to think that sdata is the better solution. The advantage of sdata is that the data can exceed 256 bytes, but the disadvantage is that (normally) it can't be read randomly. You can get around the non-random limitation by setting the 2-byte pointer yourself-- e.g., if you want to randomly access the data at offset 1624, you'd need to set the pointer to the address Array+1624. But to read the address Array+1624, you'd actually be setting Hi = (1624 / 255) : Lo = (1624 & 255), right? No, you'd need to set Hi = (Array + 1624) / 255 and Lo = Array + 1624 - 256 * Hi. You can't do that in bB, because bB doesn't have 16-bit math. That's why it's easier, given what you're wanting to do, to define constants for the hi and lo bytes of the various places you want to start reading from in the sdata (since the assembler will do all the math for you when you're compiling your program). Before I try to answer any of your other questions, I need to understand what you mean by a scrolling playfield. When you said 9 rooms of data arranged in a 3x3 grid, I thought you were going to be moving from room to room. If that's not the case-- if you're actually talking about scrolling around within a large playfield-- then I'll have to rethink this, and I'm kind of fuzzy-headed right now because of flu medicine. However, there are a couple of topics that talk about scrolling large playfields. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted February 2, 2014 Author Share Posted February 2, 2014 (edited) Before I try to answer any of your other questions, I need to understand what you mean by a scrolling playfield. When you said 9 rooms of data arranged in a 3x3 grid, I thought you were going to be moving from room to room. If that's not the case-- if you're actually talking about scrolling around within a large playfield-- then I'll have to rethink this, and I'm kind of fuzzy-headed right now because of flu medicine. However, there are a couple of topics that talk about scrolling large playfields.Yeah, that's what I mean--a data statement holding a mega-room that's the size of 9 rooms arranged in a 3x3 grid, which can scroll in and out. I'm investigating the possibility of a Zelda 2-style game, with an overworld map and sidescrolling rooms/dungeons, or a more Metroid-like game with a single large map. The format is split up and less easy for you to read and edit, but that's the cost of a less resource intensive solution.That doesn't matter to me. I'll be making a map editor in Gamemaker or something to ease the editing/output of the proper format. I just need to know how the data will be structured first and have some idea of how it will work. Also, if I had maps across multiple data sets, would I be able to feasibly read partially from one set, then another, then another, in order to do scrolling? How would that sort of logic look? Edited February 2, 2014 by Cybearg Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted February 2, 2014 Share Posted February 2, 2014 He means to have a large 4-way scrolling map bigger than this: pfreadandcol.bin All this needs is to have the game engine modified to switch to another map data array when it reached the boundaries. Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted February 2, 2014 Share Posted February 2, 2014 Yeah, that's what I mean--a data statement holding a mega-room that's the size of 9 rooms arranged in a 3x3 grid, which can scroll in and out. I'm investigating the possibility of a Zelda 2-style game, with an overworld map and sidescrolling rooms/dungeons, or a more Metroid-like game with a single large map. In that case, I'd suggest looking at the threads that talk about scrolling a large playfield. Note that data and sdata in batari Basic are just two different approaches to the same thing-- letting you read data from an array. They can accomplish the same things, but the methods will necessarily be different, so you end up picking the one that's faster and requires less work, or maybe the one you understand the best. For a large 3x3 scrolling playfield, the data should be stored differently than for a grid of 3x3 screens: 3x3 grid: byte 1 = screen 1, row 1, column 1 byte 2 = screen 1, row 1, column 2 byte 3 = screen 1, row 1, column 3 byte 4 = screen 1, row 1, column 4 byte 5 = screen 1, row 2, column 1 byte 6 = screen 1, row 2, column 2 etc. In other words, for a grid you'd store each screen as a separate screen, with its own rows and columns (byte columns, not pfpixel columns). But for a large playfield you'd want to treat the entire set of data as a single playfield. You could organize it either by row or by column: 3x3 playfield, organized by rows: byte 1 = row 1, column 1 byte 2 = row 1, column 2 byte 3 = row 1, column 3 byte 4 = row 1, column 4 byte 5 = row 1, column 5 byte 6 = row 1, column 6 etc. byte 12 = row 1, column 12 byte 13 = row 2, column 1 byte 14 = row 2, column 2 etc. 3x3 playfield, organized by columns: byte 1 = column 1, row 1 byte 2 = column 1, row 2 byte 3 = column 1, row 3 byte 4 = column 1, row 4 etc. Depending on whether you want to use (indexed) data or sdata, the method you use to organize the data may impact how large the playfield can be, since an indexed array is limited to 256 bytes. So if you organize by columns, each column could be up to 256 bytes tall, which is just over 23 screens tall. But if you organize by rows, each row could be up to 256 bytes long, which is 64 screens wide. So for your situation either method would be fine, but I'd probably go with organizing by columns. Anyway, you could use either an indexed array, or sdata, depending on which is easier for you to understand or (if both are equally easy/difficult for you) which is faster or takes less ROM for the routines (depending on whether speed or space is the more important consideration). Using indexed arrays: data column1 ; 33 bytes of data here end data column2 ; data end data column3 ; data end ; etc. For sdata it's the same, except you'd do it as a single set of data: sdata roomdata=a ; 33 bytes of data for column 1 ; 33 bytes of data for column 2 ; 33 bytes of data for column 3 ; 33 bytes of data for column 4 ; 33 bytes of data for column 5 ; etc. end With the indexed array you can just use the names of the tables (column1, column2, column3, etc.) to access the data, but with sdata you'd want to define some constants for the lo-/hi-byte pointers as mentioned previously: const column1lo = <roomdata const column1hi = >roomdata const column2lo = <(roomdata+33) const column2hi = >(roomdata+33) const column3lo = <(roomdata+66) const column3hi = >(roomdata+66) ; etc. 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.