SRAM read / write

SGDK only sub forum

Moderator: Stef

cloudstrifer
Very interested
Posts: 118
Joined: Mon Feb 19, 2018 7:31 pm

SRAM read / write

Post by cloudstrifer » Sun Sep 29, 2019 11:31 pm

How to use SRAM_readByte and SRAM_writeByte?

:(
Spy:28464 want to write a Byte at 00600001

Thank you!

Code: Select all

//write score
SRAM_writeWord(0x00200000, score);
...
//read score
score= SRAM_readWord(0x00200000);

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: SRAM read / write

Post by Stef » Mon Sep 30, 2019 8:14 am

SGDK uses SEGA SRAM mapper so it assumes base SRAM address to be 0x020000 and just require an offset (that is why the argument is called offset and not address).
So in your case just use offset 0x0000.
Also don't forget to enable SRAM (SRAM_enable()) before trying to read/write from/to it, then when it's done disable it otherwise ROM located at 0x020000 won't be accessible anymore.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: SRAM read / write

Post by Chilly Willy » Tue Oct 01, 2019 2:56 pm

And remember that the code to read/write the sram should be in either work ram or rom below 0x200000, and if you have any interrupts that use code or data above 0x200000, you need to disable ints before you enable the sram, then re-enable ints after you disable the sram.

EDIT: Stef, that reminds me. I don't see anything in SGDK to keep the sram routines from being above 0x200000. They're part of the library, and libraries are normally linked to the end of program code. So if the game is bigger than 0x200000, there's nothing to keep those functions from being above 0x200000 and crash when you enable the sram.

I'd suggest making all sram functions assembly, and put the code in the sega.s file to ensure it's not too high in the rom. Make the library functions call the functions in sega.s... which would mean each function would need to disable ints, enable sram, do the read/write, disable sram, then enable ints, just to be safe. So the SRAM functions need some changing to avoid issues on big games.

If you don't want to change the library that much, your other choice is to force the SRAM functions into work ram. You do that like this:

Code: Select all

void sd_op_delay() __attribute__ ((section (".data")));
void sd_op_delay()
{
    short i;

    for (i=0; i<16; i++)
    {
        asm("nop\n");
    }
}
That will still need the game programmer to ensure that his code that calls SRAM functions aren't above 0x200000. Changing the SRAM functions to work from sega.s makes them slower, but safe regardless of how they're used.

cloudstrifer
Very interested
Posts: 118
Joined: Mon Feb 19, 2018 7:31 pm

Re: SRAM read / write

Post by cloudstrifer » Tue Oct 01, 2019 3:43 pm

I want to make a 32Mbit rom.
There is a way to SGDK or compiler skip addresses between SRAM start and end?

Thank you!

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: SRAM read / write

Post by Stef » Tue Oct 01, 2019 4:39 pm

@Chilly Willy> Yeah indeed nothing prevent it. Even worse looking at OBJ building in makefile it looks like resources is placed before code, not a good idea. I may move SRAM methods in sega.s file (at least enable and disable functions), i don't like that solution too much but it's important to take care of that. I will also change OBJ order to get resources at the end, there is no way to get 2 MB of code :p

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: SRAM read / write

Post by Chilly Willy » Tue Oct 01, 2019 5:19 pm

Having any of the enable, read, write, or disable code not below 0x200000 or in ram would be fatal. What good is enable/disable is read/write still bombs? That said, if code always comes first (even for libraries linked at the end), it's unlikely you'll have any programs with more than 2M of code. Possible, but not likely. But there should at least be notes to programmers informing them of the dangers in case anyone does something like megs of unwound code for speed in rendering or the like.

cero
Very interested
Posts: 338
Joined: Mon Nov 30, 2015 1:55 pm

Re: SRAM read / write

Post by cero » Tue Oct 01, 2019 5:54 pm

The linker script puts code first, then rodata. It's very unlikely for you to ever have 2mb of code.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: SRAM read / write

Post by Miquel » Tue Oct 01, 2019 8:20 pm

Another solution is to create a new section and place those functions in this new section. Or reuse other previously created section. The only thing to look after is how sections are ordered.

There is no relationship between sections and files, or n<->m relationship if you want.

All this is specific to gcc.
HELP. Spanish TVs are brain washing people to be hostile to me.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: SRAM read / write

Post by Chilly Willy » Tue Oct 01, 2019 10:03 pm

It can be controlled with the linker script and custom sections, or putting the functions in ram, or in sega.s, or any number of ways. Or ignored since no one is going to make an SGDK game with more than 2M of code... until someone does. :lol:

But that's why I was mentioning the issue now. Better to deal with it now and clear it up than to ignore it and wonder what's going on years later when someone does make a game with more than 2M of code and uses the sram.

If we all throw out enough ideas, Stef will have a bunch of ideas to figure out what he thinks will work best with SGDK.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: SRAM read / write

Post by Stef » Wed Oct 02, 2019 7:52 am

Oh why i was think having enable / disable was enough ? i guess i need more sleep :lol:
But if linker script always put code *before* data then it's really unlikely to meet the problem i guess.. I maybe move them in sega.s for security.

Miquel
Very interested
Posts: 514
Joined: Sat Jul 30, 2016 12:33 am

Re: SRAM read / write

Post by Miquel » Wed Oct 02, 2019 9:56 am

How code (and if applies data) is structured depends on optimization flags, mostly related to cache hit and miss, there is no way to guarantee anything.
HELP. Spanish TVs are brain washing people to be hostile to me.

Sik
Very interested
Posts: 939
Joined: Thu Apr 10, 2008 3:03 pm
Contact:

Re: SRAM read / write

Post by Sik » Wed Oct 02, 2019 10:45 am

Chilly Willy wrote:
Tue Oct 01, 2019 2:56 pm
That will still need the game programmer to ensure that his code that calls SRAM functions aren't above 0x200000.
Or enable SRAM from work RAM and disable before returning? :​P
Chilly Willy wrote:
Tue Oct 01, 2019 2:56 pm
Changing the SRAM functions to work from sega.s makes them slower, but safe regardless of how they're used.
Wouldn't it be as slow as now? (bonus points if they can be optimized to a word-sized jump, since they'd be below the 32KB mark actually)
Stef wrote:
Tue Oct 01, 2019 4:39 pm
Even worse looking at OBJ building in makefile it looks like resources is placed before code, not a good idea.
Huh, yeah, that may be a problem. When a game reaches over 2MB it'll be likely because of lots of data (not lots of code), so it's generally safe to assume that code is below the 2MB mark save extreme freak cases… but only if things are organized correctly.

