-
Content Count
951 -
Joined
-
Last visited
Content Type
Profiles
Member Map
Forums
Blogs
Gallery
Calendar
Store
Everything posted by Cybearg
-
Setting Specific Background/Playfield Line Colors?
Cybearg replied to Cybearg's topic in batari Basic
I hope there's a better way, because in my case, I have a playfield that's 32 units high and there are 36 possible color combinations for the playfield. Which means at least 1152 bytes wasted in redundant statements, not to mention the cycles and bytes lost to the branching logic on ... goto statements. I don't see why it's impossible, since the color is just a value loaded into the memory. Why can't those values be directly modified/accessed? -
I'm not sure if my question about memory mapping was answered. If it was, sorry, I don't understand the answer. Where can I find a full memory map for DPC+ and the Multikernel sprite so I know which memory locations to modify so I can write playfield data directly to the RAM, as is the case with var0, var1, etc. with the standard kernel?
-
In my case I'm using the DPC+ kernel. Is there a way to set the background or playfield color for a certain line without changing all the other line colors?
-
Is there a full memory map for DPC+ listed somewhere? DPCplusbB.h just last a listing of values as you showed above: temp1 ds 1 ; used in sprite flickering temp2 ds 1 ;are obliterated when drawscreen is called. temp3 ds 1 temp4 ds 1 temp5 ds 1 temp6 ds 1 temp7 = topP1x ; This is used to aid in bankswitching A ds 1 a = A B ds 1 b = B C ds 1 c = C D ds 1 d = D ..etc. I assume that this just automatically takes the next memory location, but surely the defaults must be mapped somewhere, right? In particular, I want to know the memory locations for the playfield so that I can write data directly to it (such as with the var0, var1, var2, etc. memory locations in the standard kernel). Where would I find them? Ditto for the multisprite kernel--where do I find a list of memory locations for the playfield data?
-
I'm not sure how it would be done smoothly on a per-pixel basis in the standard kernel, but the basics of vertical scrolling are pretty simple. This ties into the abstract memory thread I made the other day. Basically, just copy the values of one memory location to the memory location above/below and then load in a new value. I'm not sure how the new values would be loaded (or rather, where they would be loaded from), but that's the simple basics. rem set up a for loop to go through the playfield rows, starting at the bottom for temp1 = 11 to 0 step -1 rem since each playfield row has 4 bytes, adjust to point to the current row temp2 = temp1 * 4 rem second loop used to move between horizontal columns inner_loop rem set up the next row based on the current row temp3 = temp2 - 4 rem copy the value of the current row to the next row, moving up var0[temp3] = var0[temp2] rem move to the next column temp2 = temp2 + 1 rem loop through the columns (uses mod, so requires division module to be included) if temp2 // 4 < 3 then goto inner_loop rem now do the next row next Horizontal is more complicated, since you have to do a bitwise operation, essentially, moving the value of each bit to the right or left. It can be done relatively simply in Assembly, though.
-
Well, I ended up remapping the memory locations and then using the second method described in the first post. I just want to be able to reference different sprites (whether they're players, missiles, or the ball) based on an index. I couldn't normally do it because the memory map doesn't quite allow it, but adjusting values made it possible: ; multisprite stuff below - 5 bytes each starting with spritex SpriteIndex = $80 player0x = $81 NewSpriteX = $82 ; X position player1x = $82 player2x = $83 player3x = $84 player4x = $85 player5x = $86 missile1x = $87 ballx = $88 missile0x = $89 player0y = $8A objecty = $8A NewSpriteY = $8B ; Y position player1y = $8B player2y = $8C player3y = $8D player4y = $8E player5y = $8F missile1y = $90 bally = $91 missile0y = $92 This allowed me to turn this: leap on closepixel goto leapzero leapone leaptwo leapthree leapfour leapfive leapsix leapseven leapzero if player0x = player1x - 4 && player0y = player1y + 10 then return if player0x > player1x - 4 then player0x = player0x - 1 if player0x < player1x - 4 then player0x = player0x + 1 if player0y > player1y + 10 then player0y = player0y - 1 if player0y < player1y + 10 then player0y = player0y + 1 return leapone if player0x = player2x - 4 && player0y = player2y + 10 then return if player0x > player2x - 4 then player0x = player0x - 1 if player0x < player2x - 4 then player0x = player0x + 1 if player0y > player2y + 10 then player0y = player0y - 1 if player0y < player2y + 10 then player0y = player0y + 1 return leaptwo if player0x = player3x - 4 && player0y = player3y + 10 then return if player0x > player3x - 4 then player0x = player0x - 1 if player0x < player3x - 4 then player0x = player0x + 1 if player0y > player3y + 10 then player0y = player0y - 1 if player0y < player3y + 10 then player0y = player0y + 1 return leapthree if player0x = player4x - 4 && player0y = player4y + 10 then return if player0x > player4x - 4 then player0x = player0x - 1 if player0x < player4x - 4 then player0x = player0x + 1 if player0y > player4y + 10 then player0y = player0y - 1 if player0y < player4y + 10 then player0y = player0y + 1 return leapfour if player0x = player5x - 4 && player0y = player5y + 10 then return if player0x > player5x - 4 then player0x = player0x - 1 if player0x < player5x - 4 then player0x = player0x + 1 if player0y > player5y + 10 then player0y = player0y - 1 if player0y < player5y + 10 then player0y = player0y + 1 return leapfive if player0x = missile1x - 4 && player0y = missile1y + 10 then return if player0x > missile1x - 4 then player0x = player0x - 1 if player0x < missile1x - 4 then player0x = player0x + 1 if player0y > missile1y + 10 then player0y = player0y - 1 if player0y < missile1y + 10 then player0y = player0y + 1 return leapsix if player0x = ballx - 4 && player0y = bally + 10 then return if player0x > ballx - 4 then player0x = player0x - 1 if player0x < ballx - 4 then player0x = player0x + 1 if player0y > bally + 10 then player0y = player0y - 1 if player0y < bally + 10 then player0y = player0y + 1 return leapseven if player0x = missile0x - 4 && player0y = missile0y + 10 then return if player0x > missile0x - 4 then player0x = player0x - 1 if player0x < missile0x - 4 then player0x = player0x + 1 if player0y > missile0y + 10 then player0y = player0y - 1 if player0y < missile0y + 10 then player0y = player0y + 1 return into this: leap temp1 = pixelx[closepixel] - 4 temp2 = pixely[closepixel] + 10 if player0x > temp1 then player0x = player0x - 2 if player0x < temp1 then player0x = player0x + 2 if player0y > temp2 then player0y = player0y - 2 if player0y < temp2 then player0y = player0y + 2
-
I don't follow what you're doing there. How would that be able to set values to and from player x/y positions? Is one able to make an array consisting of variables? I was under the impression only actual values were allowed. Since your code is incomplete (you reference spritex and spritey without defining them anywhere), I assume it's supposed to integrate with some of the stuff I wrote above?
-
Yeah, that's basically what I'm doing. The reason for the weird way I did it, redefining the player variables, is because I wanted to find a way to reference any memory location, not just ones that were necessarily defined in a row. For instance, let's say I'm using missile0, missile1, and the ball along with sprites. I was hoping for a way to map them, using an array or otherwise, so that they could be listed as: player0 player1 player2 player3 player4 player5 missile0 missile1 ball ... or in any other order I prefer: player4 ball player2 player3 missile1 player0 missile0 player1 ... etc. That was my overall goal--to be able to list memory locations in any order I desire and still reference them with an index. If you can think of any way to do that, please do let me know. The above example with real memory locations used the standard kernel, but ideally there would be a method that would fit for any kernel.
-
So far, I haven't found a way to abstractly reference memory locations from an array. I've tried methods one and three above, but neither works, though it's possible that my syntax is wrong and that there's another way to do it. Anyone know? I did find a less elegant but still effective way that works effectively about like how an array would: player0: %11111111 %11111111 %11111111 %11100111 %11100111 %11111111 %11111111 %11111111 end player1: %11111111 %11111111 %11111111 %11100111 %11100111 %11111111 %11111111 %11111111 end data spritex 40, 60 end data spritey 40, 60 end main_loop rem player0 is red, player1 is green COLUP0 = $40 COLUP1 = $C0 for i = 0 to 1 temp1 = spritex[i] temp2 = spritey[i] gosub storei next drawscreen goto main_loop storei on i goto pl0 pl1 pl0 asm LDA temp1 STA $80 LDX temp2 STX $85 end return pl1 asm LDA temp1 STA $81 LDX temp2 STX $86 end return The part I don't like is that, unless you want to repeat the on-goto statement or just inline add enough assembly to account for the different values of i, it requires an on-goto on top of a gosub, which is a bit pricey, cycle-wise. And then, you'd another entire subroutine for reading those memory locations, which means another on-goto and another gosub. It's more space-efficient than just writing everything out, but I don't know if the loss of cycles are worth it. Maybe someone else has a better idea for how it can be done more efficiently. EDIT: I suppose that, technically, there's no reason to use anything besides the method in the post above this one, since, if memory values don't align properly to use the a method, one can always re-map the kernel's memory locations by simplify modifying the 2600basic.h, multisprite.h, or DPCplus.h files so that they do line up.
-
Alright, I've been doing some experiments. So far, I can confirm that the second method works: dim pt0x = $80 dim pt0y = $85 player0: %11111111 %11111111 %11111111 %11100111 %11100111 %11111111 %11111111 %11111111 end player1: %11111111 %11111111 %11111111 %11100111 %11100111 %11111111 %11111111 %11111111 end data spritex 40, 60 end data spritey 40, 60 end main_loop rem player0 is red, player1 is green COLUP0 = $40 COLUP1 = $C0 for i = 0 to 1 pt0x[i] = spritex[i] pt0y[i] = spritey[i] next drawscreen goto main_loop I'll be testing the other methods to see what I find.
-
Just tested now--Yes, that must have been it. I never knew about the warp ability.
-
Is there any way that I could have abstract references to memory locations, either in bB alone or with a combination of bB and Assembly? For instance, let's say that I have a number of sprites on screen: player0 player1 player2 player3 player4 player5 ... Now in order to do anything with those, I'd have to perform the same checks on each of them, bogging down the code and slowing things down: if i then goto player0 player1 player2 player3 player4 player5 player0 if missile0x <= player0x + 4 && missile0x >= player0x && missile0y <= player0y + 8 && missile0y >= player0y then goto confirmed_hit else i = i + 1: goto denied_hit player1 if missile0x <= player1x + 4 && missile0x >= player1x && missile0y <= player1y + 8 && missile0y >= player1y then goto confirmed_hit else i = i + 1: goto denied_hit ... etc. Is there some way that I could, for instance, set up an array to point to the memory locations (the below locations are based on this)? data spritex $87, $88, $89, $8a, $8b, $8c end data spritey $8d, $8e, $8f, $90, $91, $92 end if missile0x <= spritex[i] + 4 && missile0x >= spritex[i] && missile0y <= spritey[i] + 8 && missile0y >= spritey[i] then goto confirmed_hit else i = i + 1: goto denied_hit ... Or, since memory locations are often defined in a row, something like: dim sprite0x = $87 dim sprite0y = $8d if missile0x <= spritex[i] + 4 && missile0x >= spritex[i] && missile0y <= spritey[i] + 8 && missile0y >= spritey[i] then goto confirmed_hit else i = i + 1: goto denied_hit (which would work kind of like a[0] = a, a[1] = b, a[2] = c, etc.) ... Or maybe through the use of inline assembly? (I like the use of arrays best because, while it takes more space to define the arrays, it gives you control over what is being indexed) data spritex 87, 88, 89, 8a, 8b, 8c end data spritey 8d, 8e, 8f, 90, 91, 92 end temp1 = spritex[i] temp2 = spritey[i] asm LDA $temp1 STA temp3 LDA $temp2 STA temp4 end if missile0x <= temp3 + 4 && missile0x >= temp3 && missile0y <= temp4 + 8 && missile0y >= temp4 then goto confirmed_hit else i = i + 1: goto denied_hit If none of these, is there some other way?
-
Huh... When I try to compile your code there, my postprocess.exe crashes and I get a game just consisting of a bunch of random colors and a droning tone. Any idea what's wrong? I know that the point isn't the code directly so much as the demo you're showing, which is pretty awesome, but it bothers me when my set-up can't do what others' can do, because that means potential trouble down the road.
-
Just out of curiosity, if this is a digital arts project, why are you choosing a console with such minimalist, limited visuals available to you? Or is that the point?
-
You can test other controllers with Stella if you hit Tab, go to game options, and set the controllers to Paddle or Driving, though you'll have to then restart Stella for the changes to take effect and they'll be reset if you recompile your game. I don't know of any way to set those options and make them "stick," though there's probably some way using an autoexec.inc file or something. You won't be actually using the controller, of course, but it'll emulate how it works relative to other controllers using your keyboard/mouse. Should be sufficient for basic testing and you can ask others who DO own Harmony carts/paddles/etc. to confirm test it for you. I know that most may disagree, but personally, I prefer the paddles over the driving controller. True, the paddles may be prone to jitter as they age (though I'm betting that the driving controller does as well) and the paddles are limited in their movement, while the driving controller can spin as many times as you like, but I think that the sensitivity/precision on the paddles is higher, particularly when making very precise movements or if you'll be twisting the knob very quickly. And yeah, they do work differently. From what I understand, the paddles have a "gradient" between 1 and 76 or something, each number corresponding to a degree of rotation in the knob (not a literal degree, but an amount of rotation), so you have to base how something responds on that value. Plus, the knob could begin at any degree of rotation, so you have to keep in mind that it could be in the middle just as well as far over to one side or the other. Also there's something about a buffer to read the paddle, but I don't understand it. In contrast, the driving controller has four contacts that get connected to make a full circuit as the knob is twisted, so it reports a contact as a series of bits, something like (though this may be backwards, horizontally): 00 01 10 11 The issue is that if you spin quickly, it'll be too fast for it to read the contact connection, so it may miss noticing that you've moved at all. Also, if you turn very slowly, there may be a decent amount of time where there is no connection with any contact, so the driving controller won't read any movement at all until there is a connection made. If I had a choice, Heartbreak would have used paddles, because whether the paddle is to the far right or the far left doesn't really matter in that context, plus many, many more people will have paddles as opposed to driving controllers, since only something like 6 or 8 games were ever released for the driving controller, almost all of them racing games. But apparently it's not possible because of the way Omega wrote Heartbreak's kernel and I'm not going to push for things that will take yet more of his generously-given time, especially now that he's much more busy. Hopefully that helped somewhat.
-
To be frank, I didn't go to the thread with the intention of doing thorough testing--I was frustrated by my own game not working right and I just went there because Omega was making a point with it. Also, I noticed that the thread was quite a few years old on the first post, so I assumed that the game was long since past testing, finalized, and released. And finally, I didn't mean it as an accusatory statement. I assumed I just didn't know what was going on. I WAS playing Release Candidate 7 on my Harmony, though I just tried now for 10-15 minutes and I wasn't able to replicate what happened. I would just disappear (not explode, just vanish) if I did much moving (it always happened within the central 2/3 of the screen) and then I'd respawn as though I'd died. It could have just been a fluke in how the cartridge was set and turned on or a random bug loading it on my Harmony. I don't know. Though, testing it again, I did have one instance (unrelated to the above) where, after dying, I spawned onto an asteroid rather than in the void, though the asteroid was generous enough not to harm me as long as I was over the top of it like that. It really is a fantastically put together game with a level of polish that I wouldn't have thought would be seen on a 2600 game and it's certainly an inspiration to keep things high-tier like that with my own work. So, that's all. Not much to really report. Sorry for the goat-getting.
-
That would explain why I couldn't actually put things in bank 7, though I'm assuming it's still there, but you're just not allowed to actually place stuff in it yourself and instead the assembled code stores the actual graphics bytes in it, correct? And where can one find vBb 566? I've got 565.
-
The 23rd bkcolor is the color that goes behind the score. If I only have 22, it will be some other color I don't want. Let me give this a shot and see if that fixes it, but thank God, finally there's a solution! Phew, I was starting to get really nervous. Is there anything I can do to set the player or background to be all one color? EDIT: That absolutely fixed it! Thank you so very, very much! Even going back to the version I had before I cut out all the game logic runs silky-smooth now. What a relief! That's definitely a tip that should go in this thread, but I think we should get a mod to cut out all the extra posts and put them in a different thread, since I'm afraid I've somewhat derailed this quick-tip getting started thread.
-
Sorry for the confusion. Those are separate things: 1. My game's playfield jumps around on real 2600 hardware, which is odd because: 2. According to Stella, the scanlines remain at 262 at all times, but: 3. I assumed that the scanlines must have gotten off sometime immediately when the game begins, so: 4. I added in the reboot command so I could check the scanlines of the first frame in Stella (by restarting the game once it was already open in debug mode), and sure enough, the first scanline (and ONLY the first scanline) was over 262, so I assumed that: 5. There must be something wrong in that first frame, which led me to find: 6. The first frame with DPC+ always goes over 262 scanlines, so I assumed that the fault was with DPC+ Don't mean to condescend with that, but hopefully it's a bit clearer now. I really don't see what could be wrong in my code. It's about as bare-bones as it can get. Even calling a drawscreen immediately after the kernel options are initialized still results in a playfield bounce. Huh... It works for me. The link is for Andrew Davie's 12th Assembly lesson, "Session 12: Initialization"
-
Neat, but, Omega, I didn't care about the reboot. I don't even plan to use the reboot command at all (I haven't up to this point--I prefer to keep the game logic running and just set a variable that returns things to the start). My problem is with the playfield bouncing, which doesn't have anything to do with rebooting. I didn't want you to get stuck on the rebooting thing because I really need help with this bouncing thing and the reboot stuff if a moot point. EDIT: Besides, if I wanted a more efficient clear/restart, I'd use Andrew Davie's "ultimate programmer" clearing method: ldx #0 lda #0 Clear sta 0,x inx bne Clear
-
Have you tried compiling the code I posted earlier to see if it jumps for you? Would anyone be willing to send me a zipped copy of all the kernel files that are confirmed working with DPC+? Can anyone confirm that bB 1.1d works with DPC+ on 2600 hardware?
-
Meaning that there's not enough cycles to initialize the playfield? If it was just that there aren't enough cycles to draw the playfield, that would be no problem; I'd just have to have a drawscreen command before the playfield is drawn, but that doesn't fix the bounce. I could drawscreen before the playfield and after the playfield and it would still bounce. (I know because I've tried it.)
-
It doesn't matter in the context of my problem. But bB has a "reboot" command. I checked the Assembly for it, since you asked. It's this: JMP ($FFFC) ... So it just jumps to the first line in the entire code, apparently.
-
Don't get distracted by the fact that I used reboot to check to see what the first frame was. I didn't hit the reset button on a real 2600 and in the example above, the code to reboot isn't even there, yet there is still bounce. So unless there's something I did wrong in how I initialized my playfield there, I don't see why it should bounce. It's not even being called every frame--just the first (since it's not being cleared, that shouldn't be an issue). I really have no clue why it's not working. Are you saying that you just tried compiling the code I posted with 1.1c and testing it on a Harmony and it worked fine without the bounce?
-
That's what I've been trying to say. The game is rock solid at 262 lines, even before I cut everything else out. But the very first frame (which I could only see by using the reboot command) hits 270 scanlines. That's my only hint as to a reason of why the playfield bounces on real hardware. EDIT: Note, it hits 270 scanlines on the first frame even if I do a drawscreen immediately after my kernel options are set on the first bank. Maybe you can see my frustration now. ;P
