mirror of
https://github.com/lefticus/6502-cpp.git
synced 2026-04-20 11:17:18 +00:00
Minor optimizer fixes
This commit is contained in:
+265
-69
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
@@ -5,41 +6,38 @@
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include "chargen.hpp"
|
||||
|
||||
enum struct Colors : std::uint8_t
|
||||
{
|
||||
enum struct Colors : std::uint8_t {
|
||||
black = 0,
|
||||
white = 1,
|
||||
red = 2,
|
||||
cyan=3,
|
||||
violet=4,
|
||||
green=5,
|
||||
blue=6,
|
||||
yellow=7,
|
||||
orange=8,
|
||||
brown=9,
|
||||
light_red=10,
|
||||
dark_grey=11,
|
||||
grey=12,
|
||||
light_green=13,
|
||||
light_blue=14,
|
||||
light_grey=15
|
||||
cyan = 3,
|
||||
violet = 4,
|
||||
green = 5,
|
||||
blue = 6,
|
||||
yellow = 7,
|
||||
orange = 8,
|
||||
brown = 9,
|
||||
light_red = 10,
|
||||
dark_grey = 11,
|
||||
grey = 12,
|
||||
light_green = 13,
|
||||
light_blue = 14,
|
||||
light_grey = 15
|
||||
};
|
||||
|
||||
constexpr char charToPETSCII(char c) noexcept {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
return c - 'A' + 1;
|
||||
}
|
||||
constexpr char charToPETSCII(char c) noexcept
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z') { return c - 'A' + 1; }
|
||||
return c;
|
||||
}
|
||||
|
||||
template<std::size_t Size>
|
||||
constexpr auto PETSCII(const char (&value)[Size]) noexcept
|
||||
template<std::size_t Size> constexpr auto PETSCII(const char (&value)[Size]) noexcept
|
||||
{
|
||||
std::array<char, Size-1> result{};
|
||||
std::array<char, Size - 1> result{};
|
||||
std::transform(std::begin(value), std::prev(std::end(value)), std::begin(result), charToPETSCII);
|
||||
return result;
|
||||
}
|
||||
@@ -75,7 +73,7 @@ static bool joystick_down()
|
||||
|
||||
void use_data(std::array<char, 1024> &data);
|
||||
|
||||
static void puts(uint8_t x, uint8_t y, const auto &range, const Colors color=Colors::white)
|
||||
static void puts(uint8_t x, uint8_t y, const auto &range, const Colors color = Colors::white)
|
||||
{
|
||||
const auto offset = y * 40 + x;
|
||||
|
||||
@@ -126,6 +124,12 @@ template<std::uint8_t Width, std::uint8_t Height> struct Graphic
|
||||
}
|
||||
};
|
||||
|
||||
template<std::uint8_t Width, std::uint8_t Height> struct ColoredGraphic
|
||||
{
|
||||
Graphic<Width, Height> data;
|
||||
Graphic<Width, Height> colors;
|
||||
};
|
||||
|
||||
|
||||
static constexpr auto load_charset(const std::span<const std::uint8_t, 256 * 8> &bits)
|
||||
{
|
||||
@@ -236,6 +240,12 @@ static std::uint8_t loadc(uint8_t x, uint8_t y)
|
||||
return peek(start);
|
||||
}
|
||||
|
||||
static void invertc(uint8_t x, uint8_t y)
|
||||
{
|
||||
const auto start = 0x400 + (y * 40 + x);
|
||||
memory_loc(start) += 128;
|
||||
}
|
||||
|
||||
|
||||
static void put_hex(uint8_t x, uint8_t y, uint8_t value, Colors color)
|
||||
{
|
||||
@@ -260,10 +270,22 @@ static void put_hex(uint8_t x, uint8_t y, uint16_t value, Colors color)
|
||||
static void put_graphic(uint8_t x, uint8_t y, const auto &graphic)
|
||||
{
|
||||
for (uint8_t cur_y = 0; cur_y < graphic.height(); ++cur_y) {
|
||||
for (uint8_t cur_x = 0; cur_x < graphic.width(); ++cur_x) { putc(cur_x + x, cur_y + y, graphic(cur_x, cur_y), Colors::white); }
|
||||
for (uint8_t cur_x = 0; cur_x < graphic.width(); ++cur_x) {
|
||||
putc(cur_x + x, cur_y + y, graphic(cur_x, cur_y), Colors::white);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void put_graphic(uint8_t x, uint8_t y, const auto &graphic) requires requires { graphic.colors(0, 0); }
|
||||
{
|
||||
for (uint8_t cur_y = 0; cur_y < graphic.data.height(); ++cur_y) {
|
||||
for (uint8_t cur_x = 0; cur_x < graphic.data.width(); ++cur_x) {
|
||||
putc(cur_x + x, cur_y + y, graphic.data(cur_x, cur_y), static_cast<Colors>(graphic.colors(cur_x, cur_y)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Clock
|
||||
{
|
||||
using milliseconds = std::chrono::duration<std::uint16_t, std::milli>;
|
||||
@@ -324,7 +346,8 @@ struct Screen
|
||||
}
|
||||
}
|
||||
|
||||
void hide(auto &s) {
|
||||
void hide(auto &s)
|
||||
{
|
||||
if (s.is_shown) {
|
||||
put_graphic(s.x, s.y, s.saved_background);
|
||||
s.is_shown = false;
|
||||
@@ -345,8 +368,7 @@ struct Screen
|
||||
}
|
||||
};
|
||||
|
||||
template<std::uint8_t Width, std::uint8_t Height>
|
||||
struct Map;
|
||||
template<std::uint8_t Width, std::uint8_t Height> struct Map;
|
||||
|
||||
struct GameState
|
||||
{
|
||||
@@ -363,16 +385,24 @@ struct GameState
|
||||
|
||||
Map<10, 5> const *current_map = nullptr;
|
||||
|
||||
constexpr void set_current_map(const Map<10, 5> &new_map) {
|
||||
constexpr void set_current_map(const Map<10, 5> &new_map)
|
||||
{
|
||||
current_map = &new_map;
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
constexpr void execute_actions(const auto &character) noexcept
|
||||
constexpr void execute_actions(std::uint8_t new_x, std::uint8_t new_y, const auto &character) noexcept
|
||||
{
|
||||
if (new_x + character.width() > 40) { new_x = x; }
|
||||
|
||||
if (new_y + character.height() > 20) { new_y = y; }
|
||||
|
||||
x = new_x;
|
||||
y = new_y;
|
||||
|
||||
if (current_map) {
|
||||
for (auto &action : current_map->actions) {
|
||||
action.execute_if_collision(x,y,character.width(), character.height(), *this);
|
||||
action.execute_if_collision(x, y, character.width(), character.height(), *this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -423,10 +453,13 @@ struct Map_Action
|
||||
using Action_Func = void (*)(GameState &);
|
||||
Action_Func action = nullptr;
|
||||
|
||||
constexpr void execute_if_collision(std::uint8_t obj_x, std::uint8_t obj_y, std::uint8_t obj_width, std::uint8_t obj_height, GameState &game) const {
|
||||
if (action == nullptr) {
|
||||
return;
|
||||
}
|
||||
constexpr void execute_if_collision(std::uint8_t obj_x,
|
||||
std::uint8_t obj_y,
|
||||
std::uint8_t obj_width,
|
||||
std::uint8_t obj_height,
|
||||
GameState &game) const
|
||||
{
|
||||
if (action == nullptr) { return; }
|
||||
|
||||
const std::uint8_t rect1_x1 = x;
|
||||
const std::uint8_t rect1_x2 = x + width;
|
||||
@@ -438,26 +471,43 @@ struct Map_Action
|
||||
const std::uint8_t rect2_y1 = obj_y;
|
||||
const std::uint8_t rect2_y2 = obj_y + obj_height;
|
||||
|
||||
if (rect1_x1 < rect2_x2 && rect1_x2 > rect2_x1 &&
|
||||
rect1_y1 < rect2_y2 && rect1_y2 > rect2_y1) {
|
||||
action(game);
|
||||
}
|
||||
if (rect1_x1 < rect2_x2 && rect1_x2 > rect2_x1 && rect1_y1 < rect2_y2 && rect1_y2 > rect2_y1) { action(game); }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<std::uint8_t Width, std::uint8_t Height>
|
||||
struct Map {
|
||||
template<std::uint8_t Width, std::uint8_t Height> struct Map
|
||||
{
|
||||
std::string_view name;
|
||||
Graphic<Width, Height> layout;
|
||||
|
||||
std::span<const Map_Action> actions;
|
||||
};
|
||||
|
||||
void draw_box(uint8_t x, uint8_t y, uint8_t width, uint8_t height, Colors color) {
|
||||
putc(x, y, 85, color);
|
||||
putc(x + width - 1, y, 73, color);
|
||||
putc(x + width - 1, y + height - 1, 75, color);
|
||||
putc(x, y + height - 1, 74, color);
|
||||
|
||||
for (uint8_t cur_x = x + 1; cur_x < x + width - 1; ++cur_x) {
|
||||
putc(cur_x, y, 67, color);
|
||||
putc(cur_x, y + height - 1, 67, color);
|
||||
}
|
||||
|
||||
for (uint8_t cur_y = y + 1; cur_y < y + height - 1; ++cur_y) {
|
||||
putc(x, cur_y, 93, color);
|
||||
putc(x + width - 1, cur_y, 93, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
// static constexpr auto charset = load_charset(uppercase);
|
||||
|
||||
// clang-format off
|
||||
static constexpr auto inn = Graphic<6,5> {
|
||||
32,233,160,160,223,32,
|
||||
233,160,160,160,160,223,
|
||||
@@ -482,12 +532,29 @@ int main()
|
||||
160,160,160,160,76,160,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
static constexpr auto town = Graphic<4, 4>{
|
||||
85, 67, 67, 73,
|
||||
93, 233, 223, 93,
|
||||
93, 160, 160, 93,
|
||||
74, 67, 67, 75 };
|
||||
*/
|
||||
|
||||
static constexpr auto town = ColoredGraphic<4, 4>{
|
||||
{
|
||||
32, 32,32, 32,
|
||||
233,223,233,223,
|
||||
224,224,224,224,
|
||||
104,104,104,104
|
||||
},
|
||||
{
|
||||
2,2,10,10,
|
||||
4,4,7,7,
|
||||
4,4,7,7,
|
||||
11,11,11,11
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static constexpr auto mountain = Graphic<4, 4>{
|
||||
32, 78, 77, 32,
|
||||
@@ -495,6 +562,21 @@ int main()
|
||||
78, 77, 32, 32,
|
||||
32, 78, 77, 32 };
|
||||
|
||||
static constexpr auto colored_mountain = ColoredGraphic<4, 4>{
|
||||
{
|
||||
32, 78, 77, 32,
|
||||
32, 32, 233, 223,
|
||||
233, 223, 32, 32,
|
||||
32, 78, 77, 32 },
|
||||
{
|
||||
1, 9, 9, 1,
|
||||
1, 1, 8, 8,
|
||||
9, 9, 1, 1,
|
||||
1, 8, 8, 1
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
auto character = SimpleSprite<2, 3>{
|
||||
32, 87,
|
||||
@@ -529,14 +611,14 @@ int main()
|
||||
},
|
||||
std::span<const Map_Action>(begin(overview_actions), end(overview_actions))
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
||||
static constexpr std::array<void (*)(std::uint8_t, std::uint8_t), 7> tile_types{
|
||||
[](std::uint8_t x, std::uint8_t y) {
|
||||
/* do nothing for 0th */
|
||||
},
|
||||
[](std::uint8_t x, std::uint8_t y) { put_graphic(x, y, mountain); },
|
||||
[](std::uint8_t x, std::uint8_t y) { put_graphic(x, y, colored_mountain); },
|
||||
[](std::uint8_t x, std::uint8_t y) {
|
||||
/* do nothing for 2 */
|
||||
},
|
||||
@@ -557,24 +639,6 @@ int main()
|
||||
}
|
||||
};
|
||||
|
||||
constexpr auto draw_box = [](uint8_t x, uint8_t y, uint8_t width, uint8_t height, Colors color) {
|
||||
putc(x, y, 85, color);
|
||||
putc(x + width - 1, y, 73, color);
|
||||
putc(x + width - 1, y + height - 1, 75, color);
|
||||
putc(x, y + height - 1, 74, color);
|
||||
|
||||
for (uint8_t cur_x = x + 1; cur_x < x + width - 1; ++cur_x) {
|
||||
putc(cur_x, y, 67, color);
|
||||
putc(cur_x, y + height - 1, 67, color);
|
||||
}
|
||||
|
||||
for (uint8_t cur_y = y + 1; cur_y < y + height - 1; ++cur_y) {
|
||||
putc(x, cur_y, 93, color);
|
||||
putc(x + width - 1, cur_y, 93, color);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
GameState game;
|
||||
game.current_map = &overview_map;
|
||||
|
||||
@@ -591,13 +655,132 @@ int main()
|
||||
|
||||
Screen screen;
|
||||
|
||||
auto eventHandler = overloaded{ [&](const GameState::JoyStick2StateChanged &e) {
|
||||
if (e.state.up()) { --game.y; }
|
||||
if (e.state.down()) { ++game.y; }
|
||||
if (e.state.left()) { --game.x; }
|
||||
if (e.state.right()) { ++game.x; }
|
||||
static constexpr auto menu_options =
|
||||
std::array {
|
||||
std::string_view{"info"},
|
||||
std::string_view{"test2"},
|
||||
std::string_view{"test3"},
|
||||
std::string_view{"an even longer thing"}
|
||||
};
|
||||
struct Menu {
|
||||
consteval Menu(std::span<const std::string_view> t_options)
|
||||
: options{t_options}, width{std::max_element(begin(options), end(options),
|
||||
[](std::string_view lhs, std::string_view rhs) {
|
||||
return lhs.size() < rhs.size();
|
||||
}
|
||||
)->size() + 2},
|
||||
height{options.size() + 2},
|
||||
x{(40 - width) / 2},
|
||||
y{(20 - height) / 2}
|
||||
{
|
||||
|
||||
game.execute_actions(character.graphic);
|
||||
}
|
||||
|
||||
void highlight(std::uint8_t selection) {
|
||||
const std::uint8_t cur_y = selection + 1 + y;
|
||||
for (auto cur_x = 1; cur_x < width - 1; ++cur_x) {
|
||||
invertc(x + cur_x, cur_y);
|
||||
}
|
||||
}
|
||||
|
||||
void unhighlight(std::uint8_t selection)
|
||||
{
|
||||
highlight(selection);
|
||||
}
|
||||
|
||||
void hide(GameState &game) {
|
||||
displayed = false;
|
||||
game.redraw = true;
|
||||
}
|
||||
|
||||
bool show(GameState &game, std::uint8_t &selection) {
|
||||
if (!displayed) {
|
||||
displayed = true;
|
||||
|
||||
draw_box(x, y, width, height, Colors::white);
|
||||
|
||||
for (auto cur_y = y + 1; const auto &str : options) {
|
||||
puts(x+1, cur_y++, str, Colors::grey);
|
||||
}
|
||||
|
||||
highlight(current_selection);
|
||||
}
|
||||
|
||||
if (current_selection != next_selection) {
|
||||
unhighlight(current_selection);
|
||||
highlight(next_selection);
|
||||
current_selection = next_selection;
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
selected = false;
|
||||
selection = current_selection;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool process_event(const GameState::Event &e) {
|
||||
if (not displayed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (const auto *ptr = std::get_if<GameState::JoyStick2StateChanged>(&e); ptr) {
|
||||
if (ptr->state.up()) {
|
||||
next_selection = current_selection - 1;
|
||||
}
|
||||
|
||||
if (ptr->state.down()) {
|
||||
next_selection = current_selection + 1;
|
||||
}
|
||||
|
||||
if (next_selection > options.size() - 1) {
|
||||
next_selection = options.size() - 1;
|
||||
}
|
||||
|
||||
if (ptr->state.fire()) {
|
||||
selected = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::span<const std::string_view> options;
|
||||
std::uint8_t width;
|
||||
std::uint8_t height;
|
||||
std::uint8_t x;
|
||||
std::uint8_t y;
|
||||
std::uint8_t current_selection{0};
|
||||
std::uint8_t next_selection{0};
|
||||
bool selected{false};
|
||||
bool displayed{false};
|
||||
|
||||
};
|
||||
|
||||
Menu m(menu_options);
|
||||
|
||||
bool show_game_menu = false;
|
||||
|
||||
auto eventHandler = overloaded{ [&](const GameState::JoyStick2StateChanged &e) {
|
||||
auto new_x = game.x;
|
||||
auto new_y = game.y;
|
||||
|
||||
if (e.state.fire()) {
|
||||
show_game_menu = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.state.up()) { --new_y; }
|
||||
if (e.state.down()) { ++new_y; }
|
||||
if (e.state.left()) { --new_x; }
|
||||
if (e.state.right()) { ++new_x; }
|
||||
|
||||
|
||||
game.execute_actions(new_x, new_y, character.graphic);
|
||||
|
||||
screen.show(game.x, game.y, character);
|
||||
|
||||
@@ -606,7 +789,12 @@ int main()
|
||||
[](const GameState::TimeElapsed &e) { put_hex(36, 0, e.us.count(), Colors::dark_grey); } };
|
||||
|
||||
while (true) {
|
||||
std::visit(eventHandler, game.next_event());
|
||||
const auto next_event = game.next_event();
|
||||
|
||||
if (not m.process_event(next_event)) {
|
||||
// if no gui elements needed the event, then we handle it
|
||||
std::visit(eventHandler, next_event);
|
||||
}
|
||||
|
||||
if (game.redraw) {
|
||||
screen.hide(character);
|
||||
@@ -624,6 +812,14 @@ int main()
|
||||
screen.show(game.x, game.y, character);
|
||||
}
|
||||
|
||||
if (std::uint8_t result = 0; show_game_menu && m.show(game, result)) {
|
||||
// we had a menu item selected
|
||||
m.hide(game);
|
||||
show_game_menu = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
increment_border_color();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user