mirror of
https://github.com/lefticus/6502-cpp.git
synced 2024-12-21 10:30:35 +00:00
Merge branch 'master' of github.com:lefticus/x86-to-6502
This commit is contained in:
commit
da8dcfe213
@ -121,10 +121,10 @@ namespace {
|
||||
|
||||
struct VIC_II
|
||||
{
|
||||
static constexpr uint8_t SPRITE_ALIGNMENT = 64;
|
||||
static constexpr uint16_t SPRITE_DATA_POINTERS = 2040;
|
||||
static constexpr uint16_t VIDEO_REGISTERS = 53248;
|
||||
static constexpr uint16_t VIDEO_MEMORY = 1024;
|
||||
static constexpr uint8_t SPRITE_STARTING_BANK = 192;
|
||||
static constexpr uint16_t BORDER_COLOR = 53280;
|
||||
static constexpr uint16_t BACKGROUND_COLOR = 53281;
|
||||
static constexpr uint16_t SPRITE_POSITION_REGISTERS = VIDEO_REGISTERS;
|
||||
@ -191,52 +191,62 @@ namespace {
|
||||
|
||||
return Frame(*this, p1, p2);
|
||||
}
|
||||
|
||||
void write_multi_color_pixel(uint16_t)
|
||||
{
|
||||
// 0th case
|
||||
}
|
||||
|
||||
void write_pixel(uint16_t)
|
||||
{
|
||||
// 0th case
|
||||
}
|
||||
template<bool multicolor>
|
||||
struct SpriteLine {
|
||||
uint8_t pixels[3];
|
||||
|
||||
template<typename ... D >
|
||||
void write_multi_color_pixel(uint16_t loc, uint8_t d1, uint8_t d2,
|
||||
uint8_t d3, uint8_t d4, D ... d)
|
||||
{
|
||||
memory(loc) = (d1 << 6) | (d2 << 4) | (d3 << 2) | d4;
|
||||
write_multi_color_pixel(loc + 1, d...);
|
||||
}
|
||||
typedef uint_least64_t numeric_t;
|
||||
|
||||
template<typename ... D >
|
||||
void write_pixel(uint16_t loc, bool d1, bool d2, bool d3, bool d4,
|
||||
bool d5, bool d6, bool d7, bool d8, D ... d)
|
||||
{
|
||||
memory(loc) = (d1 << 7) | (d2 << 6) | (d3 << 5) | (d4 << 4) | (d5 << 3) | (d6 << 2) | (d7 << 1) | d8;
|
||||
write_pixel(loc + 1, d...);
|
||||
}
|
||||
|
||||
template<typename ... D>
|
||||
void make_sprite(uint8_t memory_loc, D ... d)
|
||||
{
|
||||
if constexpr(sizeof...(d) == 12 * 21) {
|
||||
write_multi_color_pixel((SPRITE_STARTING_BANK + memory_loc) * 64, d...);
|
||||
} else {
|
||||
write_pixel((SPRITE_STARTING_BANK + memory_loc) * 64, d...);
|
||||
/// Pixel format converter.
|
||||
static constexpr uint8_t c(const numeric_t m)
|
||||
{
|
||||
if constexpr (multicolor)
|
||||
// 0b00ii00jj00kk00ll -> 0biijjkkll
|
||||
return uint8_t(m >> 0 & 3 << 0) |
|
||||
uint8_t(m >> 2 & 3 << 2) |
|
||||
uint8_t(m >> 4 & 3 << 4) |
|
||||
uint8_t(m >> 6 & 3 << 6);
|
||||
return uint8_t(m);
|
||||
}
|
||||
}
|
||||
|
||||
/// Input bits per byte.
|
||||
constexpr static auto ibb = multicolor ? 16 : 8;
|
||||
|
||||
/// Constructor.
|
||||
constexpr SpriteLine(const numeric_t line)
|
||||
: pixels{c(line >> (2 * ibb)), c(line >> ibb), c(line)}
|
||||
{}
|
||||
};
|
||||
|
||||
template<bool multicolor>
|
||||
struct Sprite {
|
||||
typedef SpriteLine<multicolor> Line;
|
||||
alignas(SPRITE_ALIGNMENT) Line lines[SPRITE_ALIGNMENT / sizeof(Line)];
|
||||
};
|
||||
|
||||
typedef Sprite<false> HighResSprite;
|
||||
typedef Sprite<true> MultiColorSprite;
|
||||
|
||||
///
|
||||
/// New Code
|
||||
///
|
||||
void enable_sprite(const uint8_t sprite_number, const uint8_t memory_loc,
|
||||
const bool multicolor, const bool low_priority,
|
||||
template<bool multicolor>
|
||||
void enable_sprite(const uint8_t sprite_number,
|
||||
const Sprite<multicolor>& bitmap,
|
||||
const bool low_priority,
|
||||
const bool double_width, const bool double_height)
|
||||
{
|
||||
memory(SPRITE_DATA_POINTERS + sprite_number)
|
||||
= SPRITE_STARTING_BANK + memory_loc;
|
||||
#if 0 // error: static_assert expression is not an integral constant
|
||||
static_assert((std::ptrdiff_t(bitmap.memory) & 0x7000) != 0x1000,
|
||||
"The addresses 0x1000 to 0x1fff and 0x9000 to 0x9fff"
|
||||
"point to the character generator ROM, not RAM.");
|
||||
static_assert(std::ptrdiff_t(bitmap.memory) < 0x4000,
|
||||
"The data must be within the first (default)"
|
||||
" 16KiB VIC-II bank.");
|
||||
#endif
|
||||
memory(SPRITE_DATA_POINTERS + sprite_number)
|
||||
= (std::ptrdiff_t(bitmap.lines) & 0x3fff) / SPRITE_ALIGNMENT;
|
||||
set_bit(SPRITE_ENABLE_BITS, sprite_number, true);
|
||||
set_bit(SPRITE_EXPAND_HORIZONTAL, sprite_number, double_width);
|
||||
set_bit(SPRITE_EXPAND_VERTICAL, sprite_number, double_height);
|
||||
@ -280,9 +290,6 @@ namespace {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::array<Color, 16> colors = {{
|
||||
@ -306,58 +313,60 @@ int main()
|
||||
|
||||
VIC_II vic;
|
||||
|
||||
vic.make_sprite(0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
|
||||
0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
|
||||
0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
|
||||
0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
|
||||
0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
|
||||
0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
|
||||
0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
|
||||
0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,
|
||||
0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
|
||||
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
|
||||
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
|
||||
0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
);
|
||||
/// The ball image.
|
||||
static const VIC_II::HighResSprite sBall
|
||||
{{
|
||||
0b000000000000000000000000,
|
||||
0b000000000000000000000000,
|
||||
0b000000000111111000000000,
|
||||
0b000000011111111110000000,
|
||||
0b000000110111111111000000,
|
||||
0b000001100011111111100000,
|
||||
0b000001110111111111100000,
|
||||
0b000011111111111111110000,
|
||||
0b000011111111111111110000,
|
||||
0b000011111111111111110000,
|
||||
0b000000111111111111000000,
|
||||
0b000011000000000000110000,
|
||||
0b000011111111111111110000,
|
||||
0b000001111111111111100000,
|
||||
0b000001111111111111100000,
|
||||
0b000000111111111111000000,
|
||||
0b000000011111111110000000,
|
||||
0b000000000111111000000000,
|
||||
0b000000000000000000000000,
|
||||
0b000000000000000000000000,
|
||||
0b000000000000000000000000
|
||||
}};
|
||||
|
||||
vic.make_sprite(1,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,2,2,0,0,0,0,0,
|
||||
0,0,0,0,0,3,3,0,0,0,0,0,
|
||||
0,0,0,0,0,1,1,0,0,0,0,0,
|
||||
0,0,0,0,0,3,3,0,0,0,0,0,
|
||||
0,0,0,0,0,1,1,0,0,0,0,0,
|
||||
0,0,0,0,0,3,3,0,0,0,0,0
|
||||
);
|
||||
|
||||
vic.enable_sprite(0, 0, false, true, false, false);
|
||||
vic.enable_sprite(1, 1, true, false, false, true);
|
||||
vic.enable_sprite(2, 1, true, false, false, true);
|
||||
/// The bat image.
|
||||
static const VIC_II::MultiColorSprite sBat = {{
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000002200000,
|
||||
0x000003300000,
|
||||
0x000001100000,
|
||||
0x000003300000,
|
||||
0x000001100000,
|
||||
0x000003300000
|
||||
}};
|
||||
|
||||
vic.enable_sprite(0, sBall, true, false, false);
|
||||
vic.enable_sprite(1, sBat, false, false, true);
|
||||
vic.enable_sprite(2, sBat, false, false, true);
|
||||
vic.border() = vic.nearest_color<128,128,128>(colors).num; // 50% grey
|
||||
vic.background() = vic.nearest_color<0,0,0>(colors).num; // black
|
||||
vic.sprite_1_color() = vic.nearest_color<255,0,0>(colors).num; // red
|
||||
|
39
src/main.cpp
39
src/main.cpp
@ -112,6 +112,7 @@ struct mos6502 : ASMLine
|
||||
php,
|
||||
plp,
|
||||
lsr,
|
||||
ror,
|
||||
AND,
|
||||
inc,
|
||||
dec,
|
||||
@ -148,6 +149,7 @@ struct mos6502 : ASMLine
|
||||
case OpCode::php:
|
||||
case OpCode::plp:
|
||||
case OpCode::lsr:
|
||||
case OpCode::ror:
|
||||
case OpCode::AND:
|
||||
case OpCode::inc:
|
||||
case OpCode::dec:
|
||||
@ -184,6 +186,7 @@ struct mos6502 : ASMLine
|
||||
case OpCode::php:
|
||||
case OpCode::plp:
|
||||
case OpCode::lsr:
|
||||
case OpCode::ror:
|
||||
case OpCode::AND:
|
||||
case OpCode::inc:
|
||||
case OpCode::dec:
|
||||
@ -248,6 +251,8 @@ struct mos6502 : ASMLine
|
||||
return "plp";
|
||||
case OpCode::lsr:
|
||||
return "lsr";
|
||||
case OpCode::ror:
|
||||
return "ror";
|
||||
case OpCode::AND:
|
||||
return "and";
|
||||
case OpCode::inc:
|
||||
@ -318,6 +323,7 @@ struct i386 : ASMLine
|
||||
movzbl,
|
||||
movzwl,
|
||||
shrb,
|
||||
shrl,
|
||||
xorl,
|
||||
andl,
|
||||
andb,
|
||||
@ -363,6 +369,7 @@ struct i386 : ASMLine
|
||||
if (o == "movzwl") return OpCode::movzwl;
|
||||
if (o == "movzbl") return OpCode::movzbl;
|
||||
if (o == "shrb") return OpCode::shrb;
|
||||
if (o == "shrl") return OpCode::shrl;
|
||||
if (o == "xorl") return OpCode::xorl;
|
||||
if (o == "andl") return OpCode::andl;
|
||||
if (o == "ret") return OpCode::ret;
|
||||
@ -475,6 +482,11 @@ void translate_instruction(std::vector<mos6502> &instructions, const i386::OpCod
|
||||
instructions.emplace_back(mos6502::OpCode::sta, get_register(o2.reg_num));
|
||||
instructions.emplace_back(mos6502::OpCode::lda, get_register(o1.reg_num, 1));
|
||||
instructions.emplace_back(mos6502::OpCode::sta, get_register(o2.reg_num, 1));
|
||||
} else if (o1.type == Operand::Type::literal && o2.type == Operand::Type::reg) {
|
||||
instructions.emplace_back(mos6502::OpCode::lda, Operand(o1.type, "#<" + o1.value));
|
||||
instructions.emplace_back(mos6502::OpCode::sta, get_register(o2.reg_num));
|
||||
instructions.emplace_back(mos6502::OpCode::lda, Operand(o1.type, "#>" + o1.value));
|
||||
instructions.emplace_back(mos6502::OpCode::sta, get_register(o2.reg_num, 1));
|
||||
} else {
|
||||
throw std::runtime_error("Cannot translate movl instruction");
|
||||
}
|
||||
@ -486,7 +498,7 @@ void translate_instruction(std::vector<mos6502> &instructions, const i386::OpCod
|
||||
instructions.emplace_back(mos6502::OpCode::sta, get_register(o2.reg_num));
|
||||
instructions.emplace_back(mos6502::OpCode::sta, get_register(o2.reg_num, 1));
|
||||
} else {
|
||||
throw std::runtime_error("Cannot translate movl instruction");
|
||||
throw std::runtime_error("Cannot translate xorl instruction");
|
||||
}
|
||||
break;
|
||||
case i386::OpCode::movb:
|
||||
@ -550,6 +562,25 @@ void translate_instruction(std::vector<mos6502> &instructions, const i386::OpCod
|
||||
throw std::runtime_error("Cannot translate shrb instruction");
|
||||
}
|
||||
break;
|
||||
case i386::OpCode::shrl:
|
||||
if (o1.type == Operand::Type::reg || o2.type == Operand::Type::reg) {
|
||||
const auto do_shift = [&instructions](const int reg_num) {
|
||||
instructions.emplace_back(mos6502::OpCode::lsr, get_register(reg_num, 1));
|
||||
instructions.emplace_back(mos6502::OpCode::ror, get_register(reg_num));
|
||||
};
|
||||
|
||||
if (o1.type == Operand::Type::literal) {
|
||||
const auto count = parse_8bit_literal(o1.value);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
do_shift(o2.reg_num);
|
||||
}
|
||||
} else {
|
||||
do_shift(o1.reg_num);
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Cannot translate shrl instruction");
|
||||
}
|
||||
break;
|
||||
case i386::OpCode::testb:
|
||||
if (o1.type == Operand::Type::reg && o2.type == Operand::Type::reg && o1.reg_num == o2.reg_num) {
|
||||
// this just tests the register for 0
|
||||
@ -625,7 +656,7 @@ void translate_instruction(std::vector<mos6502> &instructions, const i386::OpCod
|
||||
instructions.emplace_back(mos6502::OpCode::lda, get_register(o2.reg_num));
|
||||
instructions.emplace_back(mos6502::OpCode::cmp, Operand(o1.type, fixup_8bit_literal(o1.value)));
|
||||
} else {
|
||||
throw std::runtime_error("Cannot translate cmb instruction");
|
||||
throw std::runtime_error("Cannot translate cmpb instruction");
|
||||
}
|
||||
break;
|
||||
case i386::OpCode::andb:
|
||||
@ -684,7 +715,7 @@ void translate_instruction(std::vector<mos6502> &instructions, const i386::OpCod
|
||||
instructions.emplace_back(mos6502::OpCode::lda, get_register(o1.reg_num, 1));
|
||||
instructions.emplace_back(mos6502::OpCode::pha);
|
||||
} else {
|
||||
throw std::runtime_error("Cannot translate sbb instruction");
|
||||
throw std::runtime_error("Cannot translate pushl instruction");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -701,7 +732,7 @@ void translate_instruction(std::vector<mos6502> &instructions, const i386::OpCod
|
||||
instructions.emplace_back(mos6502::OpCode::eor, Operand(Operand::Type::literal, "#$ff")); // invert the bits
|
||||
instructions.emplace_back(mos6502::OpCode::sta, get_register(o2.reg_num)); // place the value
|
||||
} else {
|
||||
throw std::runtime_error("Cannot translate sbb instruction");
|
||||
throw std::runtime_error("Cannot translate sbbb instruction");
|
||||
}
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user