From 9fe26641b777dacc02e57973c8e5d1d1d9c6c85b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 9 May 2021 08:39:55 -0600 Subject: [PATCH] Add additional example --- .../16bit_counter_with_map_and_strings.cpp | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 examples/16bit_counter_with_map_and_strings.cpp diff --git a/examples/16bit_counter_with_map_and_strings.cpp b/examples/16bit_counter_with_map_and_strings.cpp new file mode 100644 index 0000000..634607f --- /dev/null +++ b/examples/16bit_counter_with_map_and_strings.cpp @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include + +enum Colors : uint8_t { WHITE = 0x01 }; + +static volatile uint8_t &memory_loc(const uint16_t loc) { + return *reinterpret_cast(loc); +} + +static void poke(const uint16_t loc, const uint8_t value) { + memory_loc(loc) = value; +} + +static std::uint8_t peek(const std::uint16_t loc) { return memory_loc(loc); } + +static void decrement_border_color() { --memory_loc(0xd020); } + +static void increment_border_color() { ++memory_loc(0xd020); } + +static bool joystick_down() { + uint8_t joystick_state = peek(0xDC00); + return (joystick_state & 2) == 0; +} + +void use_data(std::array &data); + +static void puts(uint8_t x, uint8_t y, std::string_view str) { + const auto start = 0x400 + (y * 40 + x); + + std::memcpy(const_cast(&memory_loc(start)), str.data(), + str.size()); +} + + +template +struct Graphic +{ + std::array data; + + static constexpr auto width() noexcept { + return Width; + } + + static constexpr auto height() noexcept { + return Height; + } + + constexpr Graphic() = default; + + constexpr Graphic(std::array data_) noexcept : data(data_) {} + constexpr Graphic(std::initializer_list data_) noexcept { + std::copy(begin(data_), end(data_), begin(data)); + } + + constexpr auto &operator()(const std::uint8_t x, const std::uint8_t y) noexcept { + return data[y * Width + x]; + } + + constexpr const auto &operator()(const std::uint8_t x, const std::uint8_t y) const noexcept { + return data[y * Width + x]; + } +}; + +static void putc(uint8_t x, uint8_t y, uint8_t c) { + const auto start = 0x400 + (y * 40 + x); + poke(start, c); +} + +static void put_hex(uint8_t x, uint8_t y, uint8_t value) { + const auto put_nibble = [](auto x, auto y, uint8_t nibble) { + if (nibble <= 9) { + putc(x, y, nibble + 48); + } else { + putc(x, y, nibble - 9); + } + }; + + put_nibble(x + 1, y, 0xF & value); + put_nibble(x, y, 0xF & (value >> 4)); +} + +static void put_hex(uint8_t x, uint8_t y, uint16_t value) { + put_hex(x+2,y, static_cast(0xFF & value)); + put_hex(x,y, static_cast(0xFF & (value >> 8))); +} + +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)); + } + } +} + +struct Clock { + using milliseconds = std::chrono::duration; + + // return elapsed time since last restart + [[nodiscard]] milliseconds restart() { + // stop Timer A + poke(0xDC0E, 0b00000000); + + // last value + const auto previous_value = static_cast( + peek(0xDC04) | (static_cast(peek(0xDC05)) << 8)); + + // reset timer + poke(0xDC04, 0xFF); + poke(0xDC05, 0xFF); + + // restart timer A + poke(0xDC0E, 0b00010001); + + return milliseconds{0xFFFF - previous_value}; + } + + Clock() { [[maybe_unused]] const auto value = restart(); } +}; + +int main() { + + // static constexpr std::array data{0}; + // std::memcpy(const_cast(&memory_loc(0x400)), data.data(), + // data.size()); + + static constexpr auto pic = + Graphic<5,4>{ + 78,119,77,32,32, + 101,32,32,80,32, + 101,79,101,103,32, + 76,101,76,122,88 + }; + + static constexpr auto map1 = + Graphic<4, 2>{ + 1,0,1,0, + 1,1,1,1 + }; + + static constexpr auto map2 = + Graphic<6, 3>{ + 1,0,1,0,0,0, + 1,1,1,1,0,1, + 0,0,0,1,0,0 + }; + +/* + static constexpr auto map = + Graphic<10, 2>{ + 0,1,0,1,0,0,0,1,0,0, + 1,0,0,0,0,0,1,0,0,0, + }; +*/ + // put_graphic(10,10,pic); + + + const auto draw_map = [](const auto &map) { + for (std::uint8_t y=0; y < map.height(); ++y) { + for (std::uint8_t x = 0; x < map.width(); ++x) { + if (map(x, y) == 1) { + put_graphic(x*4, y*4, pic); + } + } + } + }; + + puts(5, 17, "timing history"); + puts(21, 17, "16bit counter"); + + +// draw_map(map1); + draw_map(map2); + + + Clock game_clock{}; + + + std::uint16_t counter = 0; + std::uint8_t y = 19; + + while (true) { + const auto us_elapsed = game_clock.restart().count(); + + put_hex(5, y, us_elapsed); + put_hex(21, y, counter); + + if (y++ == 24) { + y = 19; + } + + ++counter; + increment_border_color(); + } + + /* + const auto background_color = [](Colors col) { + memory_loc(0xd021) = static_cast(col); + }; + + background_color(Colors::WHITE); + + while(true) { + if (joystick_down()) { + increment_border_color(); + } else { + decrement_border_color(); + } + } + */ +}