mirror of
https://github.com/lefticus/6502-cpp.git
synced 2025-05-16 15:38:15 +00:00
Better label handling
This commit is contained in:
parent
949e118ef7
commit
8b159faa59
@ -44,7 +44,8 @@ static void puts(uint8_t x, uint8_t y, std::string_view str)
|
||||
{
|
||||
const auto start = 0x400 + (y * 40 + x);
|
||||
|
||||
std::memcpy(const_cast<uint8_t *>(&memory_loc(start)), str.data(), str.size());
|
||||
std::copy(str.begin(), str.end(), &memory_loc(start));
|
||||
// std::memcpy(const_cast<uint8_t *>(&memory_loc(start)), str.data(), str.size());
|
||||
}
|
||||
|
||||
|
||||
@ -283,6 +284,13 @@ struct Screen
|
||||
}
|
||||
}
|
||||
|
||||
void hide(auto &s) {
|
||||
if (s.is_shown) {
|
||||
put_graphic(s.x, s.y, s.saved_background);
|
||||
s.is_shown = false;
|
||||
}
|
||||
}
|
||||
|
||||
void show(std::uint8_t x, std::uint8_t y, auto &s)
|
||||
{
|
||||
if (s.is_shown) { put_graphic(s.x, s.y, s.saved_background); }
|
||||
@ -309,10 +317,17 @@ struct GameState
|
||||
std::uint8_t x = 20;
|
||||
std::uint8_t y = 12;
|
||||
|
||||
bool redraw = true;
|
||||
|
||||
Clock game_clock{};
|
||||
|
||||
Map<10, 5> const *current_map = nullptr;
|
||||
|
||||
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
|
||||
{
|
||||
if (current_map) {
|
||||
@ -374,14 +389,14 @@ struct Map_Action
|
||||
}
|
||||
|
||||
const std::uint8_t rect1_x1 = x;
|
||||
const std::uint8_t rect1_x2 = x + width - 1;
|
||||
const std::uint8_t rect1_x2 = x + width;
|
||||
const std::uint8_t rect1_y1 = y;
|
||||
const std::uint8_t rect1_y2 = y + height - 1;
|
||||
const std::uint8_t rect1_y2 = y + height;
|
||||
|
||||
const std::uint8_t rect2_x1 = obj_x;
|
||||
const std::uint8_t rect2_x2 = obj_x + obj_width - 1;
|
||||
const std::uint8_t rect2_x2 = obj_x + obj_width;
|
||||
const std::uint8_t rect2_y1 = obj_y;
|
||||
const std::uint8_t rect2_y2 = obj_y + obj_height - 1;
|
||||
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) {
|
||||
@ -393,6 +408,7 @@ struct Map_Action
|
||||
|
||||
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;
|
||||
@ -402,6 +418,31 @@ int main()
|
||||
{
|
||||
// static constexpr auto charset = load_charset(uppercase);
|
||||
|
||||
static constexpr auto inn = Graphic<6,5> {
|
||||
32,233,160,160,223,32,
|
||||
233,160,160,160,160,223,
|
||||
160,137,142,142,160,160,
|
||||
160,160,160,160,79,160,
|
||||
160,160,160,160,76,160,
|
||||
};
|
||||
|
||||
static constexpr auto gym = Graphic<6,5> {
|
||||
32,233,160,160,223,32,
|
||||
233,160,160,160,160,223,
|
||||
160,135,153,141,160,160,
|
||||
160,160,160,160,79,160,
|
||||
160,160,160,160,76,160,
|
||||
};
|
||||
|
||||
static constexpr auto trading_post = Graphic<6,5> {
|
||||
32,233,160,160,223,32,
|
||||
233,160,160,160,160,223,
|
||||
148,146,129,132,133,160,
|
||||
160,160,160,160,79,160,
|
||||
160,160,160,160,76,160,
|
||||
};
|
||||
|
||||
|
||||
static constexpr auto town = Graphic<4, 4>{
|
||||
85, 67, 67, 73,
|
||||
93, 233, 223, 93,
|
||||
@ -420,11 +461,25 @@ int main()
|
||||
78, 79,
|
||||
78, 77 };
|
||||
|
||||
static constexpr auto city_map = Map<10, 5>{
|
||||
"wood town",
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 4, 0, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 5, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
},
|
||||
std::span<const Map_Action>{}
|
||||
};
|
||||
|
||||
|
||||
static constexpr auto overview_actions = std::array {
|
||||
Map_Action { 12,0,4,4, [](GameState &g) { g.x = 30; g.y=5; } }
|
||||
Map_Action { 16,0,4,4, [](GameState &g) { g.set_current_map(city_map); } }
|
||||
};
|
||||
|
||||
static constexpr auto overview_map = Map<10, 5>{
|
||||
"the world",
|
||||
{
|
||||
3, 1, 1, 0, 3, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 1, 0, 0, 0, 0, 3, 0,
|
||||
@ -435,12 +490,9 @@ int main()
|
||||
std::span<const Map_Action>(begin(overview_actions), end(overview_actions))
|
||||
};
|
||||
|
||||
cls();
|
||||
|
||||
poke(53280, 0);
|
||||
poke(53281, 0);
|
||||
|
||||
static constexpr std::array<void (*)(std::uint8_t, std::uint8_t), 4> tile_types{
|
||||
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 */
|
||||
},
|
||||
@ -449,6 +501,9 @@ int main()
|
||||
/* do nothing for 2 */
|
||||
},
|
||||
[](std::uint8_t x, std::uint8_t y) { put_graphic(x, y, town); },
|
||||
[](std::uint8_t x, std::uint8_t y) { put_graphic(x, y, inn); },
|
||||
[](std::uint8_t x, std::uint8_t y) { put_graphic(x, y, gym); },
|
||||
[](std::uint8_t x, std::uint8_t y) { put_graphic(x, y, trading_post); },
|
||||
};
|
||||
|
||||
|
||||
@ -483,10 +538,6 @@ int main()
|
||||
GameState game;
|
||||
game.current_map = &overview_map;
|
||||
|
||||
// draw_map(map1);
|
||||
draw_map(game.current_map->layout);
|
||||
draw_box(0, 20, 40, 5);
|
||||
|
||||
constexpr auto show_stats = [](const auto &cur_game) {
|
||||
puts(1, 21, "stamina:");
|
||||
put_hex(12, 21, cur_game.stamina);
|
||||
@ -500,8 +551,6 @@ int main()
|
||||
|
||||
Screen screen;
|
||||
|
||||
show_stats(game);
|
||||
|
||||
auto eventHandler = overloaded{ [&](const GameState::JoyStick2StateChanged &e) {
|
||||
if (e.state.up()) { --game.y; }
|
||||
if (e.state.down()) { ++game.y; }
|
||||
@ -519,6 +568,23 @@ int main()
|
||||
while (true) {
|
||||
std::visit(eventHandler, game.next_event());
|
||||
|
||||
if (game.redraw) {
|
||||
screen.hide(character);
|
||||
cls();
|
||||
|
||||
poke(53280, 0);
|
||||
poke(53281, 0);
|
||||
|
||||
game.redraw = false;
|
||||
draw_map(game.current_map->layout);
|
||||
draw_box(0, 20, 40, 5);
|
||||
|
||||
puts(10, 20, game.current_map->name);
|
||||
show_stats(game);
|
||||
screen.show(game.x, game.y, character);
|
||||
}
|
||||
|
||||
|
||||
increment_border_color();
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
static constexpr std::string_view __mulhi3 =
|
||||
R"(
|
||||
;;; based on protocol from gcc's calling conventions for AVR
|
||||
|
||||
;;; 16x16 = 16 multiply
|
||||
;;; R25:R24 = R23:R22 * R25:R24
|
||||
;;; Clobbers: __tmp_reg__, R21..R23
|
||||
|
||||
@ -33,3 +33,22 @@ __mulhi3:
|
||||
)";
|
||||
|
||||
|
||||
static constexpr std::string_view __mulqi3 =
|
||||
R"(
|
||||
;;; based on protocol from gcc's calling conventions for AVR
|
||||
;;; 8x8 = 8 multiply
|
||||
;;; R24 = R22 * R24
|
||||
;;; Clobbers: __tmp_reg__, R22, R24
|
||||
|
||||
__mulqi3:
|
||||
ldi __temp_reg__,0
|
||||
__mulqi_1:
|
||||
sbrc r24,0
|
||||
add __temp_reg__,r22
|
||||
lsr r24
|
||||
lsl r22
|
||||
cpse r24,__zero_reg__
|
||||
rjmp __mulqi_1
|
||||
mov r24, __temp_reg__
|
||||
ret
|
||||
)";
|
@ -285,13 +285,15 @@ bool optimize(std::vector<mos6502> &instructions, [[maybe_unused]] const Persona
|
||||
}
|
||||
}
|
||||
|
||||
bool block_optimized = false;
|
||||
bool optimizer_run = false;
|
||||
for (auto &block : get_optimizable_blocks(instructions)) {
|
||||
block_optimized = block_optimized || optimize_redundant_lda_after_sta(block)
|
||||
const bool block_optimized = optimize_redundant_lda_after_sta(block)
|
||||
|| optimize_dead_sta(block, personality) || optimize_dead_tax(block)
|
||||
|| optimize_redundant_ldy(block) || optimize_redundant_lda(block, personality);
|
||||
|
||||
optimizer_run = optimizer_run || block_optimized;
|
||||
}
|
||||
return block_optimized;
|
||||
return optimizer_run;
|
||||
}
|
||||
|
||||
#endif// INC_6502_CPP_OPTIMIZER_HPP
|
||||
|
@ -72,8 +72,8 @@ std::string fixup_8bit_literal(const std::string &s)
|
||||
|
||||
if (s.starts_with("0x")) { return "#$" + s.substr(2); }
|
||||
|
||||
if (s.starts_with("lo8(")) { return fmt::format("#<{}", strip_gs(strip_lo_hi(s))); }
|
||||
if (s.starts_with("hi8(")) { return fmt::format("#>{}", strip_gs(strip_lo_hi(s))); }
|
||||
if (s.starts_with("lo8(")) { return fmt::format("#<({})", strip_gs(strip_lo_hi(s))); }
|
||||
if (s.starts_with("hi8(")) { return fmt::format("#>({})", strip_gs(strip_lo_hi(s))); }
|
||||
|
||||
const auto is_num = std::all_of(begin(s), end(s), [](const auto c) { return (c >= '0' && c <= '9') || c == '-'; });
|
||||
|
||||
@ -292,12 +292,14 @@ void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions)
|
||||
instructions.emplace_back(ASMLine::Type::Directive, "; END remove if next is lda, bcc, bcs, ldy");
|
||||
}
|
||||
|
||||
void add_16_bit(const Personality &personality, std::vector<mos6502> &instructions, int reg, const std::string_view value)
|
||||
void add_16_bit(const Personality &personality,
|
||||
std::vector<mos6502> &instructions,
|
||||
int reg,
|
||||
const std::string_view value)
|
||||
{
|
||||
instructions.emplace_back(mos6502::OpCode::clc);
|
||||
instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg));
|
||||
instructions.emplace_back(
|
||||
mos6502::OpCode::adc, Operand(Operand::Type::literal, fmt::format("#({})", value)));
|
||||
instructions.emplace_back(mos6502::OpCode::adc, Operand(Operand::Type::literal, fmt::format("#({})", value)));
|
||||
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg));
|
||||
instructions.emplace_back(mos6502::OpCode::tax);
|
||||
instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg + 1));
|
||||
@ -330,13 +332,11 @@ void subtract_16_bit(const Personality &personality,
|
||||
{
|
||||
instructions.emplace_back(mos6502::OpCode::sec);
|
||||
instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg));
|
||||
instructions.emplace_back(
|
||||
mos6502::OpCode::sbc, Operand(Operand::Type::literal, fmt::format("#({})", value)));
|
||||
instructions.emplace_back(mos6502::OpCode::sbc, Operand(Operand::Type::literal, fmt::format("#({})", value)));
|
||||
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg));
|
||||
instructions.emplace_back(mos6502::OpCode::tax);
|
||||
instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg + 1));
|
||||
instructions.emplace_back(
|
||||
mos6502::OpCode::sbc, Operand(Operand::Type::literal, "#0"));
|
||||
instructions.emplace_back(mos6502::OpCode::sbc, Operand(Operand::Type::literal, "#0"));
|
||||
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg + 1));
|
||||
|
||||
fixup_16_bit_N_Z_flags(instructions);
|
||||
@ -809,14 +809,14 @@ void to_mos6502(const Personality &personality, const AVR &from_instruction, std
|
||||
instructions.emplace_back(ASMLine::Type::Directive, ".asc " + from_instruction.text.substr(7));
|
||||
} else if (from_instruction.text.starts_with(".word")) {
|
||||
|
||||
const auto matcher = ctre::match<R"(\s*.word\s*gs\((.*)\))">;
|
||||
const auto matcher = ctre::match<R"(\s*.word\s*(.*))">;
|
||||
|
||||
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 " + 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);
|
||||
// spdlog::warn("Unknown .word directive '{}'", from_instruction.text);
|
||||
}
|
||||
|
||||
} else if (from_instruction.text.starts_with(".byte")) {
|
||||
@ -973,8 +973,12 @@ std::vector<mos6502> run(const Personality &personality, std::istream &input, co
|
||||
const bool needs_mulhi3 = std::any_of(begin(instructions), end(instructions), [](const AVR &instruction) {
|
||||
return instruction.line_text.find("__mulhi3") != std::string::npos;
|
||||
});
|
||||
const bool needs_mulqi3 = std::any_of(begin(instructions), end(instructions), [](const AVR &instruction) {
|
||||
return instruction.line_text.find("__mulqi3") != std::string::npos;
|
||||
});
|
||||
|
||||
if (needs_mulhi3) { parse_string(__mulhi3); }
|
||||
if (needs_mulqi3) { parse_string(__mulqi3); }
|
||||
|
||||
std::set<std::string> labels;
|
||||
|
||||
@ -995,13 +999,15 @@ std::vector<mos6502> run(const Personality &personality, std::istream &input, co
|
||||
check_label(i.operand2.value);
|
||||
check_label(std::string{ strip_gs(strip_offset(strip_negate(strip_lo_hi(i.operand1.value)))) });
|
||||
check_label(std::string{ strip_gs(strip_offset(strip_negate(strip_lo_hi(i.operand2.value)))) });
|
||||
|
||||
|
||||
} else if (i.type == ASMLine::Type::Directive) {
|
||||
const auto matcher = ctre::match<R"(\s*.word\s*gs\((.*)\))">;
|
||||
const auto matcher = ctre::match<R"(\s*.word\s*(.*))">;
|
||||
|
||||
if (const auto results = matcher(i.text); results) {
|
||||
const auto matched_gs = results.get<1>().to_string();
|
||||
spdlog::trace("matched gs: '{}' from '{}'", matched_gs, i.text);
|
||||
check_label(matched_gs);
|
||||
spdlog::trace("matched .word: '{}' from '{}'", matched_gs, i.text);
|
||||
check_label(std::string{strip_gs(matched_gs)});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1009,10 +1015,6 @@ std::vector<mos6502> run(const Personality &personality, std::istream &input, co
|
||||
const auto new_labels = [&used_labels]() {
|
||||
std::map<std::string, std::string> result;
|
||||
for (const auto &l : used_labels) {
|
||||
// auto newl = l;
|
||||
// std::transform(newl.begin(), newl.end(), newl.begin(), [](const auto c) { return std::tolower(c); });
|
||||
// newl.erase(std::remove_if(newl.begin(), newl.end(), [](const auto c) { return !std::isalnum(c); }),
|
||||
// std::end(newl));
|
||||
|
||||
const auto new_label = [](auto label) -> std::string {
|
||||
if (label[0] == '.') { label.erase(0, 1); }
|
||||
@ -1044,10 +1046,28 @@ std::vector<mos6502> run(const Personality &personality, std::istream &input, co
|
||||
}
|
||||
}
|
||||
|
||||
if (i.type == ASMLine::Type::Directive) {
|
||||
const auto matcher = ctre::match<R"(\s*.word\s*(.*))">;
|
||||
|
||||
if (const auto results = matcher(i.text); results) {
|
||||
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 (i.operand2.value.starts_with("lo8(") || i.operand2.value.starts_with("hi8(")) {
|
||||
const auto potential_label = strip_lo_hi(i.operand2.value);
|
||||
const auto itr1 = new_labels.find(std::string{ potential_label });
|
||||
if (itr1 != new_labels.end()) { i.operand2.value.replace(4, potential_label.size(), itr1->second); }
|
||||
const auto lo_hi_operand = strip_lo_hi(i.operand2.value);
|
||||
const auto label_matcher = ctre::match<R"(([A-Za-z0-9.]+).*)">;
|
||||
|
||||
if (const auto results = label_matcher(lo_hi_operand); results) {
|
||||
std::string_view potential_label = results.get<1>();
|
||||
const auto itr1 = new_labels.find(std::string{ potential_label });
|
||||
if (itr1 != new_labels.end()) { i.operand2.value.replace(4, potential_label.size(), itr1->second); }
|
||||
}
|
||||
}
|
||||
|
||||
const auto itr1 = new_labels.find(i.operand1.value);
|
||||
@ -1158,23 +1178,23 @@ int main(const int argc, const char **argv)
|
||||
const auto program_output_file = make_output_file_name(filename, "prg");
|
||||
|
||||
std::string disabled_optimizations;
|
||||
/*
|
||||
disabled_optimizations += " -fno-gcse-after-reload";
|
||||
disabled_optimizations += " -fno-ipa-cp-clone";
|
||||
disabled_optimizations += " -fno-loop-interchange";
|
||||
disabled_optimizations += " -fno-loop-unroll-and-jam";
|
||||
disabled_optimizations += " -fno-peel-loops";
|
||||
disabled_optimizations += " -fno-predictive-commoning";
|
||||
disabled_optimizations += " -fno-split-loops";
|
||||
disabled_optimizations += " -fno-split-paths";
|
||||
disabled_optimizations += " -fno-tree-loop-distribution";
|
||||
disabled_optimizations += " -fno-tree-loop-vectorize";
|
||||
disabled_optimizations += " -fno-tree-partial-pre";
|
||||
disabled_optimizations += " -fno-tree-slp-vectorize";
|
||||
disabled_optimizations += " -fno-unswitch-loops";
|
||||
disabled_optimizations += " -fvect-cost-model=cheap";
|
||||
disabled_optimizations += " -fno-version-loops-for-strides";
|
||||
*/
|
||||
/*
|
||||
disabled_optimizations += " -fno-gcse-after-reload";
|
||||
disabled_optimizations += " -fno-ipa-cp-clone";
|
||||
disabled_optimizations += " -fno-loop-interchange";
|
||||
disabled_optimizations += " -fno-loop-unroll-and-jam";
|
||||
disabled_optimizations += " -fno-peel-loops";
|
||||
disabled_optimizations += " -fno-predictive-commoning";
|
||||
disabled_optimizations += " -fno-split-loops";
|
||||
disabled_optimizations += " -fno-split-paths";
|
||||
disabled_optimizations += " -fno-tree-loop-distribution";
|
||||
disabled_optimizations += " -fno-tree-loop-vectorize";
|
||||
disabled_optimizations += " -fno-tree-partial-pre";
|
||||
disabled_optimizations += " -fno-tree-slp-vectorize";
|
||||
disabled_optimizations += " -fno-unswitch-loops";
|
||||
disabled_optimizations += " -fvect-cost-model=cheap";
|
||||
disabled_optimizations += " -fno-version-loops-for-strides";
|
||||
*/
|
||||
|
||||
const std::string gcc_command = fmt::format(
|
||||
"avr-gcc -fverbose-asm -c -o {outfile} -S {warning_flags} -std=c++20 -mtiny-stack "
|
||||
|
Loading…
x
Reference in New Issue
Block a user