Oscar64: Difference between revisions
| Line 78: | Line 78: | ||
=== How to manage multiple source code files in a project === | === How to manage multiple source code files in a project === | ||
* Create .h + .c pairs of source code files by themes.<br> | |||
* Use '''whatever.h''' so that '''BASEPATH/f256lib-oscar64/doodles/myproject/src/whatever.c''' and its corresponding whatever.h are referred to<br> | |||
* Put the entirety of whatever.h's content between | |||
<pre>#ifndef WHATEVER_H | |||
#define WHATEVER_H | |||
</pre> | |||
and | |||
<pre> | |||
#endif | |||
</pre> | |||
to avoid complaints of multiple definitions if multiple files need this reference. | |||
=== Compiling a program, scripts from Mu0n === | === Compiling a program, scripts from Mu0n === | ||
Revision as of 07:46, 30 April 2026
Documentation
The main documentation website is located here: https://github.com/drmortalwombat/oscar64/blob/main/oscar64.md
Installation procedure
(this is from Mu0n, under Windows 11 but using a WSL command window)
Assumptions:
- Windows' WSL is installed (ie with Ubuntu)
- Python is installed inside windows
- make is installed inside WSL
- gcc is installed inside WSL (sudo apt install build-essential)
Step 1) in Windows, make a base directory (let's call it BASEPATH) that will hold both: * the oscar64 project, but with the 'f256k-support' branch rather than 'main' branch https://github.com/sdwfrost/oscar64 * the f256lib-oscar64 project, 'main branch' https://github.com/sdwfrost/f256lib-oscar64 (both from sdwfrost's GitHub account) Step 2) from windows, open a cmd window, go to your intended base folder Step 3) type WSL Step 4) clone oscar64 with git clone -b f256k-support https://github.com/sdwfrost/oscar64.git Step 5) clone f256lib-oscar64 side by side in the same base folder. git clone -b main https://github.com/sdwfrost/f256lib-oscar64 Both 'oscar64' and 'f256lib-oscar64' folders will be in the same location when this is done. Step 6) go into oscar64/ Step 7) type: make -f make/makefile (this assumes gcc being present in WSL, it will take a while!) Step 8) switch over to f256lib-oscar64/ and type: OSCAR64=../../oscar64/bin/oscar64 make all (warning 1: at the time of writing this guide, the 2nd project, BachHero, triggers an error that halts the whole list. Simply remove that entry from /f256lib-oscar64/doodles/MakeFile to get the rest going) (warning 2: most projects will compile, but not run properly when run in the Wildbits environment since they expect extra library files that have not been ported over) Step 9) to compile a single project in general, make sure you use a path that points to the compiled oscar64 of step 7 like so: (assuming your project myproject is in BASEPATH/f256lib-oscar64/doodles/) BASEPATH/oscar64/bin/oscar64 -tm=f256k -n -i=BASEPATH/f256lib-oscar64/f256lib BASEPATH/f256lib-oscar64/doodles/myproject/src/myproject.c -o=BASEPATH/f256lib-oscar64/doodles/myproject/myproject.pgz
Noteworthy files and folders
(some of these are merely suggestions in how to organize your local installation of oscar64)
assuming your BASEPATH = the folder where you do your installation,
BASEPATH/oscar64/ is where the compiler should be installed
BASEPATH/f256lib-oscar64/ is where the F256/wildbits libraries for oscar64 should be installed
BASEPATH/f256lib-oscar64/f256lib/ is the folder containing all the library files
BASEPATH/f256lib-oscar64/f256lib/f256lib.c is the master library file, also has a corresponding f256lib.h header file and loads all the rest.
BASEPATH/f256lib-oscar64/doodles/ is a good place to store your projects
BASEPATH/f256lib-oscar64/doodles/myproject/ is the root folder of your project called 'myproject' and where the program and linker produced files end up in
BASEPATH/f256lib-oscar64/doodles/myproject/src/ is the folder containing all of your source code
How to manage multiple source code files in a project
- Create .h + .c pairs of source code files by themes.
- Use whatever.h so that BASEPATH/f256lib-oscar64/doodles/myproject/src/whatever.c and its corresponding whatever.h are referred to
- Put the entirety of whatever.h's content between
#ifndef WHATEVER_H #define WHATEVER_H
and
#endif
to avoid complaints of multiple definitions if multiple files need this reference.
Compiling a program, scripts from Mu0n
I use a pair of scripts that are located in BASEPATH/f256lib-oscar64/doodles/
Here's the shell script ("c.sh") I use to simply compile a program, this works regardless if your project uses one .c file or multiples. Adjust your absolute paths to what you have on your modern computer. "projectname" is the folder of your project inside the "doodles" folder.
run it using the command ./c.sh myprojectname
#!/bin/bash
# --- 1. CONFIGURATION ---
OSCAR_BIN="/mnt/d/F256/oscar64/bin/oscar64"
# Use the Windows python launcher (it handles COM8 perfectly)
PYTHON_EXE="python.exe"
# Use the Windows path for the script (escaped backslashes)
FOENIX_MGR="D:\\F256\\llvm-mos\\f256dev\\FoenixMgr\\FoenixMgr\\fnxmgr.py"
# --- 2. ARGUMENTS ---
PROJ_NAME="$1"
SRC_DIR="${PROJ_NAME}/src/"
SRC_FILE="${PROJ_NAME}/src/${PROJ_NAME}.c"
OUT_DIR="${PROJ_NAME}/"
BIN_FILE="${PROJ_NAME}.pgz"
FLAGS="-tm=f256k -n -v -i=../f256lib"
# --- 3. Gather all files in src/
mapfile -t CFILES < <(find "$SRC_DIR" -maxdepth 1 -type f -name "*.c")
# --- 4. COMPILE ---
echo "Compiling:"
printf '%s\n' "${CFILES[@]}"
echo
echo "Linking into ${OUT_DIR}/${PROJ_NAME}.pgz"
$OSCAR_BIN $FLAGS "${CFILES[@]}" -o="./$OUT_DIR/$PROJ_NAME.pgz"
Here's the shell script ("car.sh" = Compile And Run) I use to compile a program and send it over to my Wildbits through the foenixmgr script. This assumes that your host is win11 and python is run from that, from inside WSL ubuntu. Tweak to your setup's situation, of course. run it using the command ./car.sh myprojectname
#!/bin/bash
# --- 1. CONFIGURATION ---
OSCAR_BIN="/mnt/d/F256/oscar64/bin/oscar64"
# Use the Windows python launcher (it handles COM8 perfectly)
PYTHON_EXE="python.exe"
# Use the Windows path for the script (escaped backslashes)
FOENIX_MGR="D:\\F256\\llvm-mos\\f256dev\\FoenixMgr\\FoenixMgr\\fnxmgr.py"
# --- 2. ARGUMENTS ---
PROJ_NAME="$1"
SRC_DIR="${PROJ_NAME}/src/"
SRC_FILE="${PROJ_NAME}/src/${PROJ_NAME}.c"
OUT_DIR="${PROJ_NAME}/"
BIN_FILE="${PROJ_NAME}.pgz"
FLAGS="-tm=f256k -n -i=../f256lib"
# --- 3. Gather all files in src/
mapfile -t CFILES < <(find "$SRC_DIR" -maxdepth 1 -type f -name "*.c")
# --- 4. COMPILE ---
echo "Compiling:"
printf '%s\n' "${CFILES[@]}"
echo
echo "Linking into ${OUT_DIR}/${PROJ_NAME}.pgz"
$OSCAR_BIN $FLAGS "${CFILES[@]}" -o="./$OUT_DIR/$PROJ_NAME.pgz"
# --- 5. TRANSFER ---
if [ $? -eq 0 ]; then
echo "Transferring to F256K2 via Windows Python..."
# We use the Windows path for the file we just built
WIN_BIN_PATH="D:\\F256\\f256lib-oscar64\\doodles\\${PROJ_NAME}\\${BIN_FILE}"
$PYTHON_EXE "$FOENIX_MGR" --port COM8 --run-pgz "$WIN_BIN_PATH"
else
echo "Compilation failed."
exit 1
fi
Embedding asset files
Here's an example of a few assets loaded in a specific spot in memory, starting from 0x10000. It needs to be part of a section, then a region and then some array identifiers that point to the data itself. When the project compiles, you can check out the layout of the memory being used inside your .map file.
/*
* The following assets will be located within these bounds
*
10000 - 10400 : grupal, DATA:assets
10400 - 10800 : sBoy1, DATA:assets
10800 - 10c00 : sThing, DATA:assets
10c00 - 11000 : sGirl1, DATA:assets
11000 - 11400 : sCath, DATA:assets
11400 - 11800 : sCat, DATA:assets
11800 - 12000 : sDash, DATA:assets
*/
#pragma section( assets, 0 )
#pragma region( assets, 0x10000, 0x20000, , , {assets} )
#pragma data(assets)
__export const char grupal[] = { //1kb palette from 0x10000 to 0x103FF
#embed "../assets/grudge.pal"
};
__export const char sBoy1[] = { //16x16 sprite of 1kb from 0x10400 to 0x107FF
#embed "../assets/boy1.bin"
};
__export const char sThing[] = {
#embed "../assets/thing.bin"
};
__export const char sGirl1[] = {
#embed "../assets/girl1.bin"
};
__export const char sCath[] = {
#embed "../assets/cath.bin"
};
__export const char sCat[] = {
#embed "../assets/cat.bin"
};
__export const char sDash[] = {
#embed "../assets/dash.bin"
};
//return to normalcy
#pragma data(data)
How to use higher memory and the MMU to store code
Much like assets, you will have to use the #pragma directive to set up a section and region for each chunk of RAM. Since a trampoline scheme gets used here in conjunction with the machine's MMU, these regions should be 0x2000 big, or 8kb.
Keep in mind that these chunks of RAM will be swapped in and out of the 0xA000 to 0xBFFF 8kb chunk visible by the CPU.
Here is the list of stuff you must define for it to work:
- A specific number for your code's block = physical address / 0x2000 you have in mind to stash your code. For example, to use the 8kb of code space between 0x10000 and 0x11FFF, this will be "overlay block 8". For the space between 0x12000 and 0x13FFF, this is "overlay block 9"
#define OVL1_BLOCK 8 // Physical 0x10000
- #pragma directive such as:
// Overlay 1: stored at physical 0x10000, compiled to run at 0xA000
#pragma section( ovl1_code, 0 )
#pragma region( ovl1, 0x10000, 0x12000, , , { ovl1_code }, 0xA000 )
- Forward declaration of a trampoline function used to access the higher memory function, such as:
// ---------------------------------------------------------------------------
// Forward declarations of trampolines (in main code, always visible)
// ---------------------------------------------------------------------------
void firstSegment(int arg1, int arg2);
// Trampolines save the current bank 5 mapping, switch to the target
// overlay's physical block, call the FAR function, then restore the
// original mapping. This supports nested cross-overlay calls.
void firstSegment(int arg1, int arg2) {
volatile byte saved = PEEK(OVERLAY_MMU_REG);
POKE(OVERLAY_MMU_REG, OVL1_BLOCK);
FAR_firstSegment(arg1, arg2);
POKE(OVERLAY_MMU_REG, saved);
}
- Your far memory function in between #pragma code directives:
#pragma code( ovl1_code )
void FAR_firstSegment(int arg1, int arg2) {
textPrint("firstSegment = ");
textPrintInt((int32_t)(arg1 + arg2));
textPrint("\n");
}
//return to normalcy
#pragma code( code )
Note: it's perfectly ok to define multiples of these high memory regions. One far memory function can call another far memory function from another region without issue, but it has to call it through its lower memory trampoline.
Accessing the extra 2x core banks of 512kb memory
Since the launch of the 2x core, the full 2MB of SRAM is accessible if you set a bit right in register 0x0000. For more details on this feature of the 2x core, see this page.
To peek a byte at these regions of memory, use this asm block as an oscar64 function:
peek24 accepts a 32bit long address, stores it temporarily into a few bytes near the beginning of zero page. It then activates bit 3 of register 0x0000 to access the new 2x core higher memory banks. Finally, it fetches the content of that byte as a returned char.
char peek24(unsigned long addr)
{
return __asm {
lda addr
sta 0x05
lda addr+1
sta 0x06
lda addr+2
sta 0x07
ldx 0x00
ldy 0x01
txa
ora #0x08
php
sei
sta 0x00
tya
ora #0x30
sta 0x01
byt 0xa7
byt 0x05
stx 0x00
sty 0x01
plp
sta accu
lda #0
sta accu+1
};
}
To write something to these higher memory banks, you can use poke24, which goes the other way:
void poke24(unsigned long addr, unsigned char value)
{
__asm {
lda addr
sta 0x05
lda addr+1
sta 0x06
lda addr+2
sta 0x07
ldx 0x00
ldy 0x01
txa
ora #0x08
php
sei
sta 0x00
tya
ora #0x30
sta 0x01
lda value
byt 0x87
byt 0x05
stx 0x00
sty 0x01
plp
ldx #0x00
};
}
"Troubleshoot Gotchas" during compilation
None to report so far.