graphic: add functions to draw stats screen borders
This also draws pokemon sprites on the screen, sequentially.
This commit is contained in:
parent
f821ac9e6d
commit
3d8110ca1c
20
Makefile
20
Makefile
@ -5,6 +5,17 @@ LIB = ./saturn
|
|||||||
|
|
||||||
GEN_PYTHON_SOURCE = $(wildcard tools/source/*.py) $(wildcard tools/generate/*.py)
|
GEN_PYTHON_SOURCE = $(wildcard tools/source/*.py) $(wildcard tools/generate/*.py)
|
||||||
|
|
||||||
|
GEN_HEADERS =
|
||||||
|
GEN_HEADERS += gen/maps.hpp
|
||||||
|
GEN_HEADERS += gen/tilesets.hpp
|
||||||
|
GEN_HEADERS += gen/sprites.hpp
|
||||||
|
GEN_HEADERS += gen/collision_tile_ids.hpp
|
||||||
|
GEN_HEADERS += gen/text.hpp
|
||||||
|
GEN_HEADERS += gen/text_pointers.hpp
|
||||||
|
GEN_HEADERS += gen/pokemon/moves.hpp
|
||||||
|
GEN_HEADERS += gen/pokemon/types.hpp
|
||||||
|
GEN_HEADERS += gen/pokemon/pokemon_enum.inc.hpp
|
||||||
|
|
||||||
GEN_SRC =
|
GEN_SRC =
|
||||||
GEN_SRC += gen/maps.cpp
|
GEN_SRC += gen/maps.cpp
|
||||||
GEN_SRC += gen/map_objects.cpp
|
GEN_SRC += gen/map_objects.cpp
|
||||||
@ -13,6 +24,8 @@ GEN_SRC += gen/tilesets.cpp
|
|||||||
GEN_SRC += gen/collision_tile_ids.cpp
|
GEN_SRC += gen/collision_tile_ids.cpp
|
||||||
GEN_SRC += gen/text.cpp
|
GEN_SRC += gen/text.cpp
|
||||||
GEN_SRC += gen/text_pointers.cpp
|
GEN_SRC += gen/text_pointers.cpp
|
||||||
|
GEN_SRC += gen/pokemon/moves.cpp
|
||||||
|
GEN_SRC += gen/pokemon/pokemon.cpp
|
||||||
|
|
||||||
SRC =
|
SRC =
|
||||||
SRC += $(GEN_SRC)
|
SRC += $(GEN_SRC)
|
||||||
@ -35,9 +48,10 @@ GFX_POKEMON = $(call res_png,2bpp,pokered/gfx/pokemon/front/) $(call res_png,2bp
|
|||||||
MAPS_BLOCKS = $(call res,blk,pokered/maps/)
|
MAPS_BLOCKS = $(call res,blk,pokered/maps/)
|
||||||
FONTS = res/font.2bpp.o
|
FONTS = res/font.2bpp.o
|
||||||
|
|
||||||
GENERATED = $(GFX_TILESETS) $(GFX_BLOCKSETS) $(GFX_SPRITES) $(GFX_POKEMON) $(MAPS_BLOCKS) $(GEN_SRC) $(FONTS)
|
GENERATED_SRC = $(GFX_TILESETS) $(GFX_BLOCKSETS) $(GFX_SPRITES) $(GFX_POKEMON) $(MAPS_BLOCKS) $(GEN_SRC) $(FONTS)
|
||||||
|
GENERATED = $(GENERATED_SRC) $(GEN_HEADERS)
|
||||||
|
|
||||||
OBJ = $(patsubst %.cpp,%.o,$(SRC) $(GENERATED))
|
OBJ = $(patsubst %.cpp,%.o,$(SRC) $(GENERATED_SRC))
|
||||||
|
|
||||||
all: main.cue
|
all: main.cue
|
||||||
|
|
||||||
@ -57,7 +71,7 @@ endef
|
|||||||
gen/%.hpp: $(GEN_PYTHON_SOURCE)
|
gen/%.hpp: $(GEN_PYTHON_SOURCE)
|
||||||
$(RUN_GENERATE) $@
|
$(RUN_GENERATE) $@
|
||||||
|
|
||||||
gen/%.cpp: gen/%.hpp $(GEN_PYTHON_SOURCE)
|
gen/%.cpp: $(GEN_PYTHON_SOURCE)
|
||||||
$(RUN_GENERATE) $@
|
$(RUN_GENERATE) $@
|
||||||
|
|
||||||
define PNG_TO_2BPP
|
define PNG_TO_2BPP
|
||||||
|
@ -22,8 +22,8 @@ struct block_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct screen_cell_t {
|
struct screen_cell_t {
|
||||||
uint32_t x;
|
int32_t x;
|
||||||
uint32_t y;
|
int32_t y;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct screen_t {
|
struct screen_t {
|
||||||
|
114
graphic.cpp
114
graphic.cpp
@ -9,7 +9,7 @@
|
|||||||
struct dialog_border {
|
struct dialog_border {
|
||||||
static constexpr uint8_t corner_top_left = 105;
|
static constexpr uint8_t corner_top_left = 105;
|
||||||
static constexpr uint8_t corner_top_right = 106;
|
static constexpr uint8_t corner_top_right = 106;
|
||||||
static constexpr uint8_t corner_bot_left = 107;
|
static constexpr uint8_t corner_bottom_left = 107;
|
||||||
static constexpr uint8_t corner_bottom_right = 108;
|
static constexpr uint8_t corner_bottom_right = 108;
|
||||||
static constexpr uint8_t vertical_end_cap = 109;
|
static constexpr uint8_t vertical_end_cap = 109;
|
||||||
static constexpr uint8_t vertical = 110;
|
static constexpr uint8_t vertical = 110;
|
||||||
@ -21,18 +21,34 @@ struct battle_border {
|
|||||||
static constexpr uint8_t corner_bottom_right = 97;
|
static constexpr uint8_t corner_bottom_right = 97;
|
||||||
static constexpr uint8_t arrow_right = 98;
|
static constexpr uint8_t arrow_right = 98;
|
||||||
static constexpr uint8_t vertical = 99;
|
static constexpr uint8_t vertical = 99;
|
||||||
static constexpr uint8_t corner_bot_left = 100;
|
static constexpr uint8_t corner_bottom_left = 100;
|
||||||
static constexpr uint8_t three_dots = 101;
|
static constexpr uint8_t three_dots = 101;
|
||||||
static constexpr uint8_t vertical_end_cap = 102;
|
static constexpr uint8_t vertical_end_cap = 102;
|
||||||
static constexpr uint8_t level = 103;
|
static constexpr uint8_t level = 103;
|
||||||
static constexpr uint8_t arrow_left = 104;
|
static constexpr uint8_t arrow_left = 104;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hp_bar {
|
||||||
|
static constexpr uint8_t hp = 0x50;
|
||||||
|
static constexpr uint8_t start_cap = 0x51;
|
||||||
|
static constexpr uint8_t seg0 = 0x52;
|
||||||
|
static constexpr uint8_t seg1 = 0x53;
|
||||||
|
static constexpr uint8_t seg2 = 0x54;
|
||||||
|
static constexpr uint8_t seg3 = 0x55;
|
||||||
|
static constexpr uint8_t seg4 = 0x56;
|
||||||
|
static constexpr uint8_t seg5 = 0x57;
|
||||||
|
static constexpr uint8_t seg6 = 0x58;
|
||||||
|
static constexpr uint8_t seg7 = 0x59;
|
||||||
|
static constexpr uint8_t seg8 = 0x5a;
|
||||||
|
static constexpr uint8_t end_cap_nobar = 0x5b;
|
||||||
|
static constexpr uint8_t end_cap_bar = 0x66;
|
||||||
|
};
|
||||||
|
|
||||||
#define S reinterpret_cast<const uint8_t *>
|
#define S reinterpret_cast<const uint8_t *>
|
||||||
|
|
||||||
void draw_text(const uint32_t base_pattern,
|
void draw_text(const uint32_t base_pattern,
|
||||||
const uint8_t * text,
|
const uint8_t * text,
|
||||||
const uint32_t x, const uint32_t y)
|
const int32_t x, const int32_t y)
|
||||||
{
|
{
|
||||||
uint8_t i = 0, x_o = 0;
|
uint8_t i = 0, x_o = 0;
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
@ -80,9 +96,9 @@ void draw_box_border(const uint32_t base_pattern,
|
|||||||
put_char(base_pattern, top_left.x, top_left.y, dialog_border::corner_top_left);
|
put_char(base_pattern, top_left.x, top_left.y, dialog_border::corner_top_left);
|
||||||
put_char(base_pattern, bottom_right.x, top_left.y, dialog_border::corner_top_right);
|
put_char(base_pattern, bottom_right.x, top_left.y, dialog_border::corner_top_right);
|
||||||
put_char(base_pattern, bottom_right.x, bottom_right.y, dialog_border::corner_bottom_right);
|
put_char(base_pattern, bottom_right.x, bottom_right.y, dialog_border::corner_bottom_right);
|
||||||
put_char(base_pattern, top_left.x, bottom_right.y, dialog_border::corner_bot_left);
|
put_char(base_pattern, top_left.x, bottom_right.y, dialog_border::corner_bottom_left);
|
||||||
|
|
||||||
for (uint32_t y = top_left.y + 1; y < bottom_right.y; y++) {
|
for (int32_t y = top_left.y + 1; y < bottom_right.y; y++) {
|
||||||
// left vertical bar
|
// left vertical bar
|
||||||
put_char(base_pattern, top_left.x, y, dialog_border::vertical);
|
put_char(base_pattern, top_left.x, y, dialog_border::vertical);
|
||||||
// right vertical bar
|
// right vertical bar
|
||||||
@ -90,7 +106,7 @@ void draw_box_border(const uint32_t base_pattern,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (uint32_t x = top_left.x + 1; x < bottom_right.x; x++) {
|
for (int32_t x = top_left.x + 1; x < bottom_right.x; x++) {
|
||||||
// top horizontal bar
|
// top horizontal bar
|
||||||
put_char(base_pattern, x, top_left.y, dialog_border::horizontal);
|
put_char(base_pattern, x, top_left.y, dialog_border::horizontal);
|
||||||
|
|
||||||
@ -102,13 +118,91 @@ void draw_box_border(const uint32_t base_pattern,
|
|||||||
void draw_box_background(const uint32_t base_pattern,
|
void draw_box_background(const uint32_t base_pattern,
|
||||||
const screen_cell_t& top_left, const screen_cell_t& bottom_right)
|
const screen_cell_t& top_left, const screen_cell_t& bottom_right)
|
||||||
{
|
{
|
||||||
for (uint32_t x = top_left.x + 1; x < bottom_right.x; x++) {
|
for (int32_t x = top_left.x + 1; x < bottom_right.x; x++) {
|
||||||
for (uint32_t y = top_left.y + 1; y < bottom_right.y; y++) {
|
for (int32_t y = top_left.y + 1; y < bottom_right.y; y++) {
|
||||||
put_char(base_pattern, x, y, ascii_to_font(' '));
|
put_char(base_pattern, x, y, ascii_to_font(' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_battle_border(const uint32_t base_pattern,
|
||||||
|
const screen_cell_t& top_corner, const screen_cell_t& bottom_corner)
|
||||||
|
{
|
||||||
|
// draw the vertical line
|
||||||
|
for (int32_t y = top_corner.y; y < bottom_corner.y; y++)
|
||||||
|
put_char(base_pattern, top_corner.x, y, battle_border::vertical);
|
||||||
|
|
||||||
|
// decide which direction we are drawing
|
||||||
|
const int32_t increment = bottom_corner.x <= top_corner.x ? 1 : -1;
|
||||||
|
|
||||||
|
// draw the horizontal line
|
||||||
|
for (int32_t x = bottom_corner.x + increment; x != top_corner.x; x += increment)
|
||||||
|
put_char(base_pattern, x, bottom_corner.y, battle_border::horizontal);
|
||||||
|
|
||||||
|
// draw the end cap and corner piece
|
||||||
|
const uint8_t end_cap = increment == 1 ? battle_border::arrow_left
|
||||||
|
: battle_border::arrow_right;
|
||||||
|
const uint8_t corner = increment == 1 ? battle_border::corner_bottom_right
|
||||||
|
: battle_border::corner_bottom_left;
|
||||||
|
put_char(base_pattern, bottom_corner.x, bottom_corner.y, end_cap);
|
||||||
|
put_char(base_pattern, top_corner.x , bottom_corner.y, corner );
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline uint8_t hp_seg(const int32_t hp_48, const int32_t ix)
|
||||||
|
{
|
||||||
|
const int32_t hp_ix = hp_48 - (ix * 8);
|
||||||
|
|
||||||
|
if (hp_ix < 0) return hp_bar::seg0;
|
||||||
|
|
||||||
|
switch (hp_ix) {
|
||||||
|
default: [[fallthrough]];
|
||||||
|
case 8: return hp_bar::seg8;
|
||||||
|
case 7: return hp_bar::seg7;
|
||||||
|
case 6: return hp_bar::seg6;
|
||||||
|
case 5: return hp_bar::seg5;
|
||||||
|
case 4: return hp_bar::seg4;
|
||||||
|
case 3: return hp_bar::seg3;
|
||||||
|
case 2: return hp_bar::seg2;
|
||||||
|
case 1: return hp_bar::seg1;
|
||||||
|
case 0: return hp_bar::seg0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_hp_bar(const uint32_t base_pattern,
|
||||||
|
const screen_cell_t& top_left,
|
||||||
|
const uint8_t end_cap,
|
||||||
|
const int32_t hp_48)
|
||||||
|
{
|
||||||
|
put_char(base_pattern, top_left.x + 0, top_left.y, hp_bar::hp);
|
||||||
|
put_char(base_pattern, top_left.x + 1, top_left.y, hp_bar::start_cap);
|
||||||
|
|
||||||
|
for (int32_t ix = 0; ix < 6; ix++) {
|
||||||
|
const uint8_t seg = hp_seg(hp_48, ix);
|
||||||
|
put_char(base_pattern, top_left.x + 2 + ix, top_left.y, seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
put_char(base_pattern, top_left.x + 8, top_left.y, end_cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t hp = 0;
|
||||||
|
|
||||||
|
void draw_stats1(const uint32_t base_pattern)
|
||||||
|
{
|
||||||
|
// white out the entire screen
|
||||||
|
draw_box_background(base_pattern, {-1, -1}, {20, 18});
|
||||||
|
|
||||||
|
// top status battle box
|
||||||
|
draw_battle_border(base_pattern, {19, 1}, {8, 7});
|
||||||
|
draw_hp_bar(base_pattern, {11, 4}, hp_bar::end_cap_bar, (hp >> 3) % 48);
|
||||||
|
hp++;
|
||||||
|
|
||||||
|
// bottom border
|
||||||
|
draw_battle_border(base_pattern, {19, 9}, {12, 17});
|
||||||
|
|
||||||
|
// bottom left dialog box
|
||||||
|
draw_box_border(base_pattern, {0, 8}, {9, 17});
|
||||||
|
}
|
||||||
|
|
||||||
void dialog_t::draw(const uint32_t base_pattern,
|
void dialog_t::draw(const uint32_t base_pattern,
|
||||||
const start_size_t& text)
|
const start_size_t& text)
|
||||||
{
|
{
|
||||||
@ -116,8 +210,8 @@ void dialog_t::draw(const uint32_t base_pattern,
|
|||||||
draw_box_background(base_pattern, top_left, bottom_right);
|
draw_box_background(base_pattern, top_left, bottom_right);
|
||||||
|
|
||||||
uint32_t ix = 0;
|
uint32_t ix = 0;
|
||||||
uint32_t x = top_left.x + 1;
|
int32_t x = top_left.x + 1;
|
||||||
uint32_t y = top_left.y + 2;
|
int32_t y = top_left.y + 2;
|
||||||
// ignore C-string null terminator
|
// ignore C-string null terminator
|
||||||
while (ix < (text.size - 1)) {
|
while (ix < (text.size - 1)) {
|
||||||
const uint8_t c = text.start[ix];
|
const uint8_t c = text.start[ix];
|
||||||
|
@ -16,7 +16,7 @@ static inline void put_char(const uint32_t base_pattern,
|
|||||||
|
|
||||||
void draw_text(const uint32_t base_pattern,
|
void draw_text(const uint32_t base_pattern,
|
||||||
const uint8_t * text,
|
const uint8_t * text,
|
||||||
const uint32_t x, const uint32_t y);
|
const int32_t x, const int32_t y);
|
||||||
|
|
||||||
void draw_box_border(const uint32_t base_pattern,
|
void draw_box_border(const uint32_t base_pattern,
|
||||||
const screen_cell_t& top_left, const screen_cell_t& bottom_right);
|
const screen_cell_t& top_left, const screen_cell_t& bottom_right);
|
||||||
@ -24,6 +24,11 @@ void draw_box_border(const uint32_t base_pattern,
|
|||||||
void draw_box_background(const uint32_t base_pattern,
|
void draw_box_background(const uint32_t base_pattern,
|
||||||
const screen_cell_t& top_left, const screen_cell_t& bottom_right);
|
const screen_cell_t& top_left, const screen_cell_t& bottom_right);
|
||||||
|
|
||||||
|
void draw_battle_border(const uint32_t base_pattern,
|
||||||
|
const screen_cell_t& top_corner, const screen_cell_t& bottom_corner);
|
||||||
|
|
||||||
|
void draw_stats1(const uint32_t base_pattern);
|
||||||
|
|
||||||
struct dialog_t
|
struct dialog_t
|
||||||
{
|
{
|
||||||
static constexpr screen_cell_t top_left = { 0, 12};
|
static constexpr screen_cell_t top_left = { 0, 12};
|
||||||
|
@ -29,8 +29,8 @@ void digital_callback(uint8_t fsm_state, uint8_t data);
|
|||||||
|
|
||||||
extern input_t input;
|
extern input_t input;
|
||||||
|
|
||||||
constexpr int input_arr = 1;
|
constexpr int input_arr = 10;
|
||||||
constexpr int input_das = 1;
|
constexpr int input_das = 20;
|
||||||
constexpr int input_debounce = 2;
|
constexpr int input_debounce = 2;
|
||||||
|
|
||||||
static constexpr inline int32_t
|
static constexpr inline int32_t
|
||||||
|
84
main.cpp
84
main.cpp
@ -26,11 +26,19 @@
|
|||||||
#include "graphic.hpp"
|
#include "graphic.hpp"
|
||||||
#include "menu.hpp"
|
#include "menu.hpp"
|
||||||
|
|
||||||
|
#include "pokemon.hpp"
|
||||||
|
|
||||||
|
static int32_t pokemon_raw_index = 0;
|
||||||
|
|
||||||
struct draw_t {
|
struct draw_t {
|
||||||
struct {
|
struct {
|
||||||
uint16_t font; // div 32
|
uint16_t font; // div 32
|
||||||
uint16_t tilesets[tileset_t::count]; // div 32
|
uint16_t tilesets[tileset_t::count]; // div 32
|
||||||
uint16_t spritesheets[spritesheet_t::count]; // div 128
|
uint16_t spritesheets[spritesheet_t::count]; // div 128
|
||||||
|
struct {
|
||||||
|
uint16_t front;
|
||||||
|
uint16_t back;
|
||||||
|
} pokemon[pokemon_t::count]; // div 16
|
||||||
} base_pattern;
|
} base_pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,21 +53,31 @@ static state_t state = { map_t::pallet_town, map_t::last_map, 0 };
|
|||||||
|
|
||||||
uint32_t load_tileset(uint32_t top, enum tileset_t::tileset tileset)
|
uint32_t load_tileset(uint32_t top, enum tileset_t::tileset tileset)
|
||||||
{
|
{
|
||||||
uint32_t base_address = top = cell_data(tilesets[tileset].tileset, top);
|
const uint32_t base_address = top = cell_data(tilesets[tileset].tileset, top);
|
||||||
state.draw.base_pattern.tilesets[tileset] = base_address / 32;
|
state.draw.base_pattern.tilesets[tileset] = base_address / 32;
|
||||||
|
|
||||||
return top;
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t load_sprite(uint32_t top, enum spritesheet_t::spritesheet spritesheet)
|
uint32_t load_spritesheet(uint32_t top, enum spritesheet_t::spritesheet spritesheet)
|
||||||
{
|
{
|
||||||
const spritesheet_t& s = spritesheets[spritesheet];
|
const spritesheet_t& s = spritesheets[spritesheet];
|
||||||
uint32_t base_address = top = character_pattern_table(s.spritesheet, top);
|
const uint32_t base_address = top = character_pattern_table(s.spritesheet, top);
|
||||||
state.draw.base_pattern.spritesheets[spritesheet] = base_address / 128;
|
state.draw.base_pattern.spritesheets[spritesheet] = base_address / 128;
|
||||||
|
|
||||||
return top;
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t load_pokemon(uint32_t top, enum pokemon_t::pokemon _pokemon)
|
||||||
|
{
|
||||||
|
const pokemon_t& p = pokemon[_pokemon];
|
||||||
|
const uint32_t base_address_front = top = character_pattern_table(p.pic.front, top);
|
||||||
|
const uint32_t base_address_back = top = character_pattern_table(p.pic.back, top);
|
||||||
|
state.draw.base_pattern.pokemon[_pokemon].front = base_address_front / 16;
|
||||||
|
state.draw.base_pattern.pokemon[_pokemon].back = base_address_back / 16;
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
void load_vram()
|
void load_vram()
|
||||||
{
|
{
|
||||||
vdp2.reg.CYCA0 = 0xeeee'eeee;
|
vdp2.reg.CYCA0 = 0xeeee'eeee;
|
||||||
@ -81,7 +99,10 @@ void load_vram()
|
|||||||
|
|
||||||
uint32_t vdp1_top = (sizeof (union vdp1_vram));
|
uint32_t vdp1_top = (sizeof (union vdp1_vram));
|
||||||
for (uint32_t i = 0; i < spritesheet_t::count; i++)
|
for (uint32_t i = 0; i < spritesheet_t::count; i++)
|
||||||
vdp1_top = load_sprite(vdp1_top, static_cast<enum spritesheet_t::spritesheet>(i));
|
vdp1_top = load_spritesheet(vdp1_top, static_cast<enum spritesheet_t::spritesheet>(i));
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < pokemon_t::count; i++)
|
||||||
|
vdp1_top = load_pokemon(vdp1_top, static_cast<enum pokemon_t::pokemon>(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t facing_offset(const actor_t::direction facing)
|
static inline uint32_t facing_offset(const actor_t::direction facing)
|
||||||
@ -109,7 +130,7 @@ static inline uint32_t facing_inverted(const actor_t::direction facing, const ui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_sprite(const uint32_t ix, const uint32_t sprite_id,
|
void render_sprite(const uint32_t ix, const enum spritesheet_t::spritesheet sprite_id,
|
||||||
const enum actor_t::direction facing, const uint32_t animation_frame, const uint32_t animation_cycle,
|
const enum actor_t::direction facing, const uint32_t animation_frame, const uint32_t animation_cycle,
|
||||||
const screen_t& screen, const offset_t& offset,
|
const screen_t& screen, const offset_t& offset,
|
||||||
int32_t y_offset)
|
int32_t y_offset)
|
||||||
@ -135,6 +156,41 @@ void render_sprite(const uint32_t ix, const uint32_t sprite_id,
|
|||||||
vdp1.vram.cmd[ix].YA = (cell_offset::y * 8) + screen.y * 16 + y_offset - offset.y;
|
vdp1.vram.cmd[ix].YA = (cell_offset::y * 8) + screen.y * 16 + y_offset - offset.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pokemon_sprite_dimension(const uint32_t size)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
default: [[fallthrough]];
|
||||||
|
case 256: return 32;
|
||||||
|
case 400: return 40;
|
||||||
|
case 576: return 48;
|
||||||
|
case 784: return 56;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_pokemon(const uint32_t ix, const enum pokemon_t::pokemon pokemon_id,
|
||||||
|
const screen_cell_t& screen_cell)
|
||||||
|
{
|
||||||
|
constexpr uint32_t color_address = 0;
|
||||||
|
const uint32_t base_pattern = state.draw.base_pattern.pokemon[pokemon_id].front;
|
||||||
|
const uint32_t character_address = (base_pattern * 16) / 8;
|
||||||
|
const uint32_t dimension = pokemon_sprite_dimension(pokemon[pokemon_id].pic.front.size);
|
||||||
|
|
||||||
|
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(dimension) | SIZE__Y(dimension);
|
||||||
|
vdp1.vram.cmd[ix].XA = (cell_offset::x * 8) + screen_cell.x * 8;
|
||||||
|
vdp1.vram.cmd[ix].YA = (cell_offset::y * 8) + screen_cell.y * 8;
|
||||||
|
}
|
||||||
|
|
||||||
void render_sprites(const offset_t& offset)
|
void render_sprites(const offset_t& offset)
|
||||||
{
|
{
|
||||||
uint32_t ix = 2;
|
uint32_t ix = 2;
|
||||||
@ -148,6 +204,10 @@ void render_sprites(const offset_t& offset)
|
|||||||
state.player.y_offset());
|
state.player.y_offset());
|
||||||
ix++;
|
ix++;
|
||||||
|
|
||||||
|
render_pokemon(ix, static_cast<enum pokemon_t::pokemon>(pokemon_raw_index),
|
||||||
|
{0, 0});
|
||||||
|
ix++;
|
||||||
|
|
||||||
const object_t& obj = map_objects[state.map];
|
const object_t& obj = map_objects[state.map];
|
||||||
for (uint32_t i = 0; i < obj.object_length; i++) {
|
for (uint32_t i = 0; i < obj.object_length; i++) {
|
||||||
const object_event_t& event = obj.object_events[i];
|
const object_event_t& event = obj.object_events[i];
|
||||||
@ -417,10 +477,18 @@ void update()
|
|||||||
change_maps();
|
change_maps();
|
||||||
update_warp();
|
update_warp();
|
||||||
|
|
||||||
|
/*
|
||||||
if (event::cursor_left() ) collision_move(maps[state.map], actor_t::left);
|
if (event::cursor_left() ) collision_move(maps[state.map], actor_t::left);
|
||||||
else if (event::cursor_right()) collision_move(maps[state.map], actor_t::right);
|
else if (event::cursor_right()) collision_move(maps[state.map], actor_t::right);
|
||||||
else if (event::cursor_up() ) collision_move(maps[state.map], actor_t::up);
|
else if (event::cursor_up() ) collision_move(maps[state.map], actor_t::up);
|
||||||
else if (event::cursor_down() ) collision_move(maps[state.map], actor_t::down);
|
else if (event::cursor_down() ) collision_move(maps[state.map], actor_t::down);
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (event::cursor_left() ) pokemon_raw_index = (pokemon_raw_index - 1);
|
||||||
|
else if (event::cursor_right()) pokemon_raw_index = (pokemon_raw_index + 1);
|
||||||
|
if (pokemon_raw_index < 0) pokemon_raw_index = pokemon_t::count - 1;
|
||||||
|
else if (pokemon_raw_index >= pokemon_t::count) pokemon_raw_index = 0;
|
||||||
|
|
||||||
//else if (event::button_a() ) check_sign();
|
//else if (event::button_a() ) check_sign();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,6 +510,8 @@ void render()
|
|||||||
draw_menu(state.draw.base_pattern.font, fight_menu);
|
draw_menu(state.draw.base_pattern.font, fight_menu);
|
||||||
cursor_t cursor = { 1, 1 };
|
cursor_t cursor = { 1, 1 };
|
||||||
draw_menu_cursor(state.draw.base_pattern.font, fight_menu, cursor);
|
draw_menu_cursor(state.draw.base_pattern.font, fight_menu, cursor);
|
||||||
|
|
||||||
|
draw_stats1(state.draw.base_pattern.font);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -529,9 +599,9 @@ void init_vdp1()
|
|||||||
|
|
||||||
void init_vdp2()
|
void init_vdp2()
|
||||||
{
|
{
|
||||||
vdp2.reg.PRISA = PRISA__S0PRIN(6); // Sprite register 0 PRIority Number
|
vdp2.reg.PRISA = PRISA__S0PRIN(7); // Sprite register 0 PRIority Number
|
||||||
vdp2.reg.PRINA = PRINA__N0PRIN(5)
|
vdp2.reg.PRINA = PRINA__N0PRIN(5)
|
||||||
| PRINA__N1PRIN(7);
|
| PRINA__N1PRIN(6);
|
||||||
|
|
||||||
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
|
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
|
||||||
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
|
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
|
||||||
|
@ -127,11 +127,14 @@ def dex_constant_to_enum_name(dex_constant):
|
|||||||
return name.lower()
|
return name.lower()
|
||||||
|
|
||||||
def enum_inc():
|
def enum_inc():
|
||||||
|
dex_constants = parse.pokemon_dex_constants_list()
|
||||||
yield "enum pokemon {"
|
yield "enum pokemon {"
|
||||||
for dex_constant in parse.pokemon_dex_constants_list():
|
for dex_constant in dex_constants:
|
||||||
name = dex_constant_to_enum_name(dex_constant)
|
name = dex_constant_to_enum_name(dex_constant)
|
||||||
yield f"{name.lower()},"
|
yield f"{name.lower()},"
|
||||||
yield "};"
|
yield "};"
|
||||||
|
yield ""
|
||||||
|
yield f"static constexpr int32_t count = {len(dex_constants)};"
|
||||||
|
|
||||||
def generate_enum_inc():
|
def generate_enum_inc():
|
||||||
render, out = renderer()
|
render, out = renderer()
|
||||||
|
@ -5,8 +5,8 @@ from PIL import Image
|
|||||||
|
|
||||||
from palette import intensity_to_index
|
from palette import intensity_to_index
|
||||||
|
|
||||||
cell_width = 16
|
cell_width = None
|
||||||
cell_height = 16
|
cell_height = None
|
||||||
|
|
||||||
def convert(image, bpp):
|
def convert(image, bpp):
|
||||||
assert bpp in {8, 4, 2}, bpp
|
assert bpp in {8, 4, 2}, bpp
|
||||||
@ -64,6 +64,8 @@ assert len(sys.argv) >= 4, sys.argv
|
|||||||
with open(out_path, 'wb') as f:
|
with open(out_path, 'wb') as f:
|
||||||
for in_path in in_paths:
|
for in_path in in_paths:
|
||||||
im = Image.open(in_path)
|
im = Image.open(in_path)
|
||||||
|
cell_width, cell_height = im.size
|
||||||
|
assert cell_width in {16, 32, 40, 48, 56}, cell_width
|
||||||
buf = convert(im, bpp)
|
buf = convert(im, bpp)
|
||||||
if 'NBPP_DEBUG' in os.environ:
|
if 'NBPP_DEBUG' in os.environ:
|
||||||
debug(buf, bpp)
|
debug(buf, bpp)
|
||||||
|
4
vram.cpp
4
vram.cpp
@ -40,8 +40,8 @@ static void _2bpp_4bpp_vram_copy(uint32_t * vram, const start_size_t& buf)
|
|||||||
|
|
||||||
uint32_t character_pattern_table(const start_size_t& buf, const uint32_t top)
|
uint32_t character_pattern_table(const start_size_t& buf, const uint32_t top)
|
||||||
{
|
{
|
||||||
// round to nearest multiple of 32
|
// round to nearest multiple of 16
|
||||||
const uint32_t table_size = ((buf.size * 2) + 0x20 - 1) & (-0x20);
|
const uint32_t table_size = ((buf.size * 2) + 0x10 - 1) & (-0x10);
|
||||||
const uint32_t base_address = top - table_size;
|
const uint32_t base_address = top - table_size;
|
||||||
|
|
||||||
uint32_t * vram = &vdp1.vram.u32[(base_address / 4)];
|
uint32_t * vram = &vdp1.vram.u32[(base_address / 4)];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user