API Design
/* --- Device Enumeration --- */
/* Port A-D (0-3), Slot 1-2 (0-1) */
typedef struct {
uint8_t port; /* 0=A, 1=B, 2=C, 3=D */
uint8_t slot; /* 0=main, 1=secondary */
} sh_vmu_addr_t;
/* Get VMU device by port/slot. Returns NULL if nothing plugged in. */
maple_device_t *sh_vmu_at(sh_vmu_addr_t addr);
/* Get the first available VMU (for single-player games). */
maple_device_t *sh_vmu_first(void);
/* Count connected VMUs. */
int sh_vmu_count(void);
/* Iterate all connected VMUs. Callback returns 0 to continue, non-zero to stop. */
void sh_vmu_each(int (*cb)(sh_vmu_addr_t addr, maple_device_t *dev, void *ctx), void *ctx);
/* --- Screen Rendering --- */
/* All screen functions wrap vmufb_t. The fb is caller-owned. */
/* Clear the VMU framebuffer. */
void sh_vmu_clear(vmufb_t *fb);
/* Draw raw 1-bit pixel data into a region. */
void sh_vmu_blit(vmufb_t *fb, int x, int y, int w, int h, const uint8_t *data);
/* Draw XBM image data. */
void sh_vmu_blit_xbm(vmufb_t *fb, int x, int y, int w, int h, const uint8_t *xbm);
/* Print text using current font. */
void sh_vmu_print(vmufb_t *fb, int x, int y, const char *text);
/* Printf variant. */
void sh_vmu_printf(vmufb_t *fb, int x, int y, const char *fmt, ...);
/* Push framebuffer to a specific VMU. */
void sh_vmu_present(const vmufb_t *fb, sh_vmu_addr_t addr);
/* Push framebuffer to ALL connected VMUs. */
void sh_vmu_present_all(const vmufb_t *fb);
/* Set VMU font. NULL = built-in. Returns previous. */
const vmufb_font_t *sh_vmu_set_font(const vmufb_font_t *font);
/* --- Save Game Management --- */
typedef struct {
char name[13]; /* Save file name (12 chars + null) */
char desc_short[20]; /* Short description (VMU file manager) */
char desc_long[36]; /* Long description (DC BIOS menu) */
char app_id[20]; /* Application ID */
const uint8_t *icon_data; /* 32x32 icon (512 bytes per frame, 4bpp) */
int icon_frames; /* Number of animated icon frames */
uint16_t icon_palette[16]; /* ARGB4444 palette */
} sh_save_info_t;
typedef enum {
SH_SAVE_OK = 0,
SH_SAVE_NO_VMU, /* No VMU at that address */
SH_SAVE_NO_SPACE, /* Not enough free blocks */
SH_SAVE_NOT_FOUND, /* Save file doesn't exist */
SH_SAVE_READ_ERROR, /* Hardware read failure */
SH_SAVE_WRITE_ERROR, /* Hardware write failure */
SH_SAVE_CRC_MISMATCH, /* Loaded save has bad CRC */
} sh_save_result_t;
/* Check if a save file exists on a VMU. */
sh_save_result_t sh_save_exists(sh_vmu_addr_t addr, const char *name);
/* Get free blocks on a VMU. Returns -1 on error. */
int sh_save_free_blocks(sh_vmu_addr_t addr);
/* Write a save file. data_len in bytes (will be padded to 512-byte blocks).
Overwrites existing save with same name. */
sh_save_result_t sh_save_write(sh_vmu_addr_t addr,
const sh_save_info_t *info,
const void *data, int data_len);
/* Read a save file. *out_data allocated via malloc, caller frees. */
sh_save_result_t sh_save_read(sh_vmu_addr_t addr,
const char *name,
void **out_data, int *out_len);
/* Delete a save file. */
sh_save_result_t sh_save_delete(sh_vmu_addr_t addr, const char *name);
/* Load .ico file for save icon (KOS vmu_pkg_load_icon wrapper). */
sh_save_result_t sh_save_load_icon(sh_save_info_t *info, const char *ico_path);