Cybearg Posted March 19, 2013 Share Posted March 19, 2013 I'm attempting to mix bB code and Assembly to do some more advanced things, such as having a single bank of colors/sprites that are assigned to players based on a variable. Note that this is using the DPC+ bB kernel. The issue here is in regards to pointers and how flexible they are in Assembly, because I don't know. For instance, I have a set of colors for a sprite: asm milCol .byte $D6 .byte $D6 .byte $D6 .byte $D6 .byte $D6 .byte $D6 .byte $D6 end I want to call this bank of color values and assign them to every player in a loop, in case I want to assign a specific color to individual players later. I noticed when looking at the game's assembly that colors are assigned like so: .L0241 ; player2color: lda #<(playerpointers+20) sta DF0LOW lda #(>(playerpointers+20)) & $0F sta DF0HI LDX #<playercolorL0241_2 STX DF0WRITE LDA #((>playercolorL0241_2) & $0f) | (((>playercolorL0241_2) / 2) & $70) STA DF0WRITE . ; .L0242 ; player3color: lda #<(playerpointers+22) sta DF0LOW lda #(>(playerpointers+22)) & $0F sta DF0HI LDX #<playercolorL0242_3 STX DF0WRITE LDA #((>playercolorL0242_3) & $0f) | (((>playercolorL0242_3) / 2) & $70) STA DF0WRITE . ; There's a pattern--players 1-9 are assigned their low and high points using the (playerpointers+x) phrase where x = 20 + (sprite# * 2) I'm attempting the following: for temp1 = 0 to 3 temp2 = 20 + temp1 + temp1 asm .enemycolor lda #<(playerpointers+temp2) sta DF0LOW lda #(>(playerpointers+temp2)) & $0F sta DF0HI LDX #<milCol STX DF0WRITE LDA #((>milCol) & $0f) | (((>milCol) / 2) & $70) STA DF0WRITE end next This should calculate where the high and low points for the player pointer will be and add it to playerpointers in order to point to the right location. It compiles, but doesn't work. Is there some special way I need to address the temp2 variable in order to allow it to be added to playerpointers? This also applies to sprites. I would like the sprite for any player to be chosen based on a certain variable (in my case it's enemy0, enemy1, enemy2, etc.) so, if enemy0 is 1, it will grab a certain sprite for that player and set it to a certain color, without the redundancy of repeating sprite and color tables for each possible combination for each player. There are two ways to do it. Either I could have a series of statements like the above .enemycolor for each possible color/sprite and then adjust the player's pointer based on a variable to point to the sprite/colors that are applicable, or (preferably) I need some way to change which data set is being loaded on the fly, such as the following mock-up: for temp1 = 0 to 3 temp2 = 20 + temp1 + temp1 data playerColors milCol, milCol, milCol, drkCol end temp3 = enemy0[temp1] temp4 = playerColors[temp3] asm .enemycolor lda #<(playerpointers+temp2) sta DF0LOW lda #(>(playerpointers+temp2)) & $0F sta DF0HI LDX #<temp4 STX DF0WRITE LDA #((>temp4) & $0f) | (((>temp4) / 2) & $70) STA DF0WRITE end next ... asm milCol .byte $D6 .byte $D6 .byte $D6 .byte $D6 .byte $D6 .byte $D6 .byte $D6 drkCol .byte $00 .byte $00 .byte $00 .byte $00 .byte $00 .byte $00 .byte $00 end So, two questions: 1. Is there any way to dynamically adjust the value being used for the player's pointer? 2. Is there any way to dynamically adjust which data set is being pointed to? Quote Link to comment Share on other sites More sharing options...
bogax Posted March 20, 2013 Share Posted March 20, 2013 I know nothing of DPC+ one thing, temp2 is a constant in the standard kenel its = $9D where you have lda #<(playerpointers+temp2) I think you want something like lda temp2 clc adc #<playerpointers so something like eg for temp1 = 20 to 26 step 2 enemycolor asm lda #<playerpointers clc adc temp1 sta DF0LOW lda #>playerpointers clc adc temp1 and #$0F sta DF0HI lda #<milCol sta DF0WRITE lda #((>milCol) & $0F) | (((>milCol) / 2) & $70) sta DF0WRITE end next Quote Link to comment Share on other sites More sharing options...
iesposta Posted March 20, 2013 Share Posted March 20, 2013 I have been able to change the playfield pixel on/off, and the playfield colors. Just by trial and error by the way and without assembly. I haven't found where to point to the players or their colors yet. I think I posted code in my pointers thread, but it is like this: DF7LO = 96 DF7HI = 40 DF7PUSH = rand DF7PUSH = rand DF7PUSH = rand DF7PUSH = rand DF7PUSH = rand drawscreen That will change the bottom of PF2R (the 8 bits of the right side playfield) in my 128 value playfield. If playfield data is in this drawscreen loop before this it will keep setting it back and changing it. Quote Link to comment Share on other sites More sharing options...
bogax Posted March 20, 2013 Share Posted March 20, 2013 There's a pattern--players 1-9 are assigned their low and high points using the (playerpointers+x) phrase where x = 20 + (sprite# * 2) . . . This also applies to sprites. I would like the sprite for any player to be chosen based on a certain variable (in my case it's enemy0, enemy1, enemy2, etc.) so, if enemy0 is 1, it will grab a certain sprite for that player and set it to a certain color, without the redundancy of repeating sprite and color tables for each possible combination for each player. There are two ways to do it. Either I could have a series of statements like the above .enemycolor for each possible color/sprite and then adjust the player's pointer based on a variable to point to the sprite/colors that are applicable, or (preferably) I need some way to change which data set is being loaded on the fly, such as the following mock-up: for temp1 = 0 to 3 temp2 = 20 + temp1 + temp1 data playerColors milCol, milCol, milCol, drkCol end temp3 = enemy0[temp1] temp4 = playerColors[temp3] asm .enemycolor lda #<(playerpointers+temp2) sta DF0LOW lda #(>(playerpointers+temp2)) & $0F sta DF0HI LDX #<temp4 STX DF0WRITE LDA #((>temp4) & $0f) | (((>temp4) / 2) & $70) STA DF0WRITE end next ... asm milCol .byte $D6 .byte $D6 .byte $D6 .byte $D6 .byte $D6 .byte $D6 .byte $D6 drkCol .byte $00 .byte $00 .byte $00 .byte $00 .byte $00 .byte $00 .byte $00 end I know nothing of DPC+ Your code is kind of goofy sometimes and I didn't try to figure out if it will do what you want it to do. Here's that code in bB const pptrs_lo = <playerpointers const pptrs_hi = >playerpointers data playerColorslo <milCol, <milCol, <milCol, <drkCol end data playerColorshi >milCol, >milCol, >milCol, >drkCol end temp1 = 0 for temp2 = 20 to 26 step 2 temp3 = enemy0[temp1] DF0LOW = pptrs_lo + temp2 DF0HI = (pptrs_hi + temp2) & $0F DF0WRITE = playerColorslo[temp3] temp3 = playerColorshi[temp3] temp4 = temp3 & $0F DF0WRITE = ((temp3 / 2) & $70) | temp4 temp1 = temp1 + 1 next It looks like DF0LOW, DF0HI, DF0WRITE are just regular variables in the DPC+ kernel (that is, they're zero page locations that can be written to) but I can never get DPC+ to work. If they're dimmed to variables in the standard kernel that code will compile. Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted March 21, 2013 Share Posted March 21, 2013 The code in bogax's second reply looks like the way to go-- although I haven't tried it. I don't think anyone really explained why your code didn't work right. You can include math in an assembly instruction like you did-- LDA #<(playerpointers+temp2)-- but that doesn't mean the math will be done at runtime. What happens is the math is done by the assembler while it's assembling the code, so what you actually end up with is something quite different than what you were expecting. The assembler can't treat temp2 like a variable, because it has no way to know ahead of time what value will be stored in temp2 when the instruction is being executed. So what is has to do is treat temp2 like a label and use the value of the label-- i.e., its address-- while boiling the math down into a single value that can be written to the ROM file in the second half of that instruction (i.e., the byte that follows the opcode). Quote Link to comment Share on other sites More sharing options...
iesposta Posted March 21, 2013 Share Posted March 21, 2013 It does something. But I'm lost here: temp3 = enemy0[temp1] What is enemy0 ? How do I replace it with player8 so I can change its bits? Or player8's colors ? Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted March 21, 2013 Share Posted March 21, 2013 By the way, it's hard to tell what's indented and what's not, because the forum software likes to eat leading spaces-- but it looks like the "asm" keyword is definitely indented but I can't see that the actual assembly code is. You need to indent assembly code the same way you do batari Basic code: asm this_is_a_label ; labels aren't indented lda #1 ; this is assembly code, it needs to be indented at least 1 space end ; the end keyword is typed as though it were a label-- do not indent it That goes for things like BYTE, WORD, and HEX, too: My_Data ; do not indent the label HEX DE AD BE EF DE AD BE EF DE AD BE EF ; but do indent HEX, BYTE, WORD, etc. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted March 21, 2013 Author Share Posted March 21, 2013 (edited) It does something. But I'm lost here: temp3 = enemy0[temp1] What is enemy0 ? How do I replace it with player8 so I can change its bits? Or player8's colors ? enemy0 is a variable set aside to hold that enemy's "status" value. dim enemy0 = j dim enemy1 = k dim enemy2 = l dim enemy3 = m dim enemy4 = n Basically, it allows me to randomize what the enemy will be (which will determine sprite, color, spawn location, etc.) and, when set to 0, will denote that the enemy is destroyed. Sorry--should have mentioned that. Haven't had a chance to try the above code yet, but I hope to do so first thing tomorrow! I've been taking today off for a bit of R&R from non-stop 2600 stuff. By the way, it's hard to tell what's indented and what's not, because the forum software likes to eat leading spaces-- but it looks like the "asm" keyword is definitely indented but I can't see that the actual assembly code is. You need to indent assembly code the same way you do batari Basic code: Yes, it's indented. I think that the assembling would fail if it wasn't indented correctly, right? Or maybe that's only bB. Edited March 21, 2013 by Cybearg Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted March 21, 2013 Share Posted March 21, 2013 Yes, it's indented. I think that the assembling would fail if it wasn't indented correctly, right? Or maybe that's only bB. Yes, the assembly should fail if the lines aren't indented. I don't know why the forum software has such an appetite for leading spaces-- it's rather frustrating. It also seems to like to convert multiple spaces into tabs. Quote Link to comment Share on other sites More sharing options...
bogax Posted March 21, 2013 Share Posted March 21, 2013 a little shorter, a little faster, uses one less temp variable. const pptrs_lo = <playerptrs const pptrs_hi = >playerptrs data playerColorslo <milCol, <milCol, <milCol, <drkCol end data playerColorshi >milCol, >milCol, >milCol, >drkCol end temp1 = 0 for temp2 = 20 to 26 step 2 temp3 = enemy0[temp1] DF0LOW = pptrs_lo + temp2 DF0HI = (pptrs_hi + temp2) & $0F DF0WRITE = playerColorslo[temp3] temp3 = playerColorshi[temp3] DF0WRITE = (((temp3 / 2) ^ temp3) & $F0) ^ temp3 temp1 = temp1 + 1 next Quote Link to comment Share on other sites More sharing options...
Cybearg Posted March 22, 2013 Author Share Posted March 22, 2013 (edited) Finally got a chance to try it. Sadly, it seems to do pretty much exactly what the other code did: i.e. it compiles, but it doesn't assign the colors. The sprites have a jumbled collection of colors instead of the solid colors they're supposed to have. EDIT: And unfortunately, this doesn't work, either: I know nothing of DPC+ one thing, temp2 is a constant in the standard kenel its = $9D where you have lda #<(playerpointers+temp2) I think you want something like lda temp2 clc adc #<playerpointers so something like eg for temp1 = 20 to 26 step 2 enemycolor asm lda #<playerpointers clc adc temp1 sta DF0LOW lda #>playerpointers clc adc temp1 and #$0F sta DF0HI lda #<milCol sta DF0WRITE lda #((>milCol) & $0F) | (((>milCol) / 2) & $70) sta DF0WRITE end next omega.bas.bin omega.bas omega.bas.asm Edited March 22, 2013 by Cybearg Quote Link to comment Share on other sites More sharing options...
Cybearg Posted March 22, 2013 Author Share Posted March 22, 2013 This is about the highest level of abstraction I can manage with the result being functional (thanks to this for letting me even get this far). It's close, but I need some way to break down that final piece of the color writing. temp1 = 0 temp2 = 0 asm ldy temp1 lda eclo, y sta DF0LOW lda echi, y sta DF0HI ldy temp2 LDX collo, y STX DF0WRITE LDA #((>milCol) & $0f) | (((>milCol) / 2) & $70) STA DF0WRITE eclo BYTE #<(playerpointers+20) echi BYTE #(>(playerpointers+20)) & $0F collo BYTE #<milCol end Quote Link to comment Share on other sites More sharing options...
Cybearg Posted March 25, 2013 Author Share Posted March 25, 2013 Just a bump to let everyone know I'm still stumped on this one. Any suggestions? Quote Link to comment Share on other sites More sharing options...
Cybearg Posted March 29, 2013 Author Share Posted March 29, 2013 (edited) Still needing this. Maybe I can start the thinking with some questions, such as: This is fine: eclo BYTE <(playerpointers+20) And this is fine: echi BYTE (>(playerpointers+20)) & $0F and this is fine: collo BYTE <milCol That is, the code compiles and everything works, but if I do this: colhi BYTE >milCol or this: colhi BYTE (>(milCol)) & $0F or this: colhi BYTE ((>milCol) & $0f) | (((>milCol) / 2) & $70) The code technically compiles, but I just get a flickering black screen with a huge scanline report, so clearly it breaks something. Why? What is this doing: LDA #((>milCol) & $0f) | (((>milCol) / 2) & $70) And how does that differ from what the playerpointer is doing? Just to make it clear on why this is important: if there is a way to reference colors (and sprites) from an array, that means that any sprite could be quickly and easily assigned for any player without the need for redundancy of multiple identical sprites for each player. It's a pretty big deal, and there are a number of game ideas I have that are rendered impractical to the point of mostly impossible without the ability to reference colors and sprites on the fly. There isn't any magic going on here--I just don't know how these pointers work or what Assembly wants in order to do what I'm trying to do. Does anyone else know? Edited March 29, 2013 by Cybearg Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted March 29, 2013 Share Posted March 29, 2013 So what does it compile to? I.e. we need to see the list file. Also, you should differentiate data tables from ram addresses in your punctuation. It'll make your code much more readable to others, and save you from mistakes as well. I looked at your label "milCol" and thought it was a ram location since it began with a lowercase letter. I follow this: ; ram location milCol ds 1 ; data label MilCol: .byte $23 .byte $a1 ; constant MIL_COL = 10 That way when I read the code, I immediately know what everything is. By far the worse thing a person could do to themselves is mix spellings on the fly, deciding to do it a particular way one day, and vice-versa the next. Standards vary from person to person, company to company. There is no absolute right way to do it, but the important thing is to at least have a standard, and preferably something most other people do. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted March 29, 2013 Author Share Posted March 29, 2013 (edited) 1. Here is how things look with the following code (which works, but it's not enough). omega_first.zip enemygfx temp1 = 0 temp2 = 0 asm ldy temp1 lda eclo, y sta DF0LOW lda echi, y sta DF0HI ldy temp2 LDX collo, y STX DF0WRITE LDA #((>MilCol) & $0f) | (((>MilCol) / 2) & $70) STA DF0WRITE eclo BYTE <(playerpointers+20) echi BYTE (>(playerpointers+20)) & $0F collo BYTE <MilCol temp1 and temp2 are placeholders for now that would eventually be a for loop index and an indexed memory location, respectively, such as: dim enemyType = a for temp1 = 0 to 3 temp2 = enemyType[temp1] *assembly here* next The following compile but don't give anything more than a blank screen in Stella: 2. colhi BYTE >milCol omega_second.zip 3. colhi BYTE (>(milCol)) & $0F omega_third.zip 4. colhi BYTE ((>milCol) & $0f) | (((>milCol) / 2) & $70) omega_fourth.zip EDIT: Sorry, but apparently my bB doesn't compile any .lst files. It used to, but doesn't anymore. It may be connected to all the troubles I've been having with DPC+ not reporting correct bytes remaining, not working on my main system (and only through a VMWare Windows XP), or something along those lines, but each of the attached directories have the .bas, .asm, and .bin files. Hopefully that's enough. Edited March 29, 2013 by Cybearg Quote Link to comment Share on other sites More sharing options...
Cybearg Posted April 3, 2013 Author Share Posted April 3, 2013 Since there are no responses, I re-posed the question here. Quote Link to comment Share on other sites More sharing options...
Mr SQL Posted April 4, 2013 Share Posted April 4, 2013 I'm attempting to mix bB code and Assembly to do some more advanced things, such as having a single bank of colors/sprites that are assigned to players based on a variable. Note that this is using the DPC+ bB kernel. The issue here is in regards to pointers and how flexible they are in Assembly, because I don't know. Cybearg, I found my way here from your other thread on Assembly, lots of complex code here! There are some simple examples of using Assembly or bB to assign sprites to players from a single sprite bank using an offset variable on my thread on learning Assembly. Quote Link to comment Share on other sites More sharing options...
Cybearg Posted April 4, 2013 Author Share Posted April 4, 2013 Cybearg, I found my way here from your other thread on Assembly, lots of complex code here! There are some simple examples of using Assembly or bB to assign sprites to players from a single sprite bank using an offset variable on my thread on learning Assembly. Thanks for the suggestion! I had been kind of feeling mixed about whether I wanted to try learning deeper or just finish my ideas with DPC+ (hopefully fairly quickly) and leave it at that, but I think I've decided to stick with homebrews longer than I had been oriignally, so I'll definitely be checking out your awesome set-up, as promised. 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.