diff --git a/examples/graphics.cpp b/examples/graphics.cpp index de514cb..85aa203 100644 --- a/examples/graphics.cpp +++ b/examples/graphics.cpp @@ -5,10 +5,45 @@ #include #include #include +#include #include "chargen.hpp" -enum Colors : uint8_t { WHITE = 0x01 }; +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 +}; + +constexpr char charToPETSCII(char c) noexcept { + if (c >= 'A' && c <= 'Z') { + return c - 'A' + 1; + } + return c; +} + +template +constexpr auto PETSCII(const char (&value)[Size]) noexcept +{ + std::array result{}; + std::transform(std::begin(value), std::prev(std::end(value)), std::begin(result), charToPETSCII); + return result; +} + static volatile uint8_t &memory_loc(const uint16_t loc) { return *reinterpret_cast(loc); } @@ -40,15 +75,18 @@ static bool joystick_down() void use_data(std::array &data); -static void puts(uint8_t x, uint8_t y, std::string_view str) +static void puts(uint8_t x, uint8_t y, const auto &range, const Colors color=Colors::white) { - const auto start = 0x400 + (y * 40 + x); + const auto offset = y * 40 + x; - std::copy(str.begin(), str.end(), &memory_loc(start)); -// std::memcpy(const_cast(&memory_loc(start)), str.data(), str.size()); + const auto start = 0x400 + offset; + std::copy(begin(range), end(range), &memory_loc(start)); + + for (std::uint16_t color_loc = 0; color_loc < range.size(); ++color_loc) { + poke(0xD800 + color_loc + offset, static_cast(color)); + } } - template struct Graphic { std::array data{}; @@ -184,10 +222,12 @@ static constexpr auto from_pixels_to_2x2(const Graphic &pixel return result; } -static void putc(uint8_t x, uint8_t y, uint8_t c) +static void putc(uint8_t x, uint8_t y, uint8_t c, Colors color) { - const auto start = 0x400 + (y * 40 + x); + const auto offset = (y * 40 + x); + const auto start = 0x400 + offset; poke(start, c); + poke(offset + 0xD800, static_cast(color)); } static std::uint8_t loadc(uint8_t x, uint8_t y) @@ -197,13 +237,13 @@ static std::uint8_t loadc(uint8_t x, uint8_t y) } -static void put_hex(uint8_t x, uint8_t y, uint8_t value) +static void put_hex(uint8_t x, uint8_t y, uint8_t value, Colors color) { - const auto put_nibble = [](auto x, auto y, uint8_t nibble) { + const auto put_nibble = [color](auto x, auto y, uint8_t nibble) { if (nibble <= 9) { - putc(x, y, nibble + 48); + putc(x, y, nibble + 48, color); } else { - putc(x, y, nibble - 9); + putc(x, y, nibble - 9, color); } }; @@ -211,16 +251,16 @@ static void put_hex(uint8_t x, uint8_t y, uint8_t value) put_nibble(x, y, 0xF & (value >> 4)); } -static void put_hex(uint8_t x, uint8_t y, uint16_t value) +static void put_hex(uint8_t x, uint8_t y, uint16_t value, Colors color) { - put_hex(x + 2, y, static_cast(0xFF & value)); - put_hex(x, y, static_cast(0xFF & (value >> 8))); + put_hex(x + 2, y, static_cast(0xFF & value), color); + put_hex(x, y, static_cast(0xFF & (value >> 8)), 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)); } + 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); } } } @@ -517,20 +557,20 @@ int main() } }; - constexpr auto draw_box = [](uint8_t x, uint8_t y, uint8_t width, uint8_t height) { - putc(x, y, 85); - putc(x + width - 1, y, 73); - putc(x + width - 1, y + height - 1, 75); - putc(x, y + height - 1, 74); + 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); - putc(cur_x, y + height - 1, 67); + 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); - putc(x + width - 1, cur_y, 93); + putc(x, cur_y, 93, color); + putc(x + width - 1, cur_y, 93, color); } }; @@ -539,14 +579,14 @@ int main() game.current_map = &overview_map; constexpr auto show_stats = [](const auto &cur_game) { - puts(1, 21, "stamina:"); - put_hex(12, 21, cur_game.stamina); - put_hex(15, 21, cur_game.max_stamina()); - puts(14, 21, "/"); - puts(1, 22, "endurance:"); - put_hex(12, 22, cur_game.endurance); - puts(1, 23, "cash: "); - put_hex(12, 23, cur_game.cash); + puts(1, 21, PETSCII("STAMINA:"), Colors::light_grey); + put_hex(12, 21, cur_game.stamina, Colors::white); + put_hex(15, 21, cur_game.max_stamina(), Colors::white); + puts(14, 21, PETSCII("/"), Colors::light_grey); + puts(1, 22, PETSCII("ENDURANCE:"), Colors::light_grey); + put_hex(12, 22, cur_game.endurance, Colors::white); + puts(1, 23, PETSCII("CASH:"), Colors::light_grey); + put_hex(12, 23, cur_game.cash, Colors::white); }; Screen screen; @@ -561,9 +601,9 @@ int main() screen.show(game.x, game.y, character); - put_hex(36, 1, e.state.state); + put_hex(36, 1, e.state.state, Colors::dark_grey); }, - [](const GameState::TimeElapsed &e) { put_hex(36, 0, e.us.count()); } }; + [](const GameState::TimeElapsed &e) { put_hex(36, 0, e.us.count(), Colors::dark_grey); } }; while (true) { std::visit(eventHandler, game.next_event()); @@ -577,9 +617,9 @@ int main() game.redraw = false; draw_map(game.current_map->layout); - draw_box(0, 20, 40, 5); + draw_box(0, 20, 40, 5, Colors::dark_grey); - puts(10, 20, game.current_map->name); + puts(10, 20, game.current_map->name, Colors::white); show_stats(game); screen.show(game.x, game.y, character); } diff --git a/src/6502-c++.cpp b/src/6502-c++.cpp index 2e798fd..02e977d 100644 --- a/src/6502-c++.cpp +++ b/src/6502-c++.cpp @@ -95,6 +95,7 @@ struct AVR : ASMLine breq, brge, + brlt, brlo, brne, brsh, @@ -127,6 +128,7 @@ struct AVR : ASMLine nop, + OR, out, pop, @@ -208,7 +210,9 @@ struct AVR : ASMLine if (o == "nop") { return OpCode::nop; } if (o == "jmp") { return OpCode::jmp; } if (o == "tst") { return OpCode::tst; } - if (o=="brge"){ return OpCode::brge; } + if (o == "brge"){ return OpCode::brge; } + if (o == "brlt") { return OpCode::brlt; } + if (o == "or") { return OpCode::OR; } } } throw std::runtime_error(fmt::format("Unknown opcode: {}", o)); @@ -410,6 +414,12 @@ void translate_instruction(const Personality &personality, const auto o2_reg_num = translate_register_number(o2); switch (op) { + case AVR::OpCode::OR: { + instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(o1_reg_num)); + instructions.emplace_back(mos6502::OpCode::ORA, personality.get_register(o2_reg_num)); + instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(o1_reg_num)); + return; + } case AVR::OpCode::jmp: instructions.emplace_back(mos6502::OpCode::jmp, o1); return; case AVR::OpCode::tst: { // just an lda will set the relevant flags that the tst operation sets, so I think this is @@ -501,6 +511,13 @@ void translate_instruction(const Personality &personality, throw std::runtime_error("Unhandled 'std'"); } + case AVR::OpCode::brlt: { + const auto [s_set, s_clear] = setup_S_flag(instructions); + instructions.emplace_back(ASMLine::Type::Label, s_set); + instructions.emplace_back(mos6502::OpCode::jmp, o1); + instructions.emplace_back(ASMLine::Type::Label, s_clear); + return; + } case AVR::OpCode::brge: { const auto [s_set, s_clear] = setup_S_flag(instructions); instructions.emplace_back(ASMLine::Type::Label, s_clear);