SD Save Sector Reservation List: Difference between revisions

From Uzebox Wiki
Jump to navigation Jump to search
m (Created page with "The EEPROM API functions are based on reading and writing "blocks". Each block is 30 bytes and is prefixed with a unique word ID (for a total of 32 bytes per block). Reserve one ...")
 
 
(28 intermediate revisions by the same user not shown)
Line 1: Line 1:
The EEPROM API functions are based on reading and writing "blocks". Each block is 30 bytes and is prefixed with a unique word ID (for a total of 32 bytes per block). Reserve one or more unique IDs for your game here. Although IDs can go up to 65534 (0xffff means an empty block), there is a maximum of 63 simultaneous block that can be allocated in the Atmega644 EEPROM (2048 bytes in the EEPROM / 32 bytes per block). Block IDs 0,1 and 0x555A are reserved for the kernel. To view, edit or remove the blocks on your console, see the [http://uzebox.org/forums/viewtopic.php?p=5078#p5078 emuze] tool.
Reserve sectors/IDs for your game here. To view, edit or remove the sectors on your SD card, see the [http://uzebox.org/forums/viewtopic.php?p=5078#p5078 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)
{| class="wikitable"
{| class="wikitable"
|-
|-
! Block ID
! Sector
! Owner
! Owner
! Game
! Game
|-
|-
| 0(0x00)
| 0(0x00)-7(0x07)
| Kernel
| Kernel
| Reserved
| Reserved
|-
|-
| 1(0x01)
| 8(0x08)-15(0x0F)
| Kernel
| Emuze
| Reserved
| (EEPROM swap space)
|-
| 2(0x02)
| Uze
| [[Megatris]]
|-
| 3(0x03)
| Uze
| [[Whack-a-Mole]]
|-
| 4(0x04)
| Jhysaun
| [[Void Fighter]]
|-
| 5(0x05)
| DaveyPocket
| [[Pong]]
|-
| 6(0x06)
| Uze
| [[Arkanoid]]
|-
| 7(0x07)
| Codecrank
| [[Dr.Mario]]
|-
| 8(0x08)
| Uze
| [[Lode Runner]]
|-
| 9(0x09)
| Harty123
| [[Lander]]
|-
| 10(0x0A)
| Harty123
| [[Memory]]
|-
| 11(0x0B)
| Paul
| [[Donkey Kong]]
|-
| 12(0x0C)
| Paul
| [[Space Invaders]]
|-
| 13(0x0D)
| Paul
| [[Pac-Man]]
|-
| 14(0x0E)
| Paul
| [[B.C. Dash]]
|-
| 15(0x0F)
| Paul
| [[B.C. Dash]]
|-
|-
| 16(0x10)
| 16(0x10)
| Paul
| D3thAdd3r(Lee Weber)
| [[Frogger]]
| [[Toorum's Quest]]
|-
|-
| 17(0x11)
| 17(0x11)
| Kilo
| D3thAdd3r(Lee Weber)
| [[Das Boot]]
| [[Dig Dug]]
|-
|-
| 18(0x12)
| 489(0x1E9)-511(0xFF)
| Kilo
| Shared Use
| [[Das Boot]]
| Small Saves
 
|}
 
For the "Small Saves" shared sectors, denote bytes used as "sector_id(sector_id_hex).bytes:start_byte..end_byte".
{| class="wikitable"
|-
|-
| 21(0x15)
! Offset
| Adrastos
! Owner
| [[Ruby Crush]]
! Game
|-
| 22(0x16)
| Harty123
| [[Gorillas]]
|-
| 23(0x17)
| Harty123
| [[Simon]]
|-
| 24(0x18)
| Harty123
| [[Happy Easter]]
|-
|-
| 25(0x19)
| 489(0x1E9).bytes:0..5
| Harty123
| D3thAdd3r(Lee Weber)
| [[Pipes]] 1/2
|-
| 26(0x1A)
| Harty123
| [[Pipes]] 2/2
|-
| 27(0x1B)
| Harty123
| [[Candle Burner]]
|-
| 28(0x1C)
| Harty123
| [[2048]]
|-
| 30(0x1E)
| Alda
| Quadrax
|-
| 42(0x2A)
| DaveyPocket
| Trestle Trouble 1/2 (UJ)
|-
| 43(0x2B)
| DaveyPocket
| Trestle Trouble 2/2 (UJ)
|-
| 52(0x34)
| Roukan
| [[Videopoker]]
|-
| 53(0x35)
| Roukan
| [[Kismet]]
|-
| 54(0x36)
| Roukan
| 2013 Winter Game Competition Entry
|-
| 61(0x3D)
| Lee Weber(D3thAdd3r)
| [[Sokoban World]] Episode 3/4
|-
| 62(0x3E)
| Lee Weber(D3thAdd3r)
| [[Sokoban World]] Episode 1/2
|-
| 63(0x3F)
| Lee Weber(D3thAdd3r)
| [[Adventures Of Lolo]]
|-
| 67(0x43)
| Lee Weber(D3thAdd3r)
| [[Solitaire]]
|-
| 68(0x44)
| Lee Weber(D3thAdd3r)
| [[Uzesweeper]]
|-
| 69(0x45)
| Lee Weber(D3thAdd3r)
| [[Alter Ego]]
| [[Alter Ego]]
|}
For the Block ID system(second half of file), reserve ID numbers.
{| class="wikitable"
|-
|-
| 70(0x46)
! Block ID
| Lee Weber(D3thAdd3r)
! Owner
| [[Frog Feast]]
! Game
|-
|-
| 71(0x47)
| 0(0x0)
| Lee Weber(D3thAdd3r)
| Free Block
| [[Toorum's Quest]]
| Available
|-
 
| 89(0x59)
| Phog
| [[Zombienator]]
|-
| 90(0x5A)
| Gerkl
| TBD
|-
| 117(0x75)
| James Elliott(kivan117)
| [[Ghosty Ghost]]
|-
| 128(0x80)
| Martin Šustek
| [[chess4uzebox]]
|-
| 129(0x81)
| Martin Šustek
| [[Atomix]]
|-
| 130 - 134(0x82-0x86)
| Martin Šustek
| [[MegaSokoban]]
|-
| 135 - 136(0x87-0x88)
| CunningFellow
| [[Tornado 2000]]
|-
| 137(0x89)
| Matt Pandina(Artcfox)
| [[Bugz]]
|-
| 138(0x8A)
| Lawrence Brooks(L4rry)
| [[Tank Fu]]
|-
| 139(0x8B)
| Lawrence Brooks(L4rry)
| [[Tank Fu]]
|-
| (0xA0-????)
| Ellipsis
| [[Holey Moley]]
|-
| 569(0x239)
| Nebososo
| [[Corrida Nebososa]]
|-
| 666(0x29A)
| Pragma
| Castlevania:Vengeance
|-
| 833(0x341)
| Vin & Hylian
| Uzebox Tactics
|-
| 22356(0x5754)
| Jan Kandziora
| [[Würgertime]]
|-
| 43788(0xAB0C)
| Mapes / DaveyPocket
| Uzebox JAMMA: soft dipswitches
|-
| 21850(0x555A)
| Kernel
| Reserved
|}
|}
==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.