diff --git a/main.cpp b/main.cpp index 58da84b..0aa1556 100644 --- a/main.cpp +++ b/main.cpp @@ -15,6 +15,8 @@ #include "gen/maps.hpp" #include "gen/sprites.hpp" #include "map_objects.hpp" +#include "maps.hpp" // hack? +#include "sprites.hpp" constexpr inline uint16_t rgb15(int32_t r, int32_t g, int32_t b) { @@ -100,52 +102,111 @@ constexpr inline void render_block(const uint32_t base_pattern, constexpr int32_t last_map = map_t::wardens_house; -struct state_t { - int32_t map_ix; - enum tileset_t::tileset tileset; - uint32_t base_pattern; +struct draw_state_t { + struct { + uint16_t tilesets[tilesets_ix_last]; // div 32 + uint16_t spritesheets[spritesheets_ix_last]; // div 128 + } base_pattern; }; -static state_t state = { 0, tileset_t::cavern, 0 }; +struct state_t { + int32_t map_ix; + draw_state_t draw; +}; -enum tileset_t::tileset load_tileset(enum tileset_t::tileset tileset) +static state_t state = { 0 }; + +uint32_t load_tileset(uint32_t top, enum tileset_t::tileset tileset) { - uint32_t top = (sizeof (union vdp2_vram)); uint32_t base_address = top = cell_data(tilesets[tileset].tileset, top); - state.base_pattern = base_address / 32; + state.draw.base_pattern.tilesets[tileset] = base_address / 32; - /* use 1-word (16-bit) pattern names */ - /* update N0SCN in the event base_pattern moves (it usually does not) */ - vdp2.reg.PNCN0 = PNCN0__N0PNB__1WORD | PNCN0__N0CNSM | PNCN0__N0SCN((state.base_pattern >> 10) & 0x1f); - - return tileset; + return top; } -// fixme: remove hack -#include "map.hpp" +uint32_t load_sprite(uint32_t top, enum spritesheet_t::spritesheet spritesheet) +{ + const spritesheet_t& s = spritesheets[spritesheet]; + uint32_t base_address = top = character_pattern_table(s.spritesheet, top); + state.draw.base_pattern.spritesheets[spritesheet] = base_address / 128; -void render() + return top; +} + +void load_vram() +{ + vdp2.reg.CYCA0 = 0xeeee'eeee; + vdp2.reg.CYCA1 = 0xeeee'eeee; + vdp2.reg.CYCB0 = 0xeeee'eeee; + vdp2.reg.CYCB1 = 0xeeee'eeee; + + uint32_t vdp2_top = (sizeof (union vdp2_vram)); + for (uint32_t i = 0; i < tilesets_ix_last; i++) + vdp2_top = load_tileset(vdp2_top, tilesets_ix[i]); + + vdp2.reg.CYCA0 = 0x0fff'ffff; + vdp2.reg.CYCA1 = 0xffff'ffff; + vdp2.reg.CYCB0 = 0xffff'ffff; + vdp2.reg.CYCB1 = 0x4fff'ffff; + + uint32_t vdp1_top = (sizeof (union vdp1_vram)); + for (uint32_t i = 0; i < spritesheets_ix_last; i++) + vdp1_top = load_sprite(vdp1_top, spritesheets_ix[i]); +} + +void render_sprites() +{ + uint32_t ix = 2; + constexpr uint32_t color_address = 0; + const uint32_t character_address = (state.draw.base_pattern.spritesheets[spritesheet_t::oak] * 128) / 8; + + vdp1.vram.cmd[ix].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE; + vdp1.vram.cmd[ix].LINK = 0; + // The "end code" is 0xf, which is being used in the mai sprite palette. If + // both transparency and end codes are enabled, it seems there are only 14 + // usable colors in the 4-bit color mode. + vdp1.vram.cmd[ix].PMOD = PMOD__ECD | PMOD__COLOR_MODE__COLOR_BANK_16; + // It appears Kronos does not correctly calculate the color address in the + // VDP1 debugger. Kronos will report FFFC when the actual color table address + // in this example is 7FFE0. + vdp1.vram.cmd[ix].COLR = color_address; // non-palettized (rgb15) color data + vdp1.vram.cmd[ix].SRCA = character_address; + vdp1.vram.cmd[ix].SIZE = SIZE__X(16) | SIZE__Y(16); + vdp1.vram.cmd[ix].XA = 5 * 16; + vdp1.vram.cmd[ix].YA = 5 * 16; + + ix++; +} + +void render_map() { const map_t& map = maps[maps_ix[state.map_ix]]; - - if (map.tileset != state.tileset) - state.tileset = load_tileset(map.tileset); - const uint8_t border_block = map_objects[maps_ix[state.map_ix]].border_block; + const uint32_t base_pattern = state.draw.base_pattern.tilesets[map.tileset]; + vdp2.reg.PNCN0 = PNCN0__N0PNB__1WORD | PNCN0__N0CNSM | PNCN0__N0SCN((base_pattern >> 10) & 0x1f); for (uint32_t map_y = 0; map_y < 16; map_y++) { for (uint32_t map_x = 0; map_x < 16; map_x++) { const uint8_t block = (map_x < map.width && map_y < map.height) - ? map.blocks.start[map.width * map_y + map_x] - : border_block; - render_block(state.base_pattern, + ? map.blocks.start[map.width * map_y + map_x] + : border_block; + + render_block(base_pattern, tilesets[map.tileset], map_x, map_y, block); } } + + vdp2.reg.BGON = BGON__N0ON | BGON__N0TPON; +} + +void render() +{ + render_map(); + render_sprites(); } void update() @@ -206,13 +267,8 @@ void smpc_int(void) intback::fsm(digital_callback, nullptr); } -void sprite() +void init_vdp1() { - uint32_t top = (sizeof (union vdp1_vram)); - const spritesheet_t& spritesheet = spritesheets[spritesheet_t::oak]; - uint32_t character_address = top = character_pattern_table(spritesheet.spritesheet, top); - uint32_t color_address = 0; - /* TVM settings must be performed from the second H-blank IN interrupt after the V-blank IN interrupt to the H-blank IN interrupt immediately after the V-blank OUT interrupt. */ @@ -243,35 +299,14 @@ void sprite() vdp1.vram.cmd[1].XA = 0; vdp1.vram.cmd[1].YA = 0; - vdp1.vram.cmd[2].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE; - vdp1.vram.cmd[2].LINK = 0; - // The "end code" is 0xf, which is being used in the mai sprite palette. If - // both transparency and end codes are enabled, it seems there are only 14 - // usable colors in the 4-bit color mode. - vdp1.vram.cmd[2].PMOD = PMOD__ECD | PMOD__COLOR_MODE__COLOR_BANK_16; - // It appears Kronos does not correctly calculate the color address in the - // VDP1 debugger. Kronos will report FFFC when the actual color table address - // in this example is 7FFE0. - vdp1.vram.cmd[2].COLR = color_address; // non-palettized (rgb15) color data - vdp1.vram.cmd[2].SRCA = character_address >> 3; - vdp1.vram.cmd[2].SIZE = SIZE__X(16) | SIZE__Y(16); - vdp1.vram.cmd[2].XA = 5 * 16; - vdp1.vram.cmd[2].YA = 5 * 16; - - vdp1.vram.cmd[3].CTRL = CTRL__END; + vdp1.vram.cmd[2].CTRL = CTRL__END; // start drawing (execute the command list) on every frame vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE; } -void main() +void init_vdp2() { - state.map_ix = map_t::celadon_city; - - v_blank_in(); - - sprite(); - vdp2.reg.PRISA = PRISA__S0PRIN(7); // Sprite register 0 PRIority Number // DISP: Please make sure to change this bit from 0 to 1 during V blank. @@ -281,8 +316,8 @@ void main() /* set the color mode to 5bits per channel, 1024 colors */ vdp2.reg.RAMCTL = RAMCTL__CRKTE | RAMCTL__CRMD__RGB_5BIT_1024 | RAMCTL__VRAMD | RAMCTL__VRBMD; - /* enable display of NBG0 */ - vdp2.reg.BGON = BGON__N0ON | BGON__N0TPON; + /* disable display of NBG0 */ + vdp2.reg.BGON = 0; /* set character format for NBG0 to palettized 16 color set enable "cell format" for NBG0 @@ -309,11 +344,18 @@ void main() vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0 palette_data(); +} - vdp2.reg.CYCA0 = 0x0fff'ffff; - vdp2.reg.CYCA1 = 0xffff'ffff; - vdp2.reg.CYCB0 = 0xffff'ffff; - vdp2.reg.CYCB1 = 0x4fff'ffff; +void main() +{ + state.map_ix = map_t::celadon_city; + + load_vram(); + + v_blank_in(); + + init_vdp1(); + init_vdp2(); // free-running timer sh2.reg.TCR = TCR__CKS__INTERNAL_DIV128; diff --git a/map.hpp b/maps.hpp similarity index 89% rename from map.hpp rename to maps.hpp index 2b4fd7f..f316d1a 100644 --- a/map.hpp +++ b/maps.hpp @@ -224,3 +224,32 @@ enum map_t::map maps_ix[] = { }; constexpr int map_ix_last = (sizeof (maps_ix)) / (sizeof (enum map_t::map)); + +enum tileset_t::tileset tilesets_ix[] = { + tileset_t::cavern, + tileset_t::cemetery, + tileset_t::club, + tileset_t::dojo, + tileset_t::facility, + tileset_t::forest, + tileset_t::forest_gate, + tileset_t::gate, + tileset_t::gym, + tileset_t::house, + tileset_t::interior, + tileset_t::lab, + tileset_t::lobby, + tileset_t::mansion, + tileset_t::mart, + tileset_t::museum, + tileset_t::overworld, + tileset_t::plateau, + tileset_t::pokecenter, + tileset_t::reds_house_1, + tileset_t::reds_house_2, + tileset_t::ship, + tileset_t::ship_port, + tileset_t::underground, +}; + +constexpr int tilesets_ix_last = (sizeof (tilesets_ix)) / (sizeof (enum tileset_t::tileset)); diff --git a/sprites.hpp b/sprites.hpp new file mode 100644 index 0000000..6af16a9 --- /dev/null +++ b/sprites.hpp @@ -0,0 +1,77 @@ +enum spritesheet_t::spritesheet spritesheets_ix[] = { + spritesheet_t::agatha, + spritesheet_t::balding_guy, + spritesheet_t::beauty, + spritesheet_t::biker, + spritesheet_t::bike_shop_clerk, + spritesheet_t::bird, + spritesheet_t::blue, + spritesheet_t::boulder, + spritesheet_t::brunette_girl, + spritesheet_t::bruno, + spritesheet_t::captain, + spritesheet_t::channeler, + spritesheet_t::clerk, + spritesheet_t::clipboard, + spritesheet_t::cook, + spritesheet_t::cooltrainer_f, + spritesheet_t::cooltrainer_m, + spritesheet_t::daisy, + spritesheet_t::fairy, + spritesheet_t::fisher, + spritesheet_t::fishing_guru, + spritesheet_t::fossil, + spritesheet_t::gambler, + spritesheet_t::gambler_asleep, + spritesheet_t::gameboy_kid, + spritesheet_t::gentleman, + spritesheet_t::giovanni, + spritesheet_t::girl, + spritesheet_t::gramps, + spritesheet_t::granny, + spritesheet_t::guard, + spritesheet_t::gym_guide, + spritesheet_t::hiker, + spritesheet_t::koga, + spritesheet_t::lance, + spritesheet_t::link_receptionist, + spritesheet_t::little_boy, + spritesheet_t::little_girl, + spritesheet_t::lorelei, + spritesheet_t::middle_aged_man, + spritesheet_t::middle_aged_woman, + spritesheet_t::mom, + spritesheet_t::monster, + spritesheet_t::mr_fuji, + spritesheet_t::none, + spritesheet_t::nurse, + spritesheet_t::oak, + spritesheet_t::old_amber, + spritesheet_t::paper, + spritesheet_t::pokedex, + spritesheet_t::poke_ball, + spritesheet_t::red, + spritesheet_t::rocker, + spritesheet_t::rocket, + spritesheet_t::safari_zone_worker, + spritesheet_t::sailor, + spritesheet_t::scientist, + spritesheet_t::seel, + spritesheet_t::silph_president, + spritesheet_t::silph_worker_f, + spritesheet_t::silph_worker_m, + spritesheet_t::snorlax, + spritesheet_t::super_nerd, + spritesheet_t::swimmer, + spritesheet_t::unused_gambler_asleep_1, + spritesheet_t::unused_gambler_asleep_2, + spritesheet_t::unused_gameboy_kid, + spritesheet_t::unused_guard, + spritesheet_t::unused_old_amber, + spritesheet_t::unused_scientist, + spritesheet_t::waiter, + spritesheet_t::warden, + spritesheet_t::youngster, +}; + +constexpr int spritesheets_ix_last = (sizeof (spritesheets_ix)) / (sizeof (enum spritesheet_t::spritesheet)); diff --git a/tools/generate/sprites.py b/tools/generate/sprites.py index c8cae72..4a1234e 100644 --- a/tools/generate/sprites.py +++ b/tools/generate/sprites.py @@ -49,7 +49,7 @@ def struct_spritesheet_t(): "start_size_t spritesheet;", "uint8_t sprite_count;", "", - "enum sprite {", + "enum spritesheet {", *sprite_names, "};", "};",