SD Save Sector Reservation List: Difference between revisions

From Uzebox Wiki
Jump to navigation Jump to search
mNo edit summary
 
(17 intermediate revisions by the same user not shown)
Line 2: Line 2:




The SD Save API functions are based on reading and writing sectors in a common fixed size(512KB, 1024x512 byte entries) SD file for all games named "_HISCORE.DAT. This allows games to use the smaller SD libraries that do not support creating new files while simultaneously easing pressure on limited EEPROM and minimizing the number of tiles on the SD card. It is not strictly for high scores, but any type of saved data a program may generate.
The SD Save API functions are based on reading and writing sectors in a common fixed size(512KB, 1024x512 byte entries) SD file for all games named "_HISCORE.DAT. This allows games to use the smaller SD libraries that do not support creating new files while simultaneously easing pressure on limited EEPROM and minimizing the number of files on the SD card. It is not strictly for high scores, but rather any type of saved data a program may generate.
 


==Direct Access Method==
==Direct Access Method==


There are 2 halves of the file. The first half is direct access and is designed to be as simple and resource saving as possible for games that do not require complex solutions. It is expected this will be the most common type, so you need not wrap your head around the more complex alternate system(though don't be scared of it, it is actually not complicated to do if necessary). Simply leave the last half of the file alone in that case. As example sector 0 is reserved for the kernel and would start at SD offset 0, whereas sector 143 would start at SD offset 143*512=73216. The reserved number here, is simply a number you multiply by 512 to get the offset to the first byte that belong to your program. You may reserve multiple sectors, but if more than ~8 is required you should probably consider the use of the alternate system. From there it is free reign to do directly what you want with the space you have reserved.
There are 2 halves of the file. The first half is direct access and is designed to be as simple and resource saving as possible for games that do not require complex solutions. It is expected this will be the most common type, so you need not wrap your head around the more complex alternate system(though don't be scared of it, it is actually not complicated to do if necessary). Simply leave the last half of the file alone in that case. As example sector 0 is reserved for the kernel and would start at SD offset 0, whereas sector 143 would start at SD offset 143*512=73216. The reserved number here, is simply a number you multiply by 512 to get the offset to the first byte that belongs to your program. You may reserve multiple sectors, but if more than ~8 is required you should probably consider the use of the alternate system. From there it is free reign to do directly what you want with the space you have reserved.
 


==Block Chain Method==
==Block Chain Method==


The second half works on a different ID based system somewhat similar to EEPROM saves and is designed for more complex games. Things like SPI ram based RTS games, sandbox games, or basically any  type of program where there is not strict upper bound to how much data can be saved(even a text editor for instance). This system requires more complexity, but it allows a more robust save structure to be implemented without simply reserving "as much as might ever be required" which is not efficient at large scales. Instead, only as much as is currently needed gets saved into a single, or chain of, free sector(s) which can be expanded later without totally formatting the space. Sectors can be used by any game on a first come first served basis and data might not end up in contiguous sectors similar to using EEPROM with multiple block IDs. To make access easier, faster, and safer, the first 16 sectors of this section are reserved for a directory of Block IDs. It is important to check code examples or ask questions on the forums to ensure the program do not overwrite existing data or corrupt the directory with an accidental bug. Each entry in the directory is a linear 32 bits forming the Block ID, and so you will need to scan these sectors 32bits at a time until you find the ID you need. If you are writing a new block then simply scan for the first Block that equals 0 indicating it is unused. When your scan finds the desired ID, divide the offset you found it at by 32, add 256*1024(to get past the first half of the file using the other system) and this number if the offset to the first byte of your sector. The 32 bit Block ID format of this system is:
The second half works on a different ID based system somewhat similar to EEPROM saves and is designed for more complex games. Things like SPI ram based RTS games, sandbox games, or basically any  type of program where there is not strict upper bound to how much data can be saved(even a text editor for instance). This system requires more complexity, but it allows a more robust save structure to be implemented without simply reserving "as much as might ever be required" which is not efficient at large scales. Instead, only as much as is currently needed gets saved into a single, or chain of, free sector(s) which can be expanded later without totally formatting the space. Sectors can be used by any game on a first come first served basis and data might not end up in contiguous sectors similar to using EEPROM with multiple block IDs. To make access easier, faster, and safer, the first 16 sectors of this section are reserved for a directory of Block IDs. It is important to check code examples or ask questions on the forums to ensure the program do not overwrite existing data or corrupt the directory with an accidental bug. Each entry in the directory is a linear 32 bits forming the Block ID, and so you will need to scan these sectors 32 bits at a time until you find the ID you need. If you are writing a new block then simply scan for the first Block that equals 0 indicating it is unused, and write a Block ID to claim it. When your scan finds the desired ID, divide the offset you found it at by 4, add 256*1024(to get past the first half of the file using the other system) and this number is the offset to the first byte of your sector. The 32 bit Block ID format of this system is:


Author ID(16 bits)
Author ID(16 bits),
Game ID(8 bits)
Game ID(8 bits),
Chain Number(8 bits, program dependent meaning)
Chain Number(8 bits, program dependent meaning)


==Reservation Tables==
==Reservation Tables==
Line 35: Line 38:
| 16(0x10)
| 16(0x10)
| D3thAdd3r(Lee Weber)
| D3thAdd3r(Lee Weber)
| Toorum's Quest
| [[Toorum's Quest]]
|-
| 17(0x11)
| D3thAdd3r(Lee Weber)
| [[Dig Dug]]
|-
|-
| 489(0x1E9)-511(0xFF)
| 489(0x1E9)-511(0xFF)
| Free Use
| Shared Use
| Small Saves
| Small Saves


|}
|}


 
For the "Small Saves" shared sectors, denote bytes used as "sector_id(sector_id_hex).bytes:start_byte..end_byte".
For the "Small Saves" spot, denote bytes used as "sector_id(sector_id_hex).start_byte..end_bbyte". This is for games only requiring a few bytes to store the last level completed or such and avoid wasting most of a sector.
 
 
{| class="wikitable"
{| class="wikitable"
|-
|-
! Offset
! Offset
! Owner
! Owner
! Game\
! Game
|-
|-
| 508(0x1FC).0..5
| 489(0x1E9).bytes:0..5
| D3thAdd3r(Lee Weber)
| D3thAdd3r(Lee Weber)
| Alter Ego
| [[Alter Ego]]
|}
|}




For the alternate Block ID system, reserve ID numbers. Remember the ID number could end up stored anywhere in the first 16 sectors of this file half(0x20000-0x22000) on a first come basis so you will need to scan.
For the Block ID system(second half of file), reserve ID numbers.
 
 
{| class="wikitable"
{| class="wikitable"
|-
|-
Line 73: Line 75:


|}
|}
==Small Saves==
As seen in the table above, there are some slots reserved in the first half of the file for small saves. This is intended for games with very simple requirements such as storing the last level that was completed per episode. Here, if an author has several such games and/or is willing to cooperate with another author with such games, this progress can be stored in reserved fixed byte positions while other games do the same, at their reserved positions, in the same sector. It would not be a bad thing to reserve a bit more than you might need(potentially waste a few bytes) as a buffer between games for future expansion. The important savings is not wasting large parts of many sectors. After a game has been stable for changes for some years, those unused buffer/expansion bytes could be reclaimed later. It is the authors discretion to use this. Since this space needs to be enough for all future games with small saves, saves bigger than perhaps ~200 bytes should probably just use the other full sector methods.

Latest revision as of 07:37, 27 December 2016

Reserve sectors/IDs for your game here. To view, edit or remove the sectors on your SD card, see the emuze tool. For examples of implementing SD Saves see [Implementing SD Saves]


The SD Save API functions are based on reading and writing sectors in a common fixed size(512KB, 1024x512 byte entries) SD file for all games named "_HISCORE.DAT. This allows games to use the smaller SD libraries that do not support creating new files while simultaneously easing pressure on limited EEPROM and minimizing the number of files on the SD card. It is not strictly for high scores, but rather any type of saved data a program may generate.


Direct Access Method

There are 2 halves of the file. The first half is direct access and is designed to be as simple and resource saving as possible for games that do not require complex solutions. It is expected this will be the most common type, so you need not wrap your head around the more complex alternate system(though don't be scared of it, it is actually not complicated to do if necessary). Simply leave the last half of the file alone in that case. As example sector 0 is reserved for the kernel and would start at SD offset 0, whereas sector 143 would start at SD offset 143*512=73216. The reserved number here, is simply a number you multiply by 512 to get the offset to the first byte that belongs to your program. You may reserve multiple sectors, but if more than ~8 is required you should probably consider the use of the alternate system. From there it is free reign to do directly what you want with the space you have reserved.


Block Chain Method

The second half works on a different ID based system somewhat similar to EEPROM saves and is designed for more complex games. Things like SPI ram based RTS games, sandbox games, or basically any type of program where there is not strict upper bound to how much data can be saved(even a text editor for instance). This system requires more complexity, but it allows a more robust save structure to be implemented without simply reserving "as much as might ever be required" which is not efficient at large scales. Instead, only as much as is currently needed gets saved into a single, or chain of, free sector(s) which can be expanded later without totally formatting the space. Sectors can be used by any game on a first come first served basis and data might not end up in contiguous sectors similar to using EEPROM with multiple block IDs. To make access easier, faster, and safer, the first 16 sectors of this section are reserved for a directory of Block IDs. It is important to check code examples or ask questions on the forums to ensure the program do not overwrite existing data or corrupt the directory with an accidental bug. Each entry in the directory is a linear 32 bits forming the Block ID, and so you will need to scan these sectors 32 bits at a time until you find the ID you need. If you are writing a new block then simply scan for the first Block that equals 0 indicating it is unused, and write a Block ID to claim it. When your scan finds the desired ID, divide the offset you found it at by 4, add 256*1024(to get past the first half of the file using the other system) and this number is the offset to the first byte of your sector. The 32 bit Block ID format of this system is:

Author ID(16 bits), Game ID(8 bits), Chain Number(8 bits, program dependent meaning)


Reservation Tables

Simple System(first half of file)

Sector Owner Game
0(0x00)-7(0x07) Kernel Reserved
8(0x08)-15(0x0F) Emuze (EEPROM swap space)
16(0x10) D3thAdd3r(Lee Weber) Toorum's Quest
17(0x11) D3thAdd3r(Lee Weber) Dig Dug
489(0x1E9)-511(0xFF) Shared Use Small Saves

For the "Small Saves" shared sectors, denote bytes used as "sector_id(sector_id_hex).bytes:start_byte..end_byte".

Offset Owner Game
489(0x1E9).bytes:0..5 D3thAdd3r(Lee Weber) Alter Ego


For the Block ID system(second half of file), reserve ID numbers.

Block ID Owner Game
0(0x0) Free Block Available

Small Saves

As seen in the table above, there are some slots reserved in the first half of the file for small saves. This is intended for games with very simple requirements such as storing the last level that was completed per episode. Here, if an author has several such games and/or is willing to cooperate with another author with such games, this progress can be stored in reserved fixed byte positions while other games do the same, at their reserved positions, in the same sector. It would not be a bad thing to reserve a bit more than you might need(potentially waste a few bytes) as a buffer between games for future expansion. The important savings is not wasting large parts of many sectors. After a game has been stable for changes for some years, those unused buffer/expansion bytes could be reclaimed later. It is the authors discretion to use this. Since this space needs to be enough for all future games with small saves, saves bigger than perhaps ~200 bytes should probably just use the other full sector methods.