Of saving, passwords, and Nintendo...

BlitzPlus Forums/BlitzPlus Programming/Of saving, passwords, and Nintendo...

Tomas Khan(Posted 2008) [#1]
It's seemed to me that, even back in the days of the Nintendo Entertainment System, a lot of the bigger adventure games -- The Legend of Zelda, Kid Icarus, Metroid, Kirby's Adventure -- used either a password or saving system. The trouble is, I don't know exactly how one would go about implementing either in less than a hundred or so lines -- or even if it would be possible. (Not that I'm anywhere close to having a game big enough to need a password system, just I'm interested in the idea and any shortcuts relating to it.)

I would imagine that a password system would be the simpler one, as it would exist entirely in the game instead of having to save data elsewhere. However, I don't understand exactly how one could set up an efficient password system (or at least one as big as the ones in Kid Icarus and Metroid), especially with that many possibilities. I suppose it would be possible to take a few keys and take their scan codes to test, something like this:

If KeyHit(M)
For space.space = Each space
If space\active = 1
space\no = M ;As M is now the variable for M's scan code
EndIf
Next
EndIf

However, I haven't tried that yet, I don't know it would work, and I only have really small games to try it with right now anyway. If you know about this kind of thing, could you please explain it to me?

Thank you!
Tomas Khan


Sauer(Posted 2008) [#2]
Well for saving, you do have to use some form of data file, but a password system (like you said) can be entirely self contained.

I've never tried this but I would imagine that when a password is generated it is simply a list of variables thrown together in a string to represent certain aspects of the game. The string is just a set of values, encrypted, and then parsed out when the game is 'loaded' through the password.

For example, if you needed to store your gold, level, and position, you could do something like this;
gold=24
level=10
x= 10
y=20

Convert it to;
gold=48 ;gold *2
level=I ;10th letter of alphabet (starting at 0 of course)
x=BA ; digits represented by letters
y=CA; digits represented by letters

Then mix it up and put it into a string, then have the program evaluate it later:
CA48IBA

For more advanced games this does lead to extremely long passwords, which is why the password system is pretty much extinct... BattleMaster for the Sega Genesis requires 60 character passwords.


Tomas Khan(Posted 2008) [#3]
For more advanced games this does lead to extremely long passwords, which is why the password system is pretty much extinct...

And, if anybody ends up caring about a game with passwords, they could easily just give out the passwords to anybody and everybody... Still, it's better than having to start over from the very beginning every time you open the program (which sure doesn't help with playtesting any).

In my most adventury adventure game as of yet, the values would generally be whether you have an item (or beat a boss) or not, which could be more complex. I suppose it would end up being, say, two characters, with each character combination indicating a different combination of max hp/items/bosses/cleared rooms/whatever.

Well, now I think we're getting somewhere. Thank you!


deps(Posted 2008) [#4]
Password codes isn't that complicated, if you ask me.

Let's say I'm on level 5, with 32 out of 100 health points. I have the magic sword, but not the magic shield. Got 25 coins (999 is the maximum) and is infected with the horribly disease that makes NPCs run away from me.

5 ' my level
032 ' health out of 100
1 ' got the sword
0 ' I dont have the shield
025 ' 25 gold coins
1 ' I'm infected

Add them, as strings, together and we get this:

5032100251

Slap a "magic header to it" so we can easily check that it's not some madeup value. I use "42" in this example, since it's the meaning of life, the universe and everything:

425032100251

Now we have a nice little string there that is easily dividable by two, so let's group them into two and two, and calculate a simple check on each pair

42: 4+2 = 6
50: 5+0 = 5
32: 3+2 = 5
10: 1+0 = 1
02: 0+2 = 2
51: 5+1 = 6

Add these into a new string:

655126

Then append it to the string we had earlier:

425032100251655126

There's your magical password!

Want to parse it?
It got "42" at the beginning, so we can assume it's a valid password.
Cut out the last 6 numbers at the end, since it's our control number:

425032100251
655126

Now, calculate the pairs in the first string and check them against the control number:
42: 4+2 = 6
50: 5+0 = 5
32: 3+2 = 5
10: 1+0 = 1
02: 0+2 = 2
51: 5+1 = 6

That looks to be in order, so place the player on the beginning of level 5, with 32 as health, with the might sword, but not the shield, and make npcs run away from him/her.

Now, There's ways to improve on this:

1) Add some "magic numbers" in the first string (425032100251 -> 42503200100251 for example. There's a "00" in there now, after the health (032))
These should not change and as long as only you know about them it will be harder to break the algorithm and cheat.
2) Replace each number with a letter, we only have 10 (0-9) numbers, so select 10 letters to use in their place. Might be easier for the players to remember them.
3) You could slap a crc16/32 or MDA5 checksum at the end instead of my little control string. But the passwords will be a lot bigger.
4) Don't overdo it. (forget about md5 for example) I feel that my little way might feel a bit complicated, but the result isn't that bad. (feel free to show me how bad it is, if you think it's worth it) It's ok a player breaks it and cheat. It's not the end of the world.


Hope my little rant was of any use. I have never done it myself in a game, but I like to think about problems and how I would solve them. :)


