wordle: basic drawing

This draws the screen and "keyboard".

I am not certain if I like the keyboard concept. Letter groupings would be more
useful.
This commit is contained in:
Zack Buhman 2023-05-10 05:48:49 -07:00
parent 8e243a435e
commit cfad16c514
8 changed files with 138 additions and 31 deletions

View File

@ -45,7 +45,7 @@ vdp1/normal_sprite_animated.elf: vdp1/normal_sprite_animated.o res/mai.data.o re
smpc/input_intback.elf: smpc/input_intback.o sh/lib1funcs.o
res/dejavusansmono.font.bin: tools/ttf-convert
./tools/ttf-convert 20 7f 32 $(shell fc-match -f '%{file}' 'DejaVu Sans Mono') $@
./tools/ttf-convert 20 7f 22 $(shell fc-match -f '%{file}' 'DejaVu Sans Mono') $@
res/ipapgothic.font.bin: tools/ttf-convert
./tools/ttf-convert 3000 30ff 28 $(shell fc-match -f '%{file}' 'IPAPGothic') $@

View File

@ -50,11 +50,13 @@ uint32_t horizontal_string(state const& s,
}
template <typename T>
void single_character(state const& s,
const uint32_t cmd_ix,
uint32_t single_character_centered(state const& s,
uint32_t cmd_ix,
const T c,
const int32_t x, // in 26.6 fixed point
const int32_t y) // in 26.6 fixed point
const int32_t x1, // in 26.6 fixed point
const int32_t y1,
const int32_t x2,
const int32_t y2)
{
//assert(c <= s.char_code_offset);
const T c_offset = c - s._font->char_code_offset;
@ -62,6 +64,25 @@ void single_character(state const& s,
glyph_bitmap const& bitmap = s._glyphs[c_offset].bitmap;
glyph_metrics const& metrics = s._glyphs[c_offset].metrics;
constexpr uint16_t magenta = (0x31 << 10) | (0x31 << 0);
vdp1.vram.cmd[cmd_ix].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__POLYLINE;
vdp1.vram.cmd[cmd_ix].LINK = 0;
vdp1.vram.cmd[cmd_ix].PMOD = PMOD__ECD | PMOD__SPD;
vdp1.vram.cmd[cmd_ix].COLR = COLR__RGB | magenta; // non-palettized (rgb15) color data
vdp1.vram.cmd[cmd_ix].XA = x1;
vdp1.vram.cmd[cmd_ix].YA = y1;
vdp1.vram.cmd[cmd_ix].XB = x2;
vdp1.vram.cmd[cmd_ix].YB = y1;
vdp1.vram.cmd[cmd_ix].XC = x2;
vdp1.vram.cmd[cmd_ix].YC = y2;
vdp1.vram.cmd[cmd_ix].XD = x1;
vdp1.vram.cmd[cmd_ix].YD = y2;
cmd_ix++;
int32_t x_gap = (((x2 - x1 + 1) << 6) - s._font->max_advance) >> 1;
int32_t y_gap = (((y2 - y1) << 6) - s._font->height) >> 2;
if (bitmap.pitch != 0) {
vdp1.vram.cmd[cmd_ix].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE;
vdp1.vram.cmd[cmd_ix].LINK = 0;
@ -69,9 +90,12 @@ void single_character(state const& s,
vdp1.vram.cmd[cmd_ix].COLR = s.color_address;
vdp1.vram.cmd[cmd_ix].SRCA = SRCA(s.character_address + bitmap.offset);
vdp1.vram.cmd[cmd_ix].SIZE = SIZE__X(bitmap.pitch) | SIZE__Y(bitmap.rows);
vdp1.vram.cmd[cmd_ix].XA = (x + metrics.horiBearingX) >> 6;
vdp1.vram.cmd[cmd_ix].YA = (y - metrics.horiBearingY) >> 6;
vdp1.vram.cmd[cmd_ix].XA = ((x1 << 6) + x_gap + metrics.horiBearingX) >> 6;
vdp1.vram.cmd[cmd_ix].YA = ((y2 << 6) + y_gap - metrics.horiBearingY) >> 6;
cmd_ix++;
}
return cmd_ix;
}
}

View File

@ -160,6 +160,7 @@ int main(int argc, char *argv[])
int font_size;
ss3 << std::dec << argv[3];
ss3 >> font_size;
std::cerr << "font_size: " << font_size << '\n';
error = FT_Set_Pixel_Sizes (face, 0, font_size);
if (error) {

View File

@ -3,24 +3,61 @@
namespace wordle {
namespace draw {
void keyboard()
constexpr int32_t box_dim = 21;
constexpr int32_t grid_space = box_dim + 2;
const static uint8_t layout[3][10] = {
{'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'},
{'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'},
{'Z', 'X', 'C', 'V', 'B', 'N', 'M'},
};
void keyboard(struct screen const& s, void (*draw_char)(uint8_t, int32_t, int32_t, int32_t, int32_t))
{
}
constexpr int32_t origin_x[3] = {46, 57, 69};
constexpr int32_t origin_y = 170;
constexpr uint32_t rows = 3;
constexpr uint32_t cols[3] = {10, 9, 7};
static inline void guess(struct row const& r, void (*draw_char)(uint8_t, int32_t, int32_t))
{
for (uint32_t i = 0; i < word_length; i++) {
uint8_t l = r.letters[i];
for (uint32_t row = 0; row < rows; row++) {
for (uint32_t col = 0; col < cols[row]; col++) {
uint8_t l = layout[row][col];
draw_char(l, 0, 0);
int32_t x1 = origin_x[row] + (col * grid_space);
int32_t y1 = origin_y + (row * grid_space);
int32_t x2 = x1 + box_dim;
int32_t y2 = y1 + box_dim;
break;
draw_char(l, x1, y1, x2, y2);
}
}
}
void guesses(struct screen& s, void (*draw_char)(uint8_t, int32_t, int32_t))
void guesses(struct screen const& s, void (*draw_char)(uint8_t, int32_t, int32_t, int32_t, int32_t))
{
guess(s.rows[0], draw_char);
// first row is at (104,23).
// midpoint is +(10,10)
// grid is +(13,13)
constexpr int32_t origin_x = 103;
constexpr int32_t origin_y = 17;
for (uint32_t row = 0; row < wordle::guesses; row++) {
struct row const& r = s.rows[row];
for (uint32_t col = 0; col < word_length; col++) {
uint8_t l = r.letters[col];
int32_t x1 = origin_x + (col * grid_space);
int32_t y1 = origin_y + (row * grid_space);
int32_t x2 = x1 + box_dim;
int32_t y2 = y1 + box_dim;
draw_char(l, x1, y1, x2, y2);
}
}
}
// end namespace

View File

@ -1,5 +1,6 @@
namespace wordle {
namespace draw {
void guesses(struct screen& s, void (*draw_char)(uint8_t, int32_t, int32_t));
void keyboard(struct screen const& s, void (*draw_char)(uint8_t, int32_t, int32_t, int32_t, int32_t));
void guesses(struct screen const& s, void (*draw_char)(uint8_t, int32_t, int32_t, int32_t, int32_t));
}
}

View File

@ -135,25 +135,26 @@ void smpc_int(void) {
// rendering
void draw_char(uint8_t c, int32_t x, int32_t y)
void draw_char(uint8_t c, int32_t x1, int32_t y1, int32_t x2, int32_t y2)
{
draw_font::single_character(draw_state.font,
draw_state.cmd_ix++,
draw_state.cmd_ix =
draw_font::single_character_centered(draw_state.font,
draw_state.cmd_ix,
c,
(x) << 6,
(y + 30) << 6);
vdp1.vram.cmd[draw_state.cmd_ix].CTRL = CTRL__END;
x1,
y1,
x2,
y2);
}
void render()
{
draw_state.cmd_ix = 2;
wordle_state.rows[0].letters[0] = 't';
wordle::draw::guesses(wordle_state, &draw_char);
wordle::draw::keyboard(wordle_state, &draw_char);
vdp1.vram.cmd[draw_state.cmd_ix].CTRL = CTRL__END;
}
void v_blank_in_int(void) __attribute__ ((interrupt_handler));
@ -217,6 +218,11 @@ void main()
// wait for the beginning of a V blank
v_blank_in();
// wordle init
const uint8_t word[] = "67890";
wordle::init_screen(wordle_state, word);
// end wordle init
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);

View File

@ -5,7 +5,7 @@
namespace wordle {
void init_game(struct screen& s, const uint8_t * word)
void init_screen(struct screen& s, const uint8_t * word)
{
s.edit.row = 0;
s.edit.index = 0;
@ -18,6 +18,42 @@ void init_game(struct screen& s, const uint8_t * word)
s.word[j] = word[j];
}
s.rows[0].letters[0] = 'A';
s.rows[0].letters[1] = 'B';
s.rows[0].letters[2] = 'C';
s.rows[0].letters[3] = 'D';
s.rows[0].letters[4] = 'E';
s.rows[1].letters[0] = 'F';
s.rows[1].letters[1] = 'G';
s.rows[1].letters[2] = 'H';
s.rows[1].letters[3] = 'I';
s.rows[1].letters[4] = 'J';
s.rows[2].letters[0] = 'K';
s.rows[2].letters[1] = 'L';
s.rows[2].letters[2] = 'M';
s.rows[2].letters[3] = 'N';
s.rows[2].letters[4] = 'O';
s.rows[3].letters[0] = 'P';
s.rows[3].letters[1] = 'Q';
s.rows[3].letters[2] = 'R';
s.rows[3].letters[3] = 'S';
s.rows[3].letters[4] = 'T';
s.rows[4].letters[0] = 'U';
s.rows[4].letters[1] = 'V';
s.rows[4].letters[2] = 'W';
s.rows[4].letters[3] = 'X';
s.rows[4].letters[4] = 'Y';
s.rows[5].letters[0] = 'Z';
s.rows[5].letters[1] = '1';
s.rows[5].letters[2] = '2';
s.rows[5].letters[3] = '3';
s.rows[5].letters[4] = '4';
s.all_letters = 0;
}

View File

@ -28,4 +28,6 @@ struct screen {
uint32_t all_letters;
};
void init_screen(struct screen& s, const uint8_t * word);
}