jrok Posted April 22, 2010 Share Posted April 22, 2010 I'm working on a project right now that uses the Superchip to write the shape data for both player sprites. It's working fine, but I seem to recall a nifty sample which Michael (SeaGTGruff) wrote in which part of the data was stored in ROM and part in RAM. I have combed the forum until my eyes hurt, but I can't seem to find it. Michael if you read this, do you recall the sample program I am talking about? I couldn't find it by searching keywords nor by searching page by page. Thanks in advance, Jarod. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted April 23, 2010 Share Posted April 23, 2010 These are the only related links I can find: http://www.atariage.com/forums/topic/93345-bankswitched-superchip-in-bb/ http://www.atariage.com/forums/topic/105806-astro-battles-attempt-two/page__view__findpost__p__1282881 Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted April 23, 2010 Share Posted April 23, 2010 I'm working on a project right now that uses the Superchip to write the shape data for both player sprites. It's working fine, but I seem to recall a nifty sample which Michael (SeaGTGruff) wrote in which part of the data was stored in ROM and part in RAM. I have combed the forum until my eyes hurt, but I can't seem to find it. Michael if you read this, do you recall the sample program I am talking about? I couldn't find it by searching keywords nor by searching page by page. Thanks in advance, Jarod. I think the example I did was in the thread called "Superchip Bankswitching in bB," which was before Fred (batari) officially added Superchip support to bB. I haven't gone back to look at the code, and I seem to recall doing another example before that which used the page zero RIOT RAM, but the concept is pretty simple... When you do a player0: or player1: statement in bB, the bB compiler stores your player shape data in ROM using .byte statements, giving it a label-- usually something like playerL01_0, though the number after the L will vary depending on the line number where the player0: or player1: statement appears. The shape data is stored after the code for your program statements. Then the bB compiler sets three bB variables-- player0pointerlo and player0pointerhi, which are set to the lo and hi bytes of the label for the shape data (i.e., the address where the data is stored in ROM), and player0height, which is set to 1 less than the number of lines of data. For example, if your player is 10 lines high, then player0height will be set to 9, since the lines are numbered starting with line 0, so 0 through 9 is equal to 10 lines. This means you can easily store your player data in ROM by yourself, such as defining 64 bytes of data for a table of 8 consecutive player shapes, each 8 lines tall, stacked one after the other, and then all you need to do is manually set the lo and hi pointers to the address of the particular shape you want to draw, and set the height variable to the appropriate value (in this case, 7 if you want the player to be 8 lines tall). To make a RAM player, you just set aside the appropriate number of consecutive bytes in RAM, then set the lo and hi player pointers to the address of the first byte, and set the height variable. Once you've done that, you don't use the player0: (or player1:) statement, because it will mess up your pointers. Instead, just copy the shape you want into the RAM variables, one byte at a time. If you're using zero-page RIOT RAM, the hi byte will be 0, and the lo byte will be the address of the first RAM variable you're using. For example, say you've decided to use variables a through h for 8 bytes of data for player0. Then you could do something like the following: const p0_lo = <a player0pointerlo = p0_lo player0pointerhi = 0 player0height = 7 player0x = 76 player0y = 44 loop a = rand b = rand c = rand d = rand e = rand f = rand g = rand h = rand COLUP0 = rand drawscreen goto loop This example just sets the player0 shape to random bytes and a random color, but you could just as easily copy a shape from ROM into the RAM variables. If you're using Superchip RAM for the player, it's pretty much the same, except the hi byte will be $F0, or the page number where the Superchip RAM is located. Also, you have to remember that you must write to one address and read from another address. That means you would set the pointers to the read address, and use the write addresses to update the data, as in the following example: set romsize 8kSC const p0_lo = <r000 const p0_hi = >r000 player0pointerlo = p0_lo player0pointerhi = p0_hi player0height = 7 player0x = 76 player0y = 44 loop w000 = rand w001 = rand w002 = rand w003 = rand w004 = rand w005 = rand w006 = rand w007 = rand COLUP0 = rand drawscreen goto loop 99% of the time, it's best to just use ROM player shapes, because drawing the player from RAM offers no real benefit. But there might be occasions when it's useful to draw the player from RAM, such as part of the player's shape will always be the same, and only the remaining part will ever vary, and you don't want to duplicate the part that will always be the same in your ROM data. Or maybe you want to do something unusual like fill the player's shape with random values, or scroll the shape, etc. Here's an example of scrolling a shape: set romsize 8kSC const p0_lo = <r000 const p0_hi = >r000 player0pointerlo = p0_lo player0pointerhi = p0_hi player0height = 7 player0x = 76 player0y = 44 w000 = p0[0] w001 = p0[1] w002 = p0[2] w003 = p0[3] w004 = p0[4] w005 = p0[5] w006 = p0[6] w007 = p0[7] loop temp3 = r000 temp4 = r001 / 128 w000 = r001 * 2 + temp4 temp4 = r002 / 128 w001 = r002 * 2 + temp4 temp4 = r003 / 128 w002 = r003 * 2 + temp4 temp4 = r004 / 128 w003 = r004 * 2 + temp4 temp4 = r005 / 128 w004 = r005 * 2 + temp4 temp4 = r006 / 128 w005 = r006 * 2 + temp4 temp4 = r007 / 128 w006 = r007 * 2 + temp4 temp4 = temp3 / 128 w007 = temp3 * 2 + temp4 COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen goto loop data p0 000000 011000 100100 %01000010 %01000010 100100 011000 000000 end (The four drawscreen statements are just to slow it down.) And here's an example of changing (scrolling) part of the shape and leaving the rest of the shape alone: include div_mul.asm set romsize 8kSC const p0_lo = <r000 const p0_hi = >r000 player0pointerlo = p0_lo player0pointerhi = p0_hi player0height = 8 player0x = 76 player0y = 44 w000 = p0[0] w001 = p0[1] w002 = p0[2] w003 = p0[3] w004 = p0[4] w005 = p0[5] w006 = p0[6] w007 = p0[7] w008 = p0[8] loop temp4 = r000 * 128 w000 = r000 / 2 + temp4 temp4 = r001 * 128 w001 = r001 / 2 + temp4 temp4 = r002 * 128 w002 = r002 / 2 + temp4 COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen COLUP0 = $4C drawscreen goto loop data p0 %11001100 %01000100 %01000100 %11111111 %01111110 111100 011000 111100 111100 end It's not a great animation, since the toes get left behind, but it's just an example to show how you can change just part of the shape if you want. Michael Quote Link to comment Share on other sites More sharing options...
jrok Posted April 23, 2010 Author Share Posted April 23, 2010 (edited) Thanks Michael. Yes, this all makes much more sense than what I was (mis)remembering. One other question I had was, is there a way to go about defining a sprite shape in ROM and then accessing it in RAM. For example, suppose I wanted to draw some trees using the Superchip. I start with one tree: dim w_GRP0 = w016 dim r_GRP0 = r016 RAMterrain asm LDA #<r_GRP0 STA player0pointerlo LDA #>r_GRP0 STA player0pointerhi end w_GRP0[14] = %00000101 w_GRP0[13] = %00011010 w_GRP0[12] = %01001011 w_GRP0[11] = %01110111 w_GRP0[10] = %01011010 w_GRP0[9] = %00111111 w_GRP0[8] = %11011011 w_GRP0[7] = %11100111 w_GRP0[6] = %01011010 w_GRP0[5] = %11111101 w_GRP0[4] = %11011011 w_GRP0[3] = %00000001 w_GRP0[2] = %00000001 w_GRP0[1] = %00000001 w_GRP0[0] = %00000011 And then I add two more by reading the data written to the first tree, forming a vertical line of three trees: w_GRP0[15] = r_GRP0[0] w_GRP0[16] = r_GRP0[1] w_GRP0[17] = r_GRP0[2] w_GRP0[18] = r_GRP0[3] w_GRP0[19] = r_GRP0[4] w_GRP0[20] = r_GRP0[5] w_GRP0[21] = r_GRP0[6] w_GRP0[22] = r_GRP0[7] w_GRP0[23] = r_GRP0[8] w_GRP0[24] = r_GRP0[9] w_GRP0[25] = r_GRP0[10] w_GRP0[26] = r_GRP0[11] w_GRP0[27] = r_GRP0[12] w_GRP0[28] = r_GRP0[13] w_GRP0[29] = r_GRP0[14] w_GRP0[30] = r_GRP0[0] w_GRP0[31] = r_GRP0[1] w_GRP0[32] = r_GRP0[2] w_GRP0[33] = r_GRP0[3] w_GRP0[34] = r_GRP0[4] w_GRP0[35] = r_GRP0[5] w_GRP0[36] = r_GRP0[6] w_GRP0[37] = r_GRP0[7] w_GRP0[38] = r_GRP0[8] w_GRP0[39] = r_GRP0[9] w_GRP0[40] = r_GRP0[10] w_GRP0[41] = r_GRP0[11] w_GRP0[42] = r_GRP0[12] w_GRP0[43] = r_GRP0[13] w_GRP0[44] = r_GRP0[14] player0height = 44 Would there be a way to define the first tree shape in ROM, while writing its duplicates to RAM? Thanks again for all the kind help. Jarod. EDT: By "writing its duplicates to RAM," I guess what i really mean is targeting the individual lines of the sprite stored in ROM. Edited April 23, 2010 by jrok Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted April 24, 2010 Share Posted April 24, 2010 (edited) Thanks Michael. Yes, this all makes much more sense than what I was (mis)remembering. One other question I had was, is there a way to go about defining a sprite shape in ROM and then accessing it in RAM. For example, suppose I wanted to draw some trees using the Superchip. I start with one tree: [...] And then I add two more by reading the data written to the first tree, forming a vertical line of three trees: [...] Would there be a way to define the first tree shape in ROM, while writing its duplicates to RAM? What you should do is store the shape for 1 tree in ROM, define the RAM player to be tall enough for 3 trees, and copy the ROM into RAM 3 times. The easiest way would probably be as follows: set romsize 8kSC const P0_lo = <r000 const P0_hi = >r000 player0pointerlo = P0_lo player0pointerhi = P0_hi player0height = 50 player0x = 76 player0y = 70 temp1 = P0[0] : w000 = temp1 : w017 = temp1 : w034 = temp1 temp1 = P0[1] : w001 = temp1 : w018 = temp1 : w035 = temp1 temp1 = P0[2] : w002 = temp1 : w019 = temp1 : w036 = temp1 temp1 = P0[3] : w003 = temp1 : w020 = temp1 : w037 = temp1 temp1 = P0[4] : w004 = temp1 : w021 = temp1 : w038 = temp1 temp1 = P0[5] : w005 = temp1 : w022 = temp1 : w039 = temp1 temp1 = P0[6] : w006 = temp1 : w023 = temp1 : w040 = temp1 temp1 = P0[7] : w007 = temp1 : w024 = temp1 : w041 = temp1 temp1 = P0[8] : w008 = temp1 : w025 = temp1 : w042 = temp1 temp1 = P0[9] : w009 = temp1 : w026 = temp1 : w043 = temp1 temp1 = P0[10] : w010 = temp1 : w027 = temp1 : w044 = temp1 temp1 = P0[11] : w011 = temp1 : w028 = temp1 : w045 = temp1 temp1 = P0[12] : w012 = temp1 : w029 = temp1 : w046 = temp1 temp1 = P0[13] : w013 = temp1 : w030 = temp1 : w047 = temp1 temp1 = P0[14] : w014 = temp1 : w031 = temp1 : w048 = temp1 w015 = 0 : w032 = 0 : w049 = 0 w016 = 0 : w033 = 0 : w050 = 0 loop COLUP0 = $C6 drawscreen goto loop data P0 %00000011 %00000001 %00000001 %00000001 %11011011 %11111101 %01011010 %11100111 %11011011 %00111111 %01011010 %01110111 %01001011 %00011010 %00000101 end I don't see any reason to dim the write addresses, because (if I'm not mistaken) you can't say "this[1] = that[1]" in bB. You can reference an array on the right side of the equals, but not on the left side. And if you want to set multiple variables to the same value, it saves some bytes (and cycles) if you do them on the same line, one afer the other (e.g., "a = 1 : b = 1 : c = 1"). I set temp1 first, then set the write variables to temp1, because I wasn't sure if "a = this[1] : b = this[1] : c = this[1]" would optimize as desired when it's compiled. Also, note my use of const to get the lo and hi bytes of the read address. I was able to code everything in bB without any inline assembly! Michael Edit: Fixed the binary values. (The forum software was hungry for %00. ) Edited April 24, 2010 by SeaGtGruff Quote Link to comment Share on other sites More sharing options...
jrok Posted April 27, 2010 Author Share Posted April 27, 2010 Thanks, Michael! This is exactly what I trying to figure out. What you should do is store the shape for 1 tree in ROM, define the RAM player to be tall enough for 3 trees, and copy the ROM into RAM 3 times. The easiest way would probably be as follows: set romsize 8kSC const P0_lo = <r000 const P0_hi = >r000 player0pointerlo = P0_lo player0pointerhi = P0_hi player0height = 50 player0x = 76 player0y = 70 temp1 = P0[0] : w000 = temp1 : w017 = temp1 : w034 = temp1 temp1 = P0[1] : w001 = temp1 : w018 = temp1 : w035 = temp1 temp1 = P0[2] : w002 = temp1 : w019 = temp1 : w036 = temp1 temp1 = P0[3] : w003 = temp1 : w020 = temp1 : w037 = temp1 temp1 = P0[4] : w004 = temp1 : w021 = temp1 : w038 = temp1 temp1 = P0[5] : w005 = temp1 : w022 = temp1 : w039 = temp1 temp1 = P0[6] : w006 = temp1 : w023 = temp1 : w040 = temp1 temp1 = P0[7] : w007 = temp1 : w024 = temp1 : w041 = temp1 temp1 = P0[8] : w008 = temp1 : w025 = temp1 : w042 = temp1 temp1 = P0[9] : w009 = temp1 : w026 = temp1 : w043 = temp1 temp1 = P0[10] : w010 = temp1 : w027 = temp1 : w044 = temp1 temp1 = P0[11] : w011 = temp1 : w028 = temp1 : w045 = temp1 temp1 = P0[12] : w012 = temp1 : w029 = temp1 : w046 = temp1 temp1 = P0[13] : w013 = temp1 : w030 = temp1 : w047 = temp1 temp1 = P0[14] : w014 = temp1 : w031 = temp1 : w048 = temp1 w015 = 0 : w032 = 0 : w049 = 0 w016 = 0 : w033 = 0 : w050 = 0 loop COLUP0 = $C6 drawscreen goto loop data P0 000011 000001 000001 000001 %11011011 %11111101 %01011010 %11100111 %11011011 111111 %01011010 %01110111 %01001011 011010 000101 end I don't see any reason to dim the write addresses, because (if I'm not mistaken) you can't say "this[1] = that[1]" in bB. You can reference an array on the right side of the equals, but not on the left side. And if you want to set multiple variables to the same value, it saves some bytes (and cycles) if you do them on the same line, one afer the other (e.g., "a = 1 : b = 1 : c = 1"). I set temp1 first, then set the write variables to temp1, because I wasn't sure if "a = this[1] : b = this[1] : c = this[1]" would optimize as desired when it's compiled. Also, note my use of const to get the lo and hi bytes of the read address. I was able to code everything in bB without any inline assembly! Michael Edit: Fixed the binary values. (The forum software was hungry for %00. ) 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.