| |
Bregalad Account closed
Registered: Jul 2008 Posts: 42 |
Memory usage for a game
I wrote a memory usage map I plan to use for my game. As I'm not that familiar with the C64 I'd ask if it looks okay or if there is something really wrong about it. It is made so that the user has very little to wait while something is loding. Since the game is linar I plan to slowly load a level while the player is playing another level but I don't know if this is possible.
Also I wonder if it was worth moving the VIC bank to $4000-$7fff to get more space, because in the standard situation $00-$1ff and $1000-$1fff are unusable, but it seems there is enough room anyway. Sprites can be manually rewritten anytime if there is no room for them so this isn't an issue (altough you probably can't rewrite many of them per frame).
C64 memory MAP :
$00-$01 : Special 6510 mappring registers
$02-$ff : Usable zero-page RAM for variables
$100-$1bf : Usable for variables
$1c0-$1ff : Processor stack
$200-$3ff : Some in-game vraibles (or should the Kernal Basic variables be preserved ?)
$400-$7ff : Screen memory
$800-$bff : Boot code, fast loader
$c00-$fff : Sprite graphics for explosions that are always loaded (16 sprites)
$1000-$1fff : Sound code, SFX data, non-level music data, loading screen
$2000-$27ff : Character set for in-game use
$2800-$297f : Player sprite that is double-buffered and re-written each time the animation changes
$2980-$3fff : Level-specific sprite graphics (90 sprites) for enemies, weapons, etc...
$4000-$8fff : Main game engine code
$9000-$bfff : Level specific data (maps, copy of the caracter set and sprites graphics, music data)
$c000-$cfff : Data for next level to be loaded / Game engine variables
$d000-$d3ff : VIC registers
$d400-$d4ff : SID registers
$d800-$dbff : Color RAM
$dc00-$dfff : Joypad, timers, commnunication, etc... registers
$e000-$fff9 : Data for next level to be loaded OR Kernal
$fffa-$ffff : Interrupt vectors
On startup :
- The Commodore OS load boot programm and fast loader programm at $800-$bff (this shouldn't take too long)
- The user types RUN and the boot programm starts at $800 (where a basic SYS token is placed to run assembly code)
- That programm send a fastloader code to the disk drive
- Some text that show the title of the game shows on the screen
- First loading screen code and graphics are loaded at $c00-$fff using the fastloading procedure
- Some graphics are shown while the sound code and loading screen code is loaded at $1000-$1fff
- Some more interesting stuff and music that will make sure the user is not bored show up by the programm at $1000-$1fff, while the main game is loading at $4000-$8fff
- Level 1 data is loaded at $9000-$bfff
- After that the loading code jumps to $4000 and the actual game starts
- During gameplay in level N when the CPU has spare time it slowly loads some data from level N+1 in memory at $e000-$fff9 (and possibly $c000-$cfff)
- When we pass from next level that data is copied to actual level data, the graphics are copied (possibly decompressed) to $2000-$3fff,
data that wasn't loaded is loaded |
|
| |
Ninja
Registered: Jan 2002 Posts: 411 |
I'd suggest using $c000-$fff9 for the graphics. Then you can make use of the RAM below $d000-$dfff. Simply put sprites there which don't need to be updated. Although the processor will work on the IO-registers at $d000, VIC will only use the RAM below. |
| |
T.M.R Account closed
Registered: Dec 2001 Posts: 749 |
It depends on what kind of game and how desperate the RAM use will get to be honest; most of mine are single loads and run $0801 to $cfff (with the music under the Kernel in some cases) and i use $0340 to $07ff for labels and work spaces but i've always kept the scale of my stuff within those boundaries deliberately. |
| |
Playboy
Registered: Feb 2005 Posts: 20 |
Also you don't need this imho:
- The user types RUN and the boot programm starts at $800 (where a basic SYS token is placed to run assembly code)
This can be achieved with a simple cruncher, which makes the job for you and you dont need to waste the SYS bytes and you can place that stuff anywhere else in RAM. |
| |
enthusi
Registered: May 2004 Posts: 677 |
looks nice though im not THAT sure about the Stack-Area.
AFAIK some carts mess with it as well so I'd rather not rely on $0100-$01ff since its half a page anyway....
You can load during gameplay but that will put some restrictions on the game itself. It rather suggest to use a fast compatible loader instead. loading time will be pretty limited then and only once per level anyway?
OR even use NO fastloader. Most people use some kind of cartridge anyway with fastloader and lets face it: it will be run alot on vice and maybe 1541u that can handle KERNAL-LOAD pretty fast also.. |
| |
Mace
Registered: May 2002 Posts: 1799 |
Or you could make a 512B, 1K, 2K or 4K game ;-) |
| |
Jetboy
Registered: Jul 2006 Posts: 337 |
1. Yeah move vic bank to c000-ffff.
2. Make stack use full page, and only reduce it if you are desperate to get few more bytes.
3. Try avoiding re-writing sprites if possible. C64 is slow enough already. If you use whole vic bank you should have enough ram to store all your sprites there.
4. basic stuff does not have to be preserved. |
| |
Bregalad Account closed
Registered: Jul 2008 Posts: 42 |
Quote:I'd suggest using $c000-$fff9 for the graphics. Then you can make use of the RAM below $d000-$dfff. Simply put sprites there which don't need to be updated. Although the processor will work on the IO-registers at $d000, VIC will only use the RAM below.
Sounds nice. And yeah this should be the ideal bank since there is no CHR-ROM, and because the VIC doesn't see the registers it's really all usuable (exept the 6-byte vectors which is negligable).
My game was originally coded for a system which has MUCH less ram but has more ROM and a faster CPU. So I guess that's why I'm trying to squeeze things in RAM, to make my code short even if it is slower and I'm not used to selfmodify code.
Anyway I'd make it something like that, to maximize the amount of sprites available :
$00-$01 : Special 6510 mappring registers
$02-$ff : Usable zero-page RAM for variables
$100-$1ff : Processor stack
$200-$3ff : Some in-game vraibles (or should the Kernal Basic variables be preserved ?)
$400-$7ff : More in-game variables
$800-$fff : Boot code, fast loader
$1000-$1fff : Sound code, SFX data, non-level music data, loading screen
$2000-$3fff : Level-specific data (maps, etc...)
$4000-$7fff : Main game engine code
$8000-$87ff : Character set for in-game use
$8800-$8bff : Screen memory
$8cff-$afff : Sprites
$b000-$bfff : Sprites that are only rewritten outiside of levels
$c000-$fff9 : More sprites
$fffa-$ffff : Interrupt vectors
Quote:
This can be achieved with a simple cruncher, which makes the job for you and you dont need to waste the SYS bytes and you can place that stuff anywhere else in RAM.
Sorry but I don't unerstand what you're talking about.
Quote:
OR even use NO fastloader. Most people use some kind of cartridge anyway with fastloader and lets face it: it will be run alot on vice and maybe 1541u that can handle KERNAL-LOAD pretty fast also..
If you have to use no fastloader, this implies that you have to leave the Kernal enabled and keep it's variables at $200-$3ff intact. Also you're forced to load whole files at a time, you can't load just one byte when the CPU has some spare time during gameplay. |
| |
Oswald
Registered: Apr 2002 Posts: 5094 |
- note that 9000-a000 behaves like 1000-2000.
- some people are scared of using the stack, but you shouldnt be, tho better only using it if you really need to.
- there are quite some loaders with sources available, you dont need the kernal. (it would kill your multiplexing irqs with SEIs anyway.)
- if you can and need to rewrite those sprites. |
| |
Bregalad Account closed
Registered: Jul 2008 Posts: 42 |
Well, don't bother with my previous post, I messed it up.
I found a good loader by Cadaver, that seems very simple and it's able to load 1 byte at a time. Altough maybe if you do a jsr to get *one* byte, I don't really know what will happen on the real HW. Probably the disc drive code has to turn the motor on and move the magnetic head before one single byte can be read, so maybe the first read would be really slow, and the following ones fast ? My game will use fast scrolling between screens and no scrolling in real time, so maybe I could load a few bytes of next level during fast scrolling, without that the user have to wait.
So I'd probably end up with a memory map similar to that, leaving me with 207 sprites to work with which isn't bad :
$00-$01 : Special 6510 mappring registers
$02-$ff : Usable zero-page RAM for variables
$100-$1ff : Processor stack
$200-$3ff : Some in-game vraibles (or should the Kernal Basic variables be preserved ?)
$400-$7ff : More in-game variables (screen memory at startup)
$800-$fff : Boot code, fast loader
$1000-$1fff : Sound code, SFX data, non-level music data, loading screen
$2000-$3fff : Level-specific data (maps, etc...)
$2000-$7fff : Main game engine code
$8000-$9fff : Level-specific data for current level
$a000-$bfff : Level-specific data for next level
$c000-$c7ff : Character set for in-game use
$c800-$cbff : Screen memory
$cc00-$cfff : Sprites (16 sprites)
$d000-$dfff : Sprites that are only rewritten outiside of levels (64 sprites)
$e000-$ffbf : More sprites (127 sprites)
$fffa-$ffff : Interrupt vectors |
| |
Oswald
Registered: Apr 2002 Posts: 5094 |
loading during gameplay is doable, but you should consult cadaver personally. he will be glad to help you out I bet. |
| |
Bregalad Account closed
Registered: Jul 2008 Posts: 42 |
Isn't he a regular here anyway ? If so he should read this :) |
| |
Twoflower
Registered: Jan 2002 Posts: 434 |
Sorry for interrupting, but I haven't really understood whether or not you intend to decrunch data during loading for the next level, or if you intend to decrunch it after loading? I would suggest the second alternative - concider the following:
$8000-$9fff : Level-specific data for current level
$a000-$bfff : Level-specific data for next level
I might be way out here, but as I have understood it you intend to load the next level-specific data during play using Cadavers interrupt-loader. Decrunching while loading is nice and fast - but it'll use up the $2000 you have. If you instead just reserve the memory needed for the maximum size of the level-data and keep the decruncher separate, I bet you'll save atleast $1000 bytes. Decrunching $2000 bytes is fast, so it won't affect the gamers experience much. |
| |
Bregalad Account closed
Registered: Jul 2008 Posts: 42 |
Sorry, but I don't really understand.
Yes, I plan to load data for next level during a level using Cadaver's interrupt "slow" loader (I just made this up). If it happen to not work or to require some great sacrifices, I might just give this idea up and load a level during a map screen showing all the level is shown on the screen, hopefully it doesn't take too long.
I just can't stand long loading times when the programmers knowns there is workarounds about them and don't use them. And I like making things to a insane level, the only games that load during gameplay I can think of are Playstaion games (PS2 too but the lector is silent so it's hard to even notice). If anyone can point out a C64 game that loads during gameplay it would be awesome. |
| |
doynax Account closed
Registered: Oct 2004 Posts: 212 |
Quote: Sorry, but I don't really understand.
Yes, I plan to load data for next level during a level using Cadaver's interrupt "slow" loader (I just made this up). If it happen to not work or to require some great sacrifices, I might just give this idea up and load a level during a map screen showing all the level is shown on the screen, hopefully it doesn't take too long.
I just can't stand long loading times when the programmers knowns there is workarounds about them and don't use them. And I like making things to a insane level, the only games that load during gameplay I can think of are Playstaion games (PS2 too but the lector is silent so it's hard to even notice). If anyone can point out a C64 game that loads during gameplay it would be awesome.
Cadaver's own MW4 does some quite fancy ingame loading, and my own eternally unfinished shooter uses streaming loading. There's probably a few other examples out there but back in the day the need to support tape releases prevented such loading techniques from seeing much use.
Still, an eight kilobyte buffer is not really going to buy you much if you want to cut down on loading times, with a fast loader and decruncher you can load that in less than a second (YMMV but that's about what I've been able to manage in practice.)
In other words you're probably better off putting your time and effort into streamlining the loader system or coming up with more fine-grained schemes instead. Relatively simple tricks like positing the drive head on the right track ahead of time, or starting up the next level before the music has been loaded can be quite helpful. |
| |
Bregalad Account closed
Registered: Jul 2008 Posts: 42 |
Quote:There's probably a few other examples out there but back in the day the need to support tape releases prevented such loading techniques from seeing much use.
Were all games released on tapes ? Tapes are so slow and limited, it should really be annoying. I guess most "recent" C64 games (past 1987) were released on disks, weren't they ? And I guess it should have been really easy to copy tapes as opposed to disks. |
| |
Twoflower
Registered: Jan 2002 Posts: 434 |
No, actually 90% of all games - including the last bitter fullpricers of 1993-94 - was released both on tape and on disk. Tape-games was easy to crack, but also a bit limited as mentioned above. Note that this counts for european releases - in the US, there was hardly any tapereleases at all.
It was all a matter of standards, in one way or the other. In the UK (= the biggest game-market in Europe) a majority of potential customers didn't have any diskdrives. In the US, the 1541 was a standard. |
| |
Bregalad Account closed
Registered: Jul 2008 Posts: 42 |
Mmh, interesting. Here in europe I'm pretty sure the 1541 is the standard but it was sold separately, and was very expensive, so people who could barely afford the C64 had to stuck with the tapes until they would spare enough to buy the 1541 drive.
I might be wrong, but when you load a programm with the tape you probably need to load the whole programm at once ? Then you're limited to 62k. Unless you can make a programm which takes over the control to the tape recorder and backwards/forwards the tape as needed during gameplay without having the use press play or anything like that. By storing it in a logical order of "GameEngine -> Satage 1 -> Stage 2 -> ...." for linear games it sounds doable.
I don't really know because my tape reader is broken, so I have to stuck with the disk.
Oh and back onto the topic I've figured that if I move the character set from $c000-$c7ff to $f800-$ffff, and if I can deal with only 255 characters I may end up leaving only $fff8-$ffff (the last character) for vectors which sounds less a waste that leving up $ffc0-$ffff (the last sprite), and I'll be able to have 208 sprites. Or even more evil, make the same data usable for both interrupt vectors and character (definitely not usefull, especially if you change the vectors while the screen is rendering). |