C Development
C Compilers
LLVM-MOS
This fork of llvm-mos was adapted for F256/Wildbits usage by user sduensing from Kangaroo Punch Studios and can be found here. The installation instructions are simple and work for both Windows and Linux. It mostly uses a one-stop-shop f256lib.h file containing macros and functions leveraging some devices (not all yet) and the MicroKernel.
The default linking configuration will have your code start at 0x300, a 8 kb stack/trampoline from 0xA000 to 0xBFFF that is used to bring in higher memory content visible into that slice of the first 64k of the CPU. The slice 0xC000 to 0xDFFF is used by IO as usual and 0xE000 to 0xFFFF is used by the MicroKernel as usual. To change any of this, you can bring a modified copy of link.ld into your /projectfolder/ and it will supersede this default mapping.
List of "Gotchas" for llvm-mos
1) When trying to use the EMBED directive in order to put data at specific memory locations, keep in mind that you CAN'T comment those lines out with
/*and*/, the compiler will try to follow them whether they're in them or not. The only way to comment them is to use//.2) When trying to use the EMBED directive, you may want to put your assets in a subfolder of your project. As in, assuming your source files are in ./src/ (where '.' is the root of your project) and your assets are in ./assets/, then you WILL need to refer to your asset files like so:
EMBED(myassetname, "../assets/myassetfile.bin", 0x10000);. Note the weird ../ folder backtracking that has to be used. No other combination worked for me (-Mu0n)3) In the f256dev/ folder, the f256build.bat file contains all you need to compile and link your project. In the "call mos-f256-clang.bat" line, one important switch is the optimization level you let the compiler use. Experiment with -O1 (no optimization), -O2 (some) and -O3 (most). Some operations and repetitions work with some and fail with others. One prominent example of where it failed was a repetitive fileRead operation that read and parsed little chunks of data from a file, byte by byte and while it compiled and linked, it failed during execution. By reducing -O3 to -O2, it all worked again.
4) One linking error kept giving me "
ld.lld: error: ld-temp.o <inline asm>:2:1: operand must be a 16-bit address sta (mos8(.LpickAudioFile_zp_stk+4)" despite not having written any inline assembly in my project. You can skirt around the issue for the problematic function by adding a compiler attribute:__attribute__((optnone))right before your function definition.5) When your code nears a size of 0x9400 and above, you may get in trouble in terms of code not being fully loaded into RAM while executing. Either deliberately put some code into far memory and devise a scheme with the MMU to swap that code in and out of reach for the CPU, or you can carve yourself a bit more space by editing f256dev/llvm-mos/mos-platform/f256/lib/link.ld and change:
/* fake C Stack */
PROVIDE(__stack = 0xA000);
to
/* fake C Stack */
PROVIDE(__stack = 0xC000);to get yourself an extra 8k of code space before it collides with the stack
6) The compiler will often complain about a missing closing curly bracket '}' at the end of your source files. Just add the one it requires at the very end even though it's an extra one, or, finish your source file by putting your last function with this notation:
void myLastFunction(uint8_t whatever) {
//bunchacode
}
jbaker8935's guide on creating trampolines for functions in higher memory:
what you can do is pick a function in one of your projects that isnt time critical and create a trampoline function for it using this pattern:
void FAR8_video_init(void);
#pragma clang optimize off __attribute__((noinline)) void video_init(void) { volatile unsigned char ___mmu = (unsigned char)*(volatile unsigned char *)0x000d; *(volatile unsigned char *)0x000d = 8; FAR8_video_init(); *(volatile unsigned char *)0x000d = ___mmu; } #pragma clang optimize on __attribute__((noinline, section(".block8"))) void FAR8_video_init(void)note: that FAR8_video_init is the renamed function that is being moved. It's just a convention. in your main you can call video_init as you do normally and the trampoline will take care of swapping the code into A000 in cpu memory. For linking you need to create file f256.ld that sits in the project directory. it is a copy of "${ROOT}/llvm-mos/mos-platform/f256/lib/link.ld" but has additional linker instructions to explain how to deal with block8. à Around line 100 or so you need to add instructions after the include output.ld statement. like so:
/* Overlay Segments and Binary Data */ INCLUDE output.ld /* Hand Coded output.ld records */ SHORT(8*0x2000) BYTE(8/8) SHORT(end_block8 - __block8_lma) BYTE(0x00) TRIM(block8)i'm using f256build.sh and the normal 'everything in src' structure. Also I didnt fiddle with moving the default stack or swap page, so this example trampoline is using A000 (writing to 0x000d). Note that the mmu is left in edit mode, so the trampolines can just write to 000d with no disabling of interrupts.
Oscar64
Oscar64 is a C/C++ cross compiler running on a modern system (such as a Windows PC, Mac or Linux machine) and targets the classic 6502 family of processors. It is mainly focused on Commodore systems such as the C64, PET or VIC20. The compiler supports C99 and many C++ features up to variadic templates and lambda functions.
The purpose of this compiler is to eliminate the need to write 6502 assembler code to achieve high code density and fast execution speed. It continues to improve with all the games, demos and tools written by it. It supports disk overlays and banked cartridges for larger projects.
Oscar64 was adapted for the F256/WildBits by swdfrost and here is a link its github page. You will also need the adaptation of the f256lib (ported over from llvm-mos) from this github page as well, which also includes many projects examples as well.
Getting set up on Windows 10/11 (-Mu0n)
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