Migrating to V3
Migrating your Classpad HHK (v2) project to HH3 (v3) require a few tweaks to your codebase.
What Needs to Be Done
Section titled “What Needs to Be Done”Update Environment Files
Section titled “Update Environment Files”Update configuration files to reflect the new SDK requirements:
- Makefile: Adjust compiler flags and target settings.
- CI Configurations: Update build pipelines to use the new toolchain.
- Devcontainer: Modify container setup to include V3 dependencies.
- clangd: Regenerate
compile_commands.jsonand restart clangd for proper IDE support. - .gitignore: Update to include new build artifacts:
*.bin*.elf*.hh3*.map# temporary files under WSL*~.*~
Remove linker.ld
Section titled “Remove linker.ld”The linker.ld file can be safely removed as the SDK now handles linking automatically.
Update the Makefile
Section titled “Update the Makefile”Replace your old Makefile with the new structure:
Before:
APP_NAME:=tetris
ifndef SDK_DIR$(error You need to define the SDK_DIR environment variable, and point it to the sdk/ folder)endif
AS:=sh4-elf-asAS_FLAGS:=
CC:=sh4-elf-gccCC_FLAGS:=-ffreestanding -fshort-wchar -Wall -Wextra -O2 -I $(SDK_DIR)/include/
CXX:=sh4-elf-g++CXX_FLAGS:=-ffreestanding -fno-exceptions -fno-rtti -fshort-wchar -Wall -Wextra -O2 -I $(SDK_DIR)/include/
LD:=sh4-elf-ldLD_FLAGS:=-nostdlib --no-undefined
READELF:=sh4-elf-readelfOBJCOPY:=sh4-elf-objcopy
AS_SOURCES:=$(wildcard *.s)CC_SOURCES:=$(wildcard *.c)CXX_SOURCES:=$(wildcard *.cpp)OBJECTS:=$(AS_SOURCES:.s=.o) $(CC_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)
APP_ELF:=$(APP_NAME).hhk
all: $(APP_ELF) Makefile
clean: rm -f $(OBJECTS) $(APP_ELF)
$(APP_ELF): $(OBJECTS) $(SDK_DIR)/sdk.o linker.ld $(LD) -T linker.ld -o $@ $(LD_FLAGS) $(OBJECTS) $(SDK_DIR)/sdk.o $(OBJCOPY) --set-section-flags .hollyhock_name=contents,strings,readonly $(APP_ELF) $(APP_ELF) $(OBJCOPY) --set-section-flags .hollyhock_description=contents,strings,readonly $(APP_ELF) $(APP_ELF) $(OBJCOPY) --set-section-flags .hollyhock_author=contents,strings,readonly $(APP_ELF) $(APP_ELF) $(OBJCOPY) --set-section-flags .hollyhock_version=contents,strings,readonly $(APP_ELF) $(APP_ELF)After:
APP_NAME:=tetris
ifndef SDK_DIR$(error You need to define the SDK_DIR environment variable, and point it to the sdk/ folder)endif
AS:=sh4a_nofpueb-elf-gccAS_FLAGS:=
FUNCTION_FLAGS=-flto -ffat-lto-objects -ffunction-sections -fdata-sections -O2 -gdwarf-5
CC:=sh4a_nofpueb-elf-gccCC_FLAGS:=$(FUNCTION_FLAGS) -Wall -Wextra -I $(SDK_DIR)/include/
CXX:=sh4a_nofpueb-elf-g++CXX_FLAGS:=$(FUNCTION_FLAGS) -Wall -Wextra -I $(SDK_DIR)/include/
LD:=sh4a_nofpueb-elf-g++LD_FLAGS:=$(FUNCTION_FLAGS) -Wl,--gc-sections -L$(SDK_DIR)
READELF:=sh4a_nofpueb-elf-readelfOBJCOPY:=sh4a_nofpueb-elf-objcopySTRIP:=sh4a_nofpueb-elf-strip
AS_SOURCES:=$(wildcard *.S)CC_SOURCES:=$(wildcard *.c)CXX_SOURCES:=$(wildcard *.cpp)OBJECTS:=$(AS_SOURCES:.S=.o) $(CC_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)
APP_ELF:=$(APP_NAME).elfAPP_OUT:=$(APP_NAME).hh3
elf: $(APP_ELF) Makefilehh3: $(APP_OUT) Makefileall: $(APP_ELF) $(APP_OUT) Makefile
.DEFAULT_GOAL := all
clean: rm -f $(OBJECTS) $(APP_ELF) $(APP_ELF).map $(APP_OUT)
$(APP_ELF): $(OBJECTS) $(SDK_DIR)/libsdk.a $(LD) -Wl,-Map $@.map -o $@ $(LD_FLAGS) $(OBJECTS) -lsdk
$(APP_OUT): $(APP_ELF) $(STRIP) -o $@ $^Update Include Headers
Section titled “Update Include Headers”Rename header extensions from .hpp to .h, except for GUI-related headers.
Before:
#include <appdef.hpp>#include <sdk/os/debug.hpp>#include <sdk/os/input.hpp>#include <sdk/os/lcd.hpp>#include <sdk/os/mem.hpp>After:
#include <appdef.h>#include <sdk/os/debug.h>#include <sdk/os/input.h>#include <sdk/os/lcd.h>#include <sdk/os/mem.h>Modernize Code Syntax
Section titled “Modernize Code Syntax”Update deprecated syntax patterns:
char *num = "0000"→char num[] = "0000"for (int x = ...→for (auto x = ...- Use
static_cast<type>(value)instead of C-style casts - Use proper types:
int32_t→int, etc.
Update Main Function Signature
Section titled “Update Main Function Signature”Change the main function:
Before:
extern "C" void main() { // code}After:
int main() { // code return 0;}Or for full environment access:
int main(int argc, char **argv, char **envp) { // code return 0;}Remove Obsolete Functions
Section titled “Remove Obsolete Functions”- Remove
LCD_VRAMBackup()andLCD_VRAMRestore() - Remove
calcInit()andcalcEnd()calls - Remove global VRAM declarations like
uint16_t *vram;
Update Memory Operations
Section titled “Update Memory Operations”Replace old memory functions:
memset→Mem_Memset- And other similar memory operations
Add App Definitions
Section titled “Add App Definitions”Ensure your main file contains proper app metadata:
APP_NAME("Your App Demo")APP_DESCRIPTION("Displays a demo on the ClassPad.")APP_AUTHOR("your_name")APP_VERSION("1.0.0")Update Struct Names
Section titled “Update Struct Names”Rename structures to match new conventions:
InputEvent→Input_EventInputScancode→Input_Scancode
Use New Features
Section titled “Use New Features”Take advantage of V3 improvements:
- Use
__builtin_unreachable();for unreachable code paths - Add
return 0;at the end of main function - Initialize LFSR directly:
uint16_t lfsr = 0x453A;
Review calcInit and calcEnd
Section titled “Review calcInit and calcEnd”Check if calcInit and calcEnd are still needed. In most cases, they are no longer required and can be removed.
Refactor to Use libc / libstdc++
Section titled “Refactor to Use libc / libstdc++”Take advantage of the new support for libc and libstdc++ by refactoring code to use standard library functions where appropriate.
Embed Binary Files into the ELF
Section titled “Embed Binary Files into the ELF”Consider embedding binary assets directly into the ELF file instead of loading them separately to simplify deployment.
Address New Compiler Warnings and Errors
Section titled “Address New Compiler Warnings and Errors”Review and fix any new warnings or errors reported by the updated compiler.
VRAM Backup Handling
Section titled “VRAM Backup Handling”If your app loads into VRAM:
- You no longer need a special launcher.
- Load directly into
vbak. - Override
calcInitandcalcEnd(they are weak by default) to implement custom VRAM backup logic and avoid overwriting your own data.
File I/O
Section titled “File I/O”- Paths: Paths are
const char_const16_t*(UTF-16). - Strings: Use
char16_tarrays andu"path"literals. Cast to(const char_const16_t*)when calling SDK functions. - Alignment: File path buffers passed to SDK functions (like
File_FindFirst) MUST be 4-byte aligned on SuperH. Use__attribute__((aligned(4))). - Structs:
File_FindInfouses scoped enums likeFile_FindInfo::EntryTypeDirectory(or justEntryTypeDirectorydepending on SDK version/macros). Check scoping.
- Polling: Use
GetInputinstead ofGetKey. - Struct:
struct Input_EventMUST be 4-byte aligned. Use__attribute__((aligned(4))). Misalignment causes crashes (address error) at runtime. - Keycodes: Use
KEYCODE_*enums. - Touch: Coordinates in
Input_Eventareint32_t. Cast touint32_tif comparing with unsigned bounds to avoid compiler warnings.
Known Issues
Section titled “Known Issues”- PEG (System) UI is currently not working.
- Input_GetKeyState is not functional in this version.
Example Update Snippet
Section titled “Example Update Snippet”Before:
#include <appdef.hpp>#include <sdk/os/debug.hpp>
extern "C" void main() { Debug_PrintString("Hello World");}After:
#include <appdef.h>#include <sdk/os/debug.h>
APP_NAME("Hello World App")APP_DESCRIPTION("Displays Hello World")APP_AUTHOR("Developer")APP_VERSION("1.0.0")
int main() { DebugPrintString("Hello World"); return 0;}Troubleshooting
Section titled “Troubleshooting”- Crashes: If it crashes in an SDK function (e.g.,
GetInput,File_Find...), check ALIGNMENT of the structs/buffers passed to it. - Linker Errors: “Multiple definition of …” usually means a conflict with SDK symbols (e.g.,
fillScreen). Rename your function or wrap in#ifdef PC. - Compile Errors: “Did you mean…?” implies the symbol exists but maybe signature mismatch or missing namespace. Check SDK headers.
- Warnings: Suppress
warn_unused_resultby checking return valueif (func() < 0) {}rather than(void)func().