One thing I wonder is about things like look-up tables and such, as those may be written as C source files and hence be lumped with the rest of the code (when they should really go with the data blobs instead).
Sik is pronounced as "seek", not as "sick".

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: SRAM read / write

Post by Chilly Willy » Wed Oct 02, 2019 2:28 pm

On my 32X stuff, I have the SRAM functions in 68k ram, so I don't have an issue. I also disable ints, and set RV to halt the SH2s if they attempt to read the cart. Having the functions in ram isn't a big deal with 32X stuff if it's more 32X and less MD in the coding. :lol:

If you're making a MD game with some 32X enhancement, it might be more of an issue as you'll probably be using more 68k ram and not have the space for code in ram. But SRAM functions are small, so it's not an issue unless you're really scrimping for every byte of ram.

What I meant by slower but safer code was to have no enable/disable functions, but rather every call to read or write sram enables the sram, does the read/write, then disables the sram every time. You only have two functions (read and write), and it's safer since you can guarantee everything is safe for sram access during access, then turn it all off before returning, but you can see where that would be slower as you'd have more overhead on reading and writing. I do it that way, myself, as I don't see the issue on making reading/writing less than 32K of sram slower. It's not something the user will notice.

The one type of game I could see having more than 2M of code would be something like Wolf3D where column rendering at different scales is unrolled into different routines for best speed, or a game that scales/rotates sprites on the fly rather than using pre-scaled/rotated images in vram/rom, and unrolls a bunch of different scaling and rotating code at different scales and angles. If something is going to use more than 2M of code, it would be something like that.

