From 2235bc742af6ce5026133506391fe830e3532f5d Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 16 Nov 2021 00:16:53 -0800 Subject: [PATCH 01/32] add stub d files --- .gitignore | 3 +- src/dusk/d_src/dusk/contrib/gbfs.d | 85 +++++++++ src/dusk/d_src/dusk/contrib/mgba.d | 42 +++++ src/dusk/d_src/dusk/load.d | 186 ++++++++++++++++++++ src/dusk/d_src/dusk/sprites.d | 271 +++++++++++++++++++++++++++++ src/dusk/d_src/dusk/sys.d | 81 +++++++++ src/dusk/include/contrib/gbfs.d | 116 ++++++++++++ 7 files changed, 783 insertions(+), 1 deletion(-) create mode 100644 src/dusk/d_src/dusk/contrib/gbfs.d create mode 100644 src/dusk/d_src/dusk/contrib/mgba.d create mode 100644 src/dusk/d_src/dusk/load.d create mode 100644 src/dusk/d_src/dusk/sprites.d create mode 100644 src/dusk/d_src/dusk/sys.d create mode 100644 src/dusk/include/contrib/gbfs.d diff --git a/.gitignore b/.gitignore index 2abc91f..508246c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,8 @@ # ---> C # Prerequisites -*.d +# *.d +build/ # Object files *.o diff --git a/src/dusk/d_src/dusk/contrib/gbfs.d b/src/dusk/d_src/dusk/contrib/gbfs.d new file mode 100644 index 0000000..ad56da1 --- /dev/null +++ b/src/dusk/d_src/dusk/contrib/gbfs.d @@ -0,0 +1,85 @@ +/* gbfs.h + access object in a GBFS file + +Copyright 2002 Damian Yerrick + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +*/ + +/* Dependency on prior include files + +Before you #include "gbfs.h", you should define the following types: + typedef (unsigned 16-bit integer) u16; + typedef (unsigned 32-bit integer) u32; +Your gba.h should do this for you. +*/ + +//\{ + +//\} + +/*! \name Volatile types +* Volatile types for registers +*/ +//\{ + +//\} + +/*! \name Const types +* Const types for const function aprameters +*/ +//\{ + +//\} + +//! 8-word type for fast struct-copies + +//! Type for consting a string as well as the pointer than points to it. + +extern (C): + +/* to make a 300 KB space called samples do GBFS_SPACE(samples, 300) */ + +enum GBFS_ENTRY_SIZE = 24; + +struct GBFS_FILE +{ + char[16] magic; /* "PinEightGBFS\r\n\032\n" */ + uint total_len; /* total length of archive */ + ushort dir_off; /* offset in bytes to directory */ + ushort dir_nmemb; /* number of files */ + char[8] reserved; /* for future use */ +} + +struct GBFS_ENTRY +{ + char[GBFS_ENTRY_SIZE] name; /* filename, nul-padded */ + uint len; /* length of object in bytes */ + uint data_offset; /* in bytes from beginning of file */ +} + +const(GBFS_FILE)* find_first_gbfs_file (const(void)* start); +const(void)* skip_gbfs_file (const(GBFS_FILE)* file); +const(void)* gbfs_get_obj (const(GBFS_FILE)* file, const(char)* name, uint* len); +const(void)* gbfs_get_nth_obj (const(GBFS_FILE)* file, size_t n, char* name, uint* len); +void* gbfs_copy_obj (void* dst, const(GBFS_FILE)* file, const(char)* name); +size_t gbfs_count_objs (const(GBFS_FILE)* file); \ No newline at end of file diff --git a/src/dusk/d_src/dusk/contrib/mgba.d b/src/dusk/d_src/dusk/contrib/mgba.d new file mode 100644 index 0000000..120bf71 --- /dev/null +++ b/src/dusk/d_src/dusk/contrib/mgba.d @@ -0,0 +1,42 @@ +module dusk.contrib.mgba; + +import tonc.tonc_types; + +enum REG_DEBUG_ENABLE = cast(vu16*) 0x4FFF780; +enum REG_DEBUG_FLAGS = cast(vu16*) 0x4FFF700; +enum REG_DEBUG_STRING = cast(char*) 0x4FFF600; + +enum MGBA_LOG_LEVEL +{ + MGBA_LOG_FATAL = 0, + MGBA_LOG_ERROR = 1, + MGBA_LOG_WARN = 2, + MGBA_LOG_INFO = 3, + MGBA_LOG_DEBUG = 4 +} + +void mgba_printf (int level, const(char)* ptr, ...); +bool mgba_open (); +void mgba_close (); + +// version (DEBUG) { +// void mgba_printf(int level, const char* ptr, ...) { +// va_list args; +// level &= 0x7; +// va_start(args, ptr); +// vsprintf(REG_DEBUG_STRING, ptr, args); +// va_end(args); +// *REG_DEBUG_FLAGS = level | 0x100; +// } + +// BOOL mgba_open() { +// *REG_DEBUG_ENABLE = 0xC0DE; +// return *REG_DEBUG_ENABLE == 0x1DEA; +// } + +// void mgba_close() { *REG_DEBUG_ENABLE = 0; } +// } else { +// void mgba_printf(int level, const char* ptr, ...) {} +// BOOL mgba_open() { return FALSE; } +// void mgba_close() {} +// } \ No newline at end of file diff --git a/src/dusk/d_src/dusk/load.d b/src/dusk/d_src/dusk/load.d new file mode 100644 index 0000000..1fc2fd1 --- /dev/null +++ b/src/dusk/d_src/dusk/load.d @@ -0,0 +1,186 @@ +module dusk.load; + +#include +#include +#include +#include +#include "ds_load.h" +#include +#include + +const GBFS_FILE* gbfs_dat; + +void dusk_load_init() { + // locate the main GBFS archive + gbfs_dat = find_first_gbfs_file(find_first_gbfs_file); +} + +const void* dusk_load_raw(char* name, u32* len) { + return gbfs_get_obj(gbfs_dat, name, len); +} + +GritImage dusk_load_image(char* name) { + GritImage img; + char tiles_name[GBFS_ENTRY_SIZE]; + strcpy(tiles_name, name); + strcat(tiles_name, ".img.bin"); + char pal_name[GBFS_ENTRY_SIZE]; + strcpy(pal_name, name); + strcat(pal_name, ".pal.bin"); + char map_name[GBFS_ENTRY_SIZE]; + strcpy(map_name, name); + strcat(map_name, ".map.bin"); + + img.tiles = (u32*)gbfs_get_obj(gbfs_dat, tiles_name, &img.tile_sz); + img.pal = (u32*)gbfs_get_obj(gbfs_dat, pal_name, &img.pal_sz); + img.map = (u32*)gbfs_get_obj(gbfs_dat, map_name, &img.map_sz); + + return img; +} + +SpriteAtlas dusk_load_atlas(char* name) { + char atlas_name[GBFS_ENTRY_SIZE]; + strcpy(atlas_name, name); + strcat(atlas_name, "_0"); + + GritImage img = dusk_load_image(atlas_name); + + SpriteAtlas atlas; + atlas.tiles = img.tiles; + atlas.tile_sz = img.tile_sz; + atlas.pal = img.pal; + atlas.pal_sz = img.pal_sz; + + // 1. pal_sz is some weird gradient thing + // we're going to detect when more than 4 in the row are the same + // so then find the actual end of the palette + + // NOTE: ASSERT pal_sz >= 2 + + u16* pal_raw = (u16*)atlas.pal; // 16-bit color + const int palscan_start = 0; + const int palscan_inarow = 6; // how many in a row we're looking for + + u16 prev_color = pal_raw[palscan_start]; + int true_pal_sz = 2; // true size of palette (starts at 1 color, so 2 bytes) + int col_match_streak = 0; // number of last few colors that matched + int last_color_index = atlas.pal_sz / 2; // last color (div by 2 cause pal_sz is in bytes, and 16-bit color) + + for (int i = palscan_start + 1; i < last_color_index; i++) { // start at 1 cause 0's in prev_color + u16 pal_col = pal_raw[i]; // color at index + // printf("p: %0x\n", (int)pal_col); + + // check for match + if (pal_col == prev_color) { + col_match_streak++; + } else { + col_match_streak = 0; + } + + if (col_match_streak >= palscan_inarow) { // 4 past colors are same + true_pal_sz = true_pal_sz - (palscan_inarow) * 2; // we'll disregard all the last 4 + break; // done + } + + prev_color = pal_col; + true_pal_sz += 2; + } + atlas.pal_sz = true_pal_sz; // set adjusted pal size + // printf("adjpal: %d\n", true_pal_sz); + + return atlas; +} + +void seek_until_null(const u8* data, int* pos) { + char last = data[*pos]; + while (last != 0) { + *pos = *pos + 1; // advance pointer + last = data[*pos]; + } +} + +SpriteAtlasLayout dusk_load_atlas_layout(const char* name) { + SpriteAtlasLayout layout; + char file_name[GBFS_ENTRY_SIZE]; + strcpy(file_name, name); + strcat(file_name, "_.sht.bin"); + + u32 data_sz = 0; + const u8* data = gbfs_get_obj(gbfs_dat, file_name, &data_sz); + + int pos = 0; + + // get the number of textures + int num_tex = data[pos] | (data[pos + 1] << 8); + assert(num_tex == 1); // there should only be a single texture + pos += 2; + // eat the texture name + seek_until_null(data, &pos); + pos++; + + layout.width = data[pos] | (data[pos + 1] << 8); + pos += 2; + layout.height = data[pos] | (data[pos + 1] << 8); + pos += 2; + + layout.num_entries = data[pos] | (data[pos + 1] << 8); + layout.entries = malloc(sizeof(SpriteAtlasEntry) * layout.num_entries); + pos += 2; + + // now read blocks + for (int i = 0; i < layout.num_entries; i++) { + // save the entry name + char last = data[pos]; + int name_len = 0; + while (last != 0) { + layout.entries[i].name[name_len] = last; + name_len++; + last = data[pos + name_len]; + } + layout.entries[i].name[name_len] = '\0'; // null terminator + pos += name_len + 1; // skip the name + + u16 x = data[pos] | (data[pos + 1] << 8); + pos += 2; + u16 y = data[pos] | (data[pos + 1] << 8); + pos += 2; + u16 w = data[pos] | (data[pos + 1] << 8); + pos += 2; + u16 h = data[pos] | (data[pos + 1] << 8); + pos += 2; + // x,y,w,h are 8-bit so don't overflow! + // these are in tile units (the final div by 8) + layout.entries[i].x = x / 8; + layout.entries[i].y = y / 8; + layout.entries[i].w = w / 8; + layout.entries[i].h = h / 8; + } + + return layout; +} + +SpriteAtlasEntry* dusk_load_atlas_entry(SpriteAtlasLayout* layout, const char* entry_name) { + for (int i = 0; i < layout->num_entries; i++) { + SpriteAtlasEntry* entry = &layout->entries[i]; + if (strncmp(entry_name, entry->name, ATLAS_ENTRY_LEN) == 0) { + return entry; + } + } + return NULL; +} + +void dusk_free_atlas_layout(SpriteAtlasLayout* layout) { + layout->num_entries = 0; + free(layout->entries); + layout->entries = NULL; +} + +Map dusk_load_map(char* name) { + char ass_name[GBFS_ENTRY_SIZE]; + strcpy(ass_name, name); + strcat(ass_name, ".bin"); + + u32 map_data_sz = 0; + const u16* map_data = gbfs_get_obj(gbfs_dat, ass_name, &map_data_sz); + return map_load_from_rom(map_data); +} diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d new file mode 100644 index 0000000..8087323 --- /dev/null +++ b/src/dusk/d_src/dusk/sprites.d @@ -0,0 +1,271 @@ +module dusk.sprites; + +#include "ds_spr.h" +#include "ds_sys.h" +#include +#include "stdio.h" + +EWRAM_DATA OBJ_ATTR obj_buffer[NUM_SPRITES]; +OBJ_AFFINE* obj_aff_buffer = (OBJ_AFFINE*)obj_buffer; + +EWRAM_DATA Sprite sprites[NUM_SPRITES]; + +/** when true, 8BPP, when false, 4BPP */ +BOOL sprites_bpp8 = TRUE; + +void dusk_sprites_init() { + // initialize object buffer + oam_init(obj_buffer, NUM_SPRITES); + memset(sprites, 0, sizeof(Sprite) * NUM_SPRITES); + + // reset bpp to default + sprites_bpp8 = TRUE; + + // enable sprite display + REG_DISPCNT |= DCNT_OBJ | DCNT_OBJ_1D; +} + +void dusk_sprites_configure(BOOL bpp8) { sprites_bpp8 = bpp8; } + +void dusk_sprites_upload_atlas(SpriteAtlas* atlas) { + // 1. upload the atlas tile palette to palette memory + // object/sprite palette, in 8bpp stores 256 colors + memcpy(&pal_obj_bank[0], atlas->pal, atlas->pal_sz); + // 2. upload the atlas tiles to tile memory + // tile memory (can store 1024 tiles (32x32 tiles or 256x256px) + // VRAM is charblocks 4 and 5, so &tile_mem[4][0] points to the first tile in object VRAM + memcpy(&tile_mem[4][0], atlas->tiles, atlas->tile_sz); +} + +void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* atlas, SpriteAtlasEntry* entry, + u16 pal_offset, u16 tile_offset) { + + // 1. upload the palette (palettes are 16-bit highcolor) + memcpy(&pal_obj_bank[0][pal_offset], &atlas->pal[0], atlas->pal_sz); + + // pal_obj_bank[0][4] = CLR_YELLOW; + // 2. upload the tiles + int entry_firsttid = + dusk_sprites_pos_to_tid(entry->x, entry->y, layout->width, layout->height); // tid of entry start in atlas + int entry_tilecount = (entry->w) * (entry->h); // entry size in tiles + int raw_firsttid = entry_firsttid * entry_tilecount * 2; // read offset + // int raw_tilecount = entry_tilecount * 2; + int raw_tileoffset = tile_offset * 2; // write offset + + // printf("ro: %d. wo: %d, n: %d\n", raw_firsttid, raw_tileoffset, raw_tilecount); // debug print tile r/w + + // memcpy(&tile_mem[4][raw_tileoffset], &atlas->tiles[raw_firsttid], entry_tilecount * 64); + + // 3. fix tiles to point at right palette + // for (int i = 0; i < raw_tilecount; i += 2) { + // TILE8 new_tile; + // // TILE8 tile.data consists of 16 u32s (a total of 64 bytes) + // // new_tile.data[j] = atlas->tiles[(entry_firsttid + i) * 2]; + // u32* rt = &atlas->tiles[raw_firsttid + i]; // read tile + + // for (int j = 0; j < 16; j++) { + // new_tile.data[j] = rt[j]; + // // new_tile.data[j] = 0x04040404; + // } + // // copy in tile + // memcpy(&tile_mem[4][raw_tileoffset + i], &new_tile, 64); + // } + + // unroll malloc + // memcpy(&tile_mem[4][raw_tileoffset], &atlas->tiles[raw_firsttid], 64); + + // reinterpret as byte pointers + u8* loc_twrite = (u8*)&tile_mem[4][raw_tileoffset]; + u8* loc_tread = (u8*)&atlas->tiles[raw_firsttid]; + for (int i = 0; i < entry_tilecount; i += 1) { + int c = i * 64; + u8 tile[64]; // create temp tile + memcpy(&tile[0], loc_tread + c, 64); // read tile + + // fix tile + for (int j = 0; j < 64; j++) { + tile[j] = tile[j] + pal_offset; + } + + memcpy(loc_twrite + c, &tile[0], 64); // write tile + } +} + +Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr) { + // automatically figure out sprite size/shape attributes + u16 shape_attr = 0; + if (height > width) { + shape_attr = ATTR0_TALL; + } else if (width > height) { + shape_attr = ATTR0_WIDE; + } else if (width == height) { + shape_attr = ATTR0_SQUARE; + } + u16 size_attr = 0; + if (shape_attr == ATTR0_TALL) { + if (width == 8 && height == 16) + size_attr = ATTR1_SIZE_8x16; + if (width == 8 && height == 32) + size_attr = ATTR1_SIZE_8x32; + if (width == 16 && height == 32) + size_attr = ATTR1_SIZE_16x32; + if (width == 16 && height == 64) + size_attr = ATTR1_SIZE_32x64; + } + if (shape_attr == ATTR0_WIDE) { + if (width == 16 && height == 8) + size_attr = ATTR1_SIZE_16x8; + if (width == 32 && height == 8) + size_attr = ATTR1_SIZE_32x8; + if (width == 32 && height == 16) + size_attr = ATTR1_SIZE_32x16; + if (width == 64 && height == 32) + size_attr = ATTR1_SIZE_64x32; + } + if (shape_attr == ATTR0_SQUARE) { + if (width == 8 && height == 8) + size_attr = ATTR1_SIZE_8x8; + if (width == 16 && height == 16) + size_attr = ATTR1_SIZE_16x16; + if (width == 32 && height == 32) + size_attr = ATTR1_SIZE_32x32; + if (width == 64 && height == 64) + size_attr = ATTR1_SIZE_64x64; + } + + // calculate the number of tiles used by one frame of this sprite (divide width and height by 8) + spr.tile_sz = (width >> 3) * (height >> 3); + + // set main attributes + // leave tile id (attr2) null, it will be set in sync + u16 bpp_flag = (sprites_bpp8 == 1) ? ATTR0_8BPP : ATTR0_4BPP; + obj_set_attr(&obj_buffer[index], ATTR0_REG | shape_attr | bpp_flag, size_attr, 0); + + // set default flags + spr.flags = (DUSKSPRITE_FLAGS_VISIBLE); + + // save sprite metadata + sprites[index] = spr; + + // sync other attributes + dusk_sprites_sync(index); + + // return pointer to this sprite + return &sprites[index]; +} + +inline void dusk_sprites_sync(int i) { + Sprite* sprite = &sprites[i]; + OBJ_ATTR* obj = &obj_buffer[i]; + // position + obj_set_pos(obj, sprite->x, sprite->y); + + // visibility + if ((sprite->flags & DUSKSPRITE_FLAGS_VISIBLE) > 0) { + obj_unhide(obj, ATTR0_REG); + } else { + obj_hide(obj); + } + + // main attrs + + // logical base tid mode + // obj_set_attr(obj, obj->attr0, obj->attr1, (sprite->tid + sprite->page) * sprite->tile_sz * 2); + + // raw base tid mode + int bpp_mult = (sprites_bpp8 == 1) ? 2 : 1; + u16 tid = (sprite->base_tid + (sprite->page * sprite->tile_sz)) * bpp_mult; + obj_set_attr(obj, obj->attr0, obj->attr1, ATTR2_ID(tid) | ATTR2_PALBANK(0)); +} + +void dusk_sprites_update() { + // sync all sprites + for (int i = 0; i < NUM_SPRITES; i++) { + dusk_sprites_sync(i); + } + + // upload shadow oam to vram + + oam_copy(oam_mem, obj_buffer, NUM_SPRITES); + // CpuFastSet(obj_buffer, oam_mem, NUM_SPRITES * 2); +} + +void dusk_sprites_anim_play(Sprite* spr, Anim* anim) { + // make sure page is within anim range + if (spr->page < anim->start || spr->page >= (anim->start + anim->len)) { + spr->page = anim->start; // reset to first + } + int ix = spr->page - anim->start; + if (frame_count % anim->rate == 0) { + ix = (ix + 1) % anim->len; + } + // set new frame + spr->page = anim->start + ix; +} + +u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height) { + // calculate corner tile id + // first get x and y in tile coords + u16 xt = x; + u16 yt = y; + u16 imw = sheet_width >> 3; // compute with bitshift (sheet_width / 8) + // u16 imh = sheet_height >> 3; + u16 tid = (yt * imw) + xt; + return tid; +} + +void enable_bg(u8 bg_id) { + int bg_flag = 0; + switch (bg_id) { + case 0: + bg_flag = DCNT_BG0; + break; + case 1: + bg_flag = DCNT_BG1; + break; + case 2: + bg_flag = DCNT_BG2; + break; + case 3: + bg_flag = DCNT_BG3; + break; + } + + REG_DISPCNT |= bg_flag; +} + +vu16* dusk_get_background_register(u8 bg_id) { + switch (bg_id) { + case 0: + return ®_BG0CNT; + case 1: + return ®_BG1CNT; + case 2: + return ®_BG2CNT; + case 3: + return ®_BG3CNT; + default: + return NULL; + } +} + +void dusk_background_upload_raw(GritImage* img, int cbb, int sbb) { + // TODO: support selecting slot + + // 1. upload the atlas tile palette to bg palette memory + memcpy(&pal_bg_bank[0], img->pal, img->pal_sz); + // 2. upload the atlas tiles to bg tile memory (CBB) + memcpy(&tile_mem[cbb][0], img->tiles, img->tile_sz); + // 3. upload the map (SBB) + memcpy(&se_mem[sbb][0], img->map, img->map_sz); +} + +void dusk_background_make(u8 bg_id, u16 size, Background bg) { + // set bg on screen enabled + enable_bg(bg_id); + // set control flags + vu16* bg_reg = dusk_get_background_register(bg_id); + + // u16 bpp_flag = (sprites_bpp8 == 1) ? BG_8BPP : BG_4BPP; + *bg_reg |= BG_CBB(bg.cbb) | BG_SBB(bg.sbb) | BG_8BPP | size; +} \ No newline at end of file diff --git a/src/dusk/d_src/dusk/sys.d b/src/dusk/d_src/dusk/sys.d new file mode 100644 index 0000000..ab10767 --- /dev/null +++ b/src/dusk/d_src/dusk/sys.d @@ -0,0 +1,81 @@ +module dusk.sys; + +#include "stdio.h" +#include +#include "ds_sys.h" +#include "ds_load.h" + +__attribute__((used)) const char* _DUSK_LIB_VERSION = ("$DUSK " DUSK_VERSION); + +uint frame_count; + +void dusk_clear_vidmem() { + // clear video memory (vram region) + memset32(vid_mem, 0, VRAM_BG_SIZE / 4); + // pal mem + memset32(pal_bg_mem, 0, 0x00200 / 4); + memset32(pal_obj_mem, 0, 0x00200 / 4); +} + +void dusk_reset_irq() { + irq_init(NULL); + irq_add(II_VBLANK, NULL); +} + +void dusk_init_all() { + // 1. initialize system graphics + dusk_init_graphics_mode0(); + + dusk_reset_irq(); + + // initialize loader + dusk_load_init(); +} + +void dusk_init_graphics_mode0() { + dusk_clear_vidmem(); + // dusk_reset_irq(); + + // reset registers + REG_DISPCNT = DCNT_MODE0; + REG_BG0CNT = 0; + REG_BG1CNT = 0; + REG_BG2CNT = 0; + REG_BG3CNT = 0; +} + +void dusk_init_graphics_mode3() { REG_DISPCNT = DCNT_MODE3 | DCNT_BG2; } + +void dusk_frame() { + // vid_vsync(); + VBlankIntrWait(); + frame_count++; +} + +static bool scene_changed = false; +static void nothing(void) {} +static Scene next_scene = { + .start = nothing, + .end = nothing, + .update = nothing, +}; +static Scene current_scene = { + .start = nothing, + .end = nothing, + .update = nothing, +}; + +void dusk_scene_set(Scene next) { + scene_changed = true; + next_scene = next; +} + +void dusk_scene_update() { + if (scene_changed) { + scene_changed = false; + current_scene.end(); + current_scene = next_scene; + current_scene.start(); + } + current_scene.update(); +} diff --git a/src/dusk/include/contrib/gbfs.d b/src/dusk/include/contrib/gbfs.d new file mode 100644 index 0000000..51ead63 --- /dev/null +++ b/src/dusk/include/contrib/gbfs.d @@ -0,0 +1,116 @@ +/* gbfs.h + access object in a GBFS file + +Copyright 2002 Damian Yerrick + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +*/ + +/* Dependency on prior include files + +Before you #include "gbfs.h", you should define the following types: + typedef (unsigned 16-bit integer) u16; + typedef (unsigned 32-bit integer) u32; +Your gba.h should do this for you. +*/ + +//\{ + +//\} + +/*! \name Volatile types +* Volatile types for registers +*/ +//\{ + +//\} + +/*! \name Const types +* Const types for const function aprameters +*/ +//\{ + +//\} + +//! 8-word type for fast struct-copies + +//! Type for consting a string as well as the pointer than points to it. + +extern (C): + +alias uchar = ubyte; +alias echar = ubyte; +alias hword = ushort; +alias eshort = ushort; +alias word = uint; +alias eint = uint; +alias vu8 = ubyte; +alias vu16 = ushort; +alias vu32 = uint; +alias vu64 = ulong; +alias vs8 = byte; +alias vs16 = short; +alias vs32 = int; +alias vs64 = long; +alias cu8 = const ubyte; +alias cu16 = const ushort; +alias cu32 = const uint; +alias cu64 = const ulong; +alias cs8 = const byte; +alias cs16 = const short; +alias cs32 = const int; +alias cs64 = const long; + +struct BLOCK +{ + uint[8] data; +} + +alias CSTR = const char*; + +/* to make a 300 KB space called samples do GBFS_SPACE(samples, 300) */ + +enum GBFS_ENTRY_SIZE = 24; + +struct GBFS_FILE +{ + char[16] magic; /* "PinEightGBFS\r\n\032\n" */ + uint total_len; /* total length of archive */ + ushort dir_off; /* offset in bytes to directory */ + ushort dir_nmemb; /* number of files */ + char[8] reserved; /* for future use */ +} + +struct GBFS_ENTRY +{ + char[GBFS_ENTRY_SIZE] name; /* filename, nul-padded */ + uint len; /* length of object in bytes */ + uint data_offset; /* in bytes from beginning of file */ +} + +const(GBFS_FILE)* find_first_gbfs_file (const(void)* start); +const(void)* skip_gbfs_file (const(GBFS_FILE)* file); +const(void)* gbfs_get_obj (const(GBFS_FILE)* file, const(char)* name, uint* len); +const(void)* gbfs_get_nth_obj (const(GBFS_FILE)* file, size_t n, char* name, uint* len); +void* gbfs_copy_obj (void* dst, const(GBFS_FILE)* file, const(char)* name); +size_t gbfs_count_objs (const(GBFS_FILE)* file); + From a09c0e0ad35fac36dfb42237cea97f10803d1c2b Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 16 Nov 2021 00:23:36 -0800 Subject: [PATCH 02/32] broken stubs for dusk --- src/dusk/d_src/dusk/contrib/gbfs.d | 2 + src/dusk/d_src/dusk/contrib/mgba.d | 24 +-- src/dusk/d_src/dusk/load.d | 55 ++++++ src/dusk/d_src/dusk/package.d | 8 + src/dusk/d_src/dusk/save.d | 13 ++ src/dusk/d_src/dusk/sprites.d | 71 ++++++++ src/dusk/d_src/dusk/sys.d | 19 ++ src/dusk/src/load.c | 184 -------------------- src/dusk/src/sprites.c | 269 ----------------------------- src/dusk/src/sys.c | 79 --------- 10 files changed, 170 insertions(+), 554 deletions(-) create mode 100644 src/dusk/d_src/dusk/package.d create mode 100644 src/dusk/d_src/dusk/save.d delete mode 100644 src/dusk/src/load.c delete mode 100644 src/dusk/src/sprites.c delete mode 100644 src/dusk/src/sys.c diff --git a/src/dusk/d_src/dusk/contrib/gbfs.d b/src/dusk/d_src/dusk/contrib/gbfs.d index ad56da1..50c1ad9 100644 --- a/src/dusk/d_src/dusk/contrib/gbfs.d +++ b/src/dusk/d_src/dusk/contrib/gbfs.d @@ -1,3 +1,5 @@ +module dusk.contrib.gbfs; + /* gbfs.h access object in a GBFS file diff --git a/src/dusk/d_src/dusk/contrib/mgba.d b/src/dusk/d_src/dusk/contrib/mgba.d index 120bf71..79f573f 100644 --- a/src/dusk/d_src/dusk/contrib/mgba.d +++ b/src/dusk/d_src/dusk/contrib/mgba.d @@ -2,6 +2,8 @@ module dusk.contrib.mgba; import tonc.tonc_types; +extern (C): + enum REG_DEBUG_ENABLE = cast(vu16*) 0x4FFF780; enum REG_DEBUG_FLAGS = cast(vu16*) 0x4FFF700; enum REG_DEBUG_STRING = cast(char*) 0x4FFF600; @@ -18,25 +20,3 @@ enum MGBA_LOG_LEVEL void mgba_printf (int level, const(char)* ptr, ...); bool mgba_open (); void mgba_close (); - -// version (DEBUG) { -// void mgba_printf(int level, const char* ptr, ...) { -// va_list args; -// level &= 0x7; -// va_start(args, ptr); -// vsprintf(REG_DEBUG_STRING, ptr, args); -// va_end(args); -// *REG_DEBUG_FLAGS = level | 0x100; -// } - -// BOOL mgba_open() { -// *REG_DEBUG_ENABLE = 0xC0DE; -// return *REG_DEBUG_ENABLE == 0x1DEA; -// } - -// void mgba_close() { *REG_DEBUG_ENABLE = 0; } -// } else { -// void mgba_printf(int level, const char* ptr, ...) {} -// BOOL mgba_open() { return FALSE; } -// void mgba_close() {} -// } \ No newline at end of file diff --git a/src/dusk/d_src/dusk/load.d b/src/dusk/d_src/dusk/load.d index 1fc2fd1..160b335 100644 --- a/src/dusk/d_src/dusk/load.d +++ b/src/dusk/d_src/dusk/load.d @@ -1,5 +1,60 @@ module dusk.load; +extern const GBFS_FILE* gbfs_dat; + +// represents an atlas, with bitmaps for the image and palette +typedef struct SpriteAtlas { + u32* tiles; + u32 tile_sz; + u32* pal; + u32 pal_sz; +} SpriteAtlas; + +typedef struct GritImage { + u32* tiles; + u32 tile_sz; + u32* pal; + u32 pal_sz; + u32* map; + u32 map_sz; +} GritImage; + +#define ATLAS_ENTRY_LEN 6 + +/** represents a single entry in the sprite atlas. + * note that names are limited to just 5 chars and a NULL terminator. */ +typedef struct SpriteAtlasEntry { + char name[ATLAS_ENTRY_LEN]; + // all of these are in tiles (8px) + u8 x; + u8 y; + u8 w; + u8 h; +} SpriteAtlasEntry; + +/** represents the layout of items in an atlas (https://github.com/xdrie/crunch#binary-format). + * we only use the first texture because the vram can only hold one */ +typedef struct SpriteAtlasLayout { + u16 width; + u16 height; + u16 num_entries; + SpriteAtlasEntry* entries; +} SpriteAtlasLayout; + +/** initialize loader */ +void dusk_load_init(); + +// - CONTENT LOADERS: pass filename without extension + +const void* dusk_load_raw(char* name, u32* len); +GritImage dusk_load_image(char* name); +SpriteAtlas dusk_load_atlas(char* name); +SpriteAtlasLayout dusk_load_atlas_layout(const char* name); +SpriteAtlasEntry* dusk_load_atlas_entry(SpriteAtlasLayout* layout, const char* entry_name); +void dusk_free_atlas_layout(SpriteAtlasLayout* layout); + +Map dusk_load_map(char* name); + #include #include #include diff --git a/src/dusk/d_src/dusk/package.d b/src/dusk/d_src/dusk/package.d new file mode 100644 index 0000000..c1fa0b1 --- /dev/null +++ b/src/dusk/d_src/dusk/package.d @@ -0,0 +1,8 @@ +module dusk; + +public { + import dusk.load; + import dusk.sys; + import dusk.spr; + import dusk.sav; +} \ No newline at end of file diff --git a/src/dusk/d_src/dusk/save.d b/src/dusk/d_src/dusk/save.d new file mode 100644 index 0000000..25a5d54 --- /dev/null +++ b/src/dusk/d_src/dusk/save.d @@ -0,0 +1,13 @@ +module lib.dusk.src.dusk.d_src.dusk.save; + +// utilities for saving and loading vars + +#define SV_LOAD_ITEM(var, offset) \ + memcpy(&var, sram_mem + offset, sizeof(typeof(var))); \ + offset += sizeof(typeof(var)); + +#define SV_SAVE_ITEM(var, offset) \ + memcpy(sram_mem + offset, &var, sizeof(typeof(var))); \ + offset += sizeof(typeof(var)); + +// utilities for saving and loading vars \ No newline at end of file diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index 8087323..093d4b9 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -1,5 +1,76 @@ module dusk.sprites; +#define NUM_SPRITES 128 +#define NUM_AFFINE_SPRITES 32 +extern OBJ_ATTR obj_buffer[NUM_SPRITES]; +extern OBJ_AFFINE* obj_aff_buffer; + +#define SPRITEFLAG_PRIORITY_SHIFT 6 +#define SPRITEFLAG_PRIORITY_GET(n) ((n >> SPRITEFLAG_PRIORITY_SHIFT) & 0b11) +#define SPRITEFLAG_PRIORITY(n) ((n << SPRITEFLAG_PRIORITY_SHIFT) & 0b11) + +#define DUSKSPRITE_FLAGS_VISIBLE (0x1 << 0) +/** sprite data */ +typedef struct Sprite { + s16 x, y; + /** the number of tiles taken up by this sprite */ + u8 tile_sz; + /** the raw tid of the top left corner tile of spritesheet frame 0 */ + u16 base_tid; + /** the frame index of the spritesheet */ + u8 page; + /** flags: 0/0/0/0/0/0/0/visible */ + u8 flags; +} Sprite; + +/** animation metadata */ +typedef struct Anim { + /** which page in the sprite the animation starts */ + u8 start; + /** number of pages in this animation */ + u8 len; + /** (60/fps), or how many frames each page lasts */ + u8 rate; +} Anim; + +/** background data */ +typedef struct Background { + s16 x, y; + int cbb, sbb; +} Background; + +/** define an animation, given a starting frame and frame count, and fps */ +#define MAKE_ANIM_EX(st, le, fps) \ + (Anim) { .start = st, .len = le, .rate = (60 / fps) } +/** define an animation, given a starting frame and frame count, at 10 fps */ +#define MAKE_ANIM(st, le) MAKE_ANIM_EX(st, le, 10) + +/** memory block used to track sprites */ +extern Sprite sprites[NUM_SPRITES]; + +/** initialize sprite and OAM memory */ +void dusk_sprites_init(); +/** set mode options for dusk sprites */ +void dusk_sprites_configure(BOOL bpp8); +/** upload a sprite atlas to tile and palette memory */ +void dusk_sprites_upload_atlas(SpriteAtlas* atlas); +/** upload a sprite atlas section to tile and palette memory */ +void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* atlas, SpriteAtlasEntry* entry, u16 pal_offset, u16 tile_offset); +/** create a sprite and store it in index of sprite memory */ +Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr); +/** synchronize a sprite from the sprites array to OAM block (vram) */ +void dusk_sprites_sync(int index); +/** synchronize all sprites to OAM block, then upload OAM block to vram */ +void dusk_sprites_update(); +/** play an animation on a sprite */ +void dusk_sprites_anim_play(Sprite* spr, Anim* anim); +/** calculate the tid of a sprite given pos and sheet dimens */ +u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height); +/** upload image data to background tile vram */ +void dusk_background_upload_raw(GritImage* img, int cbb, int sbb); +/** create a background and display it */ +void dusk_background_make(u8 bg_id, u16 size, Background bg); + #include "ds_spr.h" #include "ds_sys.h" #include diff --git a/src/dusk/d_src/dusk/sys.d b/src/dusk/d_src/dusk/sys.d index ab10767..7baf6d5 100644 --- a/src/dusk/d_src/dusk/sys.d +++ b/src/dusk/d_src/dusk/sys.d @@ -1,5 +1,24 @@ module dusk.sys; +extern uint frame_count; + +typedef struct Scene { + void (*start)(void); + void (*end)(void); + void (*update)(void); +} Scene; + +/** initialize the system for using DUSK */ +void dusk_init_all(); +/** initialize mode0 graphics */ +void dusk_init_graphics_mode0(); +/** initialize mode3 graphics */ +void dusk_init_graphics_mode3(); +/** vsync */ +void dusk_frame(); +void dusk_scene_set(Scene next); +void dusk_scene_update(); + #include "stdio.h" #include #include "ds_sys.h" diff --git a/src/dusk/src/load.c b/src/dusk/src/load.c deleted file mode 100644 index 8adeb6b..0000000 --- a/src/dusk/src/load.c +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include -#include -#include -#include "ds_load.h" -#include -#include - -const GBFS_FILE* gbfs_dat; - -void dusk_load_init() { - // locate the main GBFS archive - gbfs_dat = find_first_gbfs_file(find_first_gbfs_file); -} - -const void* dusk_load_raw(char* name, u32* len) { - return gbfs_get_obj(gbfs_dat, name, len); -} - -GritImage dusk_load_image(char* name) { - GritImage img; - char tiles_name[GBFS_ENTRY_SIZE]; - strcpy(tiles_name, name); - strcat(tiles_name, ".img.bin"); - char pal_name[GBFS_ENTRY_SIZE]; - strcpy(pal_name, name); - strcat(pal_name, ".pal.bin"); - char map_name[GBFS_ENTRY_SIZE]; - strcpy(map_name, name); - strcat(map_name, ".map.bin"); - - img.tiles = (u32*)gbfs_get_obj(gbfs_dat, tiles_name, &img.tile_sz); - img.pal = (u32*)gbfs_get_obj(gbfs_dat, pal_name, &img.pal_sz); - img.map = (u32*)gbfs_get_obj(gbfs_dat, map_name, &img.map_sz); - - return img; -} - -SpriteAtlas dusk_load_atlas(char* name) { - char atlas_name[GBFS_ENTRY_SIZE]; - strcpy(atlas_name, name); - strcat(atlas_name, "_0"); - - GritImage img = dusk_load_image(atlas_name); - - SpriteAtlas atlas; - atlas.tiles = img.tiles; - atlas.tile_sz = img.tile_sz; - atlas.pal = img.pal; - atlas.pal_sz = img.pal_sz; - - // 1. pal_sz is some weird gradient thing - // we're going to detect when more than 4 in the row are the same - // so then find the actual end of the palette - - // NOTE: ASSERT pal_sz >= 2 - - u16* pal_raw = (u16*)atlas.pal; // 16-bit color - const int palscan_start = 0; - const int palscan_inarow = 6; // how many in a row we're looking for - - u16 prev_color = pal_raw[palscan_start]; - int true_pal_sz = 2; // true size of palette (starts at 1 color, so 2 bytes) - int col_match_streak = 0; // number of last few colors that matched - int last_color_index = atlas.pal_sz / 2; // last color (div by 2 cause pal_sz is in bytes, and 16-bit color) - - for (int i = palscan_start + 1; i < last_color_index; i++) { // start at 1 cause 0's in prev_color - u16 pal_col = pal_raw[i]; // color at index - // printf("p: %0x\n", (int)pal_col); - - // check for match - if (pal_col == prev_color) { - col_match_streak++; - } else { - col_match_streak = 0; - } - - if (col_match_streak >= palscan_inarow) { // 4 past colors are same - true_pal_sz = true_pal_sz - (palscan_inarow) * 2; // we'll disregard all the last 4 - break; // done - } - - prev_color = pal_col; - true_pal_sz += 2; - } - atlas.pal_sz = true_pal_sz; // set adjusted pal size - // printf("adjpal: %d\n", true_pal_sz); - - return atlas; -} - -void seek_until_null(const u8* data, int* pos) { - char last = data[*pos]; - while (last != 0) { - *pos = *pos + 1; // advance pointer - last = data[*pos]; - } -} - -SpriteAtlasLayout dusk_load_atlas_layout(const char* name) { - SpriteAtlasLayout layout; - char file_name[GBFS_ENTRY_SIZE]; - strcpy(file_name, name); - strcat(file_name, "_.sht.bin"); - - u32 data_sz = 0; - const u8* data = gbfs_get_obj(gbfs_dat, file_name, &data_sz); - - int pos = 0; - - // get the number of textures - int num_tex = data[pos] | (data[pos + 1] << 8); - assert(num_tex == 1); // there should only be a single texture - pos += 2; - // eat the texture name - seek_until_null(data, &pos); - pos++; - - layout.width = data[pos] | (data[pos + 1] << 8); - pos += 2; - layout.height = data[pos] | (data[pos + 1] << 8); - pos += 2; - - layout.num_entries = data[pos] | (data[pos + 1] << 8); - layout.entries = malloc(sizeof(SpriteAtlasEntry) * layout.num_entries); - pos += 2; - - // now read blocks - for (int i = 0; i < layout.num_entries; i++) { - // save the entry name - char last = data[pos]; - int name_len = 0; - while (last != 0) { - layout.entries[i].name[name_len] = last; - name_len++; - last = data[pos + name_len]; - } - layout.entries[i].name[name_len] = '\0'; // null terminator - pos += name_len + 1; // skip the name - - u16 x = data[pos] | (data[pos + 1] << 8); - pos += 2; - u16 y = data[pos] | (data[pos + 1] << 8); - pos += 2; - u16 w = data[pos] | (data[pos + 1] << 8); - pos += 2; - u16 h = data[pos] | (data[pos + 1] << 8); - pos += 2; - // x,y,w,h are 8-bit so don't overflow! - // these are in tile units (the final div by 8) - layout.entries[i].x = x / 8; - layout.entries[i].y = y / 8; - layout.entries[i].w = w / 8; - layout.entries[i].h = h / 8; - } - - return layout; -} - -SpriteAtlasEntry* dusk_load_atlas_entry(SpriteAtlasLayout* layout, const char* entry_name) { - for (int i = 0; i < layout->num_entries; i++) { - SpriteAtlasEntry* entry = &layout->entries[i]; - if (strncmp(entry_name, entry->name, ATLAS_ENTRY_LEN) == 0) { - return entry; - } - } - return NULL; -} - -void dusk_free_atlas_layout(SpriteAtlasLayout* layout) { - layout->num_entries = 0; - free(layout->entries); - layout->entries = NULL; -} - -Map dusk_load_map(char* name) { - char ass_name[GBFS_ENTRY_SIZE]; - strcpy(ass_name, name); - strcat(ass_name, ".bin"); - - u32 map_data_sz = 0; - const u16* map_data = gbfs_get_obj(gbfs_dat, ass_name, &map_data_sz); - return map_load_from_rom(map_data); -} diff --git a/src/dusk/src/sprites.c b/src/dusk/src/sprites.c deleted file mode 100644 index cdf6fa2..0000000 --- a/src/dusk/src/sprites.c +++ /dev/null @@ -1,269 +0,0 @@ -#include "ds_spr.h" -#include "ds_sys.h" -#include -#include "stdio.h" - -EWRAM_DATA OBJ_ATTR obj_buffer[NUM_SPRITES]; -OBJ_AFFINE* obj_aff_buffer = (OBJ_AFFINE*)obj_buffer; - -EWRAM_DATA Sprite sprites[NUM_SPRITES]; - -/** when true, 8BPP, when false, 4BPP */ -BOOL sprites_bpp8 = TRUE; - -void dusk_sprites_init() { - // initialize object buffer - oam_init(obj_buffer, NUM_SPRITES); - memset(sprites, 0, sizeof(Sprite) * NUM_SPRITES); - - // reset bpp to default - sprites_bpp8 = TRUE; - - // enable sprite display - REG_DISPCNT |= DCNT_OBJ | DCNT_OBJ_1D; -} - -void dusk_sprites_configure(BOOL bpp8) { sprites_bpp8 = bpp8; } - -void dusk_sprites_upload_atlas(SpriteAtlas* atlas) { - // 1. upload the atlas tile palette to palette memory - // object/sprite palette, in 8bpp stores 256 colors - memcpy(&pal_obj_bank[0], atlas->pal, atlas->pal_sz); - // 2. upload the atlas tiles to tile memory - // tile memory (can store 1024 tiles (32x32 tiles or 256x256px) - // VRAM is charblocks 4 and 5, so &tile_mem[4][0] points to the first tile in object VRAM - memcpy(&tile_mem[4][0], atlas->tiles, atlas->tile_sz); -} - -void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* atlas, SpriteAtlasEntry* entry, - u16 pal_offset, u16 tile_offset) { - - // 1. upload the palette (palettes are 16-bit highcolor) - memcpy(&pal_obj_bank[0][pal_offset], &atlas->pal[0], atlas->pal_sz); - - // pal_obj_bank[0][4] = CLR_YELLOW; - // 2. upload the tiles - int entry_firsttid = - dusk_sprites_pos_to_tid(entry->x, entry->y, layout->width, layout->height); // tid of entry start in atlas - int entry_tilecount = (entry->w) * (entry->h); // entry size in tiles - int raw_firsttid = entry_firsttid * entry_tilecount * 2; // read offset - // int raw_tilecount = entry_tilecount * 2; - int raw_tileoffset = tile_offset * 2; // write offset - - // printf("ro: %d. wo: %d, n: %d\n", raw_firsttid, raw_tileoffset, raw_tilecount); // debug print tile r/w - - // memcpy(&tile_mem[4][raw_tileoffset], &atlas->tiles[raw_firsttid], entry_tilecount * 64); - - // 3. fix tiles to point at right palette - // for (int i = 0; i < raw_tilecount; i += 2) { - // TILE8 new_tile; - // // TILE8 tile.data consists of 16 u32s (a total of 64 bytes) - // // new_tile.data[j] = atlas->tiles[(entry_firsttid + i) * 2]; - // u32* rt = &atlas->tiles[raw_firsttid + i]; // read tile - - // for (int j = 0; j < 16; j++) { - // new_tile.data[j] = rt[j]; - // // new_tile.data[j] = 0x04040404; - // } - // // copy in tile - // memcpy(&tile_mem[4][raw_tileoffset + i], &new_tile, 64); - // } - - // unroll malloc - // memcpy(&tile_mem[4][raw_tileoffset], &atlas->tiles[raw_firsttid], 64); - - // reinterpret as byte pointers - u8* loc_twrite = (u8*)&tile_mem[4][raw_tileoffset]; - u8* loc_tread = (u8*)&atlas->tiles[raw_firsttid]; - for (int i = 0; i < entry_tilecount; i += 1) { - int c = i * 64; - u8 tile[64]; // create temp tile - memcpy(&tile[0], loc_tread + c, 64); // read tile - - // fix tile - for (int j = 0; j < 64; j++) { - tile[j] = tile[j] + pal_offset; - } - - memcpy(loc_twrite + c, &tile[0], 64); // write tile - } -} - -Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr) { - // automatically figure out sprite size/shape attributes - u16 shape_attr = 0; - if (height > width) { - shape_attr = ATTR0_TALL; - } else if (width > height) { - shape_attr = ATTR0_WIDE; - } else if (width == height) { - shape_attr = ATTR0_SQUARE; - } - u16 size_attr = 0; - if (shape_attr == ATTR0_TALL) { - if (width == 8 && height == 16) - size_attr = ATTR1_SIZE_8x16; - if (width == 8 && height == 32) - size_attr = ATTR1_SIZE_8x32; - if (width == 16 && height == 32) - size_attr = ATTR1_SIZE_16x32; - if (width == 16 && height == 64) - size_attr = ATTR1_SIZE_32x64; - } - if (shape_attr == ATTR0_WIDE) { - if (width == 16 && height == 8) - size_attr = ATTR1_SIZE_16x8; - if (width == 32 && height == 8) - size_attr = ATTR1_SIZE_32x8; - if (width == 32 && height == 16) - size_attr = ATTR1_SIZE_32x16; - if (width == 64 && height == 32) - size_attr = ATTR1_SIZE_64x32; - } - if (shape_attr == ATTR0_SQUARE) { - if (width == 8 && height == 8) - size_attr = ATTR1_SIZE_8x8; - if (width == 16 && height == 16) - size_attr = ATTR1_SIZE_16x16; - if (width == 32 && height == 32) - size_attr = ATTR1_SIZE_32x32; - if (width == 64 && height == 64) - size_attr = ATTR1_SIZE_64x64; - } - - // calculate the number of tiles used by one frame of this sprite (divide width and height by 8) - spr.tile_sz = (width >> 3) * (height >> 3); - - // set main attributes - // leave tile id (attr2) null, it will be set in sync - u16 bpp_flag = (sprites_bpp8 == 1) ? ATTR0_8BPP : ATTR0_4BPP; - obj_set_attr(&obj_buffer[index], ATTR0_REG | shape_attr | bpp_flag, size_attr, 0); - - // set default flags - spr.flags = (DUSKSPRITE_FLAGS_VISIBLE); - - // save sprite metadata - sprites[index] = spr; - - // sync other attributes - dusk_sprites_sync(index); - - // return pointer to this sprite - return &sprites[index]; -} - -inline void dusk_sprites_sync(int i) { - Sprite* sprite = &sprites[i]; - OBJ_ATTR* obj = &obj_buffer[i]; - // position - obj_set_pos(obj, sprite->x, sprite->y); - - // visibility - if ((sprite->flags & DUSKSPRITE_FLAGS_VISIBLE) > 0) { - obj_unhide(obj, ATTR0_REG); - } else { - obj_hide(obj); - } - - // main attrs - - // logical base tid mode - // obj_set_attr(obj, obj->attr0, obj->attr1, (sprite->tid + sprite->page) * sprite->tile_sz * 2); - - // raw base tid mode - int bpp_mult = (sprites_bpp8 == 1) ? 2 : 1; - u16 tid = (sprite->base_tid + (sprite->page * sprite->tile_sz)) * bpp_mult; - obj_set_attr(obj, obj->attr0, obj->attr1, ATTR2_ID(tid) | ATTR2_PALBANK(0)); -} - -void dusk_sprites_update() { - // sync all sprites - for (int i = 0; i < NUM_SPRITES; i++) { - dusk_sprites_sync(i); - } - - // upload shadow oam to vram - - oam_copy(oam_mem, obj_buffer, NUM_SPRITES); - // CpuFastSet(obj_buffer, oam_mem, NUM_SPRITES * 2); -} - -void dusk_sprites_anim_play(Sprite* spr, Anim* anim) { - // make sure page is within anim range - if (spr->page < anim->start || spr->page >= (anim->start + anim->len)) { - spr->page = anim->start; // reset to first - } - int ix = spr->page - anim->start; - if (frame_count % anim->rate == 0) { - ix = (ix + 1) % anim->len; - } - // set new frame - spr->page = anim->start + ix; -} - -u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height) { - // calculate corner tile id - // first get x and y in tile coords - u16 xt = x; - u16 yt = y; - u16 imw = sheet_width >> 3; // compute with bitshift (sheet_width / 8) - // u16 imh = sheet_height >> 3; - u16 tid = (yt * imw) + xt; - return tid; -} - -void enable_bg(u8 bg_id) { - int bg_flag = 0; - switch (bg_id) { - case 0: - bg_flag = DCNT_BG0; - break; - case 1: - bg_flag = DCNT_BG1; - break; - case 2: - bg_flag = DCNT_BG2; - break; - case 3: - bg_flag = DCNT_BG3; - break; - } - - REG_DISPCNT |= bg_flag; -} - -vu16* dusk_get_background_register(u8 bg_id) { - switch (bg_id) { - case 0: - return ®_BG0CNT; - case 1: - return ®_BG1CNT; - case 2: - return ®_BG2CNT; - case 3: - return ®_BG3CNT; - default: - return NULL; - } -} - -void dusk_background_upload_raw(GritImage* img, int cbb, int sbb) { - // TODO: support selecting slot - - // 1. upload the atlas tile palette to bg palette memory - memcpy(&pal_bg_bank[0], img->pal, img->pal_sz); - // 2. upload the atlas tiles to bg tile memory (CBB) - memcpy(&tile_mem[cbb][0], img->tiles, img->tile_sz); - // 3. upload the map (SBB) - memcpy(&se_mem[sbb][0], img->map, img->map_sz); -} - -void dusk_background_make(u8 bg_id, u16 size, Background bg) { - // set bg on screen enabled - enable_bg(bg_id); - // set control flags - vu16* bg_reg = dusk_get_background_register(bg_id); - - // u16 bpp_flag = (sprites_bpp8 == 1) ? BG_8BPP : BG_4BPP; - *bg_reg |= BG_CBB(bg.cbb) | BG_SBB(bg.sbb) | BG_8BPP | size; -} \ No newline at end of file diff --git a/src/dusk/src/sys.c b/src/dusk/src/sys.c deleted file mode 100644 index c844472..0000000 --- a/src/dusk/src/sys.c +++ /dev/null @@ -1,79 +0,0 @@ -#include "stdio.h" -#include -#include "ds_sys.h" -#include "ds_load.h" - -__attribute__((used)) const char* _DUSK_LIB_VERSION = ("$DUSK " DUSK_VERSION); - -uint frame_count; - -void dusk_clear_vidmem() { - // clear video memory (vram region) - memset32(vid_mem, 0, VRAM_BG_SIZE / 4); - // pal mem - memset32(pal_bg_mem, 0, 0x00200 / 4); - memset32(pal_obj_mem, 0, 0x00200 / 4); -} - -void dusk_reset_irq() { - irq_init(NULL); - irq_add(II_VBLANK, NULL); -} - -void dusk_init_all() { - // 1. initialize system graphics - dusk_init_graphics_mode0(); - - dusk_reset_irq(); - - // initialize loader - dusk_load_init(); -} - -void dusk_init_graphics_mode0() { - dusk_clear_vidmem(); - // dusk_reset_irq(); - - // reset registers - REG_DISPCNT = DCNT_MODE0; - REG_BG0CNT = 0; - REG_BG1CNT = 0; - REG_BG2CNT = 0; - REG_BG3CNT = 0; -} - -void dusk_init_graphics_mode3() { REG_DISPCNT = DCNT_MODE3 | DCNT_BG2; } - -void dusk_frame() { - // vid_vsync(); - VBlankIntrWait(); - frame_count++; -} - -static bool scene_changed = false; -static void nothing(void) {} -static Scene next_scene = { - .start = nothing, - .end = nothing, - .update = nothing, -}; -static Scene current_scene = { - .start = nothing, - .end = nothing, - .update = nothing, -}; - -void dusk_scene_set(Scene next) { - scene_changed = true; - next_scene = next; -} - -void dusk_scene_update() { - if (scene_changed) { - scene_changed = false; - current_scene.end(); - current_scene = next_scene; - current_scene.start(); - } - current_scene.update(); -} From 124ca0f785f4d4c935ce3e012ec7f33316500a91 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 16 Nov 2021 01:29:18 -0800 Subject: [PATCH 03/32] bad partial dusk port --- src/dusk/d_src/dusk/contrib/gbamap.d | 58 +++++++++++++ src/dusk/d_src/dusk/load.d | 74 ++++++++-------- src/dusk/d_src/dusk/package.d | 4 +- src/dusk/d_src/dusk/save.d | 12 +-- src/dusk/d_src/dusk/sprites.d | 123 ++++++++++++++------------- src/dusk/d_src/dusk/sys.d | 39 ++++----- 6 files changed, 181 insertions(+), 129 deletions(-) create mode 100644 src/dusk/d_src/dusk/contrib/gbamap.d diff --git a/src/dusk/d_src/dusk/contrib/gbamap.d b/src/dusk/d_src/dusk/contrib/gbamap.d new file mode 100644 index 0000000..1ec7c1f --- /dev/null +++ b/src/dusk/d_src/dusk/contrib/gbamap.d @@ -0,0 +1,58 @@ +module dusk.contrib.gbamap; + +extern (C): + +struct Map { + ushort sizeFlag, + paletteLength, + tileSetLength, + terrainMapLength, + numObjects, + numLayers, + tileMapLength; + + const ushort *palette; + const ushort *tileSet; + const ushort *terrainMap; + + MapObject[256] objects; + + const ushort[3] *tileMapLayers; +} + +align(2) struct BackgroundPoint { + align (2): + short x, y; +} + +enum MAX_LAYERS = 3; +enum ENTRIES_IN_SCREEN_BLOCK = 512; +enum NUM_SCREEN_BLOCKS = 31; + +Map map_load_from_rom(const ushort *map_data); + +void map_init_registers(); +void map_set_onscreen(Map map); +void map_shift(Map map, BackgroundPoint offset); +void map_shift_layer(ushort layer, BackgroundPoint offset); + +align(4) struct ObjectPoint { + align(4): + ushort x, y; +} + +struct MapObject +{ + uint id; + ObjectPoint position; + const char* name; + const char* type; +} + +MapObject map_load_object(const ushort* object_data, ushort* index); +uint map_load_object_id(const ushort* idData, ushort* index); +ObjectPoint map_load_object_position(const ushort* positionData, ushort* index); +char* map_load_string(const ushort* stringData, ushort* index); +ushort map_pop_value(const ushort* data, ushort* index); + +void map_shift_objects(MapObject* objects, ObjectPoint shift, uint count); \ No newline at end of file diff --git a/src/dusk/d_src/dusk/load.d b/src/dusk/d_src/dusk/load.d index 160b335..8b7634a 100644 --- a/src/dusk/d_src/dusk/load.d +++ b/src/dusk/d_src/dusk/load.d @@ -1,52 +1,58 @@ module dusk.load; -extern const GBFS_FILE* gbfs_dat; +import core.stdc.stdio; +import core.stdc.stdlib; +import core.stdc.stddef; +import core.stdc.string; +import tonc.tonc_types; +import dusk.contrib.gbfs; +import dusk.contrib.gbamap; // represents an atlas, with bitmaps for the image and palette -typedef struct SpriteAtlas { +struct SpriteAtlas { u32* tiles; u32 tile_sz; u32* pal; u32 pal_sz; -} SpriteAtlas; +} -typedef struct GritImage { +struct GritImage { u32* tiles; u32 tile_sz; u32* pal; u32 pal_sz; u32* map; u32 map_sz; -} GritImage; +} -#define ATLAS_ENTRY_LEN 6 +enum ATLAS_ENTRY_LEN = 6; /** represents a single entry in the sprite atlas. * note that names are limited to just 5 chars and a NULL terminator. */ -typedef struct SpriteAtlasEntry { - char name[ATLAS_ENTRY_LEN]; +struct SpriteAtlasEntry { + char[ATLAS_ENTRY_LEN] name; // all of these are in tiles (8px) u8 x; u8 y; u8 w; u8 h; -} SpriteAtlasEntry; +} /** represents the layout of items in an atlas (https://github.com/xdrie/crunch#binary-format). * we only use the first texture because the vram can only hold one */ -typedef struct SpriteAtlasLayout { +struct SpriteAtlasLayout { u16 width; u16 height; u16 num_entries; SpriteAtlasEntry* entries; -} SpriteAtlasLayout; +} /** initialize loader */ void dusk_load_init(); // - CONTENT LOADERS: pass filename without extension -const void* dusk_load_raw(char* name, u32* len); +void* dusk_load_raw(char* name, u32* len); GritImage dusk_load_image(char* name); SpriteAtlas dusk_load_atlas(char* name); SpriteAtlasLayout dusk_load_atlas_layout(const char* name); @@ -55,46 +61,38 @@ void dusk_free_atlas_layout(SpriteAtlasLayout* layout); Map dusk_load_map(char* name); -#include -#include -#include -#include -#include "ds_load.h" -#include -#include - -const GBFS_FILE* gbfs_dat; +GBFS_FILE* gbfs_dat; void dusk_load_init() { // locate the main GBFS archive gbfs_dat = find_first_gbfs_file(find_first_gbfs_file); } -const void* dusk_load_raw(char* name, u32* len) { +void* dusk_load_raw(char* name, u32* len) { return gbfs_get_obj(gbfs_dat, name, len); } GritImage dusk_load_image(char* name) { GritImage img; - char tiles_name[GBFS_ENTRY_SIZE]; + char[GBFS_ENTRY_SIZE] tiles_name; strcpy(tiles_name, name); strcat(tiles_name, ".img.bin"); - char pal_name[GBFS_ENTRY_SIZE]; + char[GBFS_ENTRY_SIZE] pal_name; strcpy(pal_name, name); strcat(pal_name, ".pal.bin"); - char map_name[GBFS_ENTRY_SIZE]; + char[GBFS_ENTRY_SIZE] map_name; strcpy(map_name, name); strcat(map_name, ".map.bin"); - img.tiles = (u32*)gbfs_get_obj(gbfs_dat, tiles_name, &img.tile_sz); - img.pal = (u32*)gbfs_get_obj(gbfs_dat, pal_name, &img.pal_sz); - img.map = (u32*)gbfs_get_obj(gbfs_dat, map_name, &img.map_sz); + img.tiles = cast(u32*)gbfs_get_obj(gbfs_dat, tiles_name, &img.tile_sz); + img.pal = cast(u32*)gbfs_get_obj(gbfs_dat, pal_name, &img.pal_sz); + img.map = cast(u32*)gbfs_get_obj(gbfs_dat, map_name, &img.map_sz); return img; } SpriteAtlas dusk_load_atlas(char* name) { - char atlas_name[GBFS_ENTRY_SIZE]; + char[GBFS_ENTRY_SIZE] atlas_name; strcpy(atlas_name, name); strcat(atlas_name, "_0"); @@ -112,7 +110,7 @@ SpriteAtlas dusk_load_atlas(char* name) { // NOTE: ASSERT pal_sz >= 2 - u16* pal_raw = (u16*)atlas.pal; // 16-bit color + u16* pal_raw = cast(u16*)atlas.pal; // 16-bit color const int palscan_start = 0; const int palscan_inarow = 6; // how many in a row we're looking for @@ -156,7 +154,7 @@ void seek_until_null(const u8* data, int* pos) { SpriteAtlasLayout dusk_load_atlas_layout(const char* name) { SpriteAtlasLayout layout; - char file_name[GBFS_ENTRY_SIZE]; + char[GBFS_ENTRY_SIZE] file_name; strcpy(file_name, name); strcat(file_name, "_.sht.bin"); @@ -215,9 +213,9 @@ SpriteAtlasLayout dusk_load_atlas_layout(const char* name) { } SpriteAtlasEntry* dusk_load_atlas_entry(SpriteAtlasLayout* layout, const char* entry_name) { - for (int i = 0; i < layout->num_entries; i++) { - SpriteAtlasEntry* entry = &layout->entries[i]; - if (strncmp(entry_name, entry->name, ATLAS_ENTRY_LEN) == 0) { + for (int i = 0; i < layout.num_entries; i++) { + SpriteAtlasEntry* entry = &layout.entries[i]; + if (strncmp(entry_name, entry.name, ATLAS_ENTRY_LEN) == 0) { return entry; } } @@ -225,13 +223,13 @@ SpriteAtlasEntry* dusk_load_atlas_entry(SpriteAtlasLayout* layout, const char* e } void dusk_free_atlas_layout(SpriteAtlasLayout* layout) { - layout->num_entries = 0; - free(layout->entries); - layout->entries = NULL; + layout.num_entries = 0; + free(layout.entries); + layout.entries = NULL; } Map dusk_load_map(char* name) { - char ass_name[GBFS_ENTRY_SIZE]; + char[GBFS_ENTRY_SIZE] ass_name; strcpy(ass_name, name); strcat(ass_name, ".bin"); diff --git a/src/dusk/d_src/dusk/package.d b/src/dusk/d_src/dusk/package.d index c1fa0b1..fd8b57e 100644 --- a/src/dusk/d_src/dusk/package.d +++ b/src/dusk/d_src/dusk/package.d @@ -3,6 +3,6 @@ module dusk; public { import dusk.load; import dusk.sys; - import dusk.spr; - import dusk.sav; + import dusk.sprites; + import dusk.save; } \ No newline at end of file diff --git a/src/dusk/d_src/dusk/save.d b/src/dusk/d_src/dusk/save.d index 25a5d54..b0d9cb6 100644 --- a/src/dusk/d_src/dusk/save.d +++ b/src/dusk/d_src/dusk/save.d @@ -2,12 +2,12 @@ module lib.dusk.src.dusk.d_src.dusk.save; // utilities for saving and loading vars -#define SV_LOAD_ITEM(var, offset) \ - memcpy(&var, sram_mem + offset, sizeof(typeof(var))); \ - offset += sizeof(typeof(var)); +// #define SV_LOAD_ITEM(var, offset) \ +// memcpy(&var, sram_mem + offset, sizeof(typeof(var))); \ +// offset += sizeof(typeof(var)); -#define SV_SAVE_ITEM(var, offset) \ - memcpy(sram_mem + offset, &var, sizeof(typeof(var))); \ - offset += sizeof(typeof(var)); +// #define SV_SAVE_ITEM(var, offset) \ +// memcpy(sram_mem + offset, &var, sizeof(typeof(var))); \ +// offset += sizeof(typeof(var)); // utilities for saving and loading vars \ No newline at end of file diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index 093d4b9..940a2dd 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -1,17 +1,22 @@ module dusk.sprites; -#define NUM_SPRITES 128 -#define NUM_AFFINE_SPRITES 32 -extern OBJ_ATTR obj_buffer[NUM_SPRITES]; -extern OBJ_AFFINE* obj_aff_buffer; +import dusk.sprites; +import dusk.sys; +import dusk.load; +import tonc; +import ldc.attributes; -#define SPRITEFLAG_PRIORITY_SHIFT 6 -#define SPRITEFLAG_PRIORITY_GET(n) ((n >> SPRITEFLAG_PRIORITY_SHIFT) & 0b11) -#define SPRITEFLAG_PRIORITY(n) ((n << SPRITEFLAG_PRIORITY_SHIFT) & 0b11) +enum NUM_SPRITES = 128; +enum NUM_AFFINE_SPRITES = 32; + +enum SPRITEFLAG_PRIORITY_SHIFT = 6; +// #define SPRITEFLAG_PRIORITY_GET(n) ((n >> SPRITEFLAG_PRIORITY_SHIFT) & 0b11) +// #define SPRITEFLAG_PRIORITY(n) ((n << SPRITEFLAG_PRIORITY_SHIFT) & 0b11) + +enum DUSKSPRITE_FLAGS_VISIBLE = (0x1 << 0); -#define DUSKSPRITE_FLAGS_VISIBLE (0x1 << 0) /** sprite data */ -typedef struct Sprite { +struct Sprite { s16 x, y; /** the number of tiles taken up by this sprite */ u8 tile_sz; @@ -21,37 +26,40 @@ typedef struct Sprite { u8 page; /** flags: 0/0/0/0/0/0/0/visible */ u8 flags; -} Sprite; +} /** animation metadata */ -typedef struct Anim { +struct Anim { /** which page in the sprite the animation starts */ u8 start; /** number of pages in this animation */ u8 len; /** (60/fps), or how many frames each page lasts */ u8 rate; -} Anim; +} /** background data */ -typedef struct Background { +struct Background { s16 x, y; int cbb, sbb; -} Background; +} /** define an animation, given a starting frame and frame count, and fps */ -#define MAKE_ANIM_EX(st, le, fps) \ - (Anim) { .start = st, .len = le, .rate = (60 / fps) } +// #define MAKE_ANIM_EX(st, le, fps) \ +// (Anim) { .start = st, .len = le, .rate = (60 / fps) } +Anim make_anim_ex(u8 start, u8 len, u8 fps) { + return Anim(start, len, 60 / fps); +} /** define an animation, given a starting frame and frame count, at 10 fps */ -#define MAKE_ANIM(st, le) MAKE_ANIM_EX(st, le, 10) - -/** memory block used to track sprites */ -extern Sprite sprites[NUM_SPRITES]; +// #define MAKE_ANIM(st, le) MAKE_ANIM_EX(st, le, 10) +Anim make_anim(u8 start, u8 len) { + return make_anim_ex(start, len, 10); +} /** initialize sprite and OAM memory */ void dusk_sprites_init(); /** set mode options for dusk sprites */ -void dusk_sprites_configure(BOOL bpp8); +void dusk_sprites_configure(bool bpp8); /** upload a sprite atlas to tile and palette memory */ void dusk_sprites_upload_atlas(SpriteAtlas* atlas); /** upload a sprite atlas section to tile and palette memory */ @@ -71,18 +79,15 @@ void dusk_background_upload_raw(GritImage* img, int cbb, int sbb); /** create a background and display it */ void dusk_background_make(u8 bg_id, u16 size, Background bg); -#include "ds_spr.h" -#include "ds_sys.h" -#include -#include "stdio.h" +mixin(EWRAM_DATA!("OBJ_ATTR[NUM_SPRITES]", "obj_buffer")); +// OBJ_AFFINE* obj_aff_buffer = cast(OBJ_AFFINE*) obj_buffer; +OBJ_AFFINE* obj_aff_buffer() { return cast(OBJ_AFFINE*) obj_buffer; } -EWRAM_DATA OBJ_ATTR obj_buffer[NUM_SPRITES]; -OBJ_AFFINE* obj_aff_buffer = (OBJ_AFFINE*)obj_buffer; - -EWRAM_DATA Sprite sprites[NUM_SPRITES]; +/** memory block used to track sprites */ +mixin(EWRAM_DATA!("Sprite[NUM_SPRITES]", "sprites")); /** when true, 8BPP, when false, 4BPP */ -BOOL sprites_bpp8 = TRUE; +bool sprites_bpp8 = true; void dusk_sprites_init() { // initialize object buffer @@ -90,49 +95,49 @@ void dusk_sprites_init() { memset(sprites, 0, sizeof(Sprite) * NUM_SPRITES); // reset bpp to default - sprites_bpp8 = TRUE; + sprites_bpp8 = true; // enable sprite display REG_DISPCNT |= DCNT_OBJ | DCNT_OBJ_1D; } -void dusk_sprites_configure(BOOL bpp8) { sprites_bpp8 = bpp8; } +void dusk_sprites_configure(bool bpp8) { sprites_bpp8 = bpp8; } void dusk_sprites_upload_atlas(SpriteAtlas* atlas) { // 1. upload the atlas tile palette to palette memory // object/sprite palette, in 8bpp stores 256 colors - memcpy(&pal_obj_bank[0], atlas->pal, atlas->pal_sz); + memcpy(&pal_obj_bank[0], atlas.pal, atlas.pal_sz); // 2. upload the atlas tiles to tile memory // tile memory (can store 1024 tiles (32x32 tiles or 256x256px) // VRAM is charblocks 4 and 5, so &tile_mem[4][0] points to the first tile in object VRAM - memcpy(&tile_mem[4][0], atlas->tiles, atlas->tile_sz); + memcpy(&tile_mem[4][0], atlas.tiles, atlas.tile_sz); } void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* atlas, SpriteAtlasEntry* entry, u16 pal_offset, u16 tile_offset) { // 1. upload the palette (palettes are 16-bit highcolor) - memcpy(&pal_obj_bank[0][pal_offset], &atlas->pal[0], atlas->pal_sz); + memcpy(&pal_obj_bank[0][pal_offset], &atlas.pal[0], atlas.pal_sz); // pal_obj_bank[0][4] = CLR_YELLOW; // 2. upload the tiles int entry_firsttid = - dusk_sprites_pos_to_tid(entry->x, entry->y, layout->width, layout->height); // tid of entry start in atlas - int entry_tilecount = (entry->w) * (entry->h); // entry size in tiles + dusk_sprites_pos_to_tid(entry.x, entry.y, layout.width, layout.height); // tid of entry start in atlas + int entry_tilecount = (entry.w) * (entry.h); // entry size in tiles int raw_firsttid = entry_firsttid * entry_tilecount * 2; // read offset // int raw_tilecount = entry_tilecount * 2; int raw_tileoffset = tile_offset * 2; // write offset // printf("ro: %d. wo: %d, n: %d\n", raw_firsttid, raw_tileoffset, raw_tilecount); // debug print tile r/w - // memcpy(&tile_mem[4][raw_tileoffset], &atlas->tiles[raw_firsttid], entry_tilecount * 64); + // memcpy(&tile_mem[4][raw_tileoffset], &atlas.tiles[raw_firsttid], entry_tilecount * 64); // 3. fix tiles to point at right palette // for (int i = 0; i < raw_tilecount; i += 2) { // TILE8 new_tile; // // TILE8 tile.data consists of 16 u32s (a total of 64 bytes) - // // new_tile.data[j] = atlas->tiles[(entry_firsttid + i) * 2]; - // u32* rt = &atlas->tiles[raw_firsttid + i]; // read tile + // // new_tile.data[j] = atlas.tiles[(entry_firsttid + i) * 2]; + // u32* rt = &atlas.tiles[raw_firsttid + i]; // read tile // for (int j = 0; j < 16; j++) { // new_tile.data[j] = rt[j]; @@ -143,14 +148,14 @@ void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* a // } // unroll malloc - // memcpy(&tile_mem[4][raw_tileoffset], &atlas->tiles[raw_firsttid], 64); + // memcpy(&tile_mem[4][raw_tileoffset], &atlas.tiles[raw_firsttid], 64); // reinterpret as byte pointers - u8* loc_twrite = (u8*)&tile_mem[4][raw_tileoffset]; - u8* loc_tread = (u8*)&atlas->tiles[raw_firsttid]; + u8* loc_twrite = cast(u8*)&tile_mem[4][raw_tileoffset]; + u8* loc_tread = cast(u8*)&atlas.tiles[raw_firsttid]; for (int i = 0; i < entry_tilecount; i += 1) { int c = i * 64; - u8 tile[64]; // create temp tile + u8[64] tile; // create temp tile memcpy(&tile[0], loc_tread + c, 64); // read tile // fix tile @@ -225,14 +230,14 @@ Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr) { return &sprites[index]; } -inline void dusk_sprites_sync(int i) { +pragma(inline) void dusk_sprites_sync(int i) { Sprite* sprite = &sprites[i]; OBJ_ATTR* obj = &obj_buffer[i]; // position - obj_set_pos(obj, sprite->x, sprite->y); + obj_set_pos(obj, sprite.x, sprite.y); // visibility - if ((sprite->flags & DUSKSPRITE_FLAGS_VISIBLE) > 0) { + if ((sprite.flags & DUSKSPRITE_FLAGS_VISIBLE) > 0) { obj_unhide(obj, ATTR0_REG); } else { obj_hide(obj); @@ -241,12 +246,12 @@ inline void dusk_sprites_sync(int i) { // main attrs // logical base tid mode - // obj_set_attr(obj, obj->attr0, obj->attr1, (sprite->tid + sprite->page) * sprite->tile_sz * 2); + // obj_set_attr(obj, obj.attr0, obj.attr1, (sprite.tid + sprite.page) * sprite.tile_sz * 2); // raw base tid mode int bpp_mult = (sprites_bpp8 == 1) ? 2 : 1; - u16 tid = (sprite->base_tid + (sprite->page * sprite->tile_sz)) * bpp_mult; - obj_set_attr(obj, obj->attr0, obj->attr1, ATTR2_ID(tid) | ATTR2_PALBANK(0)); + u16 tid = (sprite.base_tid + (sprite.page * sprite.tile_sz)) * bpp_mult; + obj_set_attr(obj, obj.attr0, obj.attr1, ATTR2_ID(tid) | ATTR2_PALBANK(0)); } void dusk_sprites_update() { @@ -263,15 +268,15 @@ void dusk_sprites_update() { void dusk_sprites_anim_play(Sprite* spr, Anim* anim) { // make sure page is within anim range - if (spr->page < anim->start || spr->page >= (anim->start + anim->len)) { - spr->page = anim->start; // reset to first + if (spr.page < anim.start || spr.page >= (anim.start + anim.len)) { + spr.page = anim.start; // reset to first } - int ix = spr->page - anim->start; - if (frame_count % anim->rate == 0) { - ix = (ix + 1) % anim->len; + int ix = spr.page - anim.start; + if (frame_count % anim.rate == 0) { + ix = (ix + 1) % anim.len; } // set new frame - spr->page = anim->start + ix; + spr.page = anim.start + ix; } u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height) { @@ -324,11 +329,11 @@ void dusk_background_upload_raw(GritImage* img, int cbb, int sbb) { // TODO: support selecting slot // 1. upload the atlas tile palette to bg palette memory - memcpy(&pal_bg_bank[0], img->pal, img->pal_sz); + memcpy(&pal_bg_bank[0], img.pal, img.pal_sz); // 2. upload the atlas tiles to bg tile memory (CBB) - memcpy(&tile_mem[cbb][0], img->tiles, img->tile_sz); + memcpy(&tile_mem[cbb][0], img.tiles, img.tile_sz); // 3. upload the map (SBB) - memcpy(&se_mem[sbb][0], img->map, img->map_sz); + memcpy(&se_mem[sbb][0], img.map, img.map_sz); } void dusk_background_make(u8 bg_id, u16 size, Background bg) { diff --git a/src/dusk/d_src/dusk/sys.d b/src/dusk/d_src/dusk/sys.d index 7baf6d5..f946cb6 100644 --- a/src/dusk/d_src/dusk/sys.d +++ b/src/dusk/d_src/dusk/sys.d @@ -1,12 +1,14 @@ module dusk.sys; -extern uint frame_count; - -typedef struct Scene { - void (*start)(void); - void (*end)(void); - void (*update)(void); -} Scene; +import core.stdc.stdio; +import tonc; +import dusk.load; + +struct Scene { + void function() start; + void function() end; + void function() update; +} /** initialize the system for using DUSK */ void dusk_init_all(); @@ -19,12 +21,8 @@ void dusk_frame(); void dusk_scene_set(Scene next); void dusk_scene_update(); -#include "stdio.h" -#include -#include "ds_sys.h" -#include "ds_load.h" - -__attribute__((used)) const char* _DUSK_LIB_VERSION = ("$DUSK " DUSK_VERSION); +// __attribute__((used)) const char* _DUSK_LIB_VERSION = ("$DUSK " DUSK_VERSION); +// const char* _DUSK_LIB_VERSION = ("$DUSK " ~ DUSK_VERSION); uint frame_count; @@ -72,17 +70,10 @@ void dusk_frame() { } static bool scene_changed = false; -static void nothing(void) {} -static Scene next_scene = { - .start = nothing, - .end = nothing, - .update = nothing, -}; -static Scene current_scene = { - .start = nothing, - .end = nothing, - .update = nothing, -}; +static void nothing() {} + +static Scene next_scene = Scene(¬hing, ¬hing, ¬hing); +static Scene current_scene = Scene(¬hing, ¬hing, ¬hing); void dusk_scene_set(Scene next) { scene_changed = true; From 9be72b57c23a2eee4ce0c80f929684e852c0fc9b Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 16 Nov 2021 02:03:46 -0800 Subject: [PATCH 04/32] more bad stubs --- src/dusk/d_src/dusk/load.d | 72 ++++++++++++++-------------- src/dusk/d_src/dusk/sprites.d | 88 +++++++++++++++++++---------------- src/dusk/d_src/dusk/sys.d | 26 ++++++----- 3 files changed, 100 insertions(+), 86 deletions(-) diff --git a/src/dusk/d_src/dusk/load.d b/src/dusk/d_src/dusk/load.d index 8b7634a..3f3c8a2 100644 --- a/src/dusk/d_src/dusk/load.d +++ b/src/dusk/d_src/dusk/load.d @@ -1,5 +1,7 @@ module dusk.load; +extern(C): + import core.stdc.stdio; import core.stdc.stdlib; import core.stdc.stddef; @@ -52,51 +54,51 @@ void dusk_load_init(); // - CONTENT LOADERS: pass filename without extension -void* dusk_load_raw(char* name, u32* len); -GritImage dusk_load_image(char* name); -SpriteAtlas dusk_load_atlas(char* name); -SpriteAtlasLayout dusk_load_atlas_layout(const char* name); -SpriteAtlasEntry* dusk_load_atlas_entry(SpriteAtlasLayout* layout, const char* entry_name); -void dusk_free_atlas_layout(SpriteAtlasLayout* layout); +// void* dusk_load_raw(char* name, u32* len); +// GritImage dusk_load_image(char* name); +// SpriteAtlas dusk_load_atlas(char* name); +// SpriteAtlasLayout dusk_load_atlas_layout(const char* name); +// SpriteAtlasEntry* dusk_load_atlas_entry(SpriteAtlasLayout* layout, const char* entry_name); +// void dusk_free_atlas_layout(SpriteAtlasLayout* layout); -Map dusk_load_map(char* name); +// Map dusk_load_map(char* name); GBFS_FILE* gbfs_dat; void dusk_load_init() { // locate the main GBFS archive - gbfs_dat = find_first_gbfs_file(find_first_gbfs_file); + gbfs_dat = cast(GBFS_FILE*) find_first_gbfs_file(&find_first_gbfs_file); } void* dusk_load_raw(char* name, u32* len) { - return gbfs_get_obj(gbfs_dat, name, len); + return cast(void*) gbfs_get_obj(gbfs_dat, name, len); } GritImage dusk_load_image(char* name) { GritImage img; char[GBFS_ENTRY_SIZE] tiles_name; - strcpy(tiles_name, name); - strcat(tiles_name, ".img.bin"); + strcpy(cast(char*)tiles_name, name); + strcat(cast(char*)tiles_name, cast(char*)".img.bin"); char[GBFS_ENTRY_SIZE] pal_name; - strcpy(pal_name, name); - strcat(pal_name, ".pal.bin"); + strcpy(cast(char*)pal_name, name); + strcat(cast(char*)pal_name, cast(char*)".pal.bin"); char[GBFS_ENTRY_SIZE] map_name; - strcpy(map_name, name); - strcat(map_name, ".map.bin"); + strcpy(cast(char*)map_name, name); + strcat(cast(char*)map_name, cast(char*)".map.bin"); - img.tiles = cast(u32*)gbfs_get_obj(gbfs_dat, tiles_name, &img.tile_sz); - img.pal = cast(u32*)gbfs_get_obj(gbfs_dat, pal_name, &img.pal_sz); - img.map = cast(u32*)gbfs_get_obj(gbfs_dat, map_name, &img.map_sz); + img.tiles = cast(u32*)gbfs_get_obj(gbfs_dat, cast(char*)tiles_name, &img.tile_sz); + img.pal = cast(u32*)gbfs_get_obj(gbfs_dat, cast(char*)pal_name, &img.pal_sz); + img.map = cast(u32*)gbfs_get_obj(gbfs_dat, cast(char*)map_name, &img.map_sz); return img; } SpriteAtlas dusk_load_atlas(char* name) { char[GBFS_ENTRY_SIZE] atlas_name; - strcpy(atlas_name, name); - strcat(atlas_name, "_0"); + strcpy(cast(char*)atlas_name, name); + strcat(cast(char*)atlas_name, cast(char*)"_0"); - GritImage img = dusk_load_image(atlas_name); + GritImage img = dusk_load_image(cast(char*)atlas_name); SpriteAtlas atlas; atlas.tiles = img.tiles; @@ -155,11 +157,11 @@ void seek_until_null(const u8* data, int* pos) { SpriteAtlasLayout dusk_load_atlas_layout(const char* name) { SpriteAtlasLayout layout; char[GBFS_ENTRY_SIZE] file_name; - strcpy(file_name, name); - strcat(file_name, "_.sht.bin"); + strcpy(cast(char*)file_name, name); + strcat(cast(char*)file_name, cast(char*)"_.sht.bin"); u32 data_sz = 0; - const u8* data = gbfs_get_obj(gbfs_dat, file_name, &data_sz); + const u8* data = cast(u8*) gbfs_get_obj(gbfs_dat, cast(char*)file_name, &data_sz); int pos = 0; @@ -177,7 +179,7 @@ SpriteAtlasLayout dusk_load_atlas_layout(const char* name) { pos += 2; layout.num_entries = data[pos] | (data[pos + 1] << 8); - layout.entries = malloc(sizeof(SpriteAtlasEntry) * layout.num_entries); + layout.entries = cast(SpriteAtlasEntry*) malloc((SpriteAtlasEntry.sizeof) * layout.num_entries); pos += 2; // now read blocks @@ -203,10 +205,10 @@ SpriteAtlasLayout dusk_load_atlas_layout(const char* name) { pos += 2; // x,y,w,h are 8-bit so don't overflow! // these are in tile units (the final div by 8) - layout.entries[i].x = x / 8; - layout.entries[i].y = y / 8; - layout.entries[i].w = w / 8; - layout.entries[i].h = h / 8; + layout.entries[i].x = cast(u8) x / 8; + layout.entries[i].y = cast(u8) y / 8; + layout.entries[i].w = cast(u8) w / 8; + layout.entries[i].h = cast(u8) h / 8; } return layout; @@ -215,25 +217,25 @@ SpriteAtlasLayout dusk_load_atlas_layout(const char* name) { SpriteAtlasEntry* dusk_load_atlas_entry(SpriteAtlasLayout* layout, const char* entry_name) { for (int i = 0; i < layout.num_entries; i++) { SpriteAtlasEntry* entry = &layout.entries[i]; - if (strncmp(entry_name, entry.name, ATLAS_ENTRY_LEN) == 0) { + if (strncmp(cast(char*)entry_name, cast(char*)entry.name, ATLAS_ENTRY_LEN) == 0) { return entry; } } - return NULL; + return null; } void dusk_free_atlas_layout(SpriteAtlasLayout* layout) { layout.num_entries = 0; free(layout.entries); - layout.entries = NULL; + layout.entries = null; } Map dusk_load_map(char* name) { char[GBFS_ENTRY_SIZE] ass_name; - strcpy(ass_name, name); - strcat(ass_name, ".bin"); + strcpy(cast(char*)ass_name, name); + strcat(cast(char*)ass_name, cast(char*)".bin"); u32 map_data_sz = 0; - const u16* map_data = gbfs_get_obj(gbfs_dat, ass_name, &map_data_sz); + const u16* map_data = cast(u16*) gbfs_get_obj(gbfs_dat, cast(char*)ass_name, &map_data_sz); return map_load_from_rom(map_data); } diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index 940a2dd..8bbd07b 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -1,10 +1,15 @@ module dusk.sprites; +extern(C): + import dusk.sprites; import dusk.sys; import dusk.load; import tonc; import ldc.attributes; +import core.stdc.stdlib; +import core.stdc.stdio; +import core.stdc.string; enum NUM_SPRITES = 128; enum NUM_AFFINE_SPRITES = 32; @@ -56,43 +61,47 @@ Anim make_anim(u8 start, u8 len) { return make_anim_ex(start, len, 10); } -/** initialize sprite and OAM memory */ -void dusk_sprites_init(); -/** set mode options for dusk sprites */ -void dusk_sprites_configure(bool bpp8); -/** upload a sprite atlas to tile and palette memory */ -void dusk_sprites_upload_atlas(SpriteAtlas* atlas); -/** upload a sprite atlas section to tile and palette memory */ -void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* atlas, SpriteAtlasEntry* entry, u16 pal_offset, u16 tile_offset); -/** create a sprite and store it in index of sprite memory */ -Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr); -/** synchronize a sprite from the sprites array to OAM block (vram) */ -void dusk_sprites_sync(int index); -/** synchronize all sprites to OAM block, then upload OAM block to vram */ -void dusk_sprites_update(); -/** play an animation on a sprite */ -void dusk_sprites_anim_play(Sprite* spr, Anim* anim); -/** calculate the tid of a sprite given pos and sheet dimens */ -u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height); -/** upload image data to background tile vram */ -void dusk_background_upload_raw(GritImage* img, int cbb, int sbb); -/** create a background and display it */ -void dusk_background_make(u8 bg_id, u16 size, Background bg); - -mixin(EWRAM_DATA!("OBJ_ATTR[NUM_SPRITES]", "obj_buffer")); +// /** initialize sprite and OAM memory */ +// void dusk_sprites_init(); +// /** set mode options for dusk sprites */ +// void dusk_sprites_configure(bool bpp8); +// /** upload a sprite atlas to tile and palette memory */ +// void dusk_sprites_upload_atlas(SpriteAtlas* atlas); +// /** upload a sprite atlas section to tile and palette memory */ +// void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* atlas, SpriteAtlasEntry* entry, u16 pal_offset, u16 tile_offset); +// /** create a sprite and store it in index of sprite memory */ +// Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr); +// /** synchronize a sprite from the sprites array to OAM block (vram) */ +// void dusk_sprites_sync(int index); +// /** synchronize all sprites to OAM block, then upload OAM block to vram */ +// void dusk_sprites_update(); +// /** play an animation on a sprite */ +// void dusk_sprites_anim_play(Sprite* spr, Anim* anim); +// /** calculate the tid of a sprite given pos and sheet dimens */ +// u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height); +// /** upload image data to background tile vram */ +// void dusk_background_upload_raw(GritImage* img, int cbb, int sbb); +// /** create a background and display it */ +// void dusk_background_make(u8 bg_id, u16 size, Background bg); + +// mixin(EWRAM_DATA!("OBJ_ATTR[NUM_SPRITES]", "obj_buffer")); +// @(ldc.attributes.section(".ewram")) __gshared OBJ_ATTR[NUM_SPRITES] obj_buffer; +static OBJ_ATTR[NUM_SPRITES] obj_buffer; // OBJ_AFFINE* obj_aff_buffer = cast(OBJ_AFFINE*) obj_buffer; OBJ_AFFINE* obj_aff_buffer() { return cast(OBJ_AFFINE*) obj_buffer; } /** memory block used to track sprites */ -mixin(EWRAM_DATA!("Sprite[NUM_SPRITES]", "sprites")); +// mixin(EWRAM_DATA!("Sprite[NUM_SPRITES]", "sprites")); +// @(ldc.attributes.section(".ewram")) __gshared Sprite[NUM_SPRITES] sprites; +static Sprite[NUM_SPRITES] sprites; /** when true, 8BPP, when false, 4BPP */ bool sprites_bpp8 = true; void dusk_sprites_init() { // initialize object buffer - oam_init(obj_buffer, NUM_SPRITES); - memset(sprites, 0, sizeof(Sprite) * NUM_SPRITES); + oam_init(cast(OBJ_ATTR*) obj_buffer, NUM_SPRITES); + memset(cast(void*)sprites, 0, (Sprite.sizeof) * NUM_SPRITES); // reset bpp to default sprites_bpp8 = true; @@ -160,7 +169,7 @@ void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* a // fix tile for (int j = 0; j < 64; j++) { - tile[j] = tile[j] + pal_offset; + tile[j] = cast(ubyte) (tile[j] + pal_offset); } memcpy(loc_twrite + c, &tile[0], 64); // write tile @@ -210,7 +219,7 @@ Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr) { } // calculate the number of tiles used by one frame of this sprite (divide width and height by 8) - spr.tile_sz = (width >> 3) * (height >> 3); + spr.tile_sz = cast(ubyte) ((width >> 3) * (height >> 3)); // set main attributes // leave tile id (attr2) null, it will be set in sync @@ -250,8 +259,8 @@ pragma(inline) void dusk_sprites_sync(int i) { // raw base tid mode int bpp_mult = (sprites_bpp8 == 1) ? 2 : 1; - u16 tid = (sprite.base_tid + (sprite.page * sprite.tile_sz)) * bpp_mult; - obj_set_attr(obj, obj.attr0, obj.attr1, ATTR2_ID(tid) | ATTR2_PALBANK(0)); + u16 tid = cast(u16) ((sprite.base_tid + (sprite.page * sprite.tile_sz)) * bpp_mult); + obj_set_attr(obj, obj.attr0, obj.attr1, cast(u16)(ATTR2_ID!u16(tid) | ATTR2_PALBANK!u16(0))); } void dusk_sprites_update() { @@ -262,7 +271,7 @@ void dusk_sprites_update() { // upload shadow oam to vram - oam_copy(oam_mem, obj_buffer, NUM_SPRITES); + oam_copy(oam_mem, cast(OBJ_ATTR*) obj_buffer, NUM_SPRITES); // CpuFastSet(obj_buffer, oam_mem, NUM_SPRITES * 2); } @@ -276,7 +285,7 @@ void dusk_sprites_anim_play(Sprite* spr, Anim* anim) { ix = (ix + 1) % anim.len; } // set new frame - spr.page = anim.start + ix; + spr.page = cast(u8) (anim.start + ix); } u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height) { @@ -286,7 +295,7 @@ u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height) { u16 yt = y; u16 imw = sheet_width >> 3; // compute with bitshift (sheet_width / 8) // u16 imh = sheet_height >> 3; - u16 tid = (yt * imw) + xt; + u16 tid = cast(u16) ((yt * imw) + xt); return tid; } @@ -305,6 +314,7 @@ void enable_bg(u8 bg_id) { case 3: bg_flag = DCNT_BG3; break; + default: assert(0); } REG_DISPCNT |= bg_flag; @@ -313,15 +323,15 @@ void enable_bg(u8 bg_id) { vu16* dusk_get_background_register(u8 bg_id) { switch (bg_id) { case 0: - return ®_BG0CNT; + return &(REG_BG0CNT()); case 1: - return ®_BG1CNT; + return &(REG_BG1CNT()); case 2: - return ®_BG2CNT; + return &(REG_BG2CNT()); case 3: - return ®_BG3CNT; + return &(REG_BG3CNT()); default: - return NULL; + return null; } } diff --git a/src/dusk/d_src/dusk/sys.d b/src/dusk/d_src/dusk/sys.d index f946cb6..c2560ae 100644 --- a/src/dusk/d_src/dusk/sys.d +++ b/src/dusk/d_src/dusk/sys.d @@ -1,5 +1,7 @@ module dusk.sys; +extern(C): + import core.stdc.stdio; import tonc; import dusk.load; @@ -10,16 +12,16 @@ struct Scene { void function() update; } -/** initialize the system for using DUSK */ -void dusk_init_all(); -/** initialize mode0 graphics */ -void dusk_init_graphics_mode0(); -/** initialize mode3 graphics */ -void dusk_init_graphics_mode3(); -/** vsync */ -void dusk_frame(); -void dusk_scene_set(Scene next); -void dusk_scene_update(); +// /** initialize the system for using DUSK */ +// void dusk_init_all(); +// /** initialize mode0 graphics */ +// void dusk_init_graphics_mode0(); +// /** initialize mode3 graphics */ +// void dusk_init_graphics_mode3(); +// /** vsync */ +// void dusk_frame(); +// void dusk_scene_set(Scene next); +// void dusk_scene_update(); // __attribute__((used)) const char* _DUSK_LIB_VERSION = ("$DUSK " DUSK_VERSION); // const char* _DUSK_LIB_VERSION = ("$DUSK " ~ DUSK_VERSION); @@ -35,8 +37,8 @@ void dusk_clear_vidmem() { } void dusk_reset_irq() { - irq_init(NULL); - irq_add(II_VBLANK, NULL); + irq_init(null); + irq_add(eIrqIndex.II_VBLANK, null); } void dusk_init_all() { From 3b0a70a9b2098c403868ceaf1732673bf2216899 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 16 Nov 2021 15:07:55 -0800 Subject: [PATCH 05/32] add gshared --- src/dusk/d_src/dusk/load.d | 2 +- src/dusk/d_src/dusk/sprites.d | 12 ++++++------ src/dusk/d_src/dusk/sys.d | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/dusk/d_src/dusk/load.d b/src/dusk/d_src/dusk/load.d index 3f3c8a2..315d056 100644 --- a/src/dusk/d_src/dusk/load.d +++ b/src/dusk/d_src/dusk/load.d @@ -63,7 +63,7 @@ void dusk_load_init(); // Map dusk_load_map(char* name); -GBFS_FILE* gbfs_dat; +__gshared static GBFS_FILE* gbfs_dat; void dusk_load_init() { // locate the main GBFS archive diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index 8bbd07b..b062285 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -85,18 +85,18 @@ Anim make_anim(u8 start, u8 len) { // void dusk_background_make(u8 bg_id, u16 size, Background bg); // mixin(EWRAM_DATA!("OBJ_ATTR[NUM_SPRITES]", "obj_buffer")); -// @(ldc.attributes.section(".ewram")) __gshared OBJ_ATTR[NUM_SPRITES] obj_buffer; -static OBJ_ATTR[NUM_SPRITES] obj_buffer; +// static OBJ_ATTR[NUM_SPRITES] obj_buffer; +@(ldc.attributes.section(".ewram")) __gshared OBJ_ATTR[NUM_SPRITES] obj_buffer; // OBJ_AFFINE* obj_aff_buffer = cast(OBJ_AFFINE*) obj_buffer; -OBJ_AFFINE* obj_aff_buffer() { return cast(OBJ_AFFINE*) obj_buffer; } +__gshared OBJ_AFFINE* obj_aff_buffer() { return cast(OBJ_AFFINE*) obj_buffer; } /** memory block used to track sprites */ // mixin(EWRAM_DATA!("Sprite[NUM_SPRITES]", "sprites")); -// @(ldc.attributes.section(".ewram")) __gshared Sprite[NUM_SPRITES] sprites; -static Sprite[NUM_SPRITES] sprites; +// static Sprite[NUM_SPRITES] sprites; +@(ldc.attributes.section(".ewram")) __gshared Sprite[NUM_SPRITES] sprites; /** when true, 8BPP, when false, 4BPP */ -bool sprites_bpp8 = true; +__gshared bool sprites_bpp8 = true; void dusk_sprites_init() { // initialize object buffer diff --git a/src/dusk/d_src/dusk/sys.d b/src/dusk/d_src/dusk/sys.d index c2560ae..acf5fb6 100644 --- a/src/dusk/d_src/dusk/sys.d +++ b/src/dusk/d_src/dusk/sys.d @@ -26,7 +26,7 @@ struct Scene { // __attribute__((used)) const char* _DUSK_LIB_VERSION = ("$DUSK " DUSK_VERSION); // const char* _DUSK_LIB_VERSION = ("$DUSK " ~ DUSK_VERSION); -uint frame_count; +__gshared static uint frame_count; void dusk_clear_vidmem() { // clear video memory (vram region) @@ -71,11 +71,11 @@ void dusk_frame() { frame_count++; } -static bool scene_changed = false; -static void nothing() {} +__gshared static bool scene_changed = false; +__gshared static void nothing() {} -static Scene next_scene = Scene(¬hing, ¬hing, ¬hing); -static Scene current_scene = Scene(¬hing, ¬hing, ¬hing); +__gshared static Scene next_scene = Scene(¬hing, ¬hing, ¬hing); +__gshared static Scene current_scene = Scene(¬hing, ¬hing, ¬hing); void dusk_scene_set(Scene next) { scene_changed = true; From 86ff4c8bafadca088c41ae6cbacb7f7666320be5 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 16 Nov 2021 20:38:27 -0800 Subject: [PATCH 06/32] port everything to use proper mixed D and C --- src/dusk/Makefile | 2 +- src/dusk/{src => c_src}/contrib/background.h | 0 src/dusk/{src => c_src}/contrib/bitField.h | 0 .../{src => c_src}/contrib/initMapRegisters.c | 0 src/dusk/{src => c_src}/contrib/libgbfs.c | 0 .../{src => c_src}/contrib/loadMapFromROM.c | 0 src/dusk/{src => c_src}/contrib/loadObject.c | 0 .../{src => c_src}/contrib/loadObjectID.c | 0 .../{src => c_src}/contrib/loadPosition.c | 0 src/dusk/{src => c_src}/contrib/loadString.c | 0 src/dusk/{src => c_src}/contrib/memoryMap.h | 0 src/dusk/{src => c_src}/contrib/mgba.c | 0 src/dusk/{src => c_src}/contrib/popValue.c | 0 .../{src => c_src}/contrib/setMapOnScreen.c | 0 src/dusk/{src => c_src}/contrib/shiftMap.c | 0 .../{src => c_src}/contrib/shiftMapLayer.c | 0 .../{src => c_src}/contrib/shiftMapObjects.c | 0 src/dusk/{src => c_src}/contrib/types.h | 0 src/dusk/{src => c_src}/contrib/video.h | 0 src/dusk/d_src/dusk/sprites.d | 12 +-- src/dusk/d_src/dusk/sys.d | 12 +-- src/dusk/include/ds_load.h | 63 --------------- src/dusk/include/ds_sav.h | 17 ---- src/dusk/include/ds_spr.h | 80 ------------------- src/dusk/include/ds_sys.h | 24 ------ src/dusk/include/dusk.h | 11 --- 26 files changed, 13 insertions(+), 208 deletions(-) rename src/dusk/{src => c_src}/contrib/background.h (100%) rename src/dusk/{src => c_src}/contrib/bitField.h (100%) rename src/dusk/{src => c_src}/contrib/initMapRegisters.c (100%) rename src/dusk/{src => c_src}/contrib/libgbfs.c (100%) rename src/dusk/{src => c_src}/contrib/loadMapFromROM.c (100%) rename src/dusk/{src => c_src}/contrib/loadObject.c (100%) rename src/dusk/{src => c_src}/contrib/loadObjectID.c (100%) rename src/dusk/{src => c_src}/contrib/loadPosition.c (100%) rename src/dusk/{src => c_src}/contrib/loadString.c (100%) rename src/dusk/{src => c_src}/contrib/memoryMap.h (100%) rename src/dusk/{src => c_src}/contrib/mgba.c (100%) rename src/dusk/{src => c_src}/contrib/popValue.c (100%) rename src/dusk/{src => c_src}/contrib/setMapOnScreen.c (100%) rename src/dusk/{src => c_src}/contrib/shiftMap.c (100%) rename src/dusk/{src => c_src}/contrib/shiftMapLayer.c (100%) rename src/dusk/{src => c_src}/contrib/shiftMapObjects.c (100%) rename src/dusk/{src => c_src}/contrib/types.h (100%) rename src/dusk/{src => c_src}/contrib/video.h (100%) delete mode 100644 src/dusk/include/ds_load.h delete mode 100644 src/dusk/include/ds_sav.h delete mode 100644 src/dusk/include/ds_spr.h delete mode 100644 src/dusk/include/ds_sys.h delete mode 100644 src/dusk/include/dusk.h diff --git a/src/dusk/Makefile b/src/dusk/Makefile index 9053804..37e5150 100644 --- a/src/dusk/Makefile +++ b/src/dusk/Makefile @@ -18,7 +18,7 @@ endif include $(DEVKITARM)/gba_rules BUILD := build -SRCDIRS := src src/contrib +SRCDIRS := c_src c_src/contrib INCDIRS := include include/contrib DEPFLAGS := -I$(DEVKITPRO)/libtonc/include -L$(DEVKITPRO)/libtonc/lib -ltonc diff --git a/src/dusk/src/contrib/background.h b/src/dusk/c_src/contrib/background.h similarity index 100% rename from src/dusk/src/contrib/background.h rename to src/dusk/c_src/contrib/background.h diff --git a/src/dusk/src/contrib/bitField.h b/src/dusk/c_src/contrib/bitField.h similarity index 100% rename from src/dusk/src/contrib/bitField.h rename to src/dusk/c_src/contrib/bitField.h diff --git a/src/dusk/src/contrib/initMapRegisters.c b/src/dusk/c_src/contrib/initMapRegisters.c similarity index 100% rename from src/dusk/src/contrib/initMapRegisters.c rename to src/dusk/c_src/contrib/initMapRegisters.c diff --git a/src/dusk/src/contrib/libgbfs.c b/src/dusk/c_src/contrib/libgbfs.c similarity index 100% rename from src/dusk/src/contrib/libgbfs.c rename to src/dusk/c_src/contrib/libgbfs.c diff --git a/src/dusk/src/contrib/loadMapFromROM.c b/src/dusk/c_src/contrib/loadMapFromROM.c similarity index 100% rename from src/dusk/src/contrib/loadMapFromROM.c rename to src/dusk/c_src/contrib/loadMapFromROM.c diff --git a/src/dusk/src/contrib/loadObject.c b/src/dusk/c_src/contrib/loadObject.c similarity index 100% rename from src/dusk/src/contrib/loadObject.c rename to src/dusk/c_src/contrib/loadObject.c diff --git a/src/dusk/src/contrib/loadObjectID.c b/src/dusk/c_src/contrib/loadObjectID.c similarity index 100% rename from src/dusk/src/contrib/loadObjectID.c rename to src/dusk/c_src/contrib/loadObjectID.c diff --git a/src/dusk/src/contrib/loadPosition.c b/src/dusk/c_src/contrib/loadPosition.c similarity index 100% rename from src/dusk/src/contrib/loadPosition.c rename to src/dusk/c_src/contrib/loadPosition.c diff --git a/src/dusk/src/contrib/loadString.c b/src/dusk/c_src/contrib/loadString.c similarity index 100% rename from src/dusk/src/contrib/loadString.c rename to src/dusk/c_src/contrib/loadString.c diff --git a/src/dusk/src/contrib/memoryMap.h b/src/dusk/c_src/contrib/memoryMap.h similarity index 100% rename from src/dusk/src/contrib/memoryMap.h rename to src/dusk/c_src/contrib/memoryMap.h diff --git a/src/dusk/src/contrib/mgba.c b/src/dusk/c_src/contrib/mgba.c similarity index 100% rename from src/dusk/src/contrib/mgba.c rename to src/dusk/c_src/contrib/mgba.c diff --git a/src/dusk/src/contrib/popValue.c b/src/dusk/c_src/contrib/popValue.c similarity index 100% rename from src/dusk/src/contrib/popValue.c rename to src/dusk/c_src/contrib/popValue.c diff --git a/src/dusk/src/contrib/setMapOnScreen.c b/src/dusk/c_src/contrib/setMapOnScreen.c similarity index 100% rename from src/dusk/src/contrib/setMapOnScreen.c rename to src/dusk/c_src/contrib/setMapOnScreen.c diff --git a/src/dusk/src/contrib/shiftMap.c b/src/dusk/c_src/contrib/shiftMap.c similarity index 100% rename from src/dusk/src/contrib/shiftMap.c rename to src/dusk/c_src/contrib/shiftMap.c diff --git a/src/dusk/src/contrib/shiftMapLayer.c b/src/dusk/c_src/contrib/shiftMapLayer.c similarity index 100% rename from src/dusk/src/contrib/shiftMapLayer.c rename to src/dusk/c_src/contrib/shiftMapLayer.c diff --git a/src/dusk/src/contrib/shiftMapObjects.c b/src/dusk/c_src/contrib/shiftMapObjects.c similarity index 100% rename from src/dusk/src/contrib/shiftMapObjects.c rename to src/dusk/c_src/contrib/shiftMapObjects.c diff --git a/src/dusk/src/contrib/types.h b/src/dusk/c_src/contrib/types.h similarity index 100% rename from src/dusk/src/contrib/types.h rename to src/dusk/c_src/contrib/types.h diff --git a/src/dusk/src/contrib/video.h b/src/dusk/c_src/contrib/video.h similarity index 100% rename from src/dusk/src/contrib/video.h rename to src/dusk/c_src/contrib/video.h diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index b062285..e55a427 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -107,7 +107,7 @@ void dusk_sprites_init() { sprites_bpp8 = true; // enable sprite display - REG_DISPCNT |= DCNT_OBJ | DCNT_OBJ_1D; + *REG_DISPCNT |= DCNT_OBJ | DCNT_OBJ_1D; } void dusk_sprites_configure(bool bpp8) { sprites_bpp8 = bpp8; } @@ -317,19 +317,19 @@ void enable_bg(u8 bg_id) { default: assert(0); } - REG_DISPCNT |= bg_flag; + *REG_DISPCNT |= bg_flag; } vu16* dusk_get_background_register(u8 bg_id) { switch (bg_id) { case 0: - return &(REG_BG0CNT()); + return REG_BG0CNT; case 1: - return &(REG_BG1CNT()); + return REG_BG1CNT; case 2: - return &(REG_BG2CNT()); + return REG_BG2CNT; case 3: - return &(REG_BG3CNT()); + return REG_BG3CNT; default: return null; } diff --git a/src/dusk/d_src/dusk/sys.d b/src/dusk/d_src/dusk/sys.d index acf5fb6..cd19d23 100644 --- a/src/dusk/d_src/dusk/sys.d +++ b/src/dusk/d_src/dusk/sys.d @@ -56,14 +56,14 @@ void dusk_init_graphics_mode0() { // dusk_reset_irq(); // reset registers - REG_DISPCNT = DCNT_MODE0; - REG_BG0CNT = 0; - REG_BG1CNT = 0; - REG_BG2CNT = 0; - REG_BG3CNT = 0; + *REG_DISPCNT = DCNT_MODE0; + *REG_BG0CNT = 0; + *REG_BG1CNT = 0; + *REG_BG2CNT = 0; + *REG_BG3CNT = 0; } -void dusk_init_graphics_mode3() { REG_DISPCNT = DCNT_MODE3 | DCNT_BG2; } +void dusk_init_graphics_mode3() { *REG_DISPCNT = DCNT_MODE3 | DCNT_BG2; } void dusk_frame() { // vid_vsync(); diff --git a/src/dusk/include/ds_load.h b/src/dusk/include/ds_load.h deleted file mode 100644 index 259befa..0000000 --- a/src/dusk/include/ds_load.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - DUSK: LOADER -*/ - -#pragma once - -#include "contrib/gbfs.h" -#include "contrib/gbamap.h" - -extern const GBFS_FILE* gbfs_dat; - -// represents an atlas, with bitmaps for the image and palette -typedef struct SpriteAtlas { - u32* tiles; - u32 tile_sz; - u32* pal; - u32 pal_sz; -} SpriteAtlas; - -typedef struct GritImage { - u32* tiles; - u32 tile_sz; - u32* pal; - u32 pal_sz; - u32* map; - u32 map_sz; -} GritImage; - -#define ATLAS_ENTRY_LEN 6 - -/** represents a single entry in the sprite atlas. - * note that names are limited to just 5 chars and a NULL terminator. */ -typedef struct SpriteAtlasEntry { - char name[ATLAS_ENTRY_LEN]; - // all of these are in tiles (8px) - u8 x; - u8 y; - u8 w; - u8 h; -} SpriteAtlasEntry; - -/** represents the layout of items in an atlas (https://github.com/xdrie/crunch#binary-format). - * we only use the first texture because the vram can only hold one */ -typedef struct SpriteAtlasLayout { - u16 width; - u16 height; - u16 num_entries; - SpriteAtlasEntry* entries; -} SpriteAtlasLayout; - -/** initialize loader */ -void dusk_load_init(); - -// - CONTENT LOADERS: pass filename without extension - -const void* dusk_load_raw(char* name, u32* len); -GritImage dusk_load_image(char* name); -SpriteAtlas dusk_load_atlas(char* name); -SpriteAtlasLayout dusk_load_atlas_layout(const char* name); -SpriteAtlasEntry* dusk_load_atlas_entry(SpriteAtlasLayout* layout, const char* entry_name); -void dusk_free_atlas_layout(SpriteAtlasLayout* layout); - -Map dusk_load_map(char* name); \ No newline at end of file diff --git a/src/dusk/include/ds_sav.h b/src/dusk/include/ds_sav.h deleted file mode 100644 index 7144094..0000000 --- a/src/dusk/include/ds_sav.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - DUSK: SAVE UTIL -*/ - -#pragma once - -// utilities for saving and loading vars - -#define SV_LOAD_ITEM(var, offset) \ - memcpy(&var, sram_mem + offset, sizeof(typeof(var))); \ - offset += sizeof(typeof(var)); - -#define SV_SAVE_ITEM(var, offset) \ - memcpy(sram_mem + offset, &var, sizeof(typeof(var))); \ - offset += sizeof(typeof(var)); - -// utilities for saving and loading vars \ No newline at end of file diff --git a/src/dusk/include/ds_spr.h b/src/dusk/include/ds_spr.h deleted file mode 100644 index bb1a806..0000000 --- a/src/dusk/include/ds_spr.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - DUSK: SPRITES -*/ - -#pragma once - -#include -#include -#include "ds_load.h" - -#define NUM_SPRITES 128 -#define NUM_AFFINE_SPRITES 32 -extern OBJ_ATTR obj_buffer[NUM_SPRITES]; -extern OBJ_AFFINE* obj_aff_buffer; - -#define SPRITEFLAG_PRIORITY_SHIFT 6 -#define SPRITEFLAG_PRIORITY_GET(n) ((n >> SPRITEFLAG_PRIORITY_SHIFT) & 0b11) -#define SPRITEFLAG_PRIORITY(n) ((n << SPRITEFLAG_PRIORITY_SHIFT) & 0b11) - -#define DUSKSPRITE_FLAGS_VISIBLE (0x1 << 0) -/** sprite data */ -typedef struct Sprite { - s16 x, y; - /** the number of tiles taken up by this sprite */ - u8 tile_sz; - /** the raw tid of the top left corner tile of spritesheet frame 0 */ - u16 base_tid; - /** the frame index of the spritesheet */ - u8 page; - /** flags: 0/0/0/0/0/0/0/visible */ - u8 flags; -} Sprite; - -/** animation metadata */ -typedef struct Anim { - /** which page in the sprite the animation starts */ - u8 start; - /** number of pages in this animation */ - u8 len; - /** (60/fps), or how many frames each page lasts */ - u8 rate; -} Anim; - -/** background data */ -typedef struct Background { - s16 x, y; - int cbb, sbb; -} Background; - -/** define an animation, given a starting frame and frame count, and fps */ -#define MAKE_ANIM_EX(st, le, fps) \ - (Anim) { .start = st, .len = le, .rate = (60 / fps) } -/** define an animation, given a starting frame and frame count, at 10 fps */ -#define MAKE_ANIM(st, le) MAKE_ANIM_EX(st, le, 10) - -/** memory block used to track sprites */ -extern Sprite sprites[NUM_SPRITES]; - -/** initialize sprite and OAM memory */ -void dusk_sprites_init(); -/** set mode options for dusk sprites */ -void dusk_sprites_configure(BOOL bpp8); -/** upload a sprite atlas to tile and palette memory */ -void dusk_sprites_upload_atlas(SpriteAtlas* atlas); -/** upload a sprite atlas section to tile and palette memory */ -void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* atlas, SpriteAtlasEntry* entry, u16 pal_offset, u16 tile_offset); -/** create a sprite and store it in index of sprite memory */ -Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr); -/** synchronize a sprite from the sprites array to OAM block (vram) */ -void dusk_sprites_sync(int index); -/** synchronize all sprites to OAM block, then upload OAM block to vram */ -void dusk_sprites_update(); -/** play an animation on a sprite */ -void dusk_sprites_anim_play(Sprite* spr, Anim* anim); -/** calculate the tid of a sprite given pos and sheet dimens */ -u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height); -/** upload image data to background tile vram */ -void dusk_background_upload_raw(GritImage* img, int cbb, int sbb); -/** create a background and display it */ -void dusk_background_make(u8 bg_id, u16 size, Background bg); \ No newline at end of file diff --git a/src/dusk/include/ds_sys.h b/src/dusk/include/ds_sys.h deleted file mode 100644 index d7c8afb..0000000 --- a/src/dusk/include/ds_sys.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - DUSK: SYSTEM -*/ - -#pragma once - -extern uint frame_count; - -typedef struct Scene { - void (*start)(void); - void (*end)(void); - void (*update)(void); -} Scene; - -/** initialize the system for using DUSK */ -void dusk_init_all(); -/** initialize mode0 graphics */ -void dusk_init_graphics_mode0(); -/** initialize mode3 graphics */ -void dusk_init_graphics_mode3(); -/** vsync */ -void dusk_frame(); -void dusk_scene_set(Scene next); -void dusk_scene_update(); \ No newline at end of file diff --git a/src/dusk/include/dusk.h b/src/dusk/include/dusk.h deleted file mode 100644 index b1168f3..0000000 --- a/src/dusk/include/dusk.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - DUSK: MASTER HEADER -*/ - -#pragma once - -#include -#include "ds_load.h" -#include "ds_sys.h" -#include "ds_spr.h" -#include "ds_sav.h" \ No newline at end of file From 92f2ecbf7fc4f60b48fee67e569be59720eecf1f Mon Sep 17 00:00:00 2001 From: redthing1 Date: Thu, 18 Nov 2021 01:19:09 -0800 Subject: [PATCH 07/32] fix irq add IrqIndex var --- src/dusk/d_src/dusk/sys.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dusk/d_src/dusk/sys.d b/src/dusk/d_src/dusk/sys.d index cd19d23..e4566ca 100644 --- a/src/dusk/d_src/dusk/sys.d +++ b/src/dusk/d_src/dusk/sys.d @@ -38,7 +38,7 @@ void dusk_clear_vidmem() { void dusk_reset_irq() { irq_init(null); - irq_add(eIrqIndex.II_VBLANK, null); + irq_add(IrqIndex.II_VBLANK, null); } void dusk_init_all() { From dba9e7afdea506d8a633fd63b1479da45f20efa6 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sun, 21 Nov 2021 15:59:33 -0800 Subject: [PATCH 08/32] remove enum prefix from IrqIndex --- src/dusk/d_src/dusk/sys.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dusk/d_src/dusk/sys.d b/src/dusk/d_src/dusk/sys.d index e4566ca..ef63ab6 100644 --- a/src/dusk/d_src/dusk/sys.d +++ b/src/dusk/d_src/dusk/sys.d @@ -38,7 +38,7 @@ void dusk_clear_vidmem() { void dusk_reset_irq() { irq_init(null); - irq_add(IrqIndex.II_VBLANK, null); + irq_add(IrqIndex.VBLANK, null); } void dusk_init_all() { From 6729dc1ed015a22be0f99e4d80ab44b2a4c2f57c Mon Sep 17 00:00:00 2001 From: redthing1 Date: Fri, 31 Dec 2021 18:53:39 -0800 Subject: [PATCH 09/32] use dma for bg --- src/dusk/d_src/dusk/sprites.d | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index e55a427..3a028a9 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -339,11 +339,18 @@ void dusk_background_upload_raw(GritImage* img, int cbb, int sbb) { // TODO: support selecting slot // 1. upload the atlas tile palette to bg palette memory - memcpy(&pal_bg_bank[0], img.pal, img.pal_sz); - // 2. upload the atlas tiles to bg tile memory (CBB) - memcpy(&tile_mem[cbb][0], img.tiles, img.tile_sz); - // 3. upload the map (SBB) - memcpy(&se_mem[sbb][0], img.map, img.map_sz); + // memcpy32(&pal_bg_bank[0], img.pal, img.pal_sz / 4); + // // 2. upload the atlas tiles to bg tile memory (CBB) + // memcpy32(&tile_mem[cbb][0], img.tiles, img.tile_sz / 4); + // // 3. upload the map (SBB) + // memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); + + memcpy32(&pal_bg_bank[0], img.pal, img.pal_sz / 4); + // memcpy32(&tile_mem[cbb][0], img.tiles, img.tile_sz / 4); + memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); + // dma3_cpy(&pal_bg_bank[0], img.pal, img.pal_sz); + dma3_cpy(&tile_mem[cbb][0], img.tiles, img.tile_sz); + // dma3_cpy(&se_mem[sbb][0], img.map, img.map_sz); } void dusk_background_make(u8 bg_id, u16 size, Background bg) { From a15e22e18f9377ab3b2d6577a98b0b4774864eb3 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Fri, 31 Dec 2021 19:28:55 -0800 Subject: [PATCH 10/32] optional dma --- src/dusk/d_src/dusk/sprites.d | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index 3a028a9..e7cac07 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -346,10 +346,13 @@ void dusk_background_upload_raw(GritImage* img, int cbb, int sbb) { // memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); memcpy32(&pal_bg_bank[0], img.pal, img.pal_sz / 4); - // memcpy32(&tile_mem[cbb][0], img.tiles, img.tile_sz / 4); + version (USE_DMA) { + dma3_cpy(&tile_mem[cbb][0], img.tiles, img.tile_sz); + } else { + memcpy32(&tile_mem[cbb][0], img.tiles, img.tile_sz / 4); + } memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); // dma3_cpy(&pal_bg_bank[0], img.pal, img.pal_sz); - dma3_cpy(&tile_mem[cbb][0], img.tiles, img.tile_sz); // dma3_cpy(&se_mem[sbb][0], img.map, img.map_sz); } From 9e3376aaa2658fb4839528fb3005ddce2534880c Mon Sep 17 00:00:00 2001 From: redthing1 Date: Thu, 6 Jan 2022 21:13:57 -0800 Subject: [PATCH 11/32] update log level enum --- src/dusk/d_src/dusk/contrib/mgba.d | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dusk/d_src/dusk/contrib/mgba.d b/src/dusk/d_src/dusk/contrib/mgba.d index 79f573f..8c9b129 100644 --- a/src/dusk/d_src/dusk/contrib/mgba.d +++ b/src/dusk/d_src/dusk/contrib/mgba.d @@ -8,13 +8,13 @@ enum REG_DEBUG_ENABLE = cast(vu16*) 0x4FFF780; enum REG_DEBUG_FLAGS = cast(vu16*) 0x4FFF700; enum REG_DEBUG_STRING = cast(char*) 0x4FFF600; -enum MGBA_LOG_LEVEL +enum MGBALogLevel { - MGBA_LOG_FATAL = 0, - MGBA_LOG_ERROR = 1, - MGBA_LOG_WARN = 2, - MGBA_LOG_INFO = 3, - MGBA_LOG_DEBUG = 4 + FATAL = 0, + ERROR = 1, + WARN = 2, + INFO = 3, + DEBUG = 4 } void mgba_printf (int level, const(char)* ptr, ...); From c2edf77e0431a460010f1ad3091533bbfed39d43 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Fri, 7 Jan 2022 11:13:21 -0800 Subject: [PATCH 12/32] add init func to Sprite and set visible flag without overwriting --- src/dusk/d_src/dusk/sprites.d | 50 ++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index e7cac07..b6507ae 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -1,6 +1,6 @@ module dusk.sprites; -extern(C): +extern (C): import dusk.sprites; import dusk.sys; @@ -22,6 +22,7 @@ enum DUSKSPRITE_FLAGS_VISIBLE = (0x1 << 0); /** sprite data */ struct Sprite { + /** the screen x and y of the sprite */ s16 x, y; /** the number of tiles taken up by this sprite */ u8 tile_sz; @@ -31,6 +32,18 @@ struct Sprite { u8 page; /** flags: 0/0/0/0/0/0/0/visible */ u8 flags; + + /** initialize a sprite struct */ + static Sprite init(s16 x, s16 y, u8 page = 0, u8 flags = 0) { + Sprite s; + s.x = x; + s.y = y; + s.tile_sz = 1; + s.base_tid = 0; + s.page = page; + s.flags = flags; + return s; + } } /** animation metadata */ @@ -88,7 +101,9 @@ Anim make_anim(u8 start, u8 len) { // static OBJ_ATTR[NUM_SPRITES] obj_buffer; @(ldc.attributes.section(".ewram")) __gshared OBJ_ATTR[NUM_SPRITES] obj_buffer; // OBJ_AFFINE* obj_aff_buffer = cast(OBJ_AFFINE*) obj_buffer; -__gshared OBJ_AFFINE* obj_aff_buffer() { return cast(OBJ_AFFINE*) obj_buffer; } +__gshared OBJ_AFFINE* obj_aff_buffer() { + return cast(OBJ_AFFINE*) obj_buffer; +} /** memory block used to track sprites */ // mixin(EWRAM_DATA!("Sprite[NUM_SPRITES]", "sprites")); @@ -101,7 +116,7 @@ __gshared bool sprites_bpp8 = true; void dusk_sprites_init() { // initialize object buffer oam_init(cast(OBJ_ATTR*) obj_buffer, NUM_SPRITES); - memset(cast(void*)sprites, 0, (Sprite.sizeof) * NUM_SPRITES); + memset(cast(void*) sprites, 0, (Sprite.sizeof) * NUM_SPRITES); // reset bpp to default sprites_bpp8 = true; @@ -110,7 +125,9 @@ void dusk_sprites_init() { *REG_DISPCNT |= DCNT_OBJ | DCNT_OBJ_1D; } -void dusk_sprites_configure(bool bpp8) { sprites_bpp8 = bpp8; } +void dusk_sprites_configure(bool bpp8) { + sprites_bpp8 = bpp8; +} void dusk_sprites_upload_atlas(SpriteAtlas* atlas) { // 1. upload the atlas tile palette to palette memory @@ -123,7 +140,7 @@ void dusk_sprites_upload_atlas(SpriteAtlas* atlas) { } void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* atlas, SpriteAtlasEntry* entry, - u16 pal_offset, u16 tile_offset) { + u16 pal_offset, u16 tile_offset) { // 1. upload the palette (palettes are 16-bit highcolor) memcpy(&pal_obj_bank[0][pal_offset], &atlas.pal[0], atlas.pal_sz); @@ -132,8 +149,8 @@ void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* a // 2. upload the tiles int entry_firsttid = dusk_sprites_pos_to_tid(entry.x, entry.y, layout.width, layout.height); // tid of entry start in atlas - int entry_tilecount = (entry.w) * (entry.h); // entry size in tiles - int raw_firsttid = entry_firsttid * entry_tilecount * 2; // read offset + int entry_tilecount = (entry.w) * (entry.h); // entry size in tiles + int raw_firsttid = entry_firsttid * entry_tilecount * 2; // read offset // int raw_tilecount = entry_tilecount * 2; int raw_tileoffset = tile_offset * 2; // write offset @@ -164,12 +181,12 @@ void dusk_sprites_upload_atlas_section(SpriteAtlasLayout* layout, SpriteAtlas* a u8* loc_tread = cast(u8*)&atlas.tiles[raw_firsttid]; for (int i = 0; i < entry_tilecount; i += 1) { int c = i * 64; - u8[64] tile; // create temp tile + u8[64] tile; // create temp tile memcpy(&tile[0], loc_tread + c, 64); // read tile // fix tile for (int j = 0; j < 64; j++) { - tile[j] = cast(ubyte) (tile[j] + pal_offset); + tile[j] = cast(ubyte)(tile[j] + pal_offset); } memcpy(loc_twrite + c, &tile[0], 64); // write tile @@ -219,7 +236,7 @@ Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr) { } // calculate the number of tiles used by one frame of this sprite (divide width and height by 8) - spr.tile_sz = cast(ubyte) ((width >> 3) * (height >> 3)); + spr.tile_sz = cast(ubyte)((width >> 3) * (height >> 3)); // set main attributes // leave tile id (attr2) null, it will be set in sync @@ -227,7 +244,7 @@ Sprite* dusk_sprites_make(int index, u8 width, u8 height, Sprite spr) { obj_set_attr(&obj_buffer[index], ATTR0_REG | shape_attr | bpp_flag, size_attr, 0); // set default flags - spr.flags = (DUSKSPRITE_FLAGS_VISIBLE); + spr.flags |= (DUSKSPRITE_FLAGS_VISIBLE); // save sprite metadata sprites[index] = spr; @@ -259,7 +276,7 @@ pragma(inline) void dusk_sprites_sync(int i) { // raw base tid mode int bpp_mult = (sprites_bpp8 == 1) ? 2 : 1; - u16 tid = cast(u16) ((sprite.base_tid + (sprite.page * sprite.tile_sz)) * bpp_mult); + u16 tid = cast(u16)((sprite.base_tid + (sprite.page * sprite.tile_sz)) * bpp_mult); obj_set_attr(obj, obj.attr0, obj.attr1, cast(u16)(ATTR2_ID!u16(tid) | ATTR2_PALBANK!u16(0))); } @@ -285,7 +302,7 @@ void dusk_sprites_anim_play(Sprite* spr, Anim* anim) { ix = (ix + 1) % anim.len; } // set new frame - spr.page = cast(u8) (anim.start + ix); + spr.page = cast(u8)(anim.start + ix); } u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height) { @@ -295,7 +312,7 @@ u16 dusk_sprites_pos_to_tid(u16 x, u16 y, u16 sheet_width, u16 sheet_height) { u16 yt = y; u16 imw = sheet_width >> 3; // compute with bitshift (sheet_width / 8) // u16 imh = sheet_height >> 3; - u16 tid = cast(u16) ((yt * imw) + xt); + u16 tid = cast(u16)((yt * imw) + xt); return tid; } @@ -314,7 +331,8 @@ void enable_bg(u8 bg_id) { case 3: bg_flag = DCNT_BG3; break; - default: assert(0); + default: + assert(0); } *REG_DISPCNT |= bg_flag; @@ -364,4 +382,4 @@ void dusk_background_make(u8 bg_id, u16 size, Background bg) { // u16 bpp_flag = (sprites_bpp8 == 1) ? BG_8BPP : BG_4BPP; *bg_reg |= BG_CBB(bg.cbb) | BG_SBB(bg.sbb) | BG_8BPP | size; -} \ No newline at end of file +} From 06f1bd14bd328b130b6492beee1bedf836b031f2 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Fri, 7 Jan 2022 19:45:54 -0800 Subject: [PATCH 13/32] add posprintf --- src/dusk/Makefile | 4 + src/dusk/c_src/contrib/posprintf.h | 196 +++++++++++ src/dusk/c_src/contrib/posprintf.s | 420 ++++++++++++++++++++++++ src/dusk/d_src/dusk/contrib/posprintf.d | 5 + 4 files changed, 625 insertions(+) create mode 100755 src/dusk/c_src/contrib/posprintf.h create mode 100755 src/dusk/c_src/contrib/posprintf.s create mode 100644 src/dusk/d_src/dusk/contrib/posprintf.d diff --git a/src/dusk/Makefile b/src/dusk/Makefile index 37e5150..99db424 100644 --- a/src/dusk/Makefile +++ b/src/dusk/Makefile @@ -130,6 +130,10 @@ $(TARGET): $(OFILES) @echo $(notdir $<) $(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(RCFLAGS) -c $< -o $@ +%.o : %.s + @echo $(notdir $<) + $(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(RCFLAGS) -c $< -o $@ + -include $(DEPENDS) endif diff --git a/src/dusk/c_src/contrib/posprintf.h b/src/dusk/c_src/contrib/posprintf.h new file mode 100755 index 0000000..def0909 --- /dev/null +++ b/src/dusk/c_src/contrib/posprintf.h @@ -0,0 +1,196 @@ +/* + +posprintf - a condensed version of sprintf for Thumb, esp. GBA +Copyright (C) 2003 Dan Posluns + +The person or persons who have associated work with this document (the "Dedicator" or "Certifier") hereby either (a) +certifies that, to the best of his knowledge, the work of authorship identified is in the public domain of the country +from which the work is published, or (b) hereby dedicates whatever copyright the dedicators holds in the work of +authorship identified below (the "Work") to the public domain. A certifier, moreover, dedicates any copyright interest +he may have in the associated work, and for these purposes, is described as a "dedicator" below. + +A certifier has taken reasonable steps to verify the copyright status of this work. Certifier recognizes that his good +faith efforts may not shield him from liability if in fact the work certified is not in the public domain. + +Dedicator makes this dedication for the benefit of the public at large and to the detriment of the Dedicator's heirs and +successors. Dedicator intends this dedication to be an overt act of relinquishment in perpetuity of all present and +future rights under copyright law, whether vested or contingent, in the Work. Dedicator understands that such +relinquishment of all rights includes the relinquishment of all rights to enforce (by lawsuit or otherwise) those +copyrights in the Work. + +Dedicator recognizes that, once placed in the public domain, the Work may be freely reproduced, distributed, +transmitted, used, modified, built upon, or otherwise exploited by anyone for any purpose, commercial or non-commercial, +and in any way, including by methods that have not yet been invented or conceived. + +Author contact e-mail: dan at danposluns dot com + + +INSTRUCTIONS: + +To call: posprintf(char *dest, const char *src[, param1[, param2[, ... paramN]]]); + +- src must be a valid zero-terminated C string. +- dest must point to a sufficiently large block of memory to contain the result string. + +The following format specifiers are valid: + +%% - print a '%' symbol +%s - print a string; parameter must point to a valid zero-terminated C string +%d - print a 16-bit (short) integer; must be within [-65,535 .. 65,535] +%l - print a 29-bit integer; approximate range [-500,000,000 .. 500,000,000] +%x - print a hexadecimal number (lowercase digits) +%X - print a hexadecimal number (uppercase digits) + +The specifiers %d, %l, %x and %X may be modified as follows: + +- Digits 1 through 9 indicate number of leading spaces to print, eg. + %5d would print the number 123 as " 123" + %5d would print the number 123456 as "123456" (no leading spaces) +- When above digit is prefixed with 0, leading zeros are printed instead of spaces + %05d would print the number 123 as "00123" + %04d would print the number 12345 as "12345" (no leading zeros) +- Negative sign consumes a leading space, eg. + %05d would print the number -123 as "-0123" + (Hexadecimal numbers are considered unsigned) + +IF YOU WANT MORE FUNCTIONALITY THAN THIS, YOU CAN FEEL FREE TO MODIFY THE CODE, +BUT THEN I WOULD SUGGEST MOVING TO A MORE SOPHISTICATED LIBRARY ANYWAY. + +*** CAUTION IF NOT USED ON GAMEBOY ADVANCE *** +Although this is mostly written as general Thumb code, the %l (29-bit print) +specifier code currently uses a software interrupt (SWI) specific to the +Gameboy Advance to perform a division. If you wish to port this to other ARM +machines, you may need to alter this code. I believe that most ARM machines +support SWI 7 as an alternative software divide, although you will have to +swap the numerator/denominator registers (r0 and r1). +*** END CAUTION *** + +My contact e-mail is: dan at danposluns dot com + +*/ + +/* +posprintf Documentation + +What is it? + +posprintf is a function you can call in your Gameboy Advance programs to generate strings. It is basically a somewhat +amputated version of the standard C library function, sprintf. + +Why use it? + +Probably the most significant use of it is to print out and format numbers for display on the screen. In order to do +this, the numbers need to be converted from their internal representation (base 2) to decimal (base 10). posprintf uses +an extremely efficient algorithm scammed off of the 'net to do this, and it is written entirely in Thumb assembler to +run very quickly (without consuming the internal memory needed to run efficiently in ARM mode). + +Other reasons to use it include that it's fast, extremely flexible for most GBA applications, and absolutely free. I +wouldn't say no to a credit if it is used in an application, though, commercial or otherwise. + +How do I use it? + + Include the file posprintf.h in your C source code that you want to call the function. (ie. #include "posprintf.h") + + Call it the same way you would call sprintf, keeping in mind the differences between the two (see the next section). + + Make sure to link the file posprintf.o with your project. Generally this just means including posprintf.o on the +command line when you call gcc. + +That's all there is to it. + +How do I call the function? + +The syntax is as follows: + + posprintf(char *dest, const char *src[, param1[, param2[, ... paramN]]]); + + dest is the address of the string to be printed out to. IMPORTANT: There must be sufficient memory allocated to the +buffer to hold the string, including the terminating zero. + + src is the address of the source string to print. This absolutely must be a valid, zero-terminated C string. + + The optional parameters accompany any format specifiers used in the source string. + +Format Specifiers + +The following are valid format specifiers for use with posprintf: + + %% - print a % character + %s - print a string. The accompanying parameter must be a valid, zero-terminated C string. + %d - print an integer. Important: unlike sprintf, this is only accurate for 16 bits of data, or numbers ranging from +-65,535 to 65,535. %l - print a long integer. Important: unlike sprintf this is only accurate for approximately 29 bits +of data, or numbers ranging from about -500 million to 500 million. %x - print in hexadecimal format. Provided mostly as +a programming tool, since few user applications would probably ever want to print hexadecimal numbers. %X - same as %x, +but prints capital letters for the digits 'a' through 'f'. + +Output Control + +The output of %d, %l, %x and %X tags may optionally be influenced by the following prefixes: + + Digits 1 through 9: Indicate how many leading spaces to include. Examples: + + %5d would print the number 123 as " 123" + %3d would print the number 12345 as "12345" (no leading spaces) + + Digit 0: When prefixing the above number, indicates to print leading zeros instead of leading spaces. Examples: + + %05d would print the number 123 as "00123" + %03d would print the number 12345 as "12345" (no leading zeros) + +Note: If the number printed is negative, then the negative sign will consume a leading space/zero, if there are any. + +Other Notes + +Optimized for GBA development + +One of the big realizations in understanding this code is that few GBA games need to display numbers larger than 65,535, +and when they do these are the minority of numbers, not the majority. The %d specifier is highly optimized to work with +16 bits, and you should use it whenever possible. + +For the minority of occasions when you need to display more than 16 bits worth of numerical data, %l works fine to +numbers well beyond the plus-or-minus 500 million mark. (The actual limit is +/- 655,359,999.) It takes about twice as +long to run as %d, though, and includes a slow SWI call to split the number into two chunks, so you should still use %d +instead whenever you can. + +If you need to display numbers larger than 500 million, then you will either have to heavily alter the code, use a +different utility, or break your number up into sizeable chunks. If you do need to display larger numbers than 500 +million for a GBA game, though, you may want to rethink your game design. + +What about other ARM machines? + +Although posprintf is mostly written as generic Thumb code, the %l (29-bit print) specifier code currently uses a +software interrupt (SWI) specific to the Gameboy Advance to perform a division. If you wish to port this to other ARM +machines, you may need to alter this code. I believe that most ARM machines support SWI 7 as an alternative software +divide, although you will have to swap the numerator/denominator registers (r0 and r1). + +Can't you optimize out the SWI call? Use inverse multiplication, register shifting, or somesuch? + +Not easily. Not in Thumb mode, anyway, which doesn't have the 64-bit multiply instruction. The number has many +significant digits, and is being divided by 10,000, which requires two registers to keep things accurate. My best advice +is to avoid it in the first place by keeping your numbers small and using %d instead, but also not to fret over using %l +as the SWI is only issued once in the entire routine, and everything else is still quite zippy. It is not like you will +have to call it a bazillion times per frame, and it's still a helluva lot faster than what the standard library sprintf +does. If anyone does feel like optimizing this, though, please send me the results. + +If it's displaying 16-bit numbers and they are signed, shouldn't they only be in the range +/- 32767? + +The conversion to base 10 is actually done on the number unsigned, so you get a full range up to 65,535. The sign is +taken from the extension of the number to 32 bits, which happens automatically regardless of whether you pass a short or +not. The same applies to %l. + +What are the terms and restrictions to using posprintf? + +posprintf no longer has a license; it is freely available to use as part of the public domain. + +Why "posprintf"? + +I think the "po" stood for something originally, but now the "pos" is just a play on my last name. Please, no P.O.S. +jokes. :) +*/ + +#ifndef _PSPRINTF_HEADER_ +#define _PSPRINTF_HEADER_ + +extern void posprintf(char*, const char*, ...); + +#endif diff --git a/src/dusk/c_src/contrib/posprintf.s b/src/dusk/c_src/contrib/posprintf.s new file mode 100755 index 0000000..467167e --- /dev/null +++ b/src/dusk/c_src/contrib/posprintf.s @@ -0,0 +1,420 @@ +/* + +posprintf - a condensed version of sprintf for Thumb, esp. GBA +Copyright (C) 2003 Dan Posluns + +The person or persons who have associated work with this document (the "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of his knowledge, the work of authorship identified is in the public domain of the country from which the work is published, or (b) hereby dedicates whatever copyright the dedicators holds in the work of authorship identified below (the "Work") to the public domain. A certifier, moreover, dedicates any copyright interest he may have in the associated work, and for these purposes, is described as a "dedicator" below. + +A certifier has taken reasonable steps to verify the copyright status of this work. Certifier recognizes that his good faith efforts may not shield him from liability if in fact the work certified is not in the public domain. + +Dedicator makes this dedication for the benefit of the public at large and to the detriment of the Dedicator's heirs and successors. Dedicator intends this dedication to be an overt act of relinquishment in perpetuity of all present and future rights under copyright law, whether vested or contingent, in the Work. Dedicator understands that such relinquishment of all rights includes the relinquishment of all rights to enforce (by lawsuit or otherwise) those copyrights in the Work. + +Dedicator recognizes that, once placed in the public domain, the Work may be freely reproduced, distributed, transmitted, used, modified, built upon, or otherwise exploited by anyone for any purpose, commercial or non-commercial, and in any way, including by methods that have not yet been invented or conceived. + +Author contact e-mail: dan at danposluns dot com + + +register map: + +MAIN LOOP: PROCESS16: +r0 <- dest string address r0 <- d0 +r1 <- source string address r1 <- d1 +r2 <- integer to print r2 <- d2 +r3 <- r3 <- d3 +r4 <- current char r4 <- d4 +r5 <- r5 <- work register +r6 <- r6 <- work register +r7 <- r7 <- dest string address +r8 <- number of digits to print r8 <- number of digits to print +r9 <- leading char (' ' or '0') r9 <- leading char (' ' or '0') +r10 <- current parameter pointer r10 <- current parameter ptr +r11 <- r11 <- +r12 <- r12 <- source string address +r14 <- r14 <- lr + +Function parameters: + +r0 <- destination string address +r1 <- source string address +r2 <- param1 +r3 <- param2 + +*/ + + .thumb + .thumb_func + .align + .global posprintf + .type posprintf,function +posprintf: + + push {r3} @ push our second and third parameters + push {r2} @ onto the stack in reverse order + mov r12, sp @ r12 <- first parameter pointer + + push {r4-r7} @ save clobbered registers + mov r4, r8 + mov r5, r9 + mov r6, r10 + push {r4-r6, lr} + mov r10, r12 @ r10 <- first parameter pointer + +.L_STRINGLOOP: + ldrb r4, [r1] @ load a char from r1 + add r1, #1 @ advance pointer to next char + cmp r4, #'%' @ if char == '%' then + beq .L_FORMATENTRY @ handle the format specifier + strb r4, [r0] @ store the char back to memory + add r0, #1 @ advance pointer to next char + cmp r4, #0 @ if char != 0 then + bne .L_STRINGLOOP @ repeat for next char + @ cleanup and exit + pop {r4-r7} @ restore clobbered registers + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov lr, r7 + pop {r4-r7} + add sp, #8 @ remove parameters from stack + bx lr @ return from subroutine + +.L_FORMATENTRY: + mov r5, #0 @ assume no leading character for numbers + mov r6, #' ' @ assume print spaces if we do print leads + mov r8, r5 + mov r9, r6 +.L_FORMATSPEC: + ldrb r4, [r1] @ load the next char from r1 + add r1, #1 @ advance pointer to next char + cmp r4, #'d' @ if char == 'd' + beq .L_PRINT16 @ print 16-bit number + cmp r4, #'s' @ if char == 's' + beq .L_PRINTSTR @ print string + cmp r4, #'0' @ if char == '0' + beq .L_SETLEAD @ print with leading zeros + cmp r4, #'%' @ if char == '%' + beq .L_PRINTSYMBOL @ print '%' character + cmp r4, #'l' @ if char == 'l' + beq .L_PRINT29 @ print 29-bit number + cmp r4, #'X' @ if char == 'X' + beq .L_PRINTHEXUC @ print hexadecimal uppercase + cmp r4, #'x' @ if char == 'x' + beq .L_PRINTHEXLC @ print hexadecimal lowercase + @ we now assume that we are choosing a number of leading digits to display + sub r4, #'0' + mov r8, r4 @ r8 <- char - '0' + b .L_FORMATSPEC + +.L_SETLEAD: + mov r6, #'0' + mov r9, r6 @ print leading zeros instead of spaces + b .L_FORMATSPEC + +.L_PRINTSYMBOL: + strb r4, [r0] @ store '%' symbol to memory + add r0, #1 @ advance pointer to next char + b .L_STRINGLOOP + +.L_PRINTSTR: + mov r4, r10 @ r4 <- current parameter pointer + ldr r2, [r4] @ r2 <- address of string to print + add r4, #4 + mov r10, r4 @ increase parameter pointer +.L_PRINTSTRLOOP: + ldrb r4, [r2] @ load a char from r2 + add r2, #1 @ advance pointer to next char + cmp r4, #0 @ if char == 0 + beq .L_STRINGLOOP @ then we are done + strb r4, [r0] @ store the char back to memory + add r0, #1 @ advance pointer to next char + b .L_PRINTSTRLOOP + +.L_PRINT16: + mov r7, r0 @ r7 <- dest string address + mov r4, r10 @ r4 <- current parameter pointer + ldr r0, [r4] @ r0 <- 16-bit integer to print + add r4, #4 + mov r10, r4 @ increase parameter pointer + mov r3, #0 @ temp marker for L_PRINTSIGN + cmp r0, #0 @ if integer to print is negative + blt .L_PRINTSIGN @ print the sign and adjust +.L_SIGNDONE: + mov lr, pc @ save this location + bl .L_PROCESS16 @ process a 16-bit number + b .L_STRINGLOOP @ return when done + +.L_PRINTSIGN: + mov r4, #'-' + strb r4, [r7] @ print '-' character + add r7, #1 @ advance pointer to next char + neg r0, r0 @ r2 is now positive + mov r4, r8 + sub r4, #1 @ print one fewer character + mov r8, r4 @ r8 <- new value + cmp r3, #0 @ check to see who called us + beq .L_SIGNDONE + b .L_SIGN29DONE + +.L_PRINT29: + mov r7, r0 @ r7 <- dest string address + mov r4, r10 @ r4 <- current parameter pointer + ldr r0, [r4] @ r0 <- 16-bit integer to print + add r4, #4 + mov r10, r4 @ increase parameter pointer + mov r3, #1 @ temp marker for L_PRINTSIGN + cmp r0, #0 @ if integer to print is negative + blt .L_PRINTSIGN @ print the sign and adjust +.L_SIGN29DONE: + mov r12, r1 + mov r1, #0x27 + lsl r1, r1, #8 + add r1, #0x10 @ r1 <- 0x2710 == 10000 + swi 6 @ split number by dividing by 10000 + mov r3, #0 + sub r3, #4 + add r8, r3 @ subtract 4 from digits to display + cmp r0, #0 @ if the first chunk is empty + beq .L_P29SKIP @ then skip it + push {r1} @ save the second number to display + mov r1, r12 + mov lr, pc @ save this location + bl .L_PROCESS16 @ process a 16-bit number + mov r12, r1 + pop {r1} @ load in the second number + mov r3, #0 + mov r8, r3 @ print leading symbols now! + mov r3, #'0' + mov r9, r3 @ make sure they are zeros! +.L_P29SKIP: + mov r0, r1 @ get ready to print second number + mov r1, #4 + add r8, r1 @ add 4 back on to digits + mov r1, r12 + mov lr, pc @ save this location + bl .L_PROCESS16 @ process a 16-bit number + b .L_STRINGLOOP + +.L_PRINTHEXLC: + mov r7, #39 + mov r12, r7 @ lowercase offset + b .L_PRINTHEX +.L_PRINTHEXUC: + mov r7, #7 + mov r12, r7 @ uppercase offset +.L_PRINTHEX: + mov r4, r10 @ r4 <- current parameter pointer + ldr r2, [r4] @ r2 <- integer to print + add r4, #4 + mov r10, r4 @ increase parameter pointer + mov r4, #28 @ r4 <- 8 digits to cycle through + mov r6, #0xF @ r6 <- nibble mask + mov r7, #0 @ r7 <- print flag +.L_PRINTHEXLOOP: + mov r3, r2 + lsr r3, r4 + and r3, r6 @ r3 <- (n >> (cycle * 4)) & 0xF + orr r7, r3 @ if we have not encountered a digit + beq .L_PH_LEADZERO @ then it is a leading zero + add r3, #'0' + mov r5, r12 @ get ready to print a letter + cmp r3, #'9' @ if the digit is in the alpha range + bgt .L_PH_ALPHA @ then print a letter + mov r5, #0 @ else do nothing +.L_PH_ALPHA: + add r3, r5 @ add offset to correct letter + strb r3, [r0] @ store the char in memory + add r0, #1 @ advance pointer to next char + sub r4, #4 @ advance to next digit + bge .L_PRINTHEXLOOP @ loop until done + b .L_STRINGLOOP + +.L_PH_LEADZERO: + lsr r5, r4, #2 @ r5 <- which digit we are on + sub r4, #4 @ if this is our last digit + blt .L_PH_FINAL @ then print a zero for sure + cmp r8, r5 @ if r8 < current digit + ble .L_PRINTHEXLOOP @ then keep looping + mov r5, r9 @ r5 <- leading symbol to print + strb r5, [r0] @ store the char in memory + add r0, #1 @ advance pointer to next char + b .L_PRINTHEXLOOP +.L_PH_FINAL: + mov r3, #'0' @ if n == 0, print at least one 0 + strb r3, [r0] + add r0, #1 + b .L_STRINGLOOP + +.L_PROCESS16: + mov r12, r1 @ free up registers + mov r5, #0xF + lsr r1, r0, #4 + lsr r2, r0, #8 + lsr r3, r0, #12 + and r0, r5 @ r0 <- n & 0xF + and r1, r5 @ r1 <- (n >> 4) & 0xF + and r2, r5 @ r2 <- (n >> 8) & 0xF + and r3, r5 @ r3 <- (n >> 12) & 0xF + mov r6, r3 + add r6, r2 + add r6, r1 + lsl r5, r6, #2 + lsl r6, r6, #1 + add r0, r6 + add r0, r5 @ r0 <- 6 * (d3 + d2 + d1) + d0 + @ divide by ten: multiply by 0x19A shifted right by 12 + lsr r5, r0, #2 + add r5, r0 + lsr r5, r5, #1 @ r5 <- ((d0 >> 2) + i) >> 1 + add r5, r0 + lsr r5, r5, #3 @ r5 = (r5 + d0) >> 3 + add r5, r0 + lsr r5, r5, #1 @ r5 = (r5 + d0) >> 1 + add r5, r0 + lsr r5, r5, #4 @ r5 <- d0 / 10 + @ calculate remainder as d0 + lsl r6, r5, #2 + add r6, r5 + lsl r6, r6, #1 @ r6 <- q * 10 + sub r0, r6 @ r0 <- d0 - (q * 10) + @ finished with d0, now calculate d1 + lsl r6, r3, #3 + add r5, r6 + add r5, r3 @ r5 <- q + 9 * d3 + lsl r6, r2, #2 + add r5, r6 + add r5, r2 @ r5 <- q + 9 * d3 + 5 * d2 + add r1, r5 @ r1 <- d1 + r5 + beq .L_LEAD_D1 + @ divide d1 by ten: multiply by 0x19A shifted right by 12 + lsr r5, r1, #2 + add r5, r1 + lsr r5, r5, #1 + add r5, r1 + lsr r5, r5, #3 + add r5, r1 + lsr r5, r5, #1 + add r5, r1 + lsr r5, r5, #4 @ r5 <- d1 / 10 + @ calculate remainder as d1 + lsl r6, r5, #2 + add r6, r5 + lsl r6, r6, #1 + sub r1, r6 @ r1 <- d1 - (q * 10) + @ finished with d1, now calculate d2 + lsl r2, r2, #1 + add r2, r5 @ r2 <- 2 * d2 + q + mov r5, r2 + orr r5, r3 @ if (!d2) && (!d3) + beq .L_LEAD_D2 @ then skip + @ divide d2 by ten: multiply by 0x1A >> 8 is sufficient + lsr r5, r2, #2 + add r5, r2 + lsr r5, r5, #1 + add r5, r2 + lsr r5, r5, #4 @ r5 <- d2 / 10 + @ calculate remainder as d2 + lsl r6, r5, #2 + add r6, r5 + lsl r6, r6, #1 + sub r2, r6 @ r2 <- d2 - (q * 10) + @ finished with d2, now calculate d3 + lsl r3, r3, #2 + add r3, r5 + beq .L_LEAD_D3 + @ divide d3 by ten: multiply by 0x1A >> 8 is sufficient + lsr r5, r3, #2 + add r5, r3 + lsr r5, r5, #1 + add r5, r3 + lsr r5, r5, #4 @ r5 <- d3 / 10 + @ calculate remainder as d3 + lsl r6, r5, #2 + add r6, r5 + lsl r6, r6, #1 + sub r3, r6 @ r3 <- d3 - (q * 10) + @ finished with d3, d4 will automatically be quotient + mov r4, r5 + beq .L_LEAD_D4 + @ now print any leading digits if we are using all five + mov r5, r8 + mov r6, r9 + sub r5, #4 @ already printed five digits +.L_EXTRA_LEAD_LOOP: + sub r5, #1 + ble .L_DONE_EXTRA_LEAD + strb r6, [r7] @ print a leading character + add r7, #1 + b .L_EXTRA_LEAD_LOOP +.L_DONE_EXTRA_LEAD: + @ now print the fifth digit (d4) + add r4, #'0' @ r4 <- d4 + '0' + strb r4, [r7] @ store a character + add r7, #1 @ advance string pointer +.L_DONE_D4: + add r3, #'0' + strb r3, [r7] + add r7, #1 +.L_DONE_D3: + add r2, #'0' + strb r2, [r7] + add r7, #1 +.L_DONE_D2: + add r1, #'0' + strb r1, [r7] + add r7, #1 +.L_DONE_D1: + add r0, #'0' + strb r0, [r7] + add r7, #1 + @ Done at last! Clean up and return to calling routine + mov r0, r7 @ restore r0 <- dest string address + mov r1, r12 @ restore r1 <- source string address + mov pc, lr @ return from subroutine + +.L_LEAD_D4: + mov r5, r9 @ r5 <- leading character + mov r6, r8 + sub r6, #4 @ r6 <- # of chars to print + ble .L_DONE_D4 +.L_IN_D4: + strb r5, [r7] @ store a character + add r7, #1 @ advance string pointer + sub r6, #1 @ if chars to print > 0 + bgt .L_IN_D4 @ then loop + b .L_DONE_D4 + +.L_LEAD_D3: + mov r5, r9 @ r5 <- leading character + mov r6, r8 + sub r6, #3 @ r6 <- # of chars to print + ble .L_DONE_D3 +.L_IN_D3: + strb r5, [r7] @ store a character + add r7, #1 @ advance string pointer + sub r6, #1 @ if chars to print > 0 + bgt .L_IN_D3 @ then loop + b .L_DONE_D3 + +.L_LEAD_D2: + mov r5, r9 @ r5 <- leading character + mov r6, r8 + sub r6, #2 @ r6 <- # of chars to print + ble .L_DONE_D2 +.L_IN_D2: + strb r5, [r7] @ store a character + add r7, #1 @ advance string pointer + sub r6, #1 @ if chars to print > 0 + bgt .L_IN_D2 @ then loop + b .L_DONE_D2 + +.L_LEAD_D1: + mov r5, r9 @ r5 <- leading character + mov r6, r8 + sub r6, #1 @ r6 <- # of chars to print + ble .L_DONE_D1 +.L_IN_D1: + strb r5, [r7] @ store a character + add r7, #1 @ advance string pointer + sub r6, #1 @ if chars to print > 0 + bgt .L_IN_D1 @ then loop + b .L_DONE_D1 diff --git a/src/dusk/d_src/dusk/contrib/posprintf.d b/src/dusk/d_src/dusk/contrib/posprintf.d new file mode 100644 index 0000000..40f0777 --- /dev/null +++ b/src/dusk/d_src/dusk/contrib/posprintf.d @@ -0,0 +1,5 @@ +module dusk.contrib.posprintf; + +extern (C): + +extern void posprintf(char*, const char*, ...); From 8d88b901a225e212accf60d7d270610222b4568f Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sat, 8 Jan 2022 02:32:40 -0800 Subject: [PATCH 14/32] eat prints if not open --- src/dusk/c_src/contrib/mgba.c | 9 ++++++++- src/dusk/d_src/dusk/contrib/mgba.d | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/dusk/c_src/contrib/mgba.c b/src/dusk/c_src/contrib/mgba.c index cb3c2e4..bcf3b46 100644 --- a/src/dusk/c_src/contrib/mgba.c +++ b/src/dusk/c_src/contrib/mgba.c @@ -1,7 +1,10 @@ #include "contrib/mgba.h" +int mgba_is_open = 0; + #ifdef DEBUG void mgba_printf(int level, const char* ptr, ...) { + if (!mgba_is_open) return; va_list args; level &= 0x7; va_start(args, ptr); @@ -12,7 +15,11 @@ void mgba_printf(int level, const char* ptr, ...) { BOOL mgba_open(void) { *REG_DEBUG_ENABLE = 0xC0DE; - return *REG_DEBUG_ENABLE == 0x1DEA; + if (*REG_DEBUG_ENABLE == 0x1DEA) { + mgba_is_open = 1; + return TRUE; + } + return FALSE; } void mgba_close(void) { *REG_DEBUG_ENABLE = 0; } diff --git a/src/dusk/d_src/dusk/contrib/mgba.d b/src/dusk/d_src/dusk/contrib/mgba.d index 8c9b129..624c13b 100644 --- a/src/dusk/d_src/dusk/contrib/mgba.d +++ b/src/dusk/d_src/dusk/contrib/mgba.d @@ -17,6 +17,7 @@ enum MGBALogLevel DEBUG = 4 } +__gshared extern int mgba_is_open; void mgba_printf (int level, const(char)* ptr, ...); bool mgba_open (); void mgba_close (); From 15e51e8091c1a0f637f34cd7334b948ff1e88d52 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sat, 8 Jan 2022 12:18:38 -0800 Subject: [PATCH 15/32] add ds_assert --- src/dusk/d_src/dusk/dbg.d | 24 ++++++++++++++++++++++++ src/dusk/d_src/dusk/package.d | 1 + 2 files changed, 25 insertions(+) create mode 100644 src/dusk/d_src/dusk/dbg.d diff --git a/src/dusk/d_src/dusk/dbg.d b/src/dusk/d_src/dusk/dbg.d new file mode 100644 index 0000000..6f84f2a --- /dev/null +++ b/src/dusk/d_src/dusk/dbg.d @@ -0,0 +1,24 @@ +/* debug utils */ +module dusk.dbg; + +extern (C) nothrow @nogc: +version (DEBUG) { + private { + void mgba_printf(int level, const(char)* ptr, ...); + void exit(int status); + } + + pragma(inline, true) void ds_assert_func(bool cond, string msg, string file, int line) { + if (cond) + return; + + // report fatal error to mgba + mgba_printf(0, "Assertion failed at %s:%d: %s\n", cast(char*) file, line, cast(char*) msg); + + exit(1); + } + + void ds_assert(bool cond, string msg = "", string file = __FILE__, int line = __LINE__) { + ds_assert_func(cond, msg, file, line); + } +} diff --git a/src/dusk/d_src/dusk/package.d b/src/dusk/d_src/dusk/package.d index fd8b57e..7da67d4 100644 --- a/src/dusk/d_src/dusk/package.d +++ b/src/dusk/d_src/dusk/package.d @@ -5,4 +5,5 @@ public { import dusk.sys; import dusk.sprites; import dusk.save; + import dusk.dbg; } \ No newline at end of file From 221996129b6f8b09e445f552c43346df79403e35 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sun, 9 Jan 2022 02:27:31 -0800 Subject: [PATCH 16/32] badbrok --- src/dusk/d_src/dusk/sprites.d | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index b6507ae..63a42ec 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -353,7 +353,7 @@ vu16* dusk_get_background_register(u8 bg_id) { } } -void dusk_background_upload_raw(GritImage* img, int cbb, int sbb) { +void dusk_background_upload_raw(GritImage* img, int cbb, int sbb, int pal_offset = 0) { // TODO: support selecting slot // 1. upload the atlas tile palette to bg palette memory @@ -363,7 +363,18 @@ void dusk_background_upload_raw(GritImage* img, int cbb, int sbb) { // // 3. upload the map (SBB) // memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); - memcpy32(&pal_bg_bank[0], img.pal, img.pal_sz / 4); + // fix tiles to point at new palette pos + if (pal_offset > 0) { + auto raw_tdata = cast(u8*) img.tiles; + for (int i = 0; i < img.tile_sz; i += 64) { + auto raw_tile = cast(u8[64]*)raw_tdata[i]; + for (int j = 0; j < 64; j++) { + raw_tile[0][j] += pal_offset; + } + } + } + + memcpy32(&pal_bg_bank[0][pal_offset], img.pal, img.pal_sz / 4); version (USE_DMA) { dma3_cpy(&tile_mem[cbb][0], img.tiles, img.tile_sz); } else { From c4d91368d4a573601c1c33f11c296edde6107564 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sun, 9 Jan 2022 11:11:15 -0800 Subject: [PATCH 17/32] simplify palfix --- src/dusk/d_src/dusk/sprites.d | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index 63a42ec..3fc6780 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -367,9 +367,8 @@ void dusk_background_upload_raw(GritImage* img, int cbb, int sbb, int pal_offset if (pal_offset > 0) { auto raw_tdata = cast(u8*) img.tiles; for (int i = 0; i < img.tile_sz; i += 64) { - auto raw_tile = cast(u8[64]*)raw_tdata[i]; for (int j = 0; j < 64; j++) { - raw_tile[0][j] += pal_offset; + raw_tdata[i + j] += pal_offset; } } } From 92d4ddad85e6384fa66cc7bb5cd201e0fc32560f Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sun, 9 Jan 2022 11:37:04 -0800 Subject: [PATCH 18/32] fix pal offset bg --- src/dusk/d_src/dusk/sprites.d | 37 ++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index 3fc6780..a0df4fa 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -356,32 +356,37 @@ vu16* dusk_get_background_register(u8 bg_id) { void dusk_background_upload_raw(GritImage* img, int cbb, int sbb, int pal_offset = 0) { // TODO: support selecting slot - // 1. upload the atlas tile palette to bg palette memory - // memcpy32(&pal_bg_bank[0], img.pal, img.pal_sz / 4); - // // 2. upload the atlas tiles to bg tile memory (CBB) - // memcpy32(&tile_mem[cbb][0], img.tiles, img.tile_sz / 4); - // // 3. upload the map (SBB) - // memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); - - // fix tiles to point at new palette pos + // copy palette and se + memcpy32(&pal_bg_bank[0][pal_offset], img.pal, img.pal_sz / 4); + memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); + + // copy tiles + auto tile_data = cast(u8*) img.tiles; + if (pal_offset > 0) { - auto raw_tdata = cast(u8*) img.tiles; + // we need to copy tiles to ram so we can edit them + tile_data = cast(u8*) malloc(img.tile_sz); + memcpy(tile_data, img.tiles, img.tile_sz); + + // fix tiles to point at new palette pos for (int i = 0; i < img.tile_sz; i += 64) { for (int j = 0; j < 64; j++) { - raw_tdata[i + j] += pal_offset; + tile_data[i + j] += pal_offset; } } } - memcpy32(&pal_bg_bank[0][pal_offset], img.pal, img.pal_sz / 4); + // copy tiles to vram version (USE_DMA) { - dma3_cpy(&tile_mem[cbb][0], img.tiles, img.tile_sz); + dma3_cpy(&tile_mem[cbb][0], tile_data, img.tile_sz); } else { - memcpy32(&tile_mem[cbb][0], img.tiles, img.tile_sz / 4); + memcpy32(&tile_mem[cbb][0], tile_data, img.tile_sz / 4); + } + + if (pal_offset > 0) { + // free the working tile data we copied + free(tile_data); } - memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); - // dma3_cpy(&pal_bg_bank[0], img.pal, img.pal_sz); - // dma3_cpy(&se_mem[sbb][0], img.map, img.map_sz); } void dusk_background_make(u8 bg_id, u16 size, Background bg) { From 7482bb649d70dc89cbcf3c83d188e42e0e3841d0 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sun, 9 Jan 2022 12:20:45 -0800 Subject: [PATCH 19/32] fix bgupl --- src/dusk/d_src/dusk/sprites.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index a0df4fa..a79f272 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -357,7 +357,7 @@ void dusk_background_upload_raw(GritImage* img, int cbb, int sbb, int pal_offset // TODO: support selecting slot // copy palette and se - memcpy32(&pal_bg_bank[0][pal_offset], img.pal, img.pal_sz / 4); + memcpy32(&pal_bg_mem[pal_offset], img.pal, img.pal_sz / 4); memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); // copy tiles From a1706b654f8a17594d84d212f401d8c4667d4020 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sun, 9 Jan 2022 15:13:01 -0800 Subject: [PATCH 20/32] assert always available --- src/dusk/d_src/dusk/dbg.d | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/dusk/d_src/dusk/dbg.d b/src/dusk/d_src/dusk/dbg.d index 6f84f2a..8eec9e8 100644 --- a/src/dusk/d_src/dusk/dbg.d +++ b/src/dusk/d_src/dusk/dbg.d @@ -2,23 +2,23 @@ module dusk.dbg; extern (C) nothrow @nogc: -version (DEBUG) { - private { - void mgba_printf(int level, const(char)* ptr, ...); - void exit(int status); - } +private { + void mgba_printf(int level, const(char)* ptr, ...); + void exit(int status); +} - pragma(inline, true) void ds_assert_func(bool cond, string msg, string file, int line) { - if (cond) - return; +pragma(inline, true) void ds_assert_func(bool cond, string msg, string file, int line) { + if (cond) + return; + version (DEBUG) { // report fatal error to mgba mgba_printf(0, "Assertion failed at %s:%d: %s\n", cast(char*) file, line, cast(char*) msg); - - exit(1); } - void ds_assert(bool cond, string msg = "", string file = __FILE__, int line = __LINE__) { - ds_assert_func(cond, msg, file, line); - } + exit(1); +} + +void ds_assert(bool cond, string msg = "", string file = __FILE__, int line = __LINE__) { + ds_assert_func(cond, msg, file, line); } From 942cba3184251c21cc2131dd2e81eef2a14f12f2 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Wed, 12 Jan 2022 18:32:25 -0800 Subject: [PATCH 21/32] convert gbamap to single file --- src/dusk/c_src/contrib/background.h | 46 ----- src/dusk/c_src/contrib/bitField.h | 8 - src/dusk/c_src/contrib/gbamap.c | 216 ++++++++++++++++++++++ src/dusk/c_src/contrib/initMapRegisters.c | 12 -- src/dusk/c_src/contrib/loadMapFromROM.c | 43 ----- src/dusk/c_src/contrib/loadObject.c | 11 -- src/dusk/c_src/contrib/loadObjectID.c | 8 - src/dusk/c_src/contrib/loadPosition.c | 9 - src/dusk/c_src/contrib/loadString.c | 9 - src/dusk/c_src/contrib/memoryMap.h | 17 -- src/dusk/c_src/contrib/popValue.c | 8 - src/dusk/c_src/contrib/setMapOnScreen.c | 25 --- src/dusk/c_src/contrib/shiftMap.c | 8 - src/dusk/c_src/contrib/shiftMapLayer.c | 7 - src/dusk/c_src/contrib/shiftMapObjects.c | 11 -- src/dusk/c_src/contrib/types.h | 34 ---- src/dusk/c_src/contrib/video.h | 29 --- src/dusk/include/contrib/gbamap.h | 37 ++-- src/dusk/include/contrib/gbamap_object.h | 24 --- 19 files changed, 239 insertions(+), 323 deletions(-) delete mode 100644 src/dusk/c_src/contrib/background.h delete mode 100644 src/dusk/c_src/contrib/bitField.h create mode 100644 src/dusk/c_src/contrib/gbamap.c delete mode 100644 src/dusk/c_src/contrib/initMapRegisters.c delete mode 100644 src/dusk/c_src/contrib/loadMapFromROM.c delete mode 100644 src/dusk/c_src/contrib/loadObject.c delete mode 100644 src/dusk/c_src/contrib/loadObjectID.c delete mode 100644 src/dusk/c_src/contrib/loadPosition.c delete mode 100644 src/dusk/c_src/contrib/loadString.c delete mode 100644 src/dusk/c_src/contrib/memoryMap.h delete mode 100644 src/dusk/c_src/contrib/popValue.c delete mode 100644 src/dusk/c_src/contrib/setMapOnScreen.c delete mode 100644 src/dusk/c_src/contrib/shiftMap.c delete mode 100644 src/dusk/c_src/contrib/shiftMapLayer.c delete mode 100644 src/dusk/c_src/contrib/shiftMapObjects.c delete mode 100644 src/dusk/c_src/contrib/types.h delete mode 100644 src/dusk/c_src/contrib/video.h delete mode 100644 src/dusk/include/contrib/gbamap_object.h diff --git a/src/dusk/c_src/contrib/background.h b/src/dusk/c_src/contrib/background.h deleted file mode 100644 index 1eafaf2..0000000 --- a/src/dusk/c_src/contrib/background.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef BACKGROUND_H -#define BACKGROUND_H - -#include "./video.h" - -/** - * Defines the background control. - */ - -typedef u16 ScreenEntry; - -typedef struct { - u32 data[8]; -} Tile; - -typedef ScreenEntry ScreenBlock[1024]; -typedef Tile CharBlock[512]; - -#define MEMORY_BACKGROUND_PALETTE ((Color*)MEMORY_PALETTE) -#define MEMORY_BACKGROUND_PALETTE_SIZE 0x00200 - -#define MEMORY_SCREEN_BLOCK ((ScreenBlock*)MEMORY_VIDEORAM) -#define MEMORY_CHAR_BLOCK ((CharBlock*)MEMORY_VIDEORAM) - -#define REGISTER_BACKGROUND_CONTROL ((vu16*)(REGISTER_BASE+0x0008)) -#define REGISTER_BACKGROUND_OFFSET ((BackgroundPoint*)(REGISTER_BASE+0x0010)) - -#define FLAG_BACKGROUND_4BPP 0 -#define FLAG_BACKGROUND_8BPP 0x0080 -#define FLAG_BACKGROUND_REGULAR_32x32 0 -#define FLAG_BACKGROUND_REGULAR_64x32 0x4000 -#define FLAG_BACKGROUND_REGULAR_32x64 0x8000 -#define FLAG_BACKGROUND_REGULAR_64x64 0xC000 - -#define MASK_FLAG_BACKGROUND_CHAR_BLOCK 0x000C -#define SHIFT_FLAG_BACKGROUND_CHAR_BLOCK 2 -#define FLAG_BACKGROUND_CHAR_BLOCK(n) ((n)<>name##_SHIFT ) -#define BIT_FIELD_SET(y, x, name) (y = ((y)&~name##_MASK) | BIT_FIELD_PREP(x,name) ) - -#endif \ No newline at end of file diff --git a/src/dusk/c_src/contrib/gbamap.c b/src/dusk/c_src/contrib/gbamap.c new file mode 100644 index 0000000..c79545c --- /dev/null +++ b/src/dusk/c_src/contrib/gbamap.c @@ -0,0 +1,216 @@ +#include +#include "gbamap.h" + +typedef unsigned char u8, byte; +typedef unsigned short u16, hword; +typedef unsigned int u32, word; +typedef unsigned long long u64; + +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long long s64; + +typedef volatile u8 vu8; +typedef volatile u16 vu16; +typedef volatile u32 vu32; +typedef volatile u64 vu64; + +typedef volatile s8 vs8; +typedef volatile s16 vs16; +typedef volatile s32 vs32; +typedef volatile s64 vs64; + +#define INLINE static inline +#define ALIGN(n) __attribute__((aligned(n))) + +#define TRUE 1 +#define FALSE 0 + +/** + * Defines the general memory locations. + */ + +#define MEMORY_IO 0x04000000 +#define MEMORY_PALETTE 0x05000000 +#define MEMORY_VIDEORAM 0x06000000 +#define MEMORY_OBJECT_ATTRIBUTES 0x07000000 + +#define REGISTER_BASE MEMORY_IO + +#define BIT_FIELD_PREP(x, name) (((x) << name##_SHIFT) & name##_MASK) +#define BIT_FIELD_GET(y, name) (((y)&name##_MASK) >> name##_SHIFT) +#define BIT_FIELD_SET(y, x, name) (y = ((y) & ~name##_MASK) | BIT_FIELD_PREP(x, name)) + +typedef u16 Color; + +#define SCREEN_WIDTH 240 +#define SCREEN_HEIGHT 160 + +#define REGISTER_DISPLAY_CONTROL *(vu32*)(REGISTER_BASE + 0x0000) +#define REGISTER_VERTICAL_COUNT *(vu16*)(REGISTER_BASE + 0x0006) + +#define FLAG_MODE0 0 + +/** + * Wait till the background has been rendered and it is safe to modify it. + **/ +INLINE void videoSync() { + while (REGISTER_VERTICAL_COUNT >= 160) + ; + while (REGISTER_VERTICAL_COUNT < 160) + ; +} + +typedef u16 ScreenEntry; + +typedef struct { + u32 data[8]; +} Tile; + +typedef ScreenEntry ScreenBlock[1024]; +typedef Tile CharBlock[512]; + +#define MEMORY_BACKGROUND_PALETTE ((Color*)MEMORY_PALETTE) +#define MEMORY_BACKGROUND_PALETTE_SIZE 0x00200 + +#define MEMORY_SCREEN_BLOCK ((ScreenBlock*)MEMORY_VIDEORAM) +#define MEMORY_CHAR_BLOCK ((CharBlock*)MEMORY_VIDEORAM) + +#define REGISTER_BACKGROUND_CONTROL ((vu16*)(REGISTER_BASE + 0x0008)) +#define REGISTER_BACKGROUND_OFFSET ((BackgroundPoint*)(REGISTER_BASE + 0x0010)) + +#define FLAG_BACKGROUND_4BPP 0 +#define FLAG_BACKGROUND_8BPP 0x0080 +#define FLAG_BACKGROUND_REGULAR_32x32 0 +#define FLAG_BACKGROUND_REGULAR_64x32 0x4000 +#define FLAG_BACKGROUND_REGULAR_32x64 0x8000 +#define FLAG_BACKGROUND_REGULAR_64x64 0xC000 + +#define MASK_FLAG_BACKGROUND_CHAR_BLOCK 0x000C +#define SHIFT_FLAG_BACKGROUND_CHAR_BLOCK 2 +#define FLAG_BACKGROUND_CHAR_BLOCK(n) ((n) << SHIFT_FLAG_BACKGROUND_CHAR_BLOCK) + +#define MASK_FLAG_BACKGROUND_SCREEN_BLOCK_MASK 0x1F00 +#define SHIFT_FLAG_BACKGROUND_SCREEN_BLOCK 8 +#define FLAG_BACKGROUND_SCREEN_BLOCK(n) ((n) << SHIFT_FLAG_BACKGROUND_SCREEN_BLOCK) + +#define FLAG_BACKGROUND(n) ((0x0100) << n) +#define FLAG_BACKGROUND_PRIORITY(n) ((n * 1) & 0x0003) + +void map_init_registers() { + // turn off all backgrounds + for (u32 layerIndex = MAX_LAYERS; layerIndex-- > 0;) { + REGISTER_BACKGROUND_CONTROL[layerIndex] = 0; + } + + // reset display control + REGISTER_DISPLAY_CONTROL = 0; +} + +Map map_load_from_rom(const u16* map_data) { + Map map; + u16 index = 0; + + map.sizeFlag = map_data[index++]; + + map.paletteLength = map_data[index++]; + map.palette = &map_data[index]; + index += map.paletteLength + 1; + + map.tileSetLength = map_data[index++]; + map.tileSet = &map_data[index]; + index += map.tileSetLength + 1; + + map.terrainMapLength = map_data[index++]; + map.terrainMap = &map_data[index]; + index += map.terrainMapLength; + + map.numLayers = map_data[index++]; + map.numLayers = map.numLayers > MAX_LAYERS ? MAX_LAYERS : map.numLayers; + map.tileMapLength = map_data[index++]; + for (u32 layerIndex = 0; layerIndex < map.numLayers; ++layerIndex) { + map.tileMapLayers[layerIndex] = &map_data[index]; + index += map.tileMapLength; + } + + u16 lengthObjectData = map_data[index++]; + u32 endObjectData = index + lengthObjectData; + u32 objectCount = 0; + while (index != endObjectData) { + MapObject object = map_load_object(map_data, &index); + map.objects[objectCount] = object; + objectCount++; + } + map.numObjects = objectCount; + + return map; +} + +MapObject map_load_object(const u16* object_data, u16* index) { + MapObject object; + object.id = map_load_object_id(object_data, index); + object.position = map_load_object_position(object_data, index); + object.name = map_load_string(object_data, index); + object.type = map_load_string(object_data, index); + return object; +} + +u32 map_load_object_id(const u16* idData, u16* index) { + u32 upperID = map_pop_value(idData, index); + u32 lowerID = map_pop_value(idData, index); + return (upperID << 16) | lowerID; +} + +ObjectPoint map_load_object_position(const u16* positionData, u16* index) { + ObjectPoint position; + position.x = map_pop_value(positionData, index); + position.y = map_pop_value(positionData, index); + return position; +} + +const char* map_load_string(const u16* stringData, u16* index) { + u16 length = map_pop_value(stringData, index); + const char* string = (const char*)&stringData[*index]; + *index += length; + return string; +} + +u16 map_pop_value(const u16* data, u16* index) { + u16 value = data[*index]; + *index += 1; + return value; +} + +void map_set_onscreen(Map map) { + memcpy(MEMORY_BACKGROUND_PALETTE, map.palette, map.paletteLength * 2); + memcpy(&MEMORY_CHAR_BLOCK[0][0], map.tileSet, map.tileSetLength * 2); + + u32 screenBlockStep = map.tileMapLength / ENTRIES_IN_SCREEN_BLOCK; + u32 usedBackgrounds = 0x00; + for (u32 layerIndex = map.numLayers; layerIndex-- > 0;) { + u32 screenBlockIndex = NUM_SCREEN_BLOCKS - screenBlockStep * (layerIndex + 1); + memcpy(&MEMORY_SCREEN_BLOCK[screenBlockIndex][0], map.tileMapLayers[layerIndex], map.tileMapLength * 2); + + REGISTER_BACKGROUND_CONTROL[layerIndex] |= + FLAG_BACKGROUND_CHAR_BLOCK(0) | FLAG_BACKGROUND_SCREEN_BLOCK(screenBlockIndex) | FLAG_BACKGROUND_8BPP | + map.sizeFlag | FLAG_BACKGROUND_PRIORITY(map.numLayers - layerIndex); + usedBackgrounds |= FLAG_BACKGROUND(layerIndex); + } + + REGISTER_DISPLAY_CONTROL |= FLAG_MODE0 | usedBackgrounds; +} + +void map_shift(Map map, BackgroundPoint offset) { + for (u16 layer = 0; layer < map.numLayers; layer++) + map_shift_layer(layer, offset); +} + +void map_shift_layer(u16 layer, BackgroundPoint offset) { REGISTER_BACKGROUND_OFFSET[layer] = offset; } + +void map_shift_objects(MapObject* objects, ObjectPoint shift, u32 count) { + for (u32 index = 0; index < count; index++) { + objects[index].position.x -= shift.x; + objects[index].position.y -= shift.y; + } +} \ No newline at end of file diff --git a/src/dusk/c_src/contrib/initMapRegisters.c b/src/dusk/c_src/contrib/initMapRegisters.c deleted file mode 100644 index e626227..0000000 --- a/src/dusk/c_src/contrib/initMapRegisters.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "gbamap.h" -#include "./background.h" - -void map_init_registers() { - // turn off all backgrounds - for (u32 layerIndex = MAX_LAYERS; layerIndex-- > 0;) { - REGISTER_BACKGROUND_CONTROL[layerIndex] = 0; - } - - // reset display control - REGISTER_DISPLAY_CONTROL = 0; -} \ No newline at end of file diff --git a/src/dusk/c_src/contrib/loadMapFromROM.c b/src/dusk/c_src/contrib/loadMapFromROM.c deleted file mode 100644 index e83b833..0000000 --- a/src/dusk/c_src/contrib/loadMapFromROM.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "gbamap.h" -#include -#include "./types.h" - -Map map_load_from_rom(const u16 *map_data) { - Map map; - u16 index = 0; - - map.sizeFlag = map_data[index++]; - - map.paletteLength = map_data[index++]; - map.palette = &map_data[index]; - index += map.paletteLength + 1; - - map.tileSetLength = map_data[index++]; - map.tileSet = &map_data[index]; - index += map.tileSetLength + 1; - - map.terrainMapLength = map_data[index++]; - map.terrainMap = &map_data[index]; - index += map.terrainMapLength; - - map.numLayers = map_data[index++]; - map.numLayers = map.numLayers > MAX_LAYERS ? MAX_LAYERS : map.numLayers; - map.tileMapLength = map_data[index++]; - for (u32 layerIndex = 0; layerIndex < map.numLayers; ++layerIndex) - { - map.tileMapLayers[layerIndex] = &map_data[index]; - index += map.tileMapLength; - } - - u16 lengthObjectData = map_data[index++]; - u32 endObjectData = index + lengthObjectData; - u32 objectCount = 0; - while (index != endObjectData) { - MapObject object = map_load_object(map_data, &index); - map.objects[objectCount] = object; - objectCount++; - } - map.numObjects = objectCount; - - return map; -} diff --git a/src/dusk/c_src/contrib/loadObject.c b/src/dusk/c_src/contrib/loadObject.c deleted file mode 100644 index 7cedb1c..0000000 --- a/src/dusk/c_src/contrib/loadObject.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "gbamap_object.h" -#include "./types.h" - -MapObject map_load_object(const u16* object_data, u16* index) { - MapObject object; - object.id = map_load_object_id(object_data, index); - object.position = map_load_object_position(object_data, index); - object.name = map_load_string(object_data, index); - object.type = map_load_string(object_data, index); - return object; -} \ No newline at end of file diff --git a/src/dusk/c_src/contrib/loadObjectID.c b/src/dusk/c_src/contrib/loadObjectID.c deleted file mode 100644 index 4329f2a..0000000 --- a/src/dusk/c_src/contrib/loadObjectID.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "gbamap_object.h" -#include "./types.h" - -u32 map_load_object_id(const u16* idData, u16* index) { - u32 upperID = map_pop_value(idData, index); - u32 lowerID = map_pop_value(idData, index); - return (upperID << 16) | lowerID; -} \ No newline at end of file diff --git a/src/dusk/c_src/contrib/loadPosition.c b/src/dusk/c_src/contrib/loadPosition.c deleted file mode 100644 index cc01073..0000000 --- a/src/dusk/c_src/contrib/loadPosition.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "gbamap_object.h" -#include "./types.h" - -ObjectPoint map_load_object_position(const u16* positionData, u16* index) { - ObjectPoint position; - position.x = map_pop_value(positionData, index); - position.y = map_pop_value(positionData, index); - return position; -} \ No newline at end of file diff --git a/src/dusk/c_src/contrib/loadString.c b/src/dusk/c_src/contrib/loadString.c deleted file mode 100644 index c3c98cc..0000000 --- a/src/dusk/c_src/contrib/loadString.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "gbamap_object.h" -#include "./types.h" - -const char* map_load_string(const u16* stringData, u16* index) { - u16 length = map_pop_value(stringData, index); - const char* string = (const char*) &stringData[*index]; - *index += length; - return string; -} \ No newline at end of file diff --git a/src/dusk/c_src/contrib/memoryMap.h b/src/dusk/c_src/contrib/memoryMap.h deleted file mode 100644 index 11e1bef..0000000 --- a/src/dusk/c_src/contrib/memoryMap.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef MEMORY_MAP_H -#define MEMORY_MAP_H - -#include "types.h" - -/** - * Defines the general memory locations. - */ - -#define MEMORY_IO 0x04000000 -#define MEMORY_PALETTE 0x05000000 -#define MEMORY_VIDEORAM 0x06000000 -#define MEMORY_OBJECT_ATTRIBUTES 0x07000000 - -#define REGISTER_BASE MEMORY_IO - -#endif // MEMORY_MAP_H diff --git a/src/dusk/c_src/contrib/popValue.c b/src/dusk/c_src/contrib/popValue.c deleted file mode 100644 index a797d7b..0000000 --- a/src/dusk/c_src/contrib/popValue.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "gbamap_object.h" -#include "./types.h" - -u16 map_pop_value(const u16* data, u16* index) { - u16 value = data[*index]; - *index += 1; - return value; -} \ No newline at end of file diff --git a/src/dusk/c_src/contrib/setMapOnScreen.c b/src/dusk/c_src/contrib/setMapOnScreen.c deleted file mode 100644 index 05d21c7..0000000 --- a/src/dusk/c_src/contrib/setMapOnScreen.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "./background.h" -#include "gbamap.h" -#include - -void map_set_onscreen(Map map) { - memcpy(MEMORY_BACKGROUND_PALETTE, map.palette, map.paletteLength * 2); - memcpy(&MEMORY_CHAR_BLOCK[0][0], map.tileSet, map.tileSetLength * 2); - - u32 screenBlockStep = map.tileMapLength / ENTRIES_IN_SCREEN_BLOCK; - u32 usedBackgrounds = 0x00; - for (u32 layerIndex = map.numLayers; layerIndex-- > 0;) - { - u32 screenBlockIndex = NUM_SCREEN_BLOCKS - screenBlockStep * (layerIndex + 1); - memcpy(&MEMORY_SCREEN_BLOCK[screenBlockIndex][0], map.tileMapLayers[layerIndex], map.tileMapLength * 2); - - REGISTER_BACKGROUND_CONTROL[layerIndex] |= FLAG_BACKGROUND_CHAR_BLOCK(0) | - FLAG_BACKGROUND_SCREEN_BLOCK(screenBlockIndex) | - FLAG_BACKGROUND_8BPP | - map.sizeFlag | - FLAG_BACKGROUND_PRIORITY(map.numLayers - layerIndex); - usedBackgrounds |= FLAG_BACKGROUND(layerIndex); - } - - REGISTER_DISPLAY_CONTROL |= FLAG_MODE0 | usedBackgrounds; -} diff --git a/src/dusk/c_src/contrib/shiftMap.c b/src/dusk/c_src/contrib/shiftMap.c deleted file mode 100644 index 7856ad9..0000000 --- a/src/dusk/c_src/contrib/shiftMap.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "gbamap.h" -#include "./background.h" - -void map_shift(Map map, BackgroundPoint offset) -{ - for (u16 layer = 0; layer < map.numLayers; layer++) - map_shift_layer(layer, offset); -} diff --git a/src/dusk/c_src/contrib/shiftMapLayer.c b/src/dusk/c_src/contrib/shiftMapLayer.c deleted file mode 100644 index 51d6050..0000000 --- a/src/dusk/c_src/contrib/shiftMapLayer.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "./background.h" -#include "gbamap.h" - -void map_shift_layer(u16 layer, BackgroundPoint offset) -{ - REGISTER_BACKGROUND_OFFSET[layer] = offset; -} diff --git a/src/dusk/c_src/contrib/shiftMapObjects.c b/src/dusk/c_src/contrib/shiftMapObjects.c deleted file mode 100644 index f85434c..0000000 --- a/src/dusk/c_src/contrib/shiftMapObjects.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "gbamap_object.h" -#include "./types.h" - -void map_shift_objects(MapObject* objects, ObjectPoint shift, u32 count) -{ - for (u32 index = 0; index < count; index++) - { - objects[index].position.x -= shift.x; - objects[index].position.y -= shift.y; - } -} \ No newline at end of file diff --git a/src/dusk/c_src/contrib/types.h b/src/dusk/c_src/contrib/types.h deleted file mode 100644 index fabd40f..0000000 --- a/src/dusk/c_src/contrib/types.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TYPES_H -#define TYPES_H - -/** - * Defines general data types and useful macros. - */ - -typedef unsigned char u8, byte; -typedef unsigned short u16, hword; -typedef unsigned int u32, word; -typedef unsigned long long u64; - -typedef signed char s8; -typedef signed short s16; -typedef signed int s32; -typedef signed long long s64; - -typedef volatile u8 vu8; -typedef volatile u16 vu16; -typedef volatile u32 vu32; -typedef volatile u64 vu64; - -typedef volatile s8 vs8; -typedef volatile s16 vs16; -typedef volatile s32 vs32; -typedef volatile s64 vs64; - -#define INLINE static inline -#define ALIGN(n) __attribute__((aligned(n))) - -#define TRUE 1 -#define FALSE 0 - -#endif // TYPES_H diff --git a/src/dusk/c_src/contrib/video.h b/src/dusk/c_src/contrib/video.h deleted file mode 100644 index 7b4e22e..0000000 --- a/src/dusk/c_src/contrib/video.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef VIDEO_H -#define VIDEO_H - -#include "./memoryMap.h" - -/** - * Defines general video control. - */ - -typedef u16 Color; - -#define SCREEN_WIDTH 240 -#define SCREEN_HEIGHT 160 - -#define REGISTER_DISPLAY_CONTROL *(vu32*)(REGISTER_BASE+0x0000) -#define REGISTER_VERTICAL_COUNT *(vu16*)(REGISTER_BASE+0x0006) - -#define FLAG_MODE0 0 - -/** - * Wait till the background has been rendered and it is safe to modify it. - **/ -INLINE void videoSync() -{ - while(REGISTER_VERTICAL_COUNT >= 160); - while(REGISTER_VERTICAL_COUNT < 160); -} - -#endif // VIDEO_H diff --git a/src/dusk/include/contrib/gbamap.h b/src/dusk/include/contrib/gbamap.h index 6c2f3ae..92a7b86 100644 --- a/src/dusk/include/contrib/gbamap.h +++ b/src/dusk/include/contrib/gbamap.h @@ -1,24 +1,33 @@ #ifndef MAP_H #define MAP_H -#include "gbamap_object.h" +typedef struct { + unsigned short x, y; +} __attribute__((aligned(4))) ObjectPoint; + +typedef struct { + unsigned int id; + ObjectPoint position; + const char* name; + const char* type; +} MapObject; + +MapObject map_load_object(const unsigned short* object_data, unsigned short* index); +unsigned int map_load_object_id(const unsigned short* idData, unsigned short* index); +ObjectPoint map_load_object_position(const unsigned short* positionData, unsigned short* index); +const char* map_load_string(const unsigned short* stringData, unsigned short* index); +unsigned short map_pop_value(const unsigned short* data, unsigned short* index); + +void map_shift_objects(MapObject* objects, ObjectPoint shift, unsigned int count); typedef struct Map { - unsigned short sizeFlag, - paletteLength, - tileSetLength, - terrainMapLength, - numObjects, - numLayers, - tileMapLength; - - const unsigned short *palette, - *tileSet, - *terrainMap; + unsigned short sizeFlag, paletteLength, tileSetLength, terrainMapLength, numObjects, numLayers, tileMapLength; + + const unsigned short *palette, *tileSet, *terrainMap; MapObject objects[256]; - const unsigned short *tileMapLayers[3]; + const unsigned short* tileMapLayers[3]; } Map; typedef struct BackgroundPoint { @@ -29,7 +38,7 @@ typedef struct BackgroundPoint { #define ENTRIES_IN_SCREEN_BLOCK 512 #define NUM_SCREEN_BLOCKS 31 -Map map_load_from_rom(const unsigned short *map_data); +Map map_load_from_rom(const unsigned short* map_data); void map_init_registers(); void map_set_onscreen(Map map); diff --git a/src/dusk/include/contrib/gbamap_object.h b/src/dusk/include/contrib/gbamap_object.h deleted file mode 100644 index e666853..0000000 --- a/src/dusk/include/contrib/gbamap_object.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef MAP_OBJECT_H -#define MAP_OBJECT_H - -typedef struct { - unsigned short x, y; -} __attribute__((aligned(4))) ObjectPoint; - -typedef struct -{ - unsigned int id; - ObjectPoint position; - const char* name; - const char* type; -} MapObject; - -MapObject map_load_object(const unsigned short* object_data, unsigned short* index); -unsigned int map_load_object_id(const unsigned short* idData, unsigned short* index); -ObjectPoint map_load_object_position(const unsigned short* positionData, unsigned short* index); -const char* map_load_string(const unsigned short* stringData, unsigned short* index); -unsigned short map_pop_value(const unsigned short* data, unsigned short* index); - -void map_shift_objects(MapObject* objects, ObjectPoint shift, unsigned int count); - -#endif \ No newline at end of file From a157e855db5f720f890070b87309d74236378655 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sun, 23 Jan 2022 23:10:26 -0800 Subject: [PATCH 22/32] add rtc lib --- src/dusk/c_src/contrib/rtc.c | 321 ++++++++++++++++++++++++++++++ src/dusk/d_src/dusk/contrib/rtc.d | 75 +++++++ 2 files changed, 396 insertions(+) create mode 100644 src/dusk/c_src/contrib/rtc.c create mode 100644 src/dusk/d_src/dusk/contrib/rtc.d diff --git a/src/dusk/c_src/contrib/rtc.c b/src/dusk/c_src/contrib/rtc.c new file mode 100644 index 0000000..352421f --- /dev/null +++ b/src/dusk/c_src/contrib/rtc.c @@ -0,0 +1,321 @@ +// #include "rtc.h" + +#define RTC_EPOWER ( 1 ) +#define RTC_E12HOUR ( 2 ) +#define RTC_EYEAR ( 3 ) +#define RTC_EMON ( 4 ) +#define RTC_EDAY ( 5 ) +#define RTC_EWDAY ( 6 ) +#define RTC_EHOUR ( 7 ) +#define RTC_EMIN ( 8 ) +#define RTC_ESEC ( 9 ) + +typedef int rtc_time; +typedef long long int rtc_tm; + +int __rtc_init(); +int __rtc_get_status(); +rtc_time __rtc_get_time(); +rtc_tm __rtc_get_datetime(); +void __rtc_set_time( rtc_time time ); +void __rtc_set_datetime( rtc_tm datetime ); + +typedef unsigned short u16; +typedef volatile u16 vu16; + +#define GPIO_PORT_DATA ( *( vu16 * ) 0x080000c4 ) +#define GPIO_PORT_DIRECTION ( *( vu16 * ) 0x080000c6 ) +#define GPIO_PORT_READ_ENABLE ( *( vu16 * ) 0x080000c8 ) + +#define CMD( X ) ( 0x60 | ( ( X ) << 1 ) ) +#define CMD_WR( X ) ( CMD( X ) ) +#define CMD_RD( X ) ( CMD( X ) | 0x1 ) + +#define CMD_RESET ( CMD_WR( 0 ) ) +#define CMD_STATUS_READ ( CMD_RD( 1 ) ) +#define CMD_DATETIME_READ ( CMD_RD( 2 ) ) +#define CMD_TIME_READ ( CMD_RD( 3 ) ) + +#define CMD_STATUS_WRITE ( CMD_WR( 1 ) ) +#define CMD_DATETIME_WRITE ( CMD_WR( 2 ) ) +#define CMD_TIME_WRITE ( CMD_WR( 3 ) ) + +#define RTC_STATUS_INTFE ( 0x01 ) +#define RTC_STATUS_INTME ( 0x02 ) +#define RTC_STATUS_INTAE ( 0x04 ) +#define RTC_STATUS_24HOUR ( 0x40 ) +#define RTC_STATUS_POWER ( 0x80 ) + +#define TIME_BIT_AM_PM ( 0x1 << 23 ) +#define TIME_BIT_TEST ( 0x1 << 7 ) + +#define TM_YEAR( X ) ( ( ( X ) >> 48 ) & 0xff ) +#define TM_YEAR_UNIT( X ) ( ( TM_YEAR( X ) >> 0 ) & 0x0f ) + +#define TM_MONTH( X ) ( ( ( X ) >> 40 ) & 0xff ) +#define TM_MONTH_UNIT( X ) ( ( TM_MONTH( X ) >> 0 ) & 0x0f ) + +#define TM_DAY( X ) ( ( ( X ) >> 32 ) & 0xff ) +#define TM_DAY_UNIT( X ) ( ( TM_DAY( X ) >> 0 ) & 0x0f ) + +#define TM_WDAY( X ) ( ( ( X ) >> 24 ) & 0xff ) +#define TM_WDAY_UNIT( X ) ( ( TM_WDAY( X ) >> 0 ) & 0x0f ) + +#define TM_HOUR( X ) ( ( ( X ) >> 16 ) & 0xff ) +#define TM_HOUR_UNIT( X ) ( ( TM_HOUR( X ) >> 0 ) & 0x0f ) + +#define TM_MIN( X ) ( ( ( X ) >> 8 ) & 0xff ) +#define TM_MIN_UNIT( X ) ( ( TM_MIN( X ) >> 0 ) & 0x0f ) + +#define TM_SEC( X ) ( ( ( X ) >> 0 ) & 0xff ) +#define TM_SEC_UNIT( X ) ( ( TM_SEC( X ) >> 0 ) & 0x0f ) + +static void rtc_reset(); + +int __rtc_init() { + GPIO_PORT_READ_ENABLE = 1; + int status = __rtc_get_status(); + if ( ( status & RTC_STATUS_POWER ) || ( status & RTC_STATUS_24HOUR ) == 0 ) { + // Reset (also switches to 24-hour mode) + rtc_reset(); + } + + const rtc_time time = __rtc_get_time(); + if ( time & TIME_BIT_TEST ) { + // Reset to leave test mode + rtc_reset(); + } + + status = __rtc_get_status(); + + if ( status & RTC_STATUS_POWER ) { + GPIO_PORT_READ_ENABLE = 0; + return RTC_EPOWER; + } + + if ( ( status & RTC_STATUS_24HOUR ) == 0 ) { + GPIO_PORT_READ_ENABLE = 0; + return RTC_E12HOUR; + } + + const rtc_tm datetime = __rtc_get_datetime(); + + if ( TM_YEAR( datetime ) > 0x9f || TM_YEAR_UNIT( datetime ) > 9 ) { + GPIO_PORT_READ_ENABLE = 0; + return RTC_EYEAR; + } + + if ( TM_MONTH( datetime ) == 0 || TM_MONTH( datetime ) > 0x1f || TM_MONTH_UNIT( datetime ) > 9 ) { + GPIO_PORT_READ_ENABLE = 0; + return RTC_EMON; + } + + if ( TM_DAY( datetime ) == 0 || TM_DAY( datetime ) > 0x3f || TM_DAY_UNIT( datetime ) > 9 ) { + GPIO_PORT_READ_ENABLE = 0; + return RTC_EDAY; + } + + if ( ( TM_WDAY( datetime ) & 0xf8 ) || TM_WDAY_UNIT( datetime ) > 6 ) { + GPIO_PORT_READ_ENABLE = 0; + return RTC_EWDAY; + } + + if ( TM_HOUR( datetime ) > 0x2f || TM_HOUR_UNIT( datetime ) > 9 ) { + GPIO_PORT_READ_ENABLE = 0; + return RTC_EHOUR; + } + + if ( TM_MIN( datetime ) > 0x5f || TM_MIN_UNIT( datetime ) > 9 ) { + GPIO_PORT_READ_ENABLE = 0; + return RTC_EMIN; + } + + if ( TM_SEC( datetime ) > 0x5f || TM_SEC_UNIT( datetime ) > 9 ) { + GPIO_PORT_READ_ENABLE = 0; + return RTC_ESEC; + } + + return 0; +} + +static void rtc_write_command( int cmd ); +static int rtc_read_data8(); + +int __rtc_get_status() { + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x5; + GPIO_PORT_DIRECTION = 0x7; + + rtc_write_command( CMD_STATUS_READ ); + + GPIO_PORT_DIRECTION = 0x5; + + const int status = rtc_read_data8(); + + GPIO_PORT_DATA = 1; + GPIO_PORT_DATA = 1; + + return status; +} + +static void rtc_write_command( const int cmd ) { + int bit = 7; + do { + const int value = ( ( cmd >> bit ) & 1 ) << 1; + GPIO_PORT_DATA = value | 0x4; + GPIO_PORT_DATA = value | 0x4; + GPIO_PORT_DATA = value | 0x4; + GPIO_PORT_DATA = value | 0x5; + } while ( bit-- ); +} + +static int rtc_read_data8() { + int byte = 0; + int bit = 0; + do { + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x5; + byte |= ( ( GPIO_PORT_DATA & 0x2 ) >> 1 ) << bit; + } while ( ++bit < 8 ); + return byte; +} + +static void rtc_write_data8( int data ); + +void rtc_reset() { + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x5; + GPIO_PORT_DIRECTION = 0x7; + + rtc_write_command( CMD_RESET ); + + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x1; + + // Set initial status + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x5; + GPIO_PORT_DIRECTION = 0x7; + + rtc_write_command( CMD_STATUS_WRITE ); + rtc_write_data8( RTC_STATUS_24HOUR ); + + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x1; +} + +static void rtc_write_data8( const int data ) { + int bit = 0; + do { + const int value = ( ( data >> bit ) & 1 ) << 1; + GPIO_PORT_DATA = value | 0x4; + GPIO_PORT_DATA = value | 0x4; + GPIO_PORT_DATA = value | 0x4; + GPIO_PORT_DATA = value | 0x5; + } while ( ++bit < 8 ); +} + +static int rtc_read_data24(); + +rtc_time __rtc_get_time() { + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x5; + GPIO_PORT_DIRECTION = 0x7; + + rtc_write_command( CMD_TIME_READ ); + + GPIO_PORT_DIRECTION = 0x5; + + const int time = rtc_read_data24() & ~TIME_BIT_AM_PM; + + GPIO_PORT_DATA = 1; + GPIO_PORT_DATA = 1; + + return time; +} + +static int rtc_read_data24() { + int word = 0; + int bit = 0; + do { + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x5; + word |= ( ( GPIO_PORT_DATA & 0x2 ) >> 1 ) << bit; + } while ( ++bit < 24 ); + return ( ( word & 0xff0000 ) >> 16 ) | ( ( word & 0xff ) << 16 ) | ( word & 0xff00 ); +} + +static int rtc_read_data32(); + +rtc_tm __rtc_get_datetime() { + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x5; + GPIO_PORT_DIRECTION = 0x7; + + rtc_write_command( CMD_DATETIME_READ ); + + GPIO_PORT_DIRECTION = 0x5; + + const rtc_tm date = rtc_read_data24(); + const int time = rtc_read_data32() & ~TIME_BIT_AM_PM; + + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x1; + + return ( date << 32 ) | time; +} + +static int rtc_read_data32() { + int word = 0; + int bit = 0; + do { + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x4; + GPIO_PORT_DATA = 0x5; + word |= ( ( GPIO_PORT_DATA & 0x2 ) >> 1 ) << bit; + } while ( ++bit < 32 ); + return ( int ) ( ( word & 0xff000000 ) >> 24 ) | ( word << 24 ) | ( ( word & 0xff0000 ) >> 8 ) | ( ( word & 0xff00 ) << 8 ); +} + +void __rtc_set_time( const rtc_time time ) { + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x5; + GPIO_PORT_DIRECTION = 0x7; + + rtc_write_command( CMD_TIME_WRITE ); + + int bytes = 2; + do { + rtc_write_data8( ( time >> ( bytes * 8 ) ) & 0xff ); + } while ( bytes-- > 0 ); + + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x1; +} + +void __rtc_set_datetime( const rtc_tm datetime ) { + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x5; + GPIO_PORT_DIRECTION = 0x7; + + rtc_write_command( CMD_DATETIME_WRITE ); + + int bytes = 6; + do { + rtc_write_data8( ( int ) ( datetime >> ( bytes * 8 ) ) & 0xff ); + } while ( bytes-- > 0 ); + + GPIO_PORT_DATA = 0x1; + GPIO_PORT_DATA = 0x1; +} diff --git a/src/dusk/d_src/dusk/contrib/rtc.d b/src/dusk/d_src/dusk/contrib/rtc.d new file mode 100644 index 0000000..f831cf7 --- /dev/null +++ b/src/dusk/d_src/dusk/contrib/rtc.d @@ -0,0 +1,75 @@ +module dusk.contrib.rtc; + +import tonc.tonc_types; + +// #define RTC_EPOWER ( 1 ) +// #define RTC_E12HOUR ( 2 ) +// #define RTC_EYEAR ( 3 ) +// #define RTC_EMON ( 4 ) +// #define RTC_EDAY ( 5 ) +// #define RTC_EWDAY ( 6 ) +// #define RTC_EHOUR ( 7 ) +// #define RTC_EMIN ( 8 ) +// #define RTC_ESEC ( 9 ) +// enum RTC_EPOWER = 1; +// enum RTC_E12HOUR = 2; +// enum RTC_EYEAR = 3; +// enum RTC_EMON = 4; +// enum RTC_EDAY = 5; +// enum RTC_EWDAY = 6; +// enum RTC_EHOUR = 7; +// enum RTC_EMIN = 8; +// enum RTC_ESEC = 9; + +extern (D) { + // #define RTC_TM_YEAR( X ) ( ( ( X ) >> 48 ) & 0xff ) + // #define RTC_TM_MON( X ) ( ( ( X ) >> 40 ) & 0xff ) + // #define RTC_TM_MDAY( X ) ( ( ( X ) >> 32 ) & 0xff ) + // #define RTC_TM_WDAY( X ) ( ( ( X ) >> 24 ) & 0xff ) + // #define RTC_TM_HOUR( X ) ( ( ( X ) >> 16 ) & 0xff ) + // #define RTC_TM_MIN( X ) ( ( ( X ) >> 8 ) & 0xff ) + // #define RTC_TM_SEC( X ) ( ( ( X ) >> 0 ) & 0xff ) + + auto RTC_IN_YEAR(u64 x) { + return (x >> 48) & 0xff; + } + + auto RTC_IN_MON(u64 x) { + return (x >> 40) & 0xff; + } + + auto RTC_IN_MDAY(u64 x) { + return (x >> 32) & 0xff; + } + + auto RTC_IN_WDAY(u64 x) { + return (x >> 24) & 0xff; + } + + auto RTC_IN_HOUR(u64 x) { + return (x >> 16) & 0xff; + } + + auto RTC_IN_MIN(u64 x) { + return (x >> 8) & 0xff; + } + + auto RTC_IN_SEC(u64 x) { + return (x >> 0) & 0xff; + } +} + +// typedef int rtc_time; +// typedef long long int rtc_tm; + +alias rtc_time = int; +alias rtc_tm = s64; + +extern (C) { + int __rtc_init(); + int __rtc_get_status(); + rtc_time __rtc_get_time(); + rtc_tm __rtc_get_datetime(); + void __rtc_set_time(rtc_time time); + void __rtc_set_datetime(rtc_tm datetime); +} From 8c74fe66daddfdfdc8bc19d0dfaac4fcbba335de Mon Sep 17 00:00:00 2001 From: redthing1 Date: Sun, 23 Jan 2022 23:44:51 -0800 Subject: [PATCH 23/32] rtc ex test --- src/dusk/c_src/contrib/rtc.c | 32 +++++++++++++------------- src/dusk/d_src/dusk/contrib/rtc.d | 38 ++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/dusk/c_src/contrib/rtc.c b/src/dusk/c_src/contrib/rtc.c index 352421f..05be9c2 100644 --- a/src/dusk/c_src/contrib/rtc.c +++ b/src/dusk/c_src/contrib/rtc.c @@ -13,12 +13,12 @@ typedef int rtc_time; typedef long long int rtc_tm; -int __rtc_init(); -int __rtc_get_status(); -rtc_time __rtc_get_time(); -rtc_tm __rtc_get_datetime(); -void __rtc_set_time( rtc_time time ); -void __rtc_set_datetime( rtc_tm datetime ); +int rtc_init(); +int rtc_get_status(); +rtc_time rtc_get_time(); +rtc_tm rtc_get_datetime(); +void rtc_set_time( rtc_time time ); +void rtc_set_datetime( rtc_tm datetime ); typedef unsigned short u16; typedef volatile u16 vu16; @@ -72,21 +72,21 @@ typedef volatile u16 vu16; static void rtc_reset(); -int __rtc_init() { +int rtc_init() { GPIO_PORT_READ_ENABLE = 1; - int status = __rtc_get_status(); + int status = rtc_get_status(); if ( ( status & RTC_STATUS_POWER ) || ( status & RTC_STATUS_24HOUR ) == 0 ) { // Reset (also switches to 24-hour mode) rtc_reset(); } - const rtc_time time = __rtc_get_time(); + const rtc_time time = rtc_get_time(); if ( time & TIME_BIT_TEST ) { // Reset to leave test mode rtc_reset(); } - status = __rtc_get_status(); + status = rtc_get_status(); if ( status & RTC_STATUS_POWER ) { GPIO_PORT_READ_ENABLE = 0; @@ -98,7 +98,7 @@ int __rtc_init() { return RTC_E12HOUR; } - const rtc_tm datetime = __rtc_get_datetime(); + const rtc_tm datetime = rtc_get_datetime(); if ( TM_YEAR( datetime ) > 0x9f || TM_YEAR_UNIT( datetime ) > 9 ) { GPIO_PORT_READ_ENABLE = 0; @@ -141,7 +141,7 @@ int __rtc_init() { static void rtc_write_command( int cmd ); static int rtc_read_data8(); -int __rtc_get_status() { +int rtc_get_status() { GPIO_PORT_DATA = 0x1; GPIO_PORT_DATA = 0x5; GPIO_PORT_DIRECTION = 0x7; @@ -221,7 +221,7 @@ static void rtc_write_data8( const int data ) { static int rtc_read_data24(); -rtc_time __rtc_get_time() { +rtc_time rtc_get_time() { GPIO_PORT_DATA = 0x1; GPIO_PORT_DATA = 0x5; GPIO_PORT_DIRECTION = 0x7; @@ -255,7 +255,7 @@ static int rtc_read_data24() { static int rtc_read_data32(); -rtc_tm __rtc_get_datetime() { +rtc_tm rtc_get_datetime() { GPIO_PORT_DATA = 0x1; GPIO_PORT_DATA = 0x5; GPIO_PORT_DIRECTION = 0x7; @@ -288,7 +288,7 @@ static int rtc_read_data32() { return ( int ) ( ( word & 0xff000000 ) >> 24 ) | ( word << 24 ) | ( ( word & 0xff0000 ) >> 8 ) | ( ( word & 0xff00 ) << 8 ); } -void __rtc_set_time( const rtc_time time ) { +void rtc_set_time( const rtc_time time ) { GPIO_PORT_DATA = 0x1; GPIO_PORT_DATA = 0x5; GPIO_PORT_DIRECTION = 0x7; @@ -304,7 +304,7 @@ void __rtc_set_time( const rtc_time time ) { GPIO_PORT_DATA = 0x1; } -void __rtc_set_datetime( const rtc_tm datetime ) { +void rtc_set_datetime( const rtc_tm datetime ) { GPIO_PORT_DATA = 0x1; GPIO_PORT_DATA = 0x5; GPIO_PORT_DIRECTION = 0x7; diff --git a/src/dusk/d_src/dusk/contrib/rtc.d b/src/dusk/d_src/dusk/contrib/rtc.d index f831cf7..45796ba 100644 --- a/src/dusk/d_src/dusk/contrib/rtc.d +++ b/src/dusk/d_src/dusk/contrib/rtc.d @@ -66,10 +66,36 @@ alias rtc_time = int; alias rtc_tm = s64; extern (C) { - int __rtc_init(); - int __rtc_get_status(); - rtc_time __rtc_get_time(); - rtc_tm __rtc_get_datetime(); - void __rtc_set_time(rtc_time time); - void __rtc_set_datetime(rtc_tm datetime); + int rtc_init(); + int rtc_get_status(); + rtc_time rtc_get_time(); + rtc_tm rtc_get_datetime(); + void rtc_set_time(rtc_time time); + void rtc_set_datetime(rtc_tm datetime); +} + +alias dt_field_size = int; +struct RTCDateTime { + dt_field_size year; + dt_field_size month; + dt_field_size day; + dt_field_size wday; + dt_field_size hour; + dt_field_size min; + dt_field_size sec; +} + +extern (D) RTCDateTime rtc_get_datetime_ex() { + RTCDateTime ret; + auto rawdt = rtc_get_datetime(); + + ret.year = cast(dt_field_size) RTC_IN_YEAR(rawdt); + ret.month = cast(dt_field_size) RTC_IN_MON(rawdt); + ret.day = cast(dt_field_size) RTC_IN_MDAY(rawdt); + ret.wday = cast(dt_field_size) RTC_IN_WDAY(rawdt); + ret.hour = cast(dt_field_size) RTC_IN_HOUR(rawdt); + ret.min = cast(dt_field_size) RTC_IN_MIN(rawdt); + ret.sec = cast(dt_field_size) RTC_IN_SEC(rawdt); + + return ret; } From 4b0e415ea6f635ad607130acb09af156e8d1431e Mon Sep 17 00:00:00 2001 From: redthing1 Date: Mon, 24 Jan 2022 14:31:28 -0800 Subject: [PATCH 24/32] fix rtc datetime read --- src/dusk/d_src/dusk/contrib/rtc.d | 66 ++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/src/dusk/d_src/dusk/contrib/rtc.d b/src/dusk/d_src/dusk/contrib/rtc.d index 45796ba..db000f4 100644 --- a/src/dusk/d_src/dusk/contrib/rtc.d +++ b/src/dusk/d_src/dusk/contrib/rtc.d @@ -1,6 +1,7 @@ module dusk.contrib.rtc; import tonc.tonc_types; +import tonc.tonc_memmap; // #define RTC_EPOWER ( 1 ) // #define RTC_E12HOUR ( 2 ) @@ -29,34 +30,44 @@ extern (D) { // #define RTC_TM_HOUR( X ) ( ( ( X ) >> 16 ) & 0xff ) // #define RTC_TM_MIN( X ) ( ( ( X ) >> 8 ) & 0xff ) // #define RTC_TM_SEC( X ) ( ( ( X ) >> 0 ) & 0xff ) + // #define BCD_DECODE( x ) ( ( ( x ) & 0xfu ) + ( ( ( x ) >> 4u ) * 10u ) ) + // #define BCD_ENCODE( x ) ( ( ( x ) % 10 ) + ( ( ( x ) / 10 ) << 4 ) ) - auto RTC_IN_YEAR(u64 x) { + auto RTC_TM_YEAR(u64 x) { return (x >> 48) & 0xff; } - auto RTC_IN_MON(u64 x) { + auto RTC_TM_MON(u64 x) { return (x >> 40) & 0xff; } - auto RTC_IN_MDAY(u64 x) { + auto RTC_TM_MDAY(u64 x) { return (x >> 32) & 0xff; } - auto RTC_IN_WDAY(u64 x) { + auto RTC_TM_WDAY(u64 x) { return (x >> 24) & 0xff; } - auto RTC_IN_HOUR(u64 x) { + auto RTC_TM_HOUR(u64 x) { return (x >> 16) & 0xff; } - auto RTC_IN_MIN(u64 x) { + auto RTC_TM_MIN(u64 x) { return (x >> 8) & 0xff; } - auto RTC_IN_SEC(u64 x) { + auto RTC_TM_SEC(u64 x) { return (x >> 0) & 0xff; } + + auto BCD_DECODE(u64 x) { + return (x & 0xfu) + ((x >> 4u) * 10u); + } + + auto BCD_ENCODE(u64 x) { + return (x % 10) + ((x / 10) << 4); + } } // typedef int rtc_time; @@ -87,15 +98,40 @@ struct RTCDateTime { extern (D) RTCDateTime rtc_get_datetime_ex() { RTCDateTime ret; - auto rawdt = rtc_get_datetime(); - ret.year = cast(dt_field_size) RTC_IN_YEAR(rawdt); - ret.month = cast(dt_field_size) RTC_IN_MON(rawdt); - ret.day = cast(dt_field_size) RTC_IN_MDAY(rawdt); - ret.wday = cast(dt_field_size) RTC_IN_WDAY(rawdt); - ret.hour = cast(dt_field_size) RTC_IN_HOUR(rawdt); - ret.min = cast(dt_field_size) RTC_IN_MIN(rawdt); - ret.sec = cast(dt_field_size) RTC_IN_SEC(rawdt); + // disable interrupts + auto ime = *REG_IME; + *REG_IME = 0; + // get datetime from rtc hardware + auto rawdt = rtc_get_datetime(); + // re-enable interrupts + *REG_IME = ime; + + // ret.year = cast(dt_field_size) RTC_TM_YEAR(rawdt); + // ret.month = cast(dt_field_size) RTC_TM_MON(rawdt); + // ret.day = cast(dt_field_size) RTC_TM_MDAY(rawdt); + // ret.wday = cast(dt_field_size) RTC_TM_WDAY(rawdt); + // ret.hour = cast(dt_field_size) RTC_TM_HOUR(rawdt); + // ret.min = cast(dt_field_size) RTC_TM_MIN(rawdt); + // ret.sec = cast(dt_field_size) RTC_TM_SEC(rawdt); + + // time.tm_year = BCD_DECODE( RTC_TM_YEAR( datetime ) ) + ( 2000u - 1900u ); + // time.tm_mon = BCD_DECODE( RTC_TM_MON( datetime ) ) - 1; + // time.tm_mday = BCD_DECODE( RTC_TM_MDAY( datetime ) ); + // time.tm_wday = BCD_DECODE( RTC_TM_WDAY( datetime ) ); + + // time.tm_hour = BCD_DECODE( RTC_TM_HOUR( datetime ) ); + // time.tm_min = BCD_DECODE( RTC_TM_MIN( datetime ) ); + // time.tm_sec = BCD_DECODE( RTC_TM_SEC( datetime ) ); + + ret.year = cast(dt_field_size) BCD_DECODE(RTC_TM_YEAR(rawdt)); + ret.month = cast(dt_field_size) BCD_DECODE(RTC_TM_MON(rawdt)); + ret.day = cast(dt_field_size) BCD_DECODE(RTC_TM_MDAY(rawdt)); + ret.wday = cast(dt_field_size) BCD_DECODE(RTC_TM_WDAY(rawdt)); + + ret.hour = cast(dt_field_size) BCD_DECODE(RTC_TM_HOUR(rawdt)); + ret.min = cast(dt_field_size) BCD_DECODE(RTC_TM_MIN(rawdt)); + ret.sec = cast(dt_field_size) BCD_DECODE(RTC_TM_SEC(rawdt)); return ret; } From e03f458da3da640dc3c90723ac68afcd812dc14a Mon Sep 17 00:00:00 2001 From: redthing1 Date: Mon, 24 Jan 2022 14:43:53 -0800 Subject: [PATCH 25/32] fix rtc year --- src/dusk/d_src/dusk/contrib/rtc.d | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/src/dusk/d_src/dusk/contrib/rtc.d b/src/dusk/d_src/dusk/contrib/rtc.d index db000f4..e32348a 100644 --- a/src/dusk/d_src/dusk/contrib/rtc.d +++ b/src/dusk/d_src/dusk/contrib/rtc.d @@ -106,25 +106,8 @@ extern (D) RTCDateTime rtc_get_datetime_ex() { auto rawdt = rtc_get_datetime(); // re-enable interrupts *REG_IME = ime; - - // ret.year = cast(dt_field_size) RTC_TM_YEAR(rawdt); - // ret.month = cast(dt_field_size) RTC_TM_MON(rawdt); - // ret.day = cast(dt_field_size) RTC_TM_MDAY(rawdt); - // ret.wday = cast(dt_field_size) RTC_TM_WDAY(rawdt); - // ret.hour = cast(dt_field_size) RTC_TM_HOUR(rawdt); - // ret.min = cast(dt_field_size) RTC_TM_MIN(rawdt); - // ret.sec = cast(dt_field_size) RTC_TM_SEC(rawdt); - - // time.tm_year = BCD_DECODE( RTC_TM_YEAR( datetime ) ) + ( 2000u - 1900u ); - // time.tm_mon = BCD_DECODE( RTC_TM_MON( datetime ) ) - 1; - // time.tm_mday = BCD_DECODE( RTC_TM_MDAY( datetime ) ); - // time.tm_wday = BCD_DECODE( RTC_TM_WDAY( datetime ) ); - - // time.tm_hour = BCD_DECODE( RTC_TM_HOUR( datetime ) ); - // time.tm_min = BCD_DECODE( RTC_TM_MIN( datetime ) ); - // time.tm_sec = BCD_DECODE( RTC_TM_SEC( datetime ) ); - - ret.year = cast(dt_field_size) BCD_DECODE(RTC_TM_YEAR(rawdt)); + + ret.year = cast(dt_field_size) BCD_DECODE(RTC_TM_YEAR(rawdt)) + 2000; ret.month = cast(dt_field_size) BCD_DECODE(RTC_TM_MON(rawdt)); ret.day = cast(dt_field_size) BCD_DECODE(RTC_TM_MDAY(rawdt)); ret.wday = cast(dt_field_size) BCD_DECODE(RTC_TM_WDAY(rawdt)); From 9a43fbb336c34c68457e3714b1c7b16c17cc0c0f Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 22 Feb 2022 20:55:35 -0800 Subject: [PATCH 26/32] fix versiondata strings --- src/dusk/Makefile | 13 +++++++++++-- src/dusk/c_src/version.c | 21 +++++++++++++++++++++ src/dusk/d_src/dusk/sys.d | 3 --- 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 src/dusk/c_src/version.c diff --git a/src/dusk/Makefile b/src/dusk/Makefile index 99db424..0fad5d0 100644 --- a/src/dusk/Makefile +++ b/src/dusk/Makefile @@ -33,6 +33,10 @@ IARCH := -mthumb-interwork -marm bTEMPS := 0 # Save gcc temporaries (.i and .s files) # DEBUG := 0 # Generate debug info +# get revision id from git +GITVERSION_ID := $(shell printf "r%s" "$(shell git rev-parse --short HEAD)") +$(info build id: $(GITVERSION_ID)) + #--------------------------------------------------------------------------------- # Options for code generation #--------------------------------------------------------------------------------- @@ -46,8 +50,13 @@ ifeq ($(DEBUG),1) CBASE += -g -DDEBUG endif -DEFINES = -DGBA -DDUSK_VERSION=\"$(GITVERSION)\" -CBASE += $(DEFINES) +# add define for gba +EXTRA_DEFINES := -DGBA + +# add EXTRA_DEFINES for version and git version +EXTRA_DEFINES += -DVERSION_ID_DEF="\"$(VERSION)\"" -DLIB_BUILD_ID_DEF="\"$(GITVERSION_ID)\"" + +CBASE += $(EXTRA_DEFINES) RCFLAGS := $(CBASE) $(RARCH) ICFLAGS := $(CBASE) $(IARCH) -mlong-calls #-fno-gcse diff --git a/src/dusk/c_src/version.c b/src/dusk/c_src/version.c new file mode 100644 index 0000000..a53dc92 --- /dev/null +++ b/src/dusk/c_src/version.c @@ -0,0 +1,21 @@ +/*** + * + * Version Data (Minimal Library Version) + * + *****************************************************************************/ + +#define LIB_ID "DUSK" +#define RES_LIB_ID "$LIB " LIB_ID + +#ifndef VERSION_ID_DEF +#define VERSION_ID_DEF "unknown" +#endif +#define RES_LIB_VERSION (RES_LIB_ID " $VER " VERSION_ID_DEF) + +#ifndef LIB_BUILD_ID_DEF +#define LIB_BUILD_ID_DEF "unknown" +#endif +#define RES_LIB_BUILD (RES_LIB_ID " $BUILD " LIB_BUILD_ID_DEF) + +__attribute__((used)) const char* LIB_VERSION = RES_LIB_VERSION; +__attribute__((used)) const char* LIB_BUILD = RES_LIB_BUILD; diff --git a/src/dusk/d_src/dusk/sys.d b/src/dusk/d_src/dusk/sys.d index ef63ab6..f64ef25 100644 --- a/src/dusk/d_src/dusk/sys.d +++ b/src/dusk/d_src/dusk/sys.d @@ -23,9 +23,6 @@ struct Scene { // void dusk_scene_set(Scene next); // void dusk_scene_update(); -// __attribute__((used)) const char* _DUSK_LIB_VERSION = ("$DUSK " DUSK_VERSION); -// const char* _DUSK_LIB_VERSION = ("$DUSK " ~ DUSK_VERSION); - __gshared static uint frame_count; void dusk_clear_vidmem() { From 473b11baae9835551e21985a8153e513d4d750df Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 22 Feb 2022 21:01:24 -0800 Subject: [PATCH 27/32] fix possible name conflicts --- src/dusk/c_src/version.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dusk/c_src/version.c b/src/dusk/c_src/version.c index a53dc92..3152b7d 100644 --- a/src/dusk/c_src/version.c +++ b/src/dusk/c_src/version.c @@ -17,5 +17,5 @@ #endif #define RES_LIB_BUILD (RES_LIB_ID " $BUILD " LIB_BUILD_ID_DEF) -__attribute__((used)) const char* LIB_VERSION = RES_LIB_VERSION; -__attribute__((used)) const char* LIB_BUILD = RES_LIB_BUILD; +__attribute__((used)) const char* DUSK_LIB_VERSION = RES_LIB_VERSION; +__attribute__((used)) const char* DUSK_LIB_BUILD = RES_LIB_BUILD; From cc489cff0a400c164608083d4d8ce50d270258f3 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 22 Feb 2022 21:05:19 -0800 Subject: [PATCH 28/32] bump version --- src/dusk/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dusk/Makefile b/src/dusk/Makefile index 0fad5d0..682d204 100644 --- a/src/dusk/Makefile +++ b/src/dusk/Makefile @@ -3,7 +3,7 @@ # LIBNAME := dusk -VERSION := 0.1.7 +VERSION := 0.2.0 #--------------------------------------------------------------------------------- .SUFFIXES: From 76d433b62b571a2b3e56d959a50c12e96e94048e Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 22 Feb 2022 21:12:42 -0800 Subject: [PATCH 29/32] add info on version fork --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0fa4761..898f6e6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,11 @@ # dusk -DUsK, a library for gba dev +**dusk**, a library for gba dev + +supported toolchains: +- DevkitARM/C/C++ (version 0.1.x), [view](https://github.com/redthing1/dusk/tree/lang_c) +- DevkitARM/D (version 0.2+) [view](https://github.com/redthing1/dusk/tree/d-port) ## example @@ -11,14 +15,14 @@ DUsK, a library for gba dev ## features -+ simple, intuitive C API ++ simple, intuitive C/D API + library integration + built in support for TONC, GBFS + graphics + scene architecture + 8bpp texture atlas packing + sprite/animation helpers - + tiled map exporter and loader (via Tiled2GBA) + + tiled map exporter and loader + (WIP) saves ## hacking From 033904497d25bdb765c5a75b9f59cc002605c928 Mon Sep 17 00:00:00 2001 From: redthing1 Date: Tue, 19 Apr 2022 20:18:35 -0700 Subject: [PATCH 30/32] add priority defines --- src/dusk/d_src/dusk/sprites.d | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index a79f272..a3eef9c 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -17,6 +17,13 @@ enum NUM_AFFINE_SPRITES = 32; enum SPRITEFLAG_PRIORITY_SHIFT = 6; // #define SPRITEFLAG_PRIORITY_GET(n) ((n >> SPRITEFLAG_PRIORITY_SHIFT) & 0b11) // #define SPRITEFLAG_PRIORITY(n) ((n << SPRITEFLAG_PRIORITY_SHIFT) & 0b11) +u8 SPRITEFLAG_PRIORITY_GET(u8 n) { + return (n >> SPRITEFLAG_PRIORITY_SHIFT) & 0b11; +} + +u8 SPRITEFLAG_PRIORITY(u8 n) { + return (n << SPRITEFLAG_PRIORITY_SHIFT) & 0b11; +} enum DUSKSPRITE_FLAGS_VISIBLE = (0x1 << 0); From 9dbf681838a8ea2091b02e4fc55447b5fd12209d Mon Sep 17 00:00:00 2001 From: redthing1 Date: Wed, 20 Apr 2022 10:54:00 -0700 Subject: [PATCH 31/32] stub upload section --- src/dusk/d_src/dusk/sprites.d | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index a3eef9c..3f7eb01 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -396,6 +396,32 @@ void dusk_background_upload_raw(GritImage* img, int cbb, int sbb, int pal_offset } } +void dusk_background_upload_section(GritImage* img, int cbb, int sbb, u16 tx, u16 ty, u16 tw, u16 th) { + // upload a section of the image to a 32x32 tile (256x256px) background + + auto num_tiles_cpy = 16 * 16; + enum bpp8_tile_sz = TILE8.sizeof; + + // copy palette and se + // memcpy32(&pal_bg_mem[pal_offset], img.pal, img.pal_sz / 4); + memcpy32(&pal_bg_mem[0], img.pal, img.pal_sz / 4); + memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); + + auto tile_data = cast(u8*) img.tiles; + auto tile_dest = cast(u8*) &tile_mem[cbb][0]; + + auto tile_cpy_bytes = num_tiles_cpy * bpp8_tile_sz; + + import dusk.contrib.mgba; + mgba_printf(MGBALogLevel.ERROR, + "img tile_sz: %u, num_tiles_cpy: %u, tile_cpy_bytes: %u", + img.tile_sz, num_tiles_cpy, tile_cpy_bytes); + memcpy32(tile_dest, tile_data, tile_cpy_bytes / 4); + // memcpy32(tile_dest, tile_data, img.tile_sz / 4); + + // calculate tids of the slice we want +} + void dusk_background_make(u8 bg_id, u16 size, Background bg) { // set bg on screen enabled enable_bg(bg_id); From ff1db4371b5029fea179bcffa31b88831991d02b Mon Sep 17 00:00:00 2001 From: redthing1 Date: Wed, 20 Apr 2022 10:58:30 -0700 Subject: [PATCH 32/32] move upl sec out --- src/dusk/d_src/dusk/sprites.d | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/dusk/d_src/dusk/sprites.d b/src/dusk/d_src/dusk/sprites.d index 3f7eb01..a3eef9c 100644 --- a/src/dusk/d_src/dusk/sprites.d +++ b/src/dusk/d_src/dusk/sprites.d @@ -396,32 +396,6 @@ void dusk_background_upload_raw(GritImage* img, int cbb, int sbb, int pal_offset } } -void dusk_background_upload_section(GritImage* img, int cbb, int sbb, u16 tx, u16 ty, u16 tw, u16 th) { - // upload a section of the image to a 32x32 tile (256x256px) background - - auto num_tiles_cpy = 16 * 16; - enum bpp8_tile_sz = TILE8.sizeof; - - // copy palette and se - // memcpy32(&pal_bg_mem[pal_offset], img.pal, img.pal_sz / 4); - memcpy32(&pal_bg_mem[0], img.pal, img.pal_sz / 4); - memcpy32(&se_mem[sbb][0], img.map, img.map_sz / 4); - - auto tile_data = cast(u8*) img.tiles; - auto tile_dest = cast(u8*) &tile_mem[cbb][0]; - - auto tile_cpy_bytes = num_tiles_cpy * bpp8_tile_sz; - - import dusk.contrib.mgba; - mgba_printf(MGBALogLevel.ERROR, - "img tile_sz: %u, num_tiles_cpy: %u, tile_cpy_bytes: %u", - img.tile_sz, num_tiles_cpy, tile_cpy_bytes); - memcpy32(tile_dest, tile_data, tile_cpy_bytes / 4); - // memcpy32(tile_dest, tile_data, img.tile_sz / 4); - - // calculate tids of the slice we want -} - void dusk_background_make(u8 bg_id, u16 size, Background bg) { // set bg on screen enabled enable_bg(bg_id);