1
0
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:
Jason Turner 2016-10-26 15:35:08 -06:00
commit da8dcfe213
2 changed files with 134 additions and 94 deletions

View File

@ -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

View File

@ -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;