diff --git a/examples/graphics.cpp b/examples/graphics.cpp index 85aa203..f145cd6 100644 --- a/examples/graphics.cpp +++ b/examples/graphics.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,41 +6,38 @@ #include #include #include -#include +#include #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 -constexpr auto PETSCII(const char (&value)[Size]) noexcept +template constexpr auto PETSCII(const char (&value)[Size]) noexcept { - std::array result{}; + std::array 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 &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 struct Graphic } }; +template struct ColoredGraphic +{ + Graphic data; + Graphic colors; +}; + static constexpr auto load_charset(const std::span &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(graphic.colors(cur_x, cur_y))); + } + } +} + + struct Clock { using milliseconds = std::chrono::duration; @@ -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 -struct Map; +template 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 -struct Map { +template struct Map +{ std::string_view name; Graphic layout; std::span 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(begin(overview_actions), end(overview_actions)) }; - + // clang-format on static constexpr std::array 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 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(&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 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(); } diff --git a/include/optimizer.hpp b/include/optimizer.hpp index 53aace8..86bce59 100644 --- a/include/optimizer.hpp +++ b/include/optimizer.hpp @@ -121,7 +121,7 @@ bool optimize_dead_sta(std::span &block, const Personality &personality for (auto itr = block.begin(); itr != block.end(); ++itr) { if (itr->opcode == mos6502::OpCode::sta && is_virtual_register_op(*itr, personality)) { for (auto inner = std::next(itr); inner != block.end(); ++inner) { - if (inner->op.value.find('(') != std::string::npos) { + if (not inner->op.value.starts_with("#<(") && inner->op.value.find('(') != std::string::npos) { // this is an indexed operation, which is risky to optimize a sta around on the virtual registers, // so we'll skip this block break; @@ -260,9 +260,11 @@ bool optimize(std::vector &instructions, [[maybe_unused]] const Persona // it might make sense in the future to only insert these if determined they are needed? for (size_t op = 10; op < instructions.size(); ++op) { if (instructions[op].opcode == mos6502::OpCode::lda || instructions[op].opcode == mos6502::OpCode::bcc - || instructions[op].opcode == mos6502::OpCode::bcs || instructions[op].opcode == mos6502::OpCode::ldy) { - if (instructions[op - 1].text == "; END remove if next is lda, bcc, bcs, ldy" - || (instructions[op - 2].text == "; END remove if next is lda, bcc, bcs, ldy" + || instructions[op].opcode == mos6502::OpCode::bcs || instructions[op].opcode == mos6502::OpCode::ldy + || instructions[op].opcode == mos6502::OpCode::inc || instructions[op].opcode == mos6502::OpCode::clc + || instructions[op].opcode == mos6502::OpCode::sec) { + if (instructions[op - 1].text == "; END remove if next is lda, bcc, bcs, ldy, inc, clc, sec" + || (instructions[op - 2].text == "; END remove if next is lda, bcc, bcs, ldy, inc, clc, sec" && instructions[op - 1].type == ASMLine::Type::Directive)) { for (size_t inner_op = op - 1; inner_op > 1; --inner_op) { instructions[inner_op] = diff --git a/src/6502-c++.cpp b/src/6502-c++.cpp index 02e977d..4d02dad 100644 --- a/src/6502-c++.cpp +++ b/src/6502-c++.cpp @@ -210,7 +210,7 @@ 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; } } @@ -291,7 +291,7 @@ void indirect_store(std::vector &instructions, instructions.emplace_back(ASMLine::Type::Label, n_set); instructions.emplace_back(mos6502::OpCode::bvs, Operand(Operand::Type::literal, s_clear)); instructions.emplace_back(mos6502::OpCode::jmp, Operand(Operand::Type::literal, s_set)); - return {s_set, s_clear}; + return { s_set, s_clear }; } void fixup_16_bit_N_Z_flags(std::vector &instructions) @@ -313,7 +313,7 @@ void fixup_16_bit_N_Z_flags(std::vector &instructions) // if low order byte is negative, just load 1, this will properly set the Z flag and leave C correct instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#1")); instructions.emplace_back(ASMLine::Type::Label, set_flag_label); - instructions.emplace_back(ASMLine::Type::Directive, "; END remove if next is lda, bcc, bcs, ldy"); + instructions.emplace_back(ASMLine::Type::Directive, "; END remove if next is lda, bcc, bcs, ldy, inc, clc, sec"); } void add_16_bit(const Personality &personality, @@ -617,7 +617,7 @@ void translate_instruction(const Personality &personality, case AVR::OpCode::cpse: { instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(o1_reg_num)); instructions.emplace_back(mos6502::OpCode::cmp, personality.get_register(o2_reg_num)); - std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable"; + std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()); instructions.emplace_back(mos6502::OpCode::beq, Operand(Operand::Type::literal, new_label_name)); instructions.emplace_back(ASMLine::Type::Directive, new_label_name); return; @@ -626,7 +626,7 @@ void translate_instruction(const Personality &personality, instructions.emplace_back( mos6502::OpCode::lda, Operand(o2.type, fixup_8bit_literal("$" + std::to_string(1 << (to_int(o2.value)))))); instructions.emplace_back(mos6502::OpCode::bit, personality.get_register(o1_reg_num)); - std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable"; + std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()); instructions.emplace_back(mos6502::OpCode::beq, Operand(Operand::Type::literal, new_label_name)); instructions.emplace_back(ASMLine::Type::Directive, new_label_name); return; @@ -635,7 +635,7 @@ void translate_instruction(const Personality &personality, instructions.emplace_back(mos6502::OpCode::lda, Operand(o2.type, fixup_8bit_literal("$" + std::to_string(1 << (to_int(o2.value.c_str())))))); instructions.emplace_back(mos6502::OpCode::bit, personality.get_register(o1_reg_num)); - std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable"; + std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()); instructions.emplace_back(mos6502::OpCode::bne, Operand(Operand::Type::literal, new_label_name)); instructions.emplace_back(ASMLine::Type::Directive, new_label_name); return; @@ -646,7 +646,7 @@ void translate_instruction(const Personality &personality, return; } else if (o1.value == ".+2") { // assumes 6502 'borrow' for Carry flag instead of carry, so bcc instead of bcs - std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable"; + std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()); instructions.emplace_back(mos6502::OpCode::bne, Operand(Operand::Type::literal, new_label_name)); instructions.emplace_back(ASMLine::Type::Directive, new_label_name); return; @@ -688,7 +688,6 @@ void translate_instruction(const Personality &personality, instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#$FF")); instructions.emplace_back(mos6502::OpCode::eor, personality.get_register(o1_reg_num)); instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(o1_reg_num)); - instructions.emplace_back(mos6502::OpCode::sec); return; } case AVR::OpCode::clr: { @@ -708,7 +707,7 @@ void translate_instruction(const Personality &personality, if (o1.value == ".+2") { // assumes 6502 'borrow' for Carry flag instead of carry, so bcc instead of bcs - std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable"; + std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()); instructions.emplace_back(mos6502::OpCode::bcc, Operand(Operand::Type::literal, new_label_name)); instructions.emplace_back(ASMLine::Type::Directive, new_label_name); return; @@ -773,7 +772,7 @@ void translate_instruction(const Personality &personality, case AVR::OpCode::brsh: { if (o1.value == ".+2") { // assumes 6502 'borrow' for Carry flag instead of carry, so bcs instead of bcc - std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable"; + std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()); instructions.emplace_back(mos6502::OpCode::bcs, Operand(Operand::Type::literal, new_label_name)); instructions.emplace_back(ASMLine::Type::Directive, new_label_name); return; @@ -816,7 +815,7 @@ void translate_instruction(const Personality &personality, case AVR::OpCode::breq: { if (o1.value == ".+2") { // assumes 6502 'borrow' for Carry flag instead of carry, so bcc instead of bcs - std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable"; + std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()); instructions.emplace_back(mos6502::OpCode::beq, Operand(Operand::Type::literal, new_label_name)); instructions.emplace_back(ASMLine::Type::Directive, new_label_name); return; @@ -857,7 +856,7 @@ void to_mos6502(const Personality &personality, const AVR &from_instruction, std if (const auto results = matcher(from_instruction.text); results) { const auto matched_gs = results.get<1>().to_string(); - instructions.emplace_back(ASMLine::Type::Directive, ".word " + std::string{strip_gs(matched_gs)}); + instructions.emplace_back(ASMLine::Type::Directive, ".word " + std::string{ strip_gs(matched_gs) }); } else { instructions.emplace_back(ASMLine::Type::Directive, ".word " + from_instruction.text.substr(6)); // spdlog::warn("Unknown .word directive '{}'", from_instruction.text); @@ -925,7 +924,7 @@ bool fix_long_branches(std::vector &instructions, int &branch_patch_cou for (size_t op = 0; op < instructions.size(); ++op) { if (instructions[op].is_branch - && std::abs(static_cast(labels[instructions[op].op.value]) - static_cast(op)) * 3 > 255) { + && std::abs(static_cast(labels[instructions[op].op.value]) - static_cast(op)) * 4 > 255) { ++branch_patch_count; const auto going_to = instructions[op].op.value; const auto new_pos = "patch_" + std::to_string(branch_patch_count); @@ -1051,7 +1050,7 @@ std::vector run(const Personality &personality, std::istream &input, co if (const auto results = matcher(i.text); results) { const auto matched_gs = results.get<1>().to_string(); spdlog::trace("matched .word: '{}' from '{}'", matched_gs, i.text); - check_label(std::string{strip_gs(matched_gs)}); + check_label(std::string{ strip_gs(matched_gs) }); } } } @@ -1086,6 +1085,7 @@ std::vector run(const Personality &personality, std::istream &input, co i.text = new_labels.at(i.text); } catch (...) { spdlog::warn("Unused label: '{}', consider making function static until we remove unused functions", i.text); + i.text = "; Label is unused: " + i.text; } } } @@ -1097,9 +1097,7 @@ std::vector run(const Personality &personality, std::istream &input, co const auto matched_gs = results.get<1>().to_string(); const auto possible_label = std::string{ strip_gs(matched_gs) }; const auto matched_label = new_labels.find(possible_label); - if (matched_label != new_labels.end()) { - i.text = ".word " + matched_label->second; - } + if (matched_label != new_labels.end()) { i.text = ".word " + matched_label->second; } } } @@ -1131,30 +1129,33 @@ std::vector run(const Personality &personality, std::istream &input, co new_instructions.emplace_back(mos6502::OpCode::jmp, Operand(Operand::Type::literal, "main")); - int instructions_to_skip = 0; + int instructions_to_skip = -1; std::string next_label_name; for (const auto &i : instructions) { to_mos6502(personality, i, new_instructions); // intentionally copy so we don't invalidate the reference const auto last_instruction = new_instructions.back(); - const auto last_instruction_loc = new_instructions.size() - 1; - if (instructions_to_skip == 1) { new_instructions.emplace_back(ASMLine::Type::Label, next_label_name); } + if (i.type == ASMLine::Type::Instruction) { --instructions_to_skip; } + if (instructions_to_skip == 0) { + new_instructions.emplace_back(ASMLine::Type::Label, next_label_name); + // todo: I kind of hate this -1 as a marker + instructions_to_skip = -1; + } - --instructions_to_skip; if (last_instruction.type == ASMLine::Type::Directive && last_instruction.text.starts_with("skip_next_instruction")) { instructions_to_skip = 1; next_label_name = last_instruction.text; - new_instructions.erase(std::next(new_instructions.begin(), static_cast(last_instruction_loc))); + new_instructions.pop_back(); } if (last_instruction.type == ASMLine::Type::Directive && last_instruction.text.starts_with("skip_next_2_instructions")) { instructions_to_skip = 2; next_label_name = last_instruction.text; - new_instructions.erase(std::next(new_instructions.begin(), static_cast(last_instruction_loc))); + new_instructions.pop_back(); } }