Splitting Assets from Code: Difference between revisions

Jump to navigation Jump to search
Finished the 'Loading assets from ROM' chapter
(Added a new section that I'm going to need)
(Finished the 'Loading assets from ROM' chapter)
Line 17:
Spec file =
Your Spec file, before adding the assets to it, would look something like this:<br>
<syntaxhighlight lang="c">
<pre>
beginseg
name "code"
Line 25:
stack NU_SPEC_BOOT_STACK
include "codesegment.o"
// Microcode includes go here (omitted for simplicity reasons)
endseg
 
Line 33:
include "code"
endwave
</syntaxhighlight>
</pre>
Adding in new raw assets is as simple as creating a new segment and specifying the <code>RAW</code> flag. For instance, having the data from <code>spr_bear.c</code> converted into binary form (with the name <code>spr_bear.bin</code>) and linking it to our ROM is as simple as:
<syntaxhighlight lang="c">
<pre>
beginseg
name "spr_bear" // This name is important, and should be unique
Line 42:
include "spr_bear.bin" // The file to link
endseg
</syntaxhighlight>
</pre>
Do this for all the assets, and you're almost done. The next step is to open a C header file (or better yet, create a new one) and to create some <code>extern</code> calls for your new segments:
<syntaxhighlight lang="c">
<pre>
extern u8u32 _spr_bearSegmentRomStart[];
extern u8u32 _spr_bearSegmentRomEnd[];
</syntaxhighlight>
</pre>
Remember that segment name I told you that was important and had to be unique? Whatever you set your segment name to, it needs to match the <code>extern</code>'s. Meaning, if you called your segment <code>NAME</code>, then you would need to define the <code>extern</code>'s as <code>_NAMESegmentRomStart</code> and <code>_NAMESegmentRomEnd</code> respectively.
 
Line 59:
 
== Loading assets from ROM ==
Having the segment addresses for our data in ROM, it is relatively simple to DMA them from ROM. We know the starting address of our data thanks to the SegmentRomStart, and we can infer the size of the data by subtracting the start address from the end address.
TODO
 
With Nusys, the task is relatively trivial:
<syntaxhighlight lang="c">
u32 size = _spr_bearSegmentRomEnd - _spr_bearSegmentRomStart;
nuPiReadRom((u32)_spr_bearSegmentRomStart, (void*)buffer, size);
</syntaxhighlight>
If you're not using Nusys, then there's a bit more overhead involved:
<syntaxhighlight lang="c">
OSIoMesg dmaIoMesgBuf; // The message buffer
OSMesgQueue dmaMesgQ; // The message queue
// This code already assumes a message queue exists and has been created with 'osCreateMesgQueue'
// These variables are just here for reference
 
u32 size = _spr_bearSegmentRomEnd - _spr_bearSegmentRomStart;
 
// Invalidate data cache for the buffer to prevent memory from being destroyed
osInvalDCache((void*)buffer, size);
 
// Start the DMA
osPiStartDma(&dmaIoMesgBuf, OS_MESG_PRI_NORMAL, OS_READ, _spr_bearSegmentRomStart, buffer, size, &dmaMesgQ);
 
// Wait for the DMA to finish
osRecvMesg(&dmaMesgQ, NULL, OS_MESG_BLOCK);
</syntaxhighlight>
 
Please note that the code on this wiki page '''does not replace the manuals'''. Data DMA has very strict requirements in terms of maximum size and buffer alignment, therefore you should look up the manual pages for <code>nuPiReadRom</code> or <code>osPiStartDma</code> to make sure your DMA operation will succeed.
 
You're probably wondering from the above code what <code>buffer</code> is. You probably understand that the data needs to go somewhere (like a variable in your code), but there's two different approaches to having data buffers:
 
== Having a buffer in the codesegment ==
Line 66 ⟶ 94:
== Having a buffer somewhere in RAM ==
TODO
 
== Finalizing the code ==
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu