|
Post by scotthuggins on Feb 28, 2015 15:46:46 GMT -5
Hi! I just joined this site. Love this forum! I am developing a game and have been for some time but I made the mistake of doing all my testing in MESS. Things were working well - and I seem to recall others saying the same thing when using MESS as their emulator. Well, ParaJVE definitely wasn't working so I got a friend to try it out on a real Vectrex. Same exact behavior on a Vectrex as on ParaJVE.
I now know to stay away from MESS! But to get stuff going, I had to clear out ( initialize ) ram locations for my variables to #00. However, I got so far in the development that it's turning into quite a chore.
I have scoured the BIOS routine documentations, but cannot find a simple way to do this: is there just a simple way to clear RAM out completely when the game program starts?
I hope this isn't too dumb a question, but I would greatly appreciate any suggestions. Thank you!
Scott
|
|
|
Post by VectorX on Feb 28, 2015 16:12:18 GMT -5
Great, thanks! Hope you enjoy your stay, although I can't help with the tech stuff. Someone else probably will though.
|
|
|
Post by kokovec on Feb 28, 2015 16:43:18 GMT -5
|
|
|
Post by scotthuggins on Feb 28, 2015 18:18:27 GMT -5
Thank you! I had to end up just writing a loop at the beginning of the program to clear out the ram locations. Worked fine.... but thanks for the heads up on the BIOS routines.
PS: words of wisdom - if you might be new and are getting into Vectrex Development, I hope this gets to you: DO NOT USE MESS as an emulator. As much as I love MESS, not so much for Vectrex. I could have saved a ton of time had I found ParaJVE much earlier in this project I am working on.
|
|
|
Post by christophertumber on Feb 28, 2015 22:30:43 GMT -5
I routinely use both MESS and ParaJVE for development. They both have their uses - MESS is just fine if you aren't doing anything too strange and it's much more conducive to CLI and batch file assembly. (At least I haven't noticed any CLI capabilities with ParaJVE but I may have just never looked).
Anyway - Why are you needing to bulk-clear RAM? You probably shouldn't be referencing uninitialized RAM and bulk clear is probably just covering up for bad habits you're going to have to fix or even unlearn later.
|
|
|
Post by scotthuggins on Mar 1, 2015 0:00:53 GMT -5
>You probably shouldn't be referencing uninitialized RAM and bulk clear is probably just covering up for bad >habits you're going to have to fix or even unlearn later.
Christopher - thank you for your reply. Big fan of your Vectrex work - both in tutorials and the quality of your games.
I found some (many) RAM locations had a value - something other than #00 at start up.
>just covering up for bad habits
I am not sure how to take that..... I am doing my best and I love this little machine. That's all. I am learning a ton as I go.
Again, thanks for your reply.
|
|
|
Post by christophertumber on Mar 1, 2015 8:37:10 GMT -5
I found some (many) RAM locations had a value - something other than #00 at start up. Yes, MESS assumed they're 0 when they may not be. But I think you missed my point. You must be doing something like: Variable1 equ $c880 Variable2 equ $c881 ... lda #Constant sta Variable2 ... lda Variable1 adda Variable2 sta Variable1 The problem here is not really that $c880 is non-zero at startup. The problem is that you're reading a variable before initializing it. Zeroing out all RAM is going to result in slightly more predictable behaviour (which may actually be a bad thing when you're trying to bugfix and find the problem) but it still doesn't address the underlying problem. What if Variable1 is supposed to be initialize to something other than 0? Even if in the interest of code size/speed you decide that because you have so many variables (especially table type structures) that initialize to zero that zeroing out everything is the way to go, I'd still really suggest you do something like: lda #Constant sta Variable2 ;lda #0 ; Not needed due to RAM initialization ;sta Variable1 So that it's clear to you later what's going on if it turns out there's a problem - Especially if you decide later that your variable should be initialized to a non-0 value. FWIW, I did exactly the same thing back in the day. I did an intro for the Atari 2600 Polo cartridge released around 2000. Turns out the Reset switch on the console doesn't actually reset anything, it's really just a JMP. I didn't have the capability of running it on a real machine and was relying on the emulator. When the Reset switch was hit, I didn't bother zeroing out all RAM registers. This wasn't caught until the day of PhillyClassic with a bunch of carts already manufactured and and assembled with boxes &etc. Fortunately it only resulted in a small glitch that happened rarely. But a lesson was learned...
|
|
|
Post by scotthuggins on Mar 1, 2015 9:29:57 GMT -5
Thanks, Christopher! Yep, I was doing what you mentioned, an easy mistake to make. I will change my approach - makes better sense now.
|
|
|
Post by christophertumber on Mar 1, 2015 14:30:06 GMT -5
Especially when dealing with the environments that have limited resources anything you can do to try and promote good habits as far as modular, relocatable and reusable code will only help you in the long run. If you're developing in a more modern environment it really doesn't matter if you're not particularly efficient in your variable use. The compiler will deal with it and the likelihood that you'll ever need to think about RAM usage is remote.
But on 8-bit consoles you will run out of RAM if you do anything at all ambitious. Then when you decide to re-use some RAM, all of a sudden you can't rely on it being initialized to a particular value anymore unless you explicitly do so.
When dealing with something like a game and in an environment where you don't have a compiler managing your variables for you have basically 5 types of variables:
Global variables: Variables which must be maintained throughout the entirety of your game. These are actually quite rare and usually have to do with high scores and high score tables. These variables are absolutely never for re-use.
Game variables: Variables which are "global" but only within the scope of the current game being played. These are variables such as score or current level. These variables are available for re-use outside of the current game but are otherwise unavailable. For example, these variables might be used in the GUI and navigation. Such as the title screen.
Level variables: Variables important within a certain level but which are generally reset at the beginning of each level and therefore may be used elsewhere. For example the (X,Y) of the player's ship and shots. Those variables might be available for use in any cut-scenes.
Dynamic or Local variables: These are variables which may be in use and unavailable for some time during a level. But may see frequent re-use. For example, say you have a display kernal which allows supports up to 10 enemy ships and 20 enemy shots. You are going to be re-using the (X,Y) velocity and status (etc) type variables over and over for each "wave" of enemies.
Scratch/temporary/loop variables: Variables which only have short-term meaning especially within a certain function, sub-routine or loop and may be re-used otherwise. You will need to exercise some management of these ie; nested loops or if you need multiple temp values but in general these variables are available for quick use at any time and should always be considered uninitialized.
Where you save yourself a bunch of time and effort by modular design is when you want to re-use a variable in the category below where you're current working (ie; you want to use Game variable in a Global context).
For example, say you never bothered to initialize player (X,Y) at the start of every game/level because it's always (0,0). After finishing the game you move on to designing you title screen. You decide to re-use the chunk of RAM that is used by the game for player and enemy data. So now at the start of every game PlayerY and PlayerX are going to wind up whatever value your title screen puts there. And since you've just been working on your title screen all week-end you haven't bothered continuing into the game itself. So you only notice this problem after the title screen is all done and the player's ship is starting out in a random spot very time.
So now you have to debug this. Maybe you remember you never bothered to initialize (X,Y) - but probably not. And now you have to figure out what's broken - Did you break your joystick reading routine? You're using the same routine but you had to change it because you have auto-fire in your game but auto-fire is bad for GUI navigation. Or did you break your sprite routines - your title screen uses sprites and you made some changes to your routines because you needed to handle different scales better. Speaking of Scale, maybe you're somehow using the wrong scale?
And that's for something relatively straight-forward and very visible like the player's (X,Y). What if it's something more esoteric and you won't notice right away. What if the score value of enemies is off by 10 points? What if hitboxes are off? Or what if it's the situation you describe in your OP?
|
|
|
Post by andygarton on Mar 2, 2015 2:30:15 GMT -5
Christoper - ParaJVE does have CLI capabilities. The HTML manual covers it quite well but the main one I guess is "-game=<path>" to automatically load and run a specific rom.
|
|
|
Post by cNp on Mar 2, 2015 7:55:31 GMT -5
Yeah, just to second what Chris T said... set everything explicitly, even if you could guarantee a value was 0 to start with you'd sooner or later end up with strange behaviour and very difficult to debug scenarios!
And welcome into the Programming forum!
cNp
|
|
|
Post by mikiex on Mar 3, 2015 15:54:35 GMT -5
Another point worth mentioning is that some of the ram is used for bios routines, map details here: www.playvectrex.com/designit/chrissalo/memorymap.htmI remember writing some code that stored stuff in the ram used by the bios and everything ran fine, then I added sound and all kinds of bugs appeared because the bios started using that memory... so don't use that ram unless you know what you and the bios us doing
|
|
|
Post by mikiex on Mar 3, 2015 16:11:10 GMT -5
Just as an example I used this to initialize a load of memory at the start of a game.
3 examples
If its just a few values I group those values.....
lda #10 ;load the A register with the decimal value 10 sta y_position ;store the value in A (which is 10) sta x_position ;again store what is in A (10)
or for zeroing the same.......
clra ;clra is faster than lda #0 (not that speed is essential here) sta y_position ;store the value in A (which is 0) sta x_position ;again store what is in A (0)
or clearing a bigger block of ram.......
ldb #BULLETBYTES ;Number of bytes (constant value of 48 declared earlyer) ldx #bullets ;start address of bullet memory jsr Clear_x_b ; when returns it trashes D;
|
|
|
Post by christophertumber on Mar 3, 2015 17:15:21 GMT -5
For chunks of RAM > 256 bytes:
ldd #0 ldx #Start_Of_RAM_To_Clear next_RAM_clear: std ,x++ cmpx #End_Of_RAM_To_Clear bne next_RAM_clear
|
|