nemezes
Very interested
Posts: 69
Joined: Sat Mar 31, 2018 1:09 pm

Re: SRAM read / write

Post by nemezes » Mon Apr 27, 2020 4:55 pm

Stef wrote:
Mon Sep 30, 2019 8:14 am
SGDK uses SEGA SRAM mapper so it assumes base SRAM address to be 0x020000 and just require an offset (that is why the argument is called offset and not address).
So in your case just use offset 0x0000.
Also don't forget to enable SRAM (SRAM_enable()) before trying to read/write from/to it, then when it's done disable it otherwise ROM located at 0x020000 won't be accessible anymore.
still dont get what is this offset.

without an example is hard to understand the documentation of SGDK if you dont know how everything works.

if I want to save an u8 array[3] to SRAM I should use this kind of code:

Code: Select all

u32 offset0;
u32 offset1;
u32 offset2;

offset0 = 0;
offset1 = 1;
offset2 = 2;

array[0] = 1;
array[1] = 2;
array[2] = 3;

SRAM_enable();

SRAM_writeByte(offset0,array[0]);
SRAM_writeByte(offset1,array[1]);
SRAM_writeByte(offset2,array[2]);

SRAM_disable();
then, to read it, I just do it?

Code: Select all

u8 test;

SRAM_enable();

test = SRAM_readByte(offset0);

SRAM_disable();

if (test == 1)
{
	... do stuff;
}
it will be good if it has a really simple sample, just showing how to use the SRAM.

thanks in advance.

cloudstrifer
Very interested
Posts: 118
Joined: Mon Feb 19, 2018 7:31 pm

Re: SRAM read / write

Post by cloudstrifer » Mon Apr 27, 2020 5:56 pm

Example
I don't know if it's the best way to do, but it works.

Code: Select all

//SAVE
SYS_disableInts();
SRAM_enable ();
waitMs(1000);
u32 sRamOffSet = 0x0000;

//Save ID
SRAM_writeByte(sRamOffSet, -99);
//KLog_S1("sRamOffSet:", sRamOffSet);
sRamOffSet ++;

for (u8 screenIndex = 0; screenIndex < 150; screenIndex ++)
{
	for (u8 objectIndex = 0; objectIndex < 20; objectIndex ++)
	{
		SRAM_writeByte(sRamOffSet, arrDBObjects[screenIndex][objectIndex]);
		//KLog_S1("sRamOffSet:", sRamOffSet);
		sRamOffSet ++;
	}
}	

[code]
SRAM_disable ();
SYS_enableInts();

Code: Select all

//LOAD
SYS_disableInts();
SRAM_enableRO ();
u32 sRamOffSet = 0x0000;

//Verify Save ID
s8 saveTest = SRAM_readByte(sRamOffSet);
//KLog_S1("sRamOffSet:", sRamOffSet);
sRamOffSet ++;

if(saveTest != -99)
{
	SRAM_disable();
	SYS_enableInts();
	VDP_drawText("FAILED. ", 6, 24);
	SPR_update();	
	waitMs(1000);	
	return FALSE;
}

for (u8 screenIndex = 0; screenIndex < 150; screenIndex ++)
{
	for (u8 objectIndex = 0; objectIndex < 20; objectIndex ++)
	{
		arrDBObjects[screenIndex][objectIndex] = SRAM_readByte(sRamOffSet);
		//KLog_S1("sRamOffSet:", sRamOffSet);
		sRamOffSet ++;
	}
}	

SRAM_disable ();
SYS_enableInts();

Post Reply