Ross C(Posted 2008) [#5]
Problem is your level. When it goes to 10, you introduce another digit to the passcode. Most games will have an inventory as well, which is even more items. Quest's progress too. You'd best off just saving it to disk i reckon.


deps(Posted 2008) [#6]
A password is only useful for simplier games, sure.
If the password is getting too big, a switch to savefiles is the only useful solution.
Thankfuly, that's not that difficult. A quick hack would be to save the password in the file, and show a list of found savefiles for the user. (add a string, that the user enters when saving, in the savefile that you display to the user instead of displaying the filenames, of course)

If in doubt, use savefiles.


Tomas Khan(Posted 2008) [#7]
Uh... Wow. (That's how fast my mind is going right now. Slow. I definitely need food.) How exactly would save files work, if you did it that way?

[EDIT] I have a six-digit password system going right now, with six variables called space[]$ that store characters, that looks like it'll work with all the things I need, but it's not the least unwieldy of code. How would one go about parsing the saved variables (and how would one go about saving the passwords in the first place)?


Sauer(Posted 2008) [#8]
Don't save the passwords but the variables themselves in a text file. You do this by using ReadFile and WriteFile.


Tomas Khan(Posted 2008) [#9]
And you'd do that with WriteFile, then WriteInt/WriteFloat/WriteString/WriteByte, then, to load a game, you'd use ReadFile, then ReadInt/ReadFloat/ReadString/ReadByte, and they'd all come out in order?

This is starting to get very deep. Much deeper than we ever went with Maneesh, certainly.


Nate the Great(Posted 2008) [#10]
here is what I do...

say I have values like this

phealth = 78
px = 10
py = 21

just some random values...

so I make a saved file called savedgame1 or somethin similar to that and I have it make a random number between 1 and 100 like 24

when I do this I use a method where I take the integer value of each digit of the square root like this

sqr(24) = 4.898979

it is split up into 4, 8, 9, 8, 9, 7, 9
for the next set of scramble numbers I add one to 24 and get 25 and 26 after that and so on until I have enough encrypting numbers when we squareroot 25 we get 5.000000 I program it to ignor zeros so it adds a 5 to the end of the list... our list is now 4, 8, 9, 8, 9, 7, 9, 5 (this is a bad example due to all of the nines but it still serves its purpose...) now that you have the numbers you add a "magic" header to it just to throw people off... so we get the numbers we want to save in order...

42 (magic header number), 24 (original encrypting number), 82 (the players health: 78 plus the first number in the list 4 ), 18 (player x: 10 + 8 the second number on the list), 30 (player y: 21 + 9 the third number on the list) this continues until there are no more numbers to be saved... and then you repeat the process this time multiplying rather than adding...

our final file would look like this

42, 24, 82, 18, 30, 312, 80, 189

to open the file you do the reverse and check it by making sure the numbers you get from the first half of the data match the numbers you get from the second half of the data... this system is very hard to temper with as it requires so much math that is easy and simple for the computer

I know this is long and complicated but I like coming up with tricks like this in my free time especially if it has to do with encrypting or cracking codes (my favorite subject)... you also may say this method has flaws because you can simply copy and paste the files to your friend's computer however I have a way of preventing this but it is off-topic so I wont mention it


Tomas Khan(Posted 2008) [#11]
You know, I think I kinda like my little, simple, clunky password system -- as far as password systems go. These other password systems probably work better if you really, really know what you're doing, but as I don't really, I think I'll just stick with what I have.

Thank you all for your suggestions regarding to password systems; they got me as far as I got, and they might get someone else farther later on.

Now about these save systems... From my experience, you guys explain commands I haven't used a fair bit better than the Command Reference does, so could you please try it with these ReadWhatever and WriteWhatever things? (Or, if they're not the most reasonably simple and effective tools for saving, could you please explain whatever it is that is?)

Thank you!
Tomas Khan


Nate the Great(Posted 2008) [#12]
ok... so here are some basic commands to know for open/saving files

file = writefile("myfile.fil") ; creates a new file or overwrites an old one

writeint(file,10) ; writes an intiger to the file

closefile(file) ; closes the file you write

file = openfile("myfile.fil") ;opens file

x = readint(file) ; returns the next intiger in that file

:) hope this helped


Tomas Khan(Posted 2008) [#13]
So WriteFile can create a new file? Excellent. And the ReadWhatevers reliably read in order, starting from the beginning? Also excellent. Now, what would one do about the names? They'd have to be named and then recalled in a list for the player to select, I imagine? Unless you made only one save file, in which case you could merely Start/Continue... is that simpler? Or I mean, would it work that way? I suppose you'd only need one (or two, if there are two player characters to choose from). Is that how it works?

Also, what file format do you suggest to store a save in? For example, you won't be able to read strings from a bitmap, right?

In case it matters, I don't use many floating-point numbers, and my strings are only a little more and closer between.


Nate the Great(Posted 2008) [#14]
ok... ill try to answer all of those tell me if I miss one :)

so you should only create one file per saved game or possibly one master file with all saved games

yes blitz is very reliable at reading files in the correct order

you can name it anything you want except with a file extension .exe for some reason it gives me a MAV error when I try this

you can save it in any format... one you make up or one that exists however if you make it in a format that already exists such as bmp it will treat it like an image but it will error out when you try to open it... I suggest making your own format or using a common one for random data storage, .dat

to answer your last question, you can save any type of variable in any file type except .exe


Tomas Khan(Posted 2008) [#15]
Okay. I just tried it with .dat, and it worked! Thank you!


deps(Posted 2008) [#16]
Out of curiosity... Why would it crash when you try to write an .exe file? It should not matter what file extension you give the files.


Nate the Great(Posted 2008) [#17]
im not sure... it just does... it may be my computer maybe someone else could try it?


Nate the Great(Posted 2008) [#18]
hmmm... it seems to make exe's now haha I guess it was cuz of my old computer... when I try to run them they crash my comp so dont try this at home!


Ross C(Posted 2008) [#19]
When saving a file, you should probably write a backup file first, then overwrite the save file, just incase the computer crashes.

And an easy way of encrypting your data, is just to invert every bit, or byte. Then save. Upon reading, invert again to read the correct data. It's never going to be uncrackable and anyone wanting to enjoy a game would really crack the save file.


Tomas Khan(Posted 2008) [#20]
In case the computer crashes? In what way? From the code?

And what about when you save multiple times during one run of the code? (In other words, when you save after every time the game ends -- either you lose, you win, or you quit -- and you can play/quit more than once.) Do you just WriteFile before putting in more data, or do you have to do something special first?


Nate the Great(Posted 2008) [#21]
you just call writefile to overwrite the old file... nothing special required :)


Tomas Khan(Posted 2008) [#22]
Thank you!


Stamm(Posted 2010) [#23]
i am making a game too with save possibilities of course as its a long and 'linear' one and i solved it mentally like this: the whole game data is stored in a bank while playing and when saving, i just use writebytes to copy the whole bank into a save file
when loading a game i do the inverse: i copy the game data from the selected savefile to the bank using readbytes