wallaby Posted September 8, 2016 Share Posted September 8, 2016 I'm currently having a problem where I have a single sprite, but I want to use it on two players. I have to duplicate my sprite data for both players and use up more space in my graphics bank. I can do: player3: {sprite data} end But if I want to use that exact same sprite, I have to duplicate it in ROM. player4: {exact same sprite data} end Instead of re-using the existing sprite data, I have to define it twice. It becomes a problem when I want to have many different possible sprites for many players. Instead of having to duplicate the sprite 9 times in ROM, I'd rather have one sprite data, and re-use it for each player. I tried using data to define the sprite, but there is no syntax for assigning data to a player. If there was, you could define data for your sprites and colors and swap them between players. Data is ROM, so in theory, you shouldn't need any trickery to get it to work. Maybe I can do this with an ASM macro? If it's not possible to re-use existing data, I'll have to make it so only certain players can be certain sprites so there is no duplication in my graphics bank. Quote Link to comment Share on other sites More sharing options...
wallaby Posted September 8, 2016 Author Share Posted September 8, 2016 Here is the code for setting the sprite data for player3. What I'm confused about is that it doesn't seem to matter what data I set, the assembly is always the same. I think the first 4 lines are for setting the correct address to the sprite data. But then LDX loads something which is written to the sprite data. Then LDX loads another something that is written. Then it writes how many lines the sprite uses. So it must be loading two addresses (the start and end?) of the sprite data. The start and end never seems to change, so it must load the maximum and then just set how many lines it actually uses? 7529 459f a9 e6 lda #<(playerpointers+4) 7530 45a1 8d 50 10 sta DF0LOW 7531 45a4 a9 01 lda #(>(playerpointers+4)) & $0F 7532 45a6 8d 68 10 sta DF0HI 7533 45a9 a2 ae LDX #<playerL0514_3 7534 45ab 8e 78 10 STX DF0WRITE 7535 45ae a9 67 LDA #((>playerL0514_3) & $0f) | (((>playerL0514_3) / 2) & $70) 7536 45b0 8d 78 10 STA DF0WRITE 7537 45b3 a9 0e LDA #14 7538 45b5 85 a8 STA player3height With that hypothesis, I made my own ASM. I put my own label and tried this, but it crashes. playerL9 .byte %11111111 .byte %01111100 .byte %01101000 .byte %01101000 .byte %00010100 .byte %00010100 .byte %01111110 .byte %01111110 .byte %01111110 .byte %01111110 .byte %01111110 .byte %01111110 .byte %01111110 .byte %01111110 lda #<(playerpointers+4) sta DF0LOW lda #(>(playerpointers+4)) & $0F sta DF0HI LDX #<playerL9 STX DF0WRITE LDA #((>playerL9) & $0f) | (((>playerL9) / 2) & $70) STA DF0WRITE LDA #14 STA player3height Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted September 8, 2016 Share Posted September 8, 2016 I wonder if this post would help at all: atariage.com/forums/topic/107835-sharing-the-data-of-sprites/?p=3492533 Quote Link to comment Share on other sites More sharing options...
wallaby Posted September 8, 2016 Author Share Posted September 8, 2016 Oh, I got it! Okay, first you define your sprite with data. data mysprite %01010101, %10101010, %10101010 end Then you can reference the data label using the same assembly that is normally used. lda #<(playerpointers+4) sta DF0LOW lda #(>(playerpointers+4)) & $0F sta DF0HI LDX #<mysprite STX DF0WRITE LDA #((>mysprite) & $0f) | (((>mysprite) / 2) & $70) STA DF0WRITE LDA #3 STA player3height I think this allows you to use other banks for graphics data too. You wouldn't be limited by 4k using DPC+. You could also save the sprites like normal, look in the ASM for the labels bB gave them, and use them interchangeably without having to redefine them. These would use the graphics bank. I think that adds a lot of flexibility! 1 Quote Link to comment Share on other sites More sharing options...
iesposta Posted September 29, 2016 Share Posted September 29, 2016 Do you know about the DPC+ kernel command to set a range of virtual players to one data? In DK we have a lot of players that are the barrel. Is this an answer to the question you asked? So you can code: barrels player4-7: %00111100 %01111110 %01111110 %11111111 %11111111 %01111110 %00111100 end playercolor4-7: $26 $24 $24 $24 $24 $24 $22 end 2 Quote Link to comment Share on other sites More sharing options...
Papa Posted September 29, 2016 Share Posted September 29, 2016 I think Wallaby is trying to make something where player0 and player1 can kind of 'swap' sprite data. When you assign the sprite to player0 you would then have to redraw the sprite again and call it player1, he would like to say player0 is this sprite OR player1 is this sprite, but I'm not making another!? Now in the case of one sprite it is easily shared, but if you want to swap sprite identities using more than one sprite you would have to draw an identical 'other' sprite and waste data? 1 Quote Link to comment Share on other sites More sharing options...
Mr SQL Posted September 29, 2016 Share Posted September 29, 2016 I think Wallaby is trying to make something where player0 and player1 can kind of 'swap' sprite data. When you assign the sprite to player0 you would then have to redraw the sprite again and call it player1, he would like to say player0 is this sprite OR player1 is this sprite, but I'm not making another!? Now in the case of one sprite it is easily shared, but if you want to swap sprite identities using more than one sprite you would have to draw an identical 'other' sprite and waste data? Excellent description Papa! I think the DPC+ kernel extension to map definitions to multiple players is pretty cool but imo being able to independently load the sprite definitions as you've described is very advantageous and what wallaby seems to be looking for. Virtual World BASIC has this functionality with the loadsprite and loadspriteupsidedown commands. You can also access sprites like standard array variables to overwrite just specific rows. wallaby great topic and design questions! Try vwBASIC for your next game if you need that kind of program architecture. 1 Quote Link to comment Share on other sites More sharing options...
Papa Posted September 29, 2016 Share Posted September 29, 2016 Been lookin at VWB lately and I'll have stuff done with it one of these days, sure. It's a very interesting tiny. I LOVE Tiny. (It's tiny, right? *dizzy) 1 Quote Link to comment Share on other sites More sharing options...
wallaby Posted October 25, 2016 Author Share Posted October 25, 2016 Yes, that's what I was doing. I have a number of sprites. Each of them can be a monster character, but I didn't want player1 to always be the same monster. I wanted to be able to use one sprite in ROM for more than one player, but also change them. I ended up with a non-trivial way of doing this by calculating the addresses of the sprite data and storing them in the stack. When the game decided it wanted a particular monster, it would retrieve the LO and HI addresses from the stack and write the data. It works, but it's slow. I change monster sprites during screen transitions, so the slowness isn't a problem. Quote Link to comment Share on other sites More sharing options...
iesposta Posted October 25, 2016 Share Posted October 25, 2016 Maybe you're making things too complicated Is this what you're trying to do? I coded this and it works. "dim" a variable, here I use "p0base" code: dim p0base=a Set sprite(s) data. (See image above) My draw screen is one subroutine per bank if "drawscreen" is needed from more than one place inside the bank. Then when you draw screen, set player0pointerlo and the height, and it will draw the piece of the sprite you need. frack if diff{7} then player0pointerlo = 15+p0base player0height = 15 frack3a DF0FRACINC=255: DF1FRACINC=255: DF2FRACINC=255: DF3FRACINC=255 if level=2 || level=4 then DF4FRACINC=255 drawscreen return thisbank I gosub frack when I set the sprite choice, or frack3a when all is set and I just need "drawscreen". 1 Quote Link to comment Share on other sites More sharing options...
wallaby Posted October 26, 2016 Author Share Posted October 26, 2016 That only changes the player0 sprite though. Consider an 8x8 sprite that is a skeleton. Now an 8x8 sprite that is a troll. Now let's say you want that to player1 to be a skeleton. Very straight forward. But now you want player1 to be a troll. You need to change the sprite data for player 1. You could stack the sprites, like you did in your example and that works. But wait... Now you need player2 to be a skeleton and player3 to be a skeleton. You need to re-use your skeleton data for multiple DPC+ players without duplicating it. The system I have set up defines the sprite once. Then it writes the data to whatever DPC+ player sprite that needs it. This allows me much more flexibility Quote Link to comment Share on other sites More sharing options...
iesposta Posted October 27, 2016 Share Posted October 27, 2016 That only changes the player0 sprite though. Consider an 8x8 sprite that is a skeleton. Now an 8x8 sprite that is a troll. Now let's say you want that to player1 to be a skeleton. Very straight forward. But now you want player1 to be a troll. You need to change the sprite data for player 1. You could stack the sprites, like you did in your example and that works. But wait... Now you need player2 to be a skeleton and player3 to be a skeleton. You need to re-use your skeleton data for multiple DPC+ players without duplicating it. The system I have set up defines the sprite once. Then it writes the data to whatever DPC+ player sprite that needs it. This allows me much more flexibility wallaby, Could you post publicly or PM me privately with your method? I might be able to get a lot more into DK Arcade if I did not have to redefine player numbers to different duplicated data. Quote Link to comment Share on other sites More sharing options...
wallaby Posted October 27, 2016 Author Share Posted October 27, 2016 Sure, no problem. This community has helped me numerous times and it would be great to be able to contribute for once! But this isn't very elegant as can be complicated. First, you need to define your graphics data as a data statement: data my_sprite: {sprite data here} end You'll also want the color information. You can use that as a data statement too. data my_sprite_color: {colors} end You can put this anywhere, but I put it in bank 7 (which is reserved for graphics data anyway.) Now you need to store the lo and hi bytes of the sprite and colors. I had a lot of trouble getting batari basic to work with it, so I resorted to ASM. LDA #0 LDY #<my_sprite JSR SetValue2 LDA #1 LDY #((>my_sprite) & $0f) | (((>my_sprite) / 2) & $70) JSR SetValue2 LDA #128 LDY #<my_sprite_color JSR SetValue2 LDA #129 LDY #((>my_sprite_color) & $0f) | (((>my_sprite_color) / 2) & $70) JSR SetValue2 What I'm doing is getting the address bytes and storing them in an unused portion of the cartridge. The SetValue2 sub routine I got directly from this forum where we were asking for ways to use the stack as a variables (can't remember the title of the thread.) You'll need that routine. It's only a few lines and indispensable. I store the sprite starting at 0 and the colors starting at 128. You don't have to do it this way. I have no idea why I didn't just put all 4 bytes consecutively, but whatever. At this point you have saved 4 bytes for your sprite. 2 for the graphics and 2 for the colors. To actually change our sprite, we need to get them back out and write them. sprite_lo = GetValue2(0) sprite_hi = GetValue2(1) sprite_color_lo = GetValue2(128) sprite_color_hi = GetValue2(129) LDX sprite_lo STX player0pointerlo LDA sprite_hi STA player0pointerhi LDX sprite_color_lo STX player0color LDA sprite_color_hi STA player0color+1 And that will set our player0 sprite to whatever we defined as our data. To change the sprite to something else, all you need to do is get the 4 bytes from whereever you put them, and write them again. Once you get one sprite working it's trivial to use others. What it isn't is fast. Quote Link to comment Share on other sites More sharing options...
bogax Posted October 27, 2016 Share Posted October 27, 2016 Sure, no problem. This community has helped me numerous times and it would be great to be able to contribute for once! But this isn't very elegant as can be complicated. First, you need to define your graphics data as a data statement: data my_sprite: {sprite data here} end You'll also want the color information. You can use that as a data statement too. data my_sprite_color: {colors} end You can put this anywhere, but I put it in bank 7 (which is reserved for graphics data anyway.) . . . To change the sprite to something else, all you need to do is get the 4 bytes from whereever you put them, and write them again. Once you get one sprite working it's trivial to use others. What it isn't is fast. when I tryed to put stuff in bank 7 DASM complained did you do anything special to get it to work? why not have the sprite addresses in ROM? Quote Link to comment Share on other sites More sharing options...
wallaby Posted October 27, 2016 Author Share Posted October 27, 2016 Interesting. Bank 7 works okay for me. I wonder if I have a newer or older version of DASM? I didn't expect it to work in Bank 7, but when I tried, it runs fine. As for ROM locations - it would be fine if you could calculate the address before it's compiled. I don't know how to do that. Plus, I think the address would change anytime you added anything and you'd have to re-do it. I tried experimenting with setting the address in a constant but it sometimes didn't work. Quote Link to comment Share on other sites More sharing options...
wallaby Posted November 1, 2016 Author Share Posted November 1, 2016 LDA #0 LDY #<my_sprite JSR SetValue2 LDA #1 LDY #((>my_sprite) & $0f) | (((>my_sprite) / 2) & $70) JSR SetValue2 LDA #128 LDY #<my_sprite_color JSR SetValue2 LDA #129 LDY #((>my_sprite_color) & $0f) | (((>my_sprite_color) / 2) & $70) JSR SetValue2 This set of ASM functions are costing me a fair amount of space. Is there any way to pre-calculate the addresses in constants so I can set them in bB without having to calculate them on the Atari? Quote Link to comment Share on other sites More sharing options...
RevEng Posted November 1, 2016 Share Posted November 1, 2016 This set of ASM functions are costing me a fair amount of space. Is there any way to pre-calculate the addresses in constants so I can set them in bB without having to calculate them on the Atari? I count 28 bytes of ROM in total. All of the operations in brackets are being calculated during compile-time and turned into constants. The 6502 only sees a single value in their place. Quote Link to comment Share on other sites More sharing options...
wallaby Posted November 1, 2016 Author Share Posted November 1, 2016 All of the operations in brackets are being calculated during compile-time and turned into constants. The 6502 only sees a single value in their place. That's really clever! Any other way to store memory addresses so I can just place the high and low bits without having to look them up first? The way I do it now, works, but it's slow and cumbersome. I load them up here when the game starts. When I need a sprite or color data, I have to look them up again, retrieve the values, then store them in the right places. If I could cut out the looking up and storing and just use a constant value I'd save a lot of messing around. Quote Link to comment Share on other sites More sharing options...
RevEng Posted November 1, 2016 Share Posted November 1, 2016 Yeah, for sprite and color tables there isn't an easy way to get to those location pointers from basic. What you can do instead is copy the generated assembly from the player0: command into your basic, making sure any labels will remain unique. (Ie. Ones that won't possibly match other bB auto-generated labels) 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.