mirror of https://github.com/bsnes-emu/bsnes.git
parent
5757949023
commit
96c381f91f
|
@ -1,91 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
struct BitsCaptureLo{};
|
|
||||||
struct BitsCaptureHi{};
|
|
||||||
|
|
||||||
struct BitsLo {
|
|
||||||
const uint lo;
|
|
||||||
inline BitsLo(uint lo) : lo(lo) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BitsHi {
|
|
||||||
const uint hi;
|
|
||||||
inline BitsHi(uint hi) : hi(hi) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BitsRange {
|
|
||||||
const uint lo, hi;
|
|
||||||
inline BitsRange(uint lo, uint hi) : lo(lo), hi(hi) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline auto operator*(BitsCaptureLo, uint lhs) { return BitsLo{lhs}; }
|
|
||||||
inline auto operator*(uint rhs, BitsCaptureHi) { return BitsHi{rhs}; }
|
|
||||||
inline auto operator-(const BitsLo& lhs, const BitsHi& rhs) { return BitsRange{lhs.lo, rhs.hi}; }
|
|
||||||
|
|
||||||
template<typename T> struct Bits {
|
|
||||||
T& value;
|
|
||||||
using type =
|
|
||||||
conditional_t<sizeof(T) <= 1, uint8_t,
|
|
||||||
conditional_t<sizeof(T) <= 2, uint16_t,
|
|
||||||
conditional_t<sizeof(T) <= 4, uint32_t,
|
|
||||||
conditional_t<sizeof(T) <= 8, uint64_t,
|
|
||||||
void>>>>;
|
|
||||||
const uint lo;
|
|
||||||
const type mask;
|
|
||||||
|
|
||||||
inline Bits(T& value, BitsRange range) : value(value), lo(range.lo), mask(~0ull >> 64 - (range.hi - range.lo + 1) << range.lo) {}
|
|
||||||
inline Bits(const Bits& source) { operator=((uint64_t)source); }
|
|
||||||
inline auto operator=(const Bits& source) -> Bits& { return operator=((uint64_t)source); }
|
|
||||||
|
|
||||||
inline operator type() const {
|
|
||||||
return (value & mask) >> lo;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U> inline auto operator=(U source) -> Bits& {
|
|
||||||
value = value & ~mask | source << lo & mask;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U> inline auto operator&=(U source) -> Bits& {
|
|
||||||
value = value & (~mask | source << lo & mask);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U> inline auto operator^=(U source) -> Bits& {
|
|
||||||
value = value ^ source << lo & mask;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U> inline auto operator|=(U source) -> Bits& {
|
|
||||||
value = value | source << lo & mask;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T> struct Bits<const T> {
|
|
||||||
T value;
|
|
||||||
using type =
|
|
||||||
conditional_t<sizeof(T) <= 1, uint8_t,
|
|
||||||
conditional_t<sizeof(T) <= 2, uint16_t,
|
|
||||||
conditional_t<sizeof(T) <= 4, uint32_t,
|
|
||||||
conditional_t<sizeof(T) <= 8, uint64_t,
|
|
||||||
void>>>>;
|
|
||||||
const uint lo;
|
|
||||||
const type mask;
|
|
||||||
|
|
||||||
inline Bits(const T& value, BitsRange range) : value(value), lo(range.lo), mask(~0ull >> 64 - (range.hi - range.lo + 1) << range.lo) {}
|
|
||||||
Bits(const Bits& source) = delete;
|
|
||||||
auto operator=(const Bits& source) -> Bits& = delete;
|
|
||||||
|
|
||||||
inline operator type() const {
|
|
||||||
return (value & mask) >> lo;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define bits(value,range) Bits<decltype(value)>{value,BitsCaptureLo{}*range*BitsCaptureHi{}}
|
|
||||||
#define bit1(value,index) Bits<decltype(value)>{value,BitsRange{(uint)index,(uint)index}}
|
|
||||||
#define bit8(value,index) Bits<decltype(value)>{value,BitsRange{(uint)index*8,(uint)index*8+7}}
|
|
||||||
|
|
||||||
#define cbits(value,range) Bits<const decltype(value)>{value,BitsCaptureLo{}*range*BitsCaptureHi{}}
|
|
||||||
#define cbit1(value,index) Bits<const decltype(value)>{value,BitsRange{(uint)index,(uint)index}}
|
|
||||||
#define cbit8(value,index) Bits<const decltype(value)>{value,BitsRange{(uint)index*8,(uint)index*8+7}}
|
|
|
@ -23,7 +23,6 @@ using namespace nall;
|
||||||
|
|
||||||
#include <libco/libco.h>
|
#include <libco/libco.h>
|
||||||
|
|
||||||
#include <emulator/bits.hpp>
|
|
||||||
#include <emulator/types.hpp>
|
#include <emulator/types.hpp>
|
||||||
#include <emulator/memory/readable.hpp>
|
#include <emulator/memory/readable.hpp>
|
||||||
#include <emulator/memory/writable.hpp>
|
#include <emulator/memory/writable.hpp>
|
||||||
|
@ -31,7 +30,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "bsnes";
|
static const string Name = "bsnes";
|
||||||
static const string Version = "108.6";
|
static const string Version = "108.7";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "https://byuu.org";
|
static const string Website = "https://byuu.org";
|
||||||
|
|
|
@ -65,10 +65,10 @@ struct Random {
|
||||||
if((random() & 1) == 0) hivalue = ~lovalue;
|
if((random() & 1) == 0) hivalue = ~lovalue;
|
||||||
|
|
||||||
for(uint32 address : range(size)) {
|
for(uint32 address : range(size)) {
|
||||||
uint8 value = bit1(address,lobit) ? lovalue : hivalue;
|
uint8 value = (address & 1ull << lobit) ? lovalue : hivalue;
|
||||||
if(bit1(address,hibit)) value = ~value;
|
if((address & 1ull << hibit)) value = ~value;
|
||||||
if((random() & 511) == 0) bit1(value,random() & 7) ^= 1;
|
if((random() & 511) == 0) value ^= 1 << (random() & 7);
|
||||||
if((random() & 2047) == 0) bit1(value,random() & 7) ^= 1;
|
if((random() & 2047) == 0) value ^= 1 << (random() & 7);
|
||||||
data[address] = value;
|
data[address] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
auto ARM7TDMI::ADD(uint32 source, uint32 modify, bool carry) -> uint32 {
|
auto ARM7TDMI::ADD(uint32 source, uint32 modify, bool carry) -> uint32 {
|
||||||
uint32 result = source + modify + carry;
|
uint32 result = source + modify + carry;
|
||||||
if(cpsr().t || bit1(opcode,20)) {
|
if(cpsr().t || (opcode & 1 << 20)) {
|
||||||
uint32 overflow = ~(source ^ modify) & (source ^ result);
|
uint32 overflow = ~(source ^ modify) & (source ^ result);
|
||||||
cpsr().v = 1 << 31 & (overflow);
|
cpsr().v = 1 << 31 & (overflow);
|
||||||
cpsr().c = 1 << 31 & (overflow ^ source ^ modify ^ result);
|
cpsr().c = 1 << 31 & (overflow ^ source ^ modify ^ result);
|
||||||
cpsr().z = result == 0;
|
cpsr().z = result == 0;
|
||||||
cpsr().n = bit1(result,31);
|
cpsr().n = result >> 31;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,10 @@ auto ARM7TDMI::ASR(uint32 source, uint8 shift) -> uint32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ARM7TDMI::BIT(uint32 result) -> uint32 {
|
auto ARM7TDMI::BIT(uint32 result) -> uint32 {
|
||||||
if(cpsr().t || bit1(opcode,20)) {
|
if(cpsr().t || (opcode & 1 << 20)) {
|
||||||
cpsr().c = carry;
|
cpsr().c = carry;
|
||||||
cpsr().z = result == 0;
|
cpsr().z = result == 0;
|
||||||
cpsr().n = bit1(result,31);
|
cpsr().n = result >> 31;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,9 @@ auto ARM7TDMI::MUL(uint32 product, uint32 multiplicand, uint32 multiplier) -> ui
|
||||||
if(multiplier >> 16 && multiplier >> 16 != 0xffff) idle();
|
if(multiplier >> 16 && multiplier >> 16 != 0xffff) idle();
|
||||||
if(multiplier >> 24 && multiplier >> 24 != 0xff) idle();
|
if(multiplier >> 24 && multiplier >> 24 != 0xff) idle();
|
||||||
product += multiplicand * multiplier;
|
product += multiplicand * multiplier;
|
||||||
if(cpsr().t || bit1(opcode,20)) {
|
if(cpsr().t || (opcode & 1 << 20)) {
|
||||||
cpsr().z = product == 0;
|
cpsr().z = product == 0;
|
||||||
cpsr().n = bit1(product,31);
|
cpsr().n = product >> 31;
|
||||||
}
|
}
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,14 +148,14 @@ struct ARM7TDMI {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto operator=(uint32 data) -> PSR& {
|
inline auto operator=(uint32 data) -> PSR& {
|
||||||
m = bits(data,0-4);
|
m = data >> 0 & 31;
|
||||||
t = bit1(data,5);
|
t = data >> 5 & 1;
|
||||||
f = bit1(data,6);
|
f = data >> 6 & 1;
|
||||||
i = bit1(data,7);
|
i = data >> 7 & 1;
|
||||||
v = bit1(data,28);
|
v = data >> 28 & 1;
|
||||||
c = bit1(data,29);
|
c = data >> 29 & 1;
|
||||||
z = bit1(data,30);
|
z = data >> 30 & 1;
|
||||||
n = bit1(data,31);
|
n = data >> 31 & 1;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ auto ARM7TDMI::armDisassembleMoveMultiple
|
||||||
(uint16 list, uint4 n, uint1 mode, uint1 writeback, uint1 type, uint1 up, uint1 pre) -> string {
|
(uint16 list, uint4 n, uint1 mode, uint1 writeback, uint1 type, uint1 up, uint1 pre) -> string {
|
||||||
string registers;
|
string registers;
|
||||||
for(auto index : range(16)) {
|
for(auto index : range(16)) {
|
||||||
if(bit1(list,index)) registers.append(_r[index], ",");
|
if((list & 1 << index)) registers.append(_r[index], ",");
|
||||||
}
|
}
|
||||||
registers.trimRight(",", 1L);
|
registers.trimRight(",", 1L);
|
||||||
return {mode ? "ldm" : "stm", _c,
|
return {mode ? "ldm" : "stm", _c,
|
||||||
|
@ -358,7 +358,7 @@ auto ARM7TDMI::thumbDisassembleMoveMultiple
|
||||||
(uint8 list, uint3 n, uint1 mode) -> string {
|
(uint8 list, uint3 n, uint1 mode) -> string {
|
||||||
string registers;
|
string registers;
|
||||||
for(uint m : range(8)) {
|
for(uint m : range(8)) {
|
||||||
if(bit1(list,m)) registers.append(_r[m], ",");
|
if((list & 1 << m)) registers.append(_r[m], ",");
|
||||||
}
|
}
|
||||||
registers.trimRight(",", 1L);
|
registers.trimRight(",", 1L);
|
||||||
return {mode ? "ldmia" : "stmia", " ", _r[n], "!,{", registers, "}"};
|
return {mode ? "ldmia" : "stmia", " ", _r[n], "!,{", registers, "}"};
|
||||||
|
@ -395,7 +395,7 @@ auto ARM7TDMI::thumbDisassembleStackMultiple
|
||||||
(uint8 list, uint1 lrpc, uint1 mode) -> string {
|
(uint8 list, uint1 lrpc, uint1 mode) -> string {
|
||||||
string registers;
|
string registers;
|
||||||
for(uint m : range(8)) {
|
for(uint m : range(8)) {
|
||||||
if(bit1(list,m)) registers.append(_r[m], ",");
|
if((list & 1 << m)) registers.append(_r[m], ",");
|
||||||
}
|
}
|
||||||
if(lrpc) registers.append(!mode ? "lr," : "pc,");
|
if(lrpc) registers.append(!mode ? "lr," : "pc,");
|
||||||
registers.trimRight(",", 1L);
|
registers.trimRight(",", 1L);
|
||||||
|
|
|
@ -68,8 +68,11 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#define pattern(s) \
|
#define pattern(s) \
|
||||||
std::integral_constant<uint32_t, bit::test(s)>::value
|
std::integral_constant<uint32_t, bit::test(s)>::value
|
||||||
|
|
||||||
|
#define bit1(value, index) (value >> index & 1)
|
||||||
|
#define bits(value, lo, hi) (value >> lo & (1ull << (hi - lo + 1)) - 1)
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0-23), /* displacement */ \
|
bits(opcode, 0,23), /* displacement */ \
|
||||||
bit1(opcode,24) /* link */
|
bit1(opcode,24) /* link */
|
||||||
for(uint4 displacementLo : range(16))
|
for(uint4 displacementLo : range(16))
|
||||||
for(uint4 displacementHi : range(16))
|
for(uint4 displacementHi : range(16))
|
||||||
|
@ -81,7 +84,7 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3) /* m */
|
bits(opcode, 0, 3) /* m */
|
||||||
{
|
{
|
||||||
auto opcode = pattern(".... 0001 0010 ---- ---- ---- 0001 ????");
|
auto opcode = pattern(".... 0001 0010 ---- ---- ---- 0001 ????");
|
||||||
bind(opcode, BranchExchangeRegister);
|
bind(opcode, BranchExchangeRegister);
|
||||||
|
@ -89,12 +92,12 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 7), /* immediate */ \
|
bits(opcode, 0, 7), /* immediate */ \
|
||||||
bits(opcode, 8-11), /* shift */ \
|
bits(opcode, 8,11), /* shift */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,20), /* save */ \
|
bit1(opcode,20), /* save */ \
|
||||||
bits(opcode,21-24) /* mode */
|
bits(opcode,21,24) /* mode */
|
||||||
for(uint4 shiftHi : range(16))
|
for(uint4 shiftHi : range(16))
|
||||||
for(uint1 save : range(2))
|
for(uint1 save : range(2))
|
||||||
for(uint4 mode : range(16)) {
|
for(uint4 mode : range(16)) {
|
||||||
|
@ -105,13 +108,13 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3), /* m */ \
|
bits(opcode, 0, 3), /* m */ \
|
||||||
bits(opcode, 5- 6), /* type */ \
|
bits(opcode, 5, 6), /* type */ \
|
||||||
bits(opcode, 7-11), /* shift */ \
|
bits(opcode, 7,11), /* shift */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,20), /* save */ \
|
bit1(opcode,20), /* save */ \
|
||||||
bits(opcode,21-24) /* mode */
|
bits(opcode,21,24) /* mode */
|
||||||
for(uint2 type : range(4))
|
for(uint2 type : range(4))
|
||||||
for(uint1 shiftLo : range(2))
|
for(uint1 shiftLo : range(2))
|
||||||
for(uint1 save : range(2))
|
for(uint1 save : range(2))
|
||||||
|
@ -123,13 +126,13 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3), /* m */ \
|
bits(opcode, 0, 3), /* m */ \
|
||||||
bits(opcode, 5- 6), /* type */ \
|
bits(opcode, 5, 6), /* type */ \
|
||||||
bits(opcode, 8-11), /* s */ \
|
bits(opcode, 8,11), /* s */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,20), /* save */ \
|
bit1(opcode,20), /* save */ \
|
||||||
bits(opcode,21-24) /* mode */
|
bits(opcode,21,24) /* mode */
|
||||||
for(uint2 type : range(4))
|
for(uint2 type : range(4))
|
||||||
for(uint1 save : range(2))
|
for(uint1 save : range(2))
|
||||||
for(uint4 mode : range(16)) {
|
for(uint4 mode : range(16)) {
|
||||||
|
@ -140,10 +143,10 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3) << 0 | bits(opcode, 8-11) << 4, /* immediate */ \
|
bits(opcode, 0, 3) << 0 | bits(opcode, 8,11) << 4, /* immediate */ \
|
||||||
bit1(opcode, 5), /* half */ \
|
bit1(opcode, 5), /* half */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,21), /* writeback */ \
|
bit1(opcode,21), /* writeback */ \
|
||||||
bit1(opcode,23), /* up */ \
|
bit1(opcode,23), /* up */ \
|
||||||
bit1(opcode,24) /* pre */
|
bit1(opcode,24) /* pre */
|
||||||
|
@ -157,10 +160,10 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3), /* m */ \
|
bits(opcode, 0, 3), /* m */ \
|
||||||
bit1(opcode, 5), /* half */ \
|
bit1(opcode, 5), /* half */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,21), /* writeback */ \
|
bit1(opcode,21), /* writeback */ \
|
||||||
bit1(opcode,23), /* up */ \
|
bit1(opcode,23), /* up */ \
|
||||||
bit1(opcode,24) /* pre */
|
bit1(opcode,24) /* pre */
|
||||||
|
@ -174,9 +177,9 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3), /* m */ \
|
bits(opcode, 0, 3), /* m */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,22) /* byte */
|
bit1(opcode,22) /* byte */
|
||||||
for(uint1 byte : range(2)) {
|
for(uint1 byte : range(2)) {
|
||||||
auto opcode = pattern(".... 0001 0?00 ???? ???? ---- 1001 ????") | byte << 22;
|
auto opcode = pattern(".... 0001 0?00 ???? ???? ---- 1001 ????") | byte << 22;
|
||||||
|
@ -185,9 +188,9 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3) << 0 | bits(opcode, 8-11) << 4, /* immediate */ \
|
bits(opcode, 0, 3) << 0 | bits(opcode, 8,11) << 4, /* immediate */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,20), /* mode */ \
|
bit1(opcode,20), /* mode */ \
|
||||||
bit1(opcode,21), /* writeback */ \
|
bit1(opcode,21), /* writeback */ \
|
||||||
bit1(opcode,23), /* up */ \
|
bit1(opcode,23), /* up */ \
|
||||||
|
@ -202,9 +205,9 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3), /* m */ \
|
bits(opcode, 0, 3), /* m */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,20), /* mode */ \
|
bit1(opcode,20), /* mode */ \
|
||||||
bit1(opcode,21), /* writeback */ \
|
bit1(opcode,21), /* writeback */ \
|
||||||
bit1(opcode,23), /* up */ \
|
bit1(opcode,23), /* up */ \
|
||||||
|
@ -219,9 +222,9 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0-11), /* immediate */ \
|
bits(opcode, 0,11), /* immediate */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,20), /* mode */ \
|
bit1(opcode,20), /* mode */ \
|
||||||
bit1(opcode,21), /* writeback */ \
|
bit1(opcode,21), /* writeback */ \
|
||||||
bit1(opcode,22), /* byte */ \
|
bit1(opcode,22), /* byte */ \
|
||||||
|
@ -240,8 +243,8 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0-15), /* list */ \
|
bits(opcode, 0,15), /* list */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,20), /* mode */ \
|
bit1(opcode,20), /* mode */ \
|
||||||
bit1(opcode,21), /* writeback */ \
|
bit1(opcode,21), /* writeback */ \
|
||||||
bit1(opcode,22), /* type */ \
|
bit1(opcode,22), /* type */ \
|
||||||
|
@ -260,11 +263,11 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3), /* m */ \
|
bits(opcode, 0, 3), /* m */ \
|
||||||
bits(opcode, 5- 6), /* type */ \
|
bits(opcode, 5, 6), /* type */ \
|
||||||
bits(opcode, 7-11), /* shift */ \
|
bits(opcode, 7,11), /* shift */ \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bits(opcode,16-19), /* n */ \
|
bits(opcode,16,19), /* n */ \
|
||||||
bit1(opcode,20), /* mode */ \
|
bit1(opcode,20), /* mode */ \
|
||||||
bit1(opcode,21), /* writeback */ \
|
bit1(opcode,21), /* writeback */ \
|
||||||
bit1(opcode,22), /* byte */ \
|
bit1(opcode,22), /* byte */ \
|
||||||
|
@ -284,7 +287,7 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode,12-15), /* d */ \
|
bits(opcode,12,15), /* d */ \
|
||||||
bit1(opcode,22) /* mode */
|
bit1(opcode,22) /* mode */
|
||||||
for(uint1 mode : range(2)) {
|
for(uint1 mode : range(2)) {
|
||||||
auto opcode = pattern(".... 0001 0?00 ---- ???? ---- 0000 ----") | mode << 22;
|
auto opcode = pattern(".... 0001 0?00 ---- ???? ---- 0000 ----") | mode << 22;
|
||||||
|
@ -293,9 +296,9 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 7), /* immediate */ \
|
bits(opcode, 0, 7), /* immediate */ \
|
||||||
bits(opcode, 8-11), /* rotate */ \
|
bits(opcode, 8,11), /* rotate */ \
|
||||||
bits(opcode,16-19), /* field */ \
|
bits(opcode,16,19), /* field */ \
|
||||||
bit1(opcode,22) /* mode */
|
bit1(opcode,22) /* mode */
|
||||||
for(uint4 immediateHi : range(16))
|
for(uint4 immediateHi : range(16))
|
||||||
for(uint1 mode : range(2)) {
|
for(uint1 mode : range(2)) {
|
||||||
|
@ -305,8 +308,8 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3), /* m */ \
|
bits(opcode, 0, 3), /* m */ \
|
||||||
bits(opcode,16-19), /* field */ \
|
bits(opcode,16,19), /* field */ \
|
||||||
bit1(opcode,22) /* mode */
|
bit1(opcode,22) /* mode */
|
||||||
for(uint1 mode : range(2)) {
|
for(uint1 mode : range(2)) {
|
||||||
auto opcode = pattern(".... 0001 0?10 ???? ---- ---- 0000 ????") | mode << 22;
|
auto opcode = pattern(".... 0001 0?10 ???? ---- ---- 0000 ????") | mode << 22;
|
||||||
|
@ -315,10 +318,10 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3), /* m */ \
|
bits(opcode, 0, 3), /* m */ \
|
||||||
bits(opcode, 8-11), /* s */ \
|
bits(opcode, 8,11), /* s */ \
|
||||||
bits(opcode,12-15), /* n */ \
|
bits(opcode,12,15), /* n */ \
|
||||||
bits(opcode,16-19), /* d */ \
|
bits(opcode,16,19), /* d */ \
|
||||||
bit1(opcode,20), /* save */ \
|
bit1(opcode,20), /* save */ \
|
||||||
bit1(opcode,21) /* accumulate */
|
bit1(opcode,21) /* accumulate */
|
||||||
for(uint1 save : range(2))
|
for(uint1 save : range(2))
|
||||||
|
@ -329,10 +332,10 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0- 3), /* m */ \
|
bits(opcode, 0, 3), /* m */ \
|
||||||
bits(opcode, 8-11), /* s */ \
|
bits(opcode, 8,11), /* s */ \
|
||||||
bits(opcode,12-15), /* l */ \
|
bits(opcode,12,15), /* l */ \
|
||||||
bits(opcode,16-19), /* h */ \
|
bits(opcode,16,19), /* h */ \
|
||||||
bit1(opcode,20), /* save */ \
|
bit1(opcode,20), /* save */ \
|
||||||
bit1(opcode,21), /* accumulate */ \
|
bit1(opcode,21), /* accumulate */ \
|
||||||
bit1(opcode,22) /* sign */
|
bit1(opcode,22) /* sign */
|
||||||
|
@ -345,7 +348,7 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
|
||||||
#define arguments \
|
#define arguments \
|
||||||
bits(opcode, 0-23) /* immediate */
|
bits(opcode, 0,23) /* immediate */
|
||||||
for(uint4 immediateLo : range(16))
|
for(uint4 immediateLo : range(16))
|
||||||
for(uint4 immediateHi : range(16)) {
|
for(uint4 immediateHi : range(16)) {
|
||||||
auto opcode = pattern(".... 1111 ???? ???? ???? ???? ???? ????") | immediateLo << 4 | immediateHi << 20;
|
auto opcode = pattern(".... 1111 ???? ???? ???? ???? ???? ????") | immediateLo << 4 | immediateHi << 20;
|
||||||
|
@ -356,7 +359,7 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||||
#define arguments
|
#define arguments
|
||||||
for(uint12 id : range(4096)) {
|
for(uint12 id : range(4096)) {
|
||||||
if(armInstruction[id]) continue;
|
if(armInstruction[id]) continue;
|
||||||
auto opcode = pattern(".... ???? ???? ---- ---- ---- ???? ----") | bits(id,0-3) << 4 | bits(id,4-11) << 20;
|
auto opcode = pattern(".... ???? ???? ---- ---- ---- ???? ----") | bits(id,0,3) << 4 | bits(id,4,11) << 20;
|
||||||
bind(opcode, Undefined);
|
bind(opcode, Undefined);
|
||||||
}
|
}
|
||||||
#undef arguments
|
#undef arguments
|
||||||
|
@ -386,7 +389,7 @@ auto ARM7TDMI::thumbInitialize() -> void {
|
||||||
for(uint4 m : range(16))
|
for(uint4 m : range(16))
|
||||||
for(uint2 mode : range(4)) {
|
for(uint2 mode : range(4)) {
|
||||||
if(mode == 3) continue;
|
if(mode == 3) continue;
|
||||||
auto opcode = pattern("0100 01?? ???? ????") | bits(d,0-2) << 0 | m << 3 | bit1(d,3) << 7 | mode << 8;
|
auto opcode = pattern("0100 01?? ???? ????") | bits(d,0,2) << 0 | m << 3 | bit1(d,3) << 7 | mode << 8;
|
||||||
bind(opcode, ALUExtended, d, m, mode);
|
bind(opcode, ALUExtended, d, m, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,6 +536,9 @@ auto ARM7TDMI::thumbInitialize() -> void {
|
||||||
bind(opcode, Undefined);
|
bind(opcode, Undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef bit1
|
||||||
|
#undef bits
|
||||||
|
|
||||||
#undef bind
|
#undef bind
|
||||||
#undef pattern
|
#undef pattern
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ auto ARM7TDMI::armALU(uint4 mode, uint4 d, uint4 n, uint32 rm) -> void {
|
||||||
case 15: r(d) = BIT(~rm); break; //MVN
|
case 15: r(d) = BIT(~rm); break; //MVN
|
||||||
}
|
}
|
||||||
|
|
||||||
if(exception() && d == 15 && bit1(opcode,20)) {
|
if(exception() && d == 15 && (opcode & 1 << 20)) {
|
||||||
cpsr() = spsr();
|
cpsr() = spsr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,21 +29,21 @@ auto ARM7TDMI::armMoveToStatus(uint4 field, uint1 mode, uint32 data) -> void {
|
||||||
if(mode && (cpsr().m == PSR::USR || cpsr().m == PSR::SYS)) return;
|
if(mode && (cpsr().m == PSR::USR || cpsr().m == PSR::SYS)) return;
|
||||||
PSR& psr = mode ? spsr() : cpsr();
|
PSR& psr = mode ? spsr() : cpsr();
|
||||||
|
|
||||||
if(field.bit(0)) {
|
if(field & 1) {
|
||||||
if(mode || privileged()) {
|
if(mode || privileged()) {
|
||||||
psr.m = bits(data,0-4);
|
psr.m = data >> 0 & 31;
|
||||||
psr.t = bit1(data,5);
|
psr.t = data >> 5 & 1;
|
||||||
psr.f = bit1(data,6);
|
psr.f = data >> 6 & 1;
|
||||||
psr.i = bit1(data,7);
|
psr.i = data >> 7 & 1;
|
||||||
if(!mode && psr.t) r(15).data += 2;
|
if(!mode && psr.t) r(15).data += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(field.bit(3)) {
|
if(field & 8) {
|
||||||
psr.v = bit1(data,28);
|
psr.v = data >> 28 & 1;
|
||||||
psr.c = bit1(data,29);
|
psr.c = data >> 29 & 1;
|
||||||
psr.z = bit1(data,30);
|
psr.z = data >> 30 & 1;
|
||||||
psr.n = bit1(data,31);
|
psr.n = data >> 31 & 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,13 +193,13 @@ auto ARM7TDMI::armInstructionMoveMultiple
|
||||||
|
|
||||||
auto cpsrMode = cpsr().m;
|
auto cpsrMode = cpsr().m;
|
||||||
bool usr = false;
|
bool usr = false;
|
||||||
if(type && mode == 1 && !bit1(list,15)) usr = true;
|
if(type && mode == 1 && !(list & 0x8000)) usr = true;
|
||||||
if(type && mode == 0) usr = true;
|
if(type && mode == 0) usr = true;
|
||||||
if(usr) cpsr().m = PSR::USR;
|
if(usr) cpsr().m = PSR::USR;
|
||||||
|
|
||||||
uint sequential = Nonsequential;
|
uint sequential = Nonsequential;
|
||||||
for(uint m : range(16)) {
|
for(uint m : range(16)) {
|
||||||
if(!bit1(list,m)) continue;
|
if(!(list & 1 << m)) continue;
|
||||||
if(mode == 1) r(m) = read(Word | sequential, rn);
|
if(mode == 1) r(m) = read(Word | sequential, rn);
|
||||||
if(mode == 0) write(Word | sequential, rn, r(m));
|
if(mode == 0) write(Word | sequential, rn, r(m));
|
||||||
rn += 4;
|
rn += 4;
|
||||||
|
@ -210,7 +210,7 @@ auto ARM7TDMI::armInstructionMoveMultiple
|
||||||
|
|
||||||
if(mode) {
|
if(mode) {
|
||||||
idle();
|
idle();
|
||||||
if(type && bit1(list,15) && cpsr().m != PSR::USR && cpsr().m != PSR::SYS) {
|
if(type && (list & 0x8000) && cpsr().m != PSR::USR && cpsr().m != PSR::SYS) {
|
||||||
cpsr() = spsr();
|
cpsr() = spsr();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -299,7 +299,7 @@ auto ARM7TDMI::armInstructionMultiplyLong
|
||||||
|
|
||||||
if(save) {
|
if(save) {
|
||||||
cpsr().z = rd == 0;
|
cpsr().z = rd == 0;
|
||||||
cpsr().n = bit1(rd,63);
|
cpsr().n = rd >> 63 & 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ auto ARM7TDMI::thumbInstructionMoveMultiple
|
||||||
uint32 rn = r(n);
|
uint32 rn = r(n);
|
||||||
|
|
||||||
for(uint m : range(8)) {
|
for(uint m : range(8)) {
|
||||||
if(!bit1(list,m)) continue;
|
if(!(list & 1 << m)) continue;
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case 0: write(Word | Nonsequential, rn, r(m)); break; //STMIA
|
case 0: write(Word | Nonsequential, rn, r(m)); break; //STMIA
|
||||||
case 1: r(m) = read(Word | Nonsequential, rn); break; //LDMIA
|
case 1: r(m) = read(Word | Nonsequential, rn); break; //LDMIA
|
||||||
|
@ -135,7 +135,7 @@ auto ARM7TDMI::thumbInstructionMoveMultiple
|
||||||
rn += 4;
|
rn += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mode == 0 || !bit1(list,n)) r(n) = rn;
|
if(mode == 0 || !(list & 1 << n)) r(n) = rn;
|
||||||
if(mode == 1) idle();
|
if(mode == 1) idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ auto ARM7TDMI::thumbInstructionStackMultiple
|
||||||
|
|
||||||
uint sequential = Nonsequential;
|
uint sequential = Nonsequential;
|
||||||
for(uint m : range(8)) {
|
for(uint m : range(8)) {
|
||||||
if(!bit1(list,m)) continue;
|
if(!(list & 1 << m)) continue;
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case 0: write(Word | sequential, sp, r(m)); break; //PUSH
|
case 0: write(Word | sequential, sp, r(m)); break; //PUSH
|
||||||
case 1: r(m) = read(Word | sequential, sp); break; //POP
|
case 1: r(m) = read(Word | sequential, sp); break; //POP
|
||||||
|
|
|
@ -84,8 +84,8 @@ auto HG51B::cache() -> bool {
|
||||||
|
|
||||||
io.cache.address[io.cache.page] = address;
|
io.cache.address[io.cache.page] = address;
|
||||||
for(uint offset : range(256)) {
|
for(uint offset : range(256)) {
|
||||||
step(wait(address)); bit8(programRAM[io.cache.page][offset],0) = read(address++);
|
step(wait(address)); programRAM[io.cache.page][offset] = read(address++) << 0;
|
||||||
step(wait(address)); bit8(programRAM[io.cache.page][offset],1) = read(address++);
|
step(wait(address)); programRAM[io.cache.page][offset] |= read(address++) << 8;
|
||||||
}
|
}
|
||||||
return io.cache.enable = 0, true;
|
return io.cache.enable = 0, true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,11 +203,11 @@ auto HG51B::instructionLD(uint15& out, uint8 imm) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HG51B::instructionLDL(uint15& out, uint8 imm) -> void {
|
auto HG51B::instructionLDL(uint15& out, uint8 imm) -> void {
|
||||||
bits(out,0-7) = imm;
|
out = out & 0x7f00 | imm << 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HG51B::instructionLDH(uint15& out, uint7 imm) -> void {
|
auto HG51B::instructionLDH(uint15& out, uint7 imm) -> void {
|
||||||
bits(out,8-14) = imm;
|
out = out & 0x00ff | (imm & 0x7f) << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HG51B::instructionMUL(uint7 reg) -> void {
|
auto HG51B::instructionMUL(uint7 reg) -> void {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
auto HG51B::readRegister(uint7 address) -> uint24 {
|
auto HG51B::readRegister(uint7 address) -> uint24 {
|
||||||
switch(address) {
|
switch(address) {
|
||||||
case 0x01: return bits(r.mul,24-47);
|
case 0x01: return r.mul >> 24 & 0xffffff;
|
||||||
case 0x02: return bits(r.mul, 0-23);
|
case 0x02: return r.mul >> 0 & 0xffffff;
|
||||||
case 0x03: return r.mdr;
|
case 0x03: return r.mdr;
|
||||||
case 0x08: return r.rom;
|
case 0x08: return r.rom;
|
||||||
case 0x0c: return r.ram;
|
case 0x0c: return r.ram;
|
||||||
|
@ -64,8 +64,8 @@ auto HG51B::readRegister(uint7 address) -> uint24 {
|
||||||
|
|
||||||
auto HG51B::writeRegister(uint7 address, uint24 data) -> void {
|
auto HG51B::writeRegister(uint7 address, uint24 data) -> void {
|
||||||
switch(address) {
|
switch(address) {
|
||||||
case 0x01: bits(r.mul,24-47) = data; return;
|
case 0x01: r.mul = r.mul & ~0xffffffull | data << 0; return;
|
||||||
case 0x02: bits(r.mul, 0-23) = data; return;
|
case 0x02: r.mul = r.mul & 0xffffffull | data << 24; return;
|
||||||
case 0x03: r.mdr = data; return;
|
case 0x03: r.mdr = data; return;
|
||||||
case 0x08: r.rom = data; return;
|
case 0x08: r.rom = data; return;
|
||||||
case 0x0c: r.ram = data; return;
|
case 0x0c: r.ram = data; return;
|
||||||
|
|
|
@ -7,32 +7,33 @@ auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void {
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case 0: //or addr:bit
|
case 0: //or addr:bit
|
||||||
idle();
|
idle();
|
||||||
CF |= bit1(data,bit);
|
CF |= bool(data & 1 << bit);
|
||||||
break;
|
break;
|
||||||
case 1: //or !addr:bit
|
case 1: //or !addr:bit
|
||||||
idle();
|
idle();
|
||||||
CF |= !bit1(data,bit);
|
CF |= !bool(data & 1 << bit);
|
||||||
break;
|
break;
|
||||||
case 2: //and addr:bit
|
case 2: //and addr:bit
|
||||||
CF &= bit1(data,bit);
|
CF &= bool(data & 1 << bit);
|
||||||
break;
|
break;
|
||||||
case 3: //and !addr:bit
|
case 3: //and !addr:bit
|
||||||
CF &= !bit1(data,bit);
|
CF &= !bool(data & 1 << bit);
|
||||||
break;
|
break;
|
||||||
case 4: //eor addr:bit
|
case 4: //eor addr:bit
|
||||||
idle();
|
idle();
|
||||||
CF ^= bit1(data,bit);
|
CF ^= bool(data & 1 << bit);
|
||||||
break;
|
break;
|
||||||
case 5: //ld addr:bit
|
case 5: //ld addr:bit
|
||||||
CF = bit1(data,bit);
|
CF = bool(data & 1 << bit);
|
||||||
break;
|
break;
|
||||||
case 6: //st addr:bit
|
case 6: //st addr:bit
|
||||||
idle();
|
idle();
|
||||||
bit1(data,bit) = CF;
|
data &= ~(1 << bit);
|
||||||
|
data |= CF << bit;
|
||||||
write(address, data);
|
write(address, data);
|
||||||
break;
|
break;
|
||||||
case 7: //not addr:bit
|
case 7: //not addr:bit
|
||||||
bit1(data,bit) ^= 1;
|
data ^= 1 << bit;
|
||||||
write(address, data);
|
write(address, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +42,8 @@ auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void {
|
||||||
auto SPC700::instructionAbsoluteBitSet(uint3 bit, bool value) -> void {
|
auto SPC700::instructionAbsoluteBitSet(uint3 bit, bool value) -> void {
|
||||||
uint8 address = fetch();
|
uint8 address = fetch();
|
||||||
uint8 data = load(address);
|
uint8 data = load(address);
|
||||||
bit1(data,bit) = value;
|
data &= ~(1 << bit);
|
||||||
|
data |= value << bit;
|
||||||
store(address, data);
|
store(address, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +97,7 @@ auto SPC700::instructionBranchBit(uint3 bit, bool match) -> void {
|
||||||
uint8 data = load(address);
|
uint8 data = load(address);
|
||||||
idle();
|
idle();
|
||||||
uint8 displacement = fetch();
|
uint8 displacement = fetch();
|
||||||
if(bit1(data,bit) != match) return;
|
if(bool(data & 1 << bit) != match) return;
|
||||||
idle();
|
idle();
|
||||||
idle();
|
idle();
|
||||||
PC += (int8)displacement;
|
PC += (int8)displacement;
|
||||||
|
|
|
@ -134,14 +134,14 @@ struct SPC700 {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto& operator=(uint8 data) {
|
inline auto& operator=(uint8 data) {
|
||||||
c = bit1(data,0);
|
c = data & 0x01;
|
||||||
z = bit1(data,1);
|
z = data & 0x02;
|
||||||
i = bit1(data,2);
|
i = data & 0x04;
|
||||||
h = bit1(data,3);
|
h = data & 0x08;
|
||||||
b = bit1(data,4);
|
b = data & 0x10;
|
||||||
p = bit1(data,5);
|
p = data & 0x20;
|
||||||
v = bit1(data,6);
|
v = data & 0x40;
|
||||||
n = bit1(data,7);
|
n = data & 0x80;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,12 +37,12 @@ struct uPD96050 {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto operator=(uint16 data) -> Flag& {
|
inline auto operator=(uint16 data) -> Flag& {
|
||||||
ov0 = bit1(data,0);
|
ov0 = data >> 0 & 1;
|
||||||
ov1 = bit1(data,1);
|
ov1 = data >> 1 & 1;
|
||||||
z = bit1(data,2);
|
z = data >> 2 & 1;
|
||||||
c = bit1(data,3);
|
c = data >> 3 & 1;
|
||||||
s0 = bit1(data,4);
|
s0 = data >> 4 & 1;
|
||||||
s1 = bit1(data,5);
|
s1 = data >> 5 & 1;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,17 +64,17 @@ struct uPD96050 {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto operator=(uint16 data) -> Status& {
|
inline auto operator=(uint16 data) -> Status& {
|
||||||
p0 = bit1(data, 0);
|
p0 = data >> 0 & 1;
|
||||||
p1 = bit1(data, 1);
|
p1 = data >> 1 & 1;
|
||||||
ei = bit1(data, 7);
|
ei = data >> 7 & 1;
|
||||||
sic = bit1(data, 8);
|
sic = data >> 8 & 1;
|
||||||
soc = bit1(data, 9);
|
soc = data >> 9 & 1;
|
||||||
drc = bit1(data,10);
|
drc = data >> 10 & 1;
|
||||||
dma = bit1(data,11);
|
dma = data >> 11 & 1;
|
||||||
drs = bit1(data,12);
|
drs = data >> 12 & 1;
|
||||||
usf0 = bit1(data,13);
|
usf0 = data >> 13 & 1;
|
||||||
usf1 = bit1(data,14);
|
usf1 = data >> 14 & 1;
|
||||||
rqm = bit1(data,15);
|
rqm = data >> 15 & 1;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,9 +83,9 @@ auto ArmDSP::set(uint mode, uint32 addr, uint32 word) -> void {
|
||||||
|
|
||||||
if(addr == 0x4000'0010) bridge.signal = true;
|
if(addr == 0x4000'0010) bridge.signal = true;
|
||||||
|
|
||||||
if(addr == 0x4000'0020) bit8(bridge.timerlatch,0) = word;
|
if(addr == 0x4000'0020) bridge.timerlatch = bridge.timerlatch & 0xffff00 | word << 0;
|
||||||
if(addr == 0x4000'0024) bit8(bridge.timerlatch,1) = word;
|
if(addr == 0x4000'0024) bridge.timerlatch = bridge.timerlatch & 0xff00ff | word << 8;
|
||||||
if(addr == 0x4000'0028) bit8(bridge.timerlatch,2) = word;
|
if(addr == 0x4000'0028) bridge.timerlatch = bridge.timerlatch & 0x00ffff | word << 16;
|
||||||
|
|
||||||
if(addr == 0x4000'002c) bridge.timer = bridge.timerlatch;
|
if(addr == 0x4000'002c) bridge.timer = bridge.timerlatch;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ auto Event::power() -> void {
|
||||||
create(Event::Enter, 1);
|
create(Event::Enter, 1);
|
||||||
|
|
||||||
//DIP switches 0-3 control the time: 3 minutes + 0-15 extra minutes
|
//DIP switches 0-3 control the time: 3 minutes + 0-15 extra minutes
|
||||||
timer = (3 + bits(dip.value,0-3)) * 60; //in seconds
|
timer = (3 + (dip.value & 15)) * 60; //in seconds
|
||||||
//DIP switches 4-5 serve an unknown purpose
|
//DIP switches 4-5 serve an unknown purpose
|
||||||
//DIP switches 6-7 are not connected
|
//DIP switches 6-7 are not connected
|
||||||
|
|
||||||
|
|
|
@ -134,21 +134,21 @@ auto HitachiDSP::readIO(uint address, uint8 data) -> uint8 {
|
||||||
|
|
||||||
//IO
|
//IO
|
||||||
switch(address) {
|
switch(address) {
|
||||||
case 0x7f40: return bit8(io.dma.source,0);
|
case 0x7f40: return io.dma.source >> 0;
|
||||||
case 0x7f41: return bit8(io.dma.source,1);
|
case 0x7f41: return io.dma.source >> 8;
|
||||||
case 0x7f42: return bit8(io.dma.source,2);
|
case 0x7f42: return io.dma.source >> 16;
|
||||||
case 0x7f43: return bit8(io.dma.length,0);
|
case 0x7f43: return io.dma.length >> 0;
|
||||||
case 0x7f44: return bit8(io.dma.length,1);
|
case 0x7f44: return io.dma.length >> 8;
|
||||||
case 0x7f45: return bit8(io.dma.target,0);
|
case 0x7f45: return io.dma.target >> 0;
|
||||||
case 0x7f46: return bit8(io.dma.target,1);
|
case 0x7f46: return io.dma.target >> 8;
|
||||||
case 0x7f47: return bit8(io.dma.target,2);
|
case 0x7f47: return io.dma.target >> 16;
|
||||||
case 0x7f48: return io.cache.page;
|
case 0x7f48: return io.cache.page;
|
||||||
case 0x7f49: return bit8(io.cache.base,0);
|
case 0x7f49: return io.cache.base >> 0;
|
||||||
case 0x7f4a: return bit8(io.cache.base,1);
|
case 0x7f4a: return io.cache.base >> 8;
|
||||||
case 0x7f4b: return bit8(io.cache.base,2);
|
case 0x7f4b: return io.cache.base >> 16;
|
||||||
case 0x7f4c: return io.cache.lock[0] << 0 | io.cache.lock[1] << 1;
|
case 0x7f4c: return io.cache.lock[0] << 0 | io.cache.lock[1] << 1;
|
||||||
case 0x7f4d: return bit8(io.cache.pb,0);
|
case 0x7f4d: return io.cache.pb >> 0;
|
||||||
case 0x7f4e: return bit8(io.cache.pb,1);
|
case 0x7f4e: return io.cache.pb >> 8;
|
||||||
case 0x7f4f: return io.cache.pc;
|
case 0x7f4f: return io.cache.pc;
|
||||||
case 0x7f50: return io.wait.ram << 0 | io.wait.rom << 4;
|
case 0x7f50: return io.wait.ram << 0 | io.wait.rom << 4;
|
||||||
case 0x7f51: return io.irq;
|
case 0x7f51: return io.irq;
|
||||||
|
@ -166,7 +166,11 @@ auto HitachiDSP::readIO(uint address, uint8 data) -> uint8 {
|
||||||
//registers
|
//registers
|
||||||
if((address >= 0x7f80 && address <= 0x7faf) || (address >= 0x7fc0 && address <= 0x7fef)) {
|
if((address >= 0x7f80 && address <= 0x7faf) || (address >= 0x7fc0 && address <= 0x7fef)) {
|
||||||
address &= 0x3f;
|
address &= 0x3f;
|
||||||
return r.gpr[address / 3].byte(address % 3);
|
switch(address % 3) {
|
||||||
|
case 0: return r.gpr[address / 3] >> 0;
|
||||||
|
case 1: return r.gpr[address / 3] >> 8;
|
||||||
|
case 2: return r.gpr[address / 3] >> 16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0x00;
|
return 0x00;
|
||||||
|
@ -177,16 +181,16 @@ auto HitachiDSP::writeIO(uint address, uint8 data) -> void {
|
||||||
|
|
||||||
//IO
|
//IO
|
||||||
switch(address) {
|
switch(address) {
|
||||||
case 0x7f40: bit8(io.dma.source,0) = data; return;
|
case 0x7f40: io.dma.source = io.dma.source & 0xffff00 | data << 0; return;
|
||||||
case 0x7f41: bit8(io.dma.source,1) = data; return;
|
case 0x7f41: io.dma.source = io.dma.source & 0xff00ff | data << 8; return;
|
||||||
case 0x7f42: bit8(io.dma.source,2) = data; return;
|
case 0x7f42: io.dma.source = io.dma.source & 0x00ffff | data << 16; return;
|
||||||
|
|
||||||
case 0x7f43: bit8(io.dma.length,0) = data; return;
|
case 0x7f43: io.dma.length = io.dma.length & 0xff00 | data << 0; return;
|
||||||
case 0x7f44: bit8(io.dma.length,1) = data; return;
|
case 0x7f44: io.dma.length = io.dma.length & 0x00ff | data << 8; return;
|
||||||
|
|
||||||
case 0x7f45: bit8(io.dma.target,0) = data; return;
|
case 0x7f45: io.dma.target = io.dma.target & 0xffff00 | data << 0; return;
|
||||||
case 0x7f46: bit8(io.dma.target,1) = data; return;
|
case 0x7f46: io.dma.target = io.dma.target & 0xff00ff | data << 8; return;
|
||||||
case 0x7f47: bit8(io.dma.target,2) = data;
|
case 0x7f47: io.dma.target = io.dma.target & 0x00ffff | data << 16;
|
||||||
if(io.halt) io.dma.enable = 1;
|
if(io.halt) io.dma.enable = 1;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -195,17 +199,17 @@ auto HitachiDSP::writeIO(uint address, uint8 data) -> void {
|
||||||
if(io.halt) io.cache.enable = 1;
|
if(io.halt) io.cache.enable = 1;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x7f49: bit8(io.cache.base,0) = data; return;
|
case 0x7f49: io.cache.base = io.cache.base & 0xffff00 | data << 0; return;
|
||||||
case 0x7f4a: bit8(io.cache.base,1) = data; return;
|
case 0x7f4a: io.cache.base = io.cache.base & 0xff00ff | data << 8; return;
|
||||||
case 0x7f4b: bit8(io.cache.base,2) = data; return;
|
case 0x7f4b: io.cache.base = io.cache.base & 0x00ffff | data << 16; return;
|
||||||
|
|
||||||
case 0x7f4c:
|
case 0x7f4c:
|
||||||
io.cache.lock[0] = bit1(data,0);
|
io.cache.lock[0] = bool(data & 1);
|
||||||
io.cache.lock[1] = bit1(data,1);
|
io.cache.lock[1] = bool(data & 2);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x7f4d: bit8(io.cache.pb,0) = data; return;
|
case 0x7f4d: io.cache.pb = io.cache.pb & 0xff00 | data << 0; return;
|
||||||
case 0x7f4e: bit8(io.cache.pb,1) = data; return;
|
case 0x7f4e: io.cache.pb = io.cache.pb & 0x00ff | data << 8; return;
|
||||||
|
|
||||||
case 0x7f4f:
|
case 0x7f4f:
|
||||||
io.cache.pc = data;
|
io.cache.pc = data;
|
||||||
|
@ -217,8 +221,8 @@ auto HitachiDSP::writeIO(uint address, uint8 data) -> void {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x7f50:
|
case 0x7f50:
|
||||||
io.wait.ram = bits(data,0-2);
|
io.wait.ram = data >> 0 & 7;
|
||||||
io.wait.rom = bits(data,4-6);
|
io.wait.rom = data >> 4 & 7;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x7f51:
|
case 0x7f51:
|
||||||
|
@ -259,6 +263,11 @@ auto HitachiDSP::writeIO(uint address, uint8 data) -> void {
|
||||||
//registers
|
//registers
|
||||||
if((address >= 0x7f80 && address <= 0x7faf) || (address >= 0x7fc0 && address <= 0x7fef)) {
|
if((address >= 0x7f80 && address <= 0x7faf) || (address >= 0x7fc0 && address <= 0x7fef)) {
|
||||||
address &= 0x3f;
|
address &= 0x3f;
|
||||||
bit8(r.gpr[address / 3],address % 3) = data;
|
switch(address % 3) {
|
||||||
|
case 0: r.gpr[address / 3] = r.gpr[address / 3] & 0xffff00 | data << 0; break;
|
||||||
|
case 1: r.gpr[address / 3] = r.gpr[address / 3] & 0xff00ff | data << 8; break;
|
||||||
|
case 2: r.gpr[address / 3] = r.gpr[address / 3] & 0x00ffff | data << 16; break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,8 +46,8 @@ auto ICD::joypWrite(bool p14, bool p15) -> void {
|
||||||
|
|
||||||
uint4 input = 0xf;
|
uint4 input = 0xf;
|
||||||
if(p14 == 1 && p15 == 1) input = 0xf - joypID;
|
if(p14 == 1 && p15 == 1) input = 0xf - joypID;
|
||||||
if(p14 == 0) input &= bits(joypad,0-3); //d-pad
|
if(p14 == 0) input &= (joypad >> 0 & 15); //d-pad
|
||||||
if(p15 == 0) input &= bits(joypad,4-7); //buttons
|
if(p15 == 0) input &= (joypad >> 4 & 15); //buttons
|
||||||
|
|
||||||
GB_icd_set_joyp(&sameboy, input);
|
GB_icd_set_joyp(&sameboy, input);
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,8 @@ auto MCC::read(uint address, uint8 data) -> uint8 {
|
||||||
case 2: return r.mapping << 7;
|
case 2: return r.mapping << 7;
|
||||||
case 3: return r.psramEnableLo << 7;
|
case 3: return r.psramEnableLo << 7;
|
||||||
case 4: return r.psramEnableHi << 7;
|
case 4: return r.psramEnableHi << 7;
|
||||||
case 5: return r.psramMapping.bit(0) << 7;
|
case 5: return (r.psramMapping >> 0 & 1) << 7;
|
||||||
case 6: return r.psramMapping.bit(1) << 7;
|
case 6: return (r.psramMapping >> 1 & 1) << 7;
|
||||||
case 7: return r.romEnableLo << 7;
|
case 7: return r.romEnableLo << 7;
|
||||||
case 8: return r.romEnableHi << 7;
|
case 8: return r.romEnableHi << 7;
|
||||||
case 9: return r.exEnableLo << 7;
|
case 9: return r.exEnableLo << 7;
|
||||||
|
@ -60,20 +60,20 @@ auto MCC::read(uint address, uint8 data) -> uint8 {
|
||||||
auto MCC::write(uint address, uint8 data) -> void {
|
auto MCC::write(uint address, uint8 data) -> void {
|
||||||
if((address & 0xf0f000) == 0x005000) { //$00-0f:5000-5fff
|
if((address & 0xf0f000) == 0x005000) { //$00-0f:5000-5fff
|
||||||
switch(address >> 16 & 15) {
|
switch(address >> 16 & 15) {
|
||||||
case 1: irq.enable = bit1(data,7); break;
|
case 1: irq.enable = data >> 7; break;
|
||||||
case 2: w.mapping = bit1(data,7); break;
|
case 2: w.mapping = data >> 7; break;
|
||||||
case 3: w.psramEnableLo = bit1(data,7); break;
|
case 3: w.psramEnableLo = data >> 7; break;
|
||||||
case 4: w.psramEnableHi = bit1(data,7); break;
|
case 4: w.psramEnableHi = data >> 7; break;
|
||||||
case 5: bit1(w.psramMapping,0) = bit1(data,7); break;
|
case 5: w.psramMapping = w.psramMapping & 2 | data >> 7 << 0; break;
|
||||||
case 6: bit1(w.psramMapping,1) = bit1(data,7); break;
|
case 6: w.psramMapping = w.psramMapping & 1 | data >> 7 << 1; break;
|
||||||
case 7: w.romEnableLo = bit1(data,7); break;
|
case 7: w.romEnableLo = data >> 7; break;
|
||||||
case 8: w.romEnableHi = bit1(data,7); break;
|
case 8: w.romEnableHi = data >> 7; break;
|
||||||
case 9: w.exEnableLo = bit1(data,7); break;
|
case 9: w.exEnableLo = data >> 7; break;
|
||||||
case 10: w.exEnableHi = bit1(data,7); break;
|
case 10: w.exEnableHi = data >> 7; break;
|
||||||
case 11: w.exMapping = bit1(data,7); break;
|
case 11: w.exMapping = data >> 7; break;
|
||||||
case 12: w.internallyWritable = bit1(data,7); break;
|
case 12: w.internallyWritable = data >> 7; break;
|
||||||
case 13: w.externallyWritable = bit1(data,7); break;
|
case 13: w.externallyWritable = data >> 7; break;
|
||||||
case 14: if(bit1(data,7)) commit(); break;
|
case 14: if(data >> 7) commit(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ auto MSU1::audioOpen() -> void {
|
||||||
auto MSU1::readIO(uint addr, uint8) -> uint8 {
|
auto MSU1::readIO(uint addr, uint8) -> uint8 {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
|
|
||||||
switch(0x2000 | (addr & 7)) {
|
switch(0x2000 | addr & 7) {
|
||||||
case 0x2000:
|
case 0x2000:
|
||||||
return (
|
return (
|
||||||
Revision << 0
|
Revision << 0
|
||||||
|
@ -139,16 +139,16 @@ auto MSU1::readIO(uint addr, uint8) -> uint8 {
|
||||||
auto MSU1::writeIO(uint addr, uint8 data) -> void {
|
auto MSU1::writeIO(uint addr, uint8 data) -> void {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
|
|
||||||
switch(0x2000 | (addr & 7)) {
|
switch(0x2000 | addr & 7) {
|
||||||
case 0x2000: bit8(io.dataSeekOffset,0) = data; break;
|
case 0x2000: io.dataSeekOffset = io.dataSeekOffset & 0xffffff00 | data << 0; break;
|
||||||
case 0x2001: bit8(io.dataSeekOffset,1) = data; break;
|
case 0x2001: io.dataSeekOffset = io.dataSeekOffset & 0xffff00ff | data << 8; break;
|
||||||
case 0x2002: bit8(io.dataSeekOffset,2) = data; break;
|
case 0x2002: io.dataSeekOffset = io.dataSeekOffset & 0xff00ffff | data << 16; break;
|
||||||
case 0x2003: bit8(io.dataSeekOffset,3) = data;
|
case 0x2003: io.dataSeekOffset = io.dataSeekOffset & 0x00ffffff | data << 24;
|
||||||
io.dataReadOffset = io.dataSeekOffset;
|
io.dataReadOffset = io.dataSeekOffset;
|
||||||
if(dataFile) dataFile->seek(io.dataReadOffset);
|
if(dataFile) dataFile->seek(io.dataReadOffset);
|
||||||
break;
|
break;
|
||||||
case 0x2004: bit8(io.audioTrack,0) = data; break;
|
case 0x2004: io.audioTrack = io.audioTrack & 0xff00 | data << 0; break;
|
||||||
case 0x2005: bit8(io.audioTrack,1) = data;
|
case 0x2005: io.audioTrack = io.audioTrack & 0x00ff | data << 8;
|
||||||
io.audioPlay = false;
|
io.audioPlay = false;
|
||||||
io.audioRepeat = false;
|
io.audioRepeat = false;
|
||||||
io.audioPlayOffset = 8;
|
io.audioPlayOffset = 8;
|
||||||
|
@ -165,9 +165,9 @@ auto MSU1::writeIO(uint addr, uint8 data) -> void {
|
||||||
case 0x2007:
|
case 0x2007:
|
||||||
if(io.audioBusy) break;
|
if(io.audioBusy) break;
|
||||||
if(io.audioError) break;
|
if(io.audioError) break;
|
||||||
io.audioPlay = bit1(data,0);
|
io.audioPlay = bool(data & 1);
|
||||||
io.audioRepeat = bit1(data,1);
|
io.audioRepeat = bool(data & 2);
|
||||||
boolean audioResume = bit1(data,2);
|
boolean audioResume = bool(data & 4);
|
||||||
if(!io.audioPlay && audioResume) {
|
if(!io.audioPlay && audioResume) {
|
||||||
io.audioResumeTrack = io.audioTrack;
|
io.audioResumeTrack = io.audioTrack;
|
||||||
io.audioResumeOffset = io.audioPlayOffset;
|
io.audioResumeOffset = io.audioPlayOffset;
|
||||||
|
|
|
@ -80,18 +80,18 @@ auto SA1::BWRAM::readBitmap(uint20 address, uint8 data) -> uint8 {
|
||||||
uint shift = address & 1;
|
uint shift = address & 1;
|
||||||
address >>= 1;
|
address >>= 1;
|
||||||
switch(shift) {
|
switch(shift) {
|
||||||
case 0: return cbits(read(address),0-3);
|
case 0: return read(address) >> 0 & 15;
|
||||||
case 1: return cbits(read(address),4-7);
|
case 1: return read(address) >> 4 & 15;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//2bpp
|
//2bpp
|
||||||
uint shift = address & 3;
|
uint shift = address & 3;
|
||||||
address >>= 2;
|
address >>= 2;
|
||||||
switch(shift) {
|
switch(shift) {
|
||||||
case 0: return cbits(read(address),0-1);
|
case 0: return read(address) >> 0 & 3;
|
||||||
case 1: return cbits(read(address),2-3);
|
case 1: return read(address) >> 2 & 3;
|
||||||
case 2: return cbits(read(address),4-5);
|
case 2: return read(address) >> 4 & 3;
|
||||||
case 3: return cbits(read(address),6-7);
|
case 3: return read(address) >> 6 & 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unreachable;
|
unreachable;
|
||||||
|
|
|
@ -403,19 +403,19 @@ auto SA1::writeIOSA1(uint address, uint8 data) -> void {
|
||||||
|
|
||||||
//(MAL) multiplicand / dividend low
|
//(MAL) multiplicand / dividend low
|
||||||
case 0x2251: {
|
case 0x2251: {
|
||||||
bit8(mmio.ma,0) = data;
|
mmio.ma = mmio.ma & ~0x00ff | data << 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//(MAH) multiplicand / dividend high
|
//(MAH) multiplicand / dividend high
|
||||||
case 0x2252: {
|
case 0x2252: {
|
||||||
bit8(mmio.ma,1) = data;
|
mmio.ma = mmio.ma & ~0xff00 | data << 8;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//(MBL) multiplier / divisor low
|
//(MBL) multiplier / divisor low
|
||||||
case 0x2253: {
|
case 0x2253: {
|
||||||
bit8(mmio.mb,0) = data;
|
mmio.mb = mmio.mb & ~0x00ff | data << 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ auto SA1::writeIOSA1(uint address, uint8 data) -> void {
|
||||||
//multiplication / cumulative sum only resets MB
|
//multiplication / cumulative sum only resets MB
|
||||||
//division resets both MA and MB
|
//division resets both MA and MB
|
||||||
case 0x2254: {
|
case 0x2254: {
|
||||||
bit8(mmio.mb,1) = data;
|
mmio.mb = mmio.mb & ~0xff00 | data << 8;
|
||||||
|
|
||||||
if(mmio.acm == 0) {
|
if(mmio.acm == 0) {
|
||||||
if(mmio.md == 0) {
|
if(mmio.md == 0) {
|
||||||
|
|
|
@ -66,11 +66,11 @@ auto SDD1::dmaRead(uint addr, uint8 data) -> uint8 {
|
||||||
auto SDD1::dmaWrite(uint addr, uint8 data) -> void {
|
auto SDD1::dmaWrite(uint addr, uint8 data) -> void {
|
||||||
uint channel = addr >> 4 & 7;
|
uint channel = addr >> 4 & 7;
|
||||||
switch(addr & 15) {
|
switch(addr & 15) {
|
||||||
case 2: bit8(dma[channel].addr,0) = data; break;
|
case 2: dma[channel].addr = dma[channel].addr & 0xffff00 | data << 0; break;
|
||||||
case 3: bit8(dma[channel].addr,1) = data; break;
|
case 3: dma[channel].addr = dma[channel].addr & 0xff00ff | data << 8; break;
|
||||||
case 4: bit8(dma[channel].addr,2) = data; break;
|
case 4: dma[channel].addr = dma[channel].addr & 0x00ffff | data << 16; break;
|
||||||
case 5: bit8(dma[channel].size,0) = data; break;
|
case 5: dma[channel].size = dma[channel].size & 0xff00 | data << 0; break;
|
||||||
case 6: bit8(dma[channel].size,1) = data; break;
|
case 6: dma[channel].size = dma[channel].size & 0x00ff | data << 8; break;
|
||||||
}
|
}
|
||||||
return cpu.writeDMA(addr, data);
|
return cpu.writeDMA(addr, data);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ auto SDD1::mcuRead(uint addr, uint8 data) -> uint8 {
|
||||||
if(r4800 & r4801) {
|
if(r4800 & r4801) {
|
||||||
//at least one channel has S-DD1 decompression enabled ...
|
//at least one channel has S-DD1 decompression enabled ...
|
||||||
for(auto n : range(8)) {
|
for(auto n : range(8)) {
|
||||||
if(bit1(r4800,n) && bit1(r4801,n)) {
|
if((r4800 & 1 << n) && (r4801 & 1 << n)) {
|
||||||
//S-DD1 always uses fixed transfer mode, so address will not change during transfer
|
//S-DD1 always uses fixed transfer mode, so address will not change during transfer
|
||||||
if(addr == dma[n].addr) {
|
if(addr == dma[n].addr) {
|
||||||
if(!dmaReady) {
|
if(!dmaReady) {
|
||||||
|
@ -113,7 +113,7 @@ auto SDD1::mcuRead(uint addr, uint8 data) -> uint8 {
|
||||||
data = decompressor.read();
|
data = decompressor.read();
|
||||||
if(--dma[n].size == 0) {
|
if(--dma[n].size == 0) {
|
||||||
dmaReady = false;
|
dmaReady = false;
|
||||||
bit1(r4801,n) = 0;
|
r4801 &= ~(1 << n);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
|
@ -175,6 +175,6 @@ auto CPU::Channel::hdmaTransfer() -> void {
|
||||||
auto CPU::Channel::hdmaAdvance() -> void {
|
auto CPU::Channel::hdmaAdvance() -> void {
|
||||||
if(!hdmaActive()) return;
|
if(!hdmaActive()) return;
|
||||||
lineCounter--;
|
lineCounter--;
|
||||||
hdmaDoTransfer = bit1(lineCounter,7);
|
hdmaDoTransfer = bool(lineCounter & 0x80);
|
||||||
hdmaReload();
|
hdmaReload();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,21 +41,21 @@ auto CPU::readCPU(uint addr, uint8 data) -> uint8 {
|
||||||
data |= (vcounter() >= ppu.vdisp()) << 7; //vblank
|
data |= (vcounter() >= ppu.vdisp()) << 7; //vblank
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
case 0x4213: return io.pio; //RDIO
|
case 0x4213: return io.pio; //RDIO
|
||||||
|
|
||||||
case 0x4214: return bit8(io.rddiv,0); //RDDIVL
|
case 0x4214: return io.rddiv >> 0; //RDDIVL
|
||||||
case 0x4215: return bit8(io.rddiv,1); //RDDIVH
|
case 0x4215: return io.rddiv >> 8; //RDDIVH
|
||||||
case 0x4216: return bit8(io.rdmpy,0); //RDMPYL
|
case 0x4216: return io.rdmpy >> 0; //RDMPYL
|
||||||
case 0x4217: return bit8(io.rdmpy,1); //RDMPYH
|
case 0x4217: return io.rdmpy >> 8; //RDMPYH
|
||||||
|
|
||||||
case 0x4218: return bit8(io.joy1,0); //JOY1L
|
case 0x4218: return io.joy1 >> 0; //JOY1L
|
||||||
case 0x4219: return bit8(io.joy1,1); //JOY1H
|
case 0x4219: return io.joy1 >> 8; //JOY1H
|
||||||
case 0x421a: return bit8(io.joy2,0); //JOY2L
|
case 0x421a: return io.joy2 >> 0; //JOY2L
|
||||||
case 0x421b: return bit8(io.joy2,1); //JOY2H
|
case 0x421b: return io.joy2 >> 8; //JOY2H
|
||||||
case 0x421c: return bit8(io.joy3,0); //JOY3L
|
case 0x421c: return io.joy3 >> 0; //JOY3L
|
||||||
case 0x421d: return bit8(io.joy3,1); //JOY3H
|
case 0x421d: return io.joy3 >> 8; //JOY3H
|
||||||
case 0x421e: return bit8(io.joy4,0); //JOY4L
|
case 0x421e: return io.joy4 >> 0; //JOY4L
|
||||||
case 0x421f: return bit8(io.joy4,1); //JOY4H
|
case 0x421f: return io.joy4 >> 8; //JOY4H
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,18 +77,18 @@ auto CPU::readDMA(uint addr, uint8 data) -> uint8 {
|
||||||
| channel.direction << 7
|
| channel.direction << 7
|
||||||
);
|
);
|
||||||
|
|
||||||
case 0x4301: return channel.targetAddress; //BBADx
|
case 0x4301: return channel.targetAddress; //BBADx
|
||||||
case 0x4302: return bit8(channel.sourceAddress,0); //A1TxL
|
case 0x4302: return channel.sourceAddress >> 0; //A1TxL
|
||||||
case 0x4303: return bit8(channel.sourceAddress,1); //A1TxH
|
case 0x4303: return channel.sourceAddress >> 8; //A1TxH
|
||||||
case 0x4304: return channel.sourceBank; //A1Bx
|
case 0x4304: return channel.sourceBank; //A1Bx
|
||||||
case 0x4305: return bit8(channel.transferSize,0); //DASxL
|
case 0x4305: return channel.transferSize >> 0; //DASxL
|
||||||
case 0x4306: return bit8(channel.transferSize,1); //DASxH
|
case 0x4306: return channel.transferSize >> 8; //DASxH
|
||||||
case 0x4307: return channel.indirectBank; //DASBx
|
case 0x4307: return channel.indirectBank; //DASBx
|
||||||
case 0x4308: return bit8(channel.hdmaAddress,0); //A2AxL
|
case 0x4308: return channel.hdmaAddress >> 0; //A2AxL
|
||||||
case 0x4309: return bit8(channel.hdmaAddress,1); //A2AxH
|
case 0x4309: return channel.hdmaAddress >> 8; //A2AxH
|
||||||
case 0x430a: return channel.lineCounter; //NTRLx
|
case 0x430a: return channel.lineCounter; //NTRLx
|
||||||
case 0x430b: return channel.unknown; //???x
|
case 0x430b: return channel.unknown; //???x
|
||||||
case 0x430f: return channel.unknown; //???x ($43xb mirror)
|
case 0x430f: return channel.unknown; //???x ($43xb mirror)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,15 +111,15 @@ auto CPU::writeCPU(uint addr, uint8 data) -> void {
|
||||||
return bus.write(0x7e0000 | io.wramAddress++, data);
|
return bus.write(0x7e0000 | io.wramAddress++, data);
|
||||||
|
|
||||||
case 0x2181: //WMADDL
|
case 0x2181: //WMADDL
|
||||||
bits(io.wramAddress,0-7) = data;
|
io.wramAddress = io.wramAddress & 0x1ff00 | data << 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x2182: //WMADDM
|
case 0x2182: //WMADDM
|
||||||
bits(io.wramAddress,8-15) = data;
|
io.wramAddress = io.wramAddress & 0x100ff | data << 8;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x2183: //WMADDH
|
case 0x2183: //WMADDH
|
||||||
bit1(io.wramAddress,16) = bit1(data,0);
|
io.wramAddress = io.wramAddress & 0x0ffff | (data & 1) << 16;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4016: //JOYSER0
|
case 0x4016: //JOYSER0
|
||||||
|
@ -136,7 +136,7 @@ auto CPU::writeCPU(uint addr, uint8 data) -> void {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4201: //WRIO
|
case 0x4201: //WRIO
|
||||||
if(bit1(io.pio,7) && !bit1(data,7)) ppu.latchCounters();
|
if((io.pio & 0x80) && !(data & 0x80)) ppu.latchCounters();
|
||||||
io.pio = data;
|
io.pio = data;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -149,18 +149,18 @@ auto CPU::writeCPU(uint addr, uint8 data) -> void {
|
||||||
if(alu.mpyctr || alu.divctr) return;
|
if(alu.mpyctr || alu.divctr) return;
|
||||||
|
|
||||||
io.wrmpyb = data;
|
io.wrmpyb = data;
|
||||||
io.rddiv = (io.wrmpyb << 8) | io.wrmpya;
|
io.rddiv = io.wrmpyb << 8 | io.wrmpya;
|
||||||
|
|
||||||
alu.mpyctr = 8; //perform multiplication over the next eight cycles
|
alu.mpyctr = 8; //perform multiplication over the next eight cycles
|
||||||
alu.shift = io.wrmpyb;
|
alu.shift = io.wrmpyb;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4204: //WRDIVL
|
case 0x4204: //WRDIVL
|
||||||
bit8(io.wrdiva,0) = data;
|
io.wrdiva = io.wrdiva & 0xff00 | data << 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4205: //WRDIVH
|
case 0x4205: //WRDIVH
|
||||||
bit8(io.wrdiva,1) = data;
|
io.wrdiva = io.wrdiva & 0x00ff | data << 8;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4206: //WRDIVB
|
case 0x4206: //WRDIVB
|
||||||
|
@ -175,31 +175,31 @@ auto CPU::writeCPU(uint addr, uint8 data) -> void {
|
||||||
|
|
||||||
case 0x4207: //HTIMEL
|
case 0x4207: //HTIMEL
|
||||||
io.htime = (io.htime >> 2) - 1;
|
io.htime = (io.htime >> 2) - 1;
|
||||||
bits(io.htime,0-7) = data;
|
io.htime = io.htime & 0x100 | data << 0;
|
||||||
io.htime = (io.htime + 1) << 2;
|
io.htime = (io.htime + 1) << 2;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4208: //HTIMEH
|
case 0x4208: //HTIMEH
|
||||||
io.htime = (io.htime >> 2) - 1;
|
io.htime = (io.htime >> 2) - 1;
|
||||||
bit1(io.htime,8) = data & 1;
|
io.htime = io.htime & 0x0ff | (data & 1) << 8;
|
||||||
io.htime = (io.htime + 1) << 2;
|
io.htime = (io.htime + 1) << 2;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4209: //VTIMEL
|
case 0x4209: //VTIMEL
|
||||||
bits(io.vtime,0-7) = data;
|
io.vtime = io.vtime & 0x100 | data << 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x420a: //VTIMEH
|
case 0x420a: //VTIMEH
|
||||||
bit1(io.vtime,8) = data & 1;
|
io.vtime = io.vtime & 0x0ff | (data & 1) << 8;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x420b: //DMAEN
|
case 0x420b: //DMAEN
|
||||||
for(auto n : range(8)) channels[n].dmaEnable = bit1(data,n);
|
for(auto n : range(8)) channels[n].dmaEnable = bool(data & 1 << n);
|
||||||
if(data) status.dmaPending = true;
|
if(data) status.dmaPending = true;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x420c: //HDMAEN
|
case 0x420c: //HDMAEN
|
||||||
for(auto n : range(8)) channels[n].hdmaEnable = bit1(data,n);
|
for(auto n : range(8)) channels[n].hdmaEnable = bool(data & 1 << n);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x420d: //MEMSEL
|
case 0x420d: //MEMSEL
|
||||||
|
@ -215,12 +215,12 @@ auto CPU::writeDMA(uint addr, uint8 data) -> void {
|
||||||
switch(addr & 0xff8f) {
|
switch(addr & 0xff8f) {
|
||||||
|
|
||||||
case 0x4300: //DMAPx
|
case 0x4300: //DMAPx
|
||||||
channel.transferMode = bits(data,0-2);
|
channel.transferMode = data >> 0 & 7;
|
||||||
channel.fixedTransfer = bit1(data,3);
|
channel.fixedTransfer = data >> 3 & 1;
|
||||||
channel.reverseTransfer = bit1(data,4);
|
channel.reverseTransfer = data >> 4 & 1;
|
||||||
channel.unused = bit1(data,5);
|
channel.unused = data >> 5 & 1;
|
||||||
channel.indirect = bit1(data,6);
|
channel.indirect = data >> 6 & 1;
|
||||||
channel.direction = bit1(data,7);
|
channel.direction = data >> 7 & 1;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4301: //BBADx
|
case 0x4301: //BBADx
|
||||||
|
@ -228,11 +228,11 @@ auto CPU::writeDMA(uint addr, uint8 data) -> void {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4302: //A1TxL
|
case 0x4302: //A1TxL
|
||||||
bit8(channel.sourceAddress,0) = data;
|
channel.sourceAddress = channel.sourceAddress & 0xff00 | data << 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4303: //A1TxH
|
case 0x4303: //A1TxH
|
||||||
bit8(channel.sourceAddress,1) = data;
|
channel.sourceAddress = channel.sourceAddress & 0x00ff | data << 8;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4304: //A1Bx
|
case 0x4304: //A1Bx
|
||||||
|
@ -240,11 +240,11 @@ auto CPU::writeDMA(uint addr, uint8 data) -> void {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4305: //DASxL
|
case 0x4305: //DASxL
|
||||||
bit8(channel.transferSize,0) = data;
|
channel.transferSize = channel.transferSize & 0xff00 | data << 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4306: //DASxH
|
case 0x4306: //DASxH
|
||||||
bit8(channel.transferSize,1) = data;
|
channel.transferSize = channel.transferSize & 0x00ff | data << 8;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4307: //DASBx
|
case 0x4307: //DASBx
|
||||||
|
@ -252,11 +252,11 @@ auto CPU::writeDMA(uint addr, uint8 data) -> void {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4308: //A2AxL
|
case 0x4308: //A2AxL
|
||||||
bit8(channel.hdmaAddress,0) = data;
|
channel.hdmaAddress = channel.hdmaAddress & 0xff00 | data << 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x4309: //A2AxH
|
case 0x4309: //A2AxH
|
||||||
bit8(channel.hdmaAddress,1) = data;
|
channel.hdmaAddress = channel.hdmaAddress & 0x00ff | data << 8;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x430a: //NTRLx
|
case 0x430a: //NTRLx
|
||||||
|
|
|
@ -27,10 +27,10 @@ auto Interface::display() -> Display {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Interface::color(uint32 color) -> uint64 {
|
auto Interface::color(uint32 color) -> uint64 {
|
||||||
uint r = bits(color, 0- 4);
|
uint r = color >> 0 & 31;
|
||||||
uint g = bits(color, 5- 9);
|
uint g = color >> 5 & 31;
|
||||||
uint b = bits(color,10-14);
|
uint b = color >> 10 & 31;
|
||||||
uint l = bits(color,15-18);
|
uint l = color >> 15 & 15;
|
||||||
|
|
||||||
//luma=0 is not 100% black; but it's much darker than normal linear scaling
|
//luma=0 is not 100% black; but it's much darker than normal linear scaling
|
||||||
//exact effect seems to be analog; requires > 24-bit color depth to represent accurately
|
//exact effect seems to be analog; requires > 24-bit color depth to represent accurately
|
||||||
|
|
|
@ -84,19 +84,19 @@ auto PPU::Background::getTile() -> void {
|
||||||
if(offsetX >= 8) {
|
if(offsetX >= 8) {
|
||||||
auto hlookup = ppu.bg3.getTile((offsetX - 8) + (ppu.bg3.hoffset() & ~7), ppu.bg3.voffset() + 0);
|
auto hlookup = ppu.bg3.getTile((offsetX - 8) + (ppu.bg3.hoffset() & ~7), ppu.bg3.voffset() + 0);
|
||||||
auto vlookup = ppu.bg3.getTile((offsetX - 8) + (ppu.bg3.hoffset() & ~7), ppu.bg3.voffset() + 8);
|
auto vlookup = ppu.bg3.getTile((offsetX - 8) + (ppu.bg3.hoffset() & ~7), ppu.bg3.voffset() + 8);
|
||||||
uint valid = 13 + id;
|
uint valid = 1 << 13 + id;
|
||||||
|
|
||||||
if(ppu.io.bgMode == 4) {
|
if(ppu.io.bgMode == 4) {
|
||||||
if(bit1(hlookup,valid)) {
|
if(hlookup & valid) {
|
||||||
if(!bit1(hlookup,15)) {
|
if(!(hlookup & 0x8000)) {
|
||||||
hoffset = offsetX + (hlookup & ~7);
|
hoffset = offsetX + (hlookup & ~7);
|
||||||
} else {
|
} else {
|
||||||
voffset = py + hlookup;
|
voffset = py + hlookup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(bit1(hlookup,valid)) hoffset = offsetX + (hlookup & ~7);
|
if(hlookup & valid) hoffset = offsetX + (hlookup & ~7);
|
||||||
if(bit1(vlookup,valid)) voffset = py + vlookup;
|
if(vlookup & valid) voffset = py + vlookup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,27 +116,30 @@ auto PPU::Background::getTile() -> void {
|
||||||
|
|
||||||
uint16 address = io.screenAddress + offset;
|
uint16 address = io.screenAddress + offset;
|
||||||
tile = ppu.vram[address];
|
tile = ppu.vram[address];
|
||||||
bool mirrorY = bit1(tile,15);
|
bool mirrorY = tile & 0x8000;
|
||||||
bool mirrorX = bit1(tile,14);
|
bool mirrorX = tile & 0x4000;
|
||||||
priority = io.priority[bit1(tile,13)];
|
priority = io.priority[bool(tile & 0x2000)];
|
||||||
paletteNumber = bits(tile,10-12);
|
paletteNumber = tile >> 10 & 7;
|
||||||
paletteIndex = paletteOffset + (paletteNumber << paletteSize);
|
paletteIndex = paletteOffset + (paletteNumber << paletteSize);
|
||||||
|
|
||||||
if(tileWidth == 4 && (bool)(hoffset & 8) != mirrorX) tile += 1;
|
if(tileWidth == 4 && bool(hoffset & 8) != mirrorX) tile += 1;
|
||||||
if(tileHeight == 4 && (bool)(voffset & 8) != mirrorY) tile += 16;
|
if(tileHeight == 4 && bool(voffset & 8) != mirrorY) tile += 16;
|
||||||
uint16 character = bits(tile,0-9) + tiledataIndex & tileMask;
|
uint16 character = (tile & 0x03ff) + tiledataIndex & tileMask;
|
||||||
|
|
||||||
if(mirrorY) voffset ^= 7;
|
if(mirrorY) voffset ^= 7;
|
||||||
offset = (character << 3 + io.mode) + (voffset & 7);
|
offset = (character << 3 + io.mode) + (voffset & 7);
|
||||||
|
|
||||||
switch(io.mode) {
|
switch(io.mode) {
|
||||||
case Mode::BPP8:
|
case Mode::BPP8:
|
||||||
bits(data[1],16-31) = ppu.vram[offset + 24];
|
data[0] = ppu.vram[offset + 0] << 0 | ppu.vram[offset + 8] << 16;
|
||||||
bits(data[1], 0-15) = ppu.vram[offset + 16];
|
data[1] = ppu.vram[offset + 16] << 0 | ppu.vram[offset + 24] << 16;
|
||||||
|
break;
|
||||||
case Mode::BPP4:
|
case Mode::BPP4:
|
||||||
bits(data[0],16-31) = ppu.vram[offset + 8];
|
data[0] = ppu.vram[offset + 0] << 0 | ppu.vram[offset + 8] << 16;
|
||||||
|
break;
|
||||||
case Mode::BPP2:
|
case Mode::BPP2:
|
||||||
bits(data[0], 0-15) = ppu.vram[offset + 0];
|
data[0] = ppu.vram[offset + 0] << 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mirrorX) for(auto n : range(2)) {
|
if(mirrorX) for(auto n : range(2)) {
|
||||||
|
|
|
@ -23,9 +23,9 @@ auto PPU::addressVRAM() const -> uint16 {
|
||||||
uint16 address = io.vramAddress;
|
uint16 address = io.vramAddress;
|
||||||
switch(io.vramMapping) {
|
switch(io.vramMapping) {
|
||||||
case 0: return address;
|
case 0: return address;
|
||||||
case 1: return bits(address, 8-15) << 8 | bits(address,0-4) << 3 | bits(address,5-7);
|
case 1: return address & 0xff00 | address << 3 & 0x00f8 | address >> 5 & 7;
|
||||||
case 2: return bits(address, 9-15) << 9 | bits(address,0-5) << 3 | bits(address,6-8);
|
case 2: return address & 0xfe00 | address << 3 & 0x01f8 | address >> 6 & 7;
|
||||||
case 3: return bits(address,10-15) << 10 | bits(address,0-6) << 3 | bits(address,7-9);
|
case 3: return address & 0xfc00 | address << 3 & 0x03f8 | address >> 7 & 7;
|
||||||
}
|
}
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,8 @@ auto PPU::readVRAM() -> uint16 {
|
||||||
auto PPU::writeVRAM(bool byte, uint8 data) -> void {
|
auto PPU::writeVRAM(bool byte, uint8 data) -> void {
|
||||||
if(!io.displayDisable && vcounter() < vdisp()) return;
|
if(!io.displayDisable && vcounter() < vdisp()) return;
|
||||||
auto address = addressVRAM();
|
auto address = addressVRAM();
|
||||||
bit8(vram[address],byte) = data;
|
if(byte == 0) vram[address] = vram[address] & 0xff00 | data << 0;
|
||||||
|
if(byte == 1) vram[address] = vram[address] & 0x00ff | data << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::readOAM(uint10 addr) -> uint8 {
|
auto PPU::readOAM(uint10 addr) -> uint8 {
|
||||||
|
@ -101,7 +102,7 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
|
||||||
|
|
||||||
//SLHV
|
//SLHV
|
||||||
case 0x2137: {
|
case 0x2137: {
|
||||||
if(cbit1(cpu.pio(),7)) latchCounters();
|
if(cpu.pio() & 0x80) latchCounters();
|
||||||
return data; //CPU MDR
|
return data; //CPU MDR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +115,7 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
|
||||||
|
|
||||||
//VMDATALREAD
|
//VMDATALREAD
|
||||||
case 0x2139: {
|
case 0x2139: {
|
||||||
ppu1.mdr = bit8(latch.vram,0);
|
ppu1.mdr = latch.vram >> 0;
|
||||||
if(io.vramIncrementMode == 0) {
|
if(io.vramIncrementMode == 0) {
|
||||||
latch.vram = readVRAM();
|
latch.vram = readVRAM();
|
||||||
io.vramAddress += io.vramIncrementSize;
|
io.vramAddress += io.vramIncrementSize;
|
||||||
|
@ -124,7 +125,7 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
|
||||||
|
|
||||||
//VMDATAHREAD
|
//VMDATAHREAD
|
||||||
case 0x213a: {
|
case 0x213a: {
|
||||||
ppu1.mdr = bit8(latch.vram,1);
|
ppu1.mdr = latch.vram >> 8;
|
||||||
if(io.vramIncrementMode == 1) {
|
if(io.vramIncrementMode == 1) {
|
||||||
latch.vram = readVRAM();
|
latch.vram = readVRAM();
|
||||||
io.vramAddress += io.vramIncrementSize;
|
io.vramAddress += io.vramIncrementSize;
|
||||||
|
@ -135,9 +136,10 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
|
||||||
//CGDATAREAD
|
//CGDATAREAD
|
||||||
case 0x213b: {
|
case 0x213b: {
|
||||||
if(io.cgramAddressLatch++ == 0) {
|
if(io.cgramAddressLatch++ == 0) {
|
||||||
bits(ppu2.mdr,0-7) = readCGRAM(0, io.cgramAddress);
|
ppu2.mdr = readCGRAM(0, io.cgramAddress);
|
||||||
} else {
|
} else {
|
||||||
bits(ppu2.mdr,0-6) = readCGRAM(1, io.cgramAddress++);
|
ppu2.mdr &= 0x80;
|
||||||
|
ppu2.mdr |= readCGRAM(1, io.cgramAddress++) & 0x7f;
|
||||||
}
|
}
|
||||||
return ppu2.mdr;
|
return ppu2.mdr;
|
||||||
}
|
}
|
||||||
|
@ -145,9 +147,10 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
|
||||||
//OPHCT
|
//OPHCT
|
||||||
case 0x213c: {
|
case 0x213c: {
|
||||||
if(latch.hcounter++ == 0) {
|
if(latch.hcounter++ == 0) {
|
||||||
bits(ppu2.mdr,0-7) = bits(io.hcounter,0-7);
|
ppu2.mdr = io.hcounter >> 0;
|
||||||
} else {
|
} else {
|
||||||
bit1(ppu2.mdr,0 ) = bit1(io.hcounter,8 );
|
ppu2.mdr &= 0xfe;
|
||||||
|
ppu2.mdr |= io.hcounter >> 8 & 1;
|
||||||
}
|
}
|
||||||
return ppu2.mdr;
|
return ppu2.mdr;
|
||||||
}
|
}
|
||||||
|
@ -155,19 +158,20 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
|
||||||
//OPVCT
|
//OPVCT
|
||||||
case 0x213d: {
|
case 0x213d: {
|
||||||
if(latch.vcounter++ == 0) {
|
if(latch.vcounter++ == 0) {
|
||||||
bits(ppu2.mdr,0-7) = bits(io.vcounter,0-7);
|
ppu2.mdr = io.vcounter >> 0;
|
||||||
} else {
|
} else {
|
||||||
bit1(ppu2.mdr,0 ) = bit1(io.vcounter,8 );
|
ppu2.mdr &= 0xfe;
|
||||||
|
ppu2.mdr |= io.vcounter >> 8 & 1;
|
||||||
}
|
}
|
||||||
return ppu2.mdr;
|
return ppu2.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//STAT77
|
//STAT77
|
||||||
case 0x213e: {
|
case 0x213e: {
|
||||||
bits(ppu1.mdr,0-3) = ppu1.version;
|
ppu1.mdr &= 1 << 4;
|
||||||
bit1(ppu1.mdr, 5) = 0;
|
ppu1.mdr |= ppu1.version << 0;
|
||||||
bit1(ppu1.mdr, 6) = obj.io.rangeOver;
|
ppu1.mdr |= obj.io.rangeOver << 6;
|
||||||
bit1(ppu1.mdr, 7) = obj.io.timeOver;
|
ppu1.mdr |= obj.io.timeOver << 7;
|
||||||
return ppu1.mdr;
|
return ppu1.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,15 +179,16 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
|
||||||
case 0x213f: {
|
case 0x213f: {
|
||||||
latch.hcounter = 0;
|
latch.hcounter = 0;
|
||||||
latch.vcounter = 0;
|
latch.vcounter = 0;
|
||||||
bits(ppu2.mdr,0-3) = ppu2.version;
|
ppu2.mdr &= 1 << 5;
|
||||||
bit1(ppu2.mdr, 4) = Region::PAL(); //0 = NTSC, 1 = PAL
|
ppu2.mdr |= ppu2.version;
|
||||||
if(!cbit1(cpu.pio(),7)) {
|
ppu2.mdr |= Region::PAL() << 4; //0 = NTSC, 1 = PAL
|
||||||
bit1(ppu2.mdr, 6) = 1;
|
if(!(cpu.pio() & 0x80)) {
|
||||||
|
ppu2.mdr |= 1 << 6;;
|
||||||
} else {
|
} else {
|
||||||
bit1(ppu2.mdr, 6) = latch.counters;
|
ppu2.mdr |= latch.counters << 6;
|
||||||
latch.counters = 0;
|
latch.counters = 0;
|
||||||
}
|
}
|
||||||
bit1(ppu2.mdr, 7) = field();
|
ppu2.mdr |= field() << 7;
|
||||||
return ppu2.mdr;
|
return ppu2.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,16 +205,16 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
|
||||||
//INIDISP
|
//INIDISP
|
||||||
case 0x2100: {
|
case 0x2100: {
|
||||||
if(io.displayDisable && vcounter() == vdisp()) obj.addressReset();
|
if(io.displayDisable && vcounter() == vdisp()) obj.addressReset();
|
||||||
io.displayBrightness = bits(data,0-3);
|
io.displayBrightness = data >> 0 & 15;
|
||||||
io.displayDisable = bit1(data,7);
|
io.displayDisable = data >> 7 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//OBSEL
|
//OBSEL
|
||||||
case 0x2101: {
|
case 0x2101: {
|
||||||
obj.io.tiledataAddress = bits(data,0-2) << 13;
|
obj.io.tiledataAddress = (data & 7) << 13;
|
||||||
obj.io.nameselect = bits(data,3-4);
|
obj.io.nameselect = data >> 3 & 3;
|
||||||
obj.io.baseSize = bits(data,5-7);
|
obj.io.baseSize = data >> 5 & 7;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,18 +227,18 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
|
||||||
|
|
||||||
//OAMADDH
|
//OAMADDH
|
||||||
case 0x2103: {
|
case 0x2103: {
|
||||||
io.oamBaseAddress = bit1(data,0) << 9 | (io.oamBaseAddress & 0x01fe);
|
io.oamBaseAddress = (data & 1) << 9 | (io.oamBaseAddress & 0x01fe);
|
||||||
io.oamPriority = bit1(data,7);
|
io.oamPriority = bool(data & 0x80);
|
||||||
obj.addressReset();
|
obj.addressReset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//OAMDATA
|
//OAMDATA
|
||||||
case 0x2104: {
|
case 0x2104: {
|
||||||
uint1 latchBit = bit1(io.oamAddress,0);
|
uint1 latchBit = io.oamAddress & 1;
|
||||||
uint10 address = io.oamAddress++;
|
uint10 address = io.oamAddress++;
|
||||||
if(latchBit == 0) latch.oam = data;
|
if(latchBit == 0) latch.oam = data;
|
||||||
if(bit1(address,9)) {
|
if(address & 0x200) {
|
||||||
writeOAM(address, data);
|
writeOAM(address, data);
|
||||||
} else if(latchBit == 1) {
|
} else if(latchBit == 1) {
|
||||||
writeOAM((address & ~1) + 0, latch.oam);
|
writeOAM((address & ~1) + 0, latch.oam);
|
||||||
|
@ -245,65 +250,65 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
|
||||||
|
|
||||||
//BGMODE
|
//BGMODE
|
||||||
case 0x2105: {
|
case 0x2105: {
|
||||||
io.bgMode = bits(data,0-2);
|
io.bgMode = data >> 0 & 7;
|
||||||
io.bgPriority = bit1(data, 3);
|
io.bgPriority = data >> 3 & 1;
|
||||||
bg1.io.tileSize = bit1(data, 4);
|
bg1.io.tileSize = data >> 4 & 1;
|
||||||
bg2.io.tileSize = bit1(data, 5);
|
bg2.io.tileSize = data >> 5 & 1;
|
||||||
bg3.io.tileSize = bit1(data, 6);
|
bg3.io.tileSize = data >> 6 & 1;
|
||||||
bg4.io.tileSize = bit1(data, 7);
|
bg4.io.tileSize = data >> 7 & 1;
|
||||||
updateVideoMode();
|
updateVideoMode();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//MOSAIC
|
//MOSAIC
|
||||||
case 0x2106: {
|
case 0x2106: {
|
||||||
bg1.mosaic.enable = bit1(data,0);
|
bg1.mosaic.enable = data >> 0 & 1;
|
||||||
bg2.mosaic.enable = bit1(data,1);
|
bg2.mosaic.enable = data >> 1 & 1;
|
||||||
bg3.mosaic.enable = bit1(data,2);
|
bg3.mosaic.enable = data >> 2 & 1;
|
||||||
bg4.mosaic.enable = bit1(data,3);
|
bg4.mosaic.enable = data >> 3 & 1;
|
||||||
Background::Mosaic::size = bits(data,4-7);
|
Background::Mosaic::size = data >> 4 & 15;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BG1SC
|
//BG1SC
|
||||||
case 0x2107: {
|
case 0x2107: {
|
||||||
bg1.io.screenSize = bits(data,0-1);
|
bg1.io.screenSize = data & 3;
|
||||||
bg1.io.screenAddress = bits(data,2-7) << 10;
|
bg1.io.screenAddress = data >> 2 << 10;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BG2SC
|
//BG2SC
|
||||||
case 0x2108: {
|
case 0x2108: {
|
||||||
bg2.io.screenSize = bits(data,0-1);
|
bg2.io.screenSize = data & 3;
|
||||||
bg2.io.screenAddress = bits(data,2-7) << 10;
|
bg2.io.screenAddress = data >> 2 << 10;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BG3SC
|
//BG3SC
|
||||||
case 0x2109: {
|
case 0x2109: {
|
||||||
bg3.io.screenSize = bits(data,0-1);
|
bg3.io.screenSize = data & 3;
|
||||||
bg3.io.screenAddress = bits(data,2-7) << 10;
|
bg3.io.screenAddress = data >> 2 << 10;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BG4SC
|
//BG4SC
|
||||||
case 0x210a: {
|
case 0x210a: {
|
||||||
bg4.io.screenSize = bits(data,0-1);
|
bg4.io.screenSize = data & 3;
|
||||||
bg4.io.screenAddress = bits(data,2-7) << 10;
|
bg4.io.screenAddress = data >> 2 << 10;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BG12NBA
|
//BG12NBA
|
||||||
case 0x210b: {
|
case 0x210b: {
|
||||||
bg1.io.tiledataAddress = bits(data,0-3) << 12;
|
bg1.io.tiledataAddress = (data >> 0 & 15) << 12;
|
||||||
bg2.io.tiledataAddress = bits(data,4-7) << 12;
|
bg2.io.tiledataAddress = (data >> 4 & 15) << 12;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BG34NBA
|
//BG34NBA
|
||||||
case 0x210c: {
|
case 0x210c: {
|
||||||
bg3.io.tiledataAddress = bits(data,0-3) << 12;
|
bg3.io.tiledataAddress = (data >> 0 & 15) << 12;
|
||||||
bg4.io.tiledataAddress = bits(data,4-7) << 12;
|
bg4.io.tiledataAddress = (data >> 4 & 15) << 12;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,21 +382,21 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
|
||||||
case 0x2115: {
|
case 0x2115: {
|
||||||
static const uint size[4] = {1, 32, 128, 128};
|
static const uint size[4] = {1, 32, 128, 128};
|
||||||
io.vramIncrementSize = size[data & 3];
|
io.vramIncrementSize = size[data & 3];
|
||||||
io.vramMapping = bits(data,2-3);
|
io.vramMapping = data >> 2 & 3;
|
||||||
io.vramIncrementMode = bit1(data, 7);
|
io.vramIncrementMode = data >> 7 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//VMADDL
|
//VMADDL
|
||||||
case 0x2116: {
|
case 0x2116: {
|
||||||
bit8(io.vramAddress,0) = data;
|
io.vramAddress = io.vramAddress & 0xff00 | data << 0;
|
||||||
latch.vram = readVRAM();
|
latch.vram = readVRAM();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//VMADDH
|
//VMADDH
|
||||||
case 0x2117: {
|
case 0x2117: {
|
||||||
bit8(io.vramAddress,1) = data;
|
io.vramAddress = io.vramAddress & 0x00ff | data << 8;
|
||||||
latch.vram = readVRAM();
|
latch.vram = readVRAM();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -412,9 +417,9 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
|
||||||
|
|
||||||
//M7SEL
|
//M7SEL
|
||||||
case 0x211a: {
|
case 0x211a: {
|
||||||
io.hflipMode7 = bit1(data, 0);
|
io.hflipMode7 = data >> 0 & 1;
|
||||||
io.vflipMode7 = bit1(data, 1);
|
io.vflipMode7 = data >> 1 & 1;
|
||||||
io.repeatMode7 = bits(data,6-7);
|
io.repeatMode7 = data >> 6 & 3;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,47 +477,47 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
|
||||||
if(io.cgramAddressLatch++ == 0) {
|
if(io.cgramAddressLatch++ == 0) {
|
||||||
latch.cgram = data;
|
latch.cgram = data;
|
||||||
} else {
|
} else {
|
||||||
writeCGRAM(io.cgramAddress++, bits(data,0-6) << 8 | latch.cgram);
|
writeCGRAM(io.cgramAddress++, (data & 0x7f) << 8 | latch.cgram);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//W12SEL
|
//W12SEL
|
||||||
case 0x2123: {
|
case 0x2123: {
|
||||||
window.io.bg1.oneInvert = bit1(data,0);
|
window.io.bg1.oneInvert = data >> 0 & 1;
|
||||||
window.io.bg1.oneEnable = bit1(data,1);
|
window.io.bg1.oneEnable = data >> 1 & 1;
|
||||||
window.io.bg1.twoInvert = bit1(data,2);
|
window.io.bg1.twoInvert = data >> 2 & 1;
|
||||||
window.io.bg1.twoEnable = bit1(data,3);
|
window.io.bg1.twoEnable = data >> 3 & 1;
|
||||||
window.io.bg2.oneInvert = bit1(data,4);
|
window.io.bg2.oneInvert = data >> 4 & 1;
|
||||||
window.io.bg2.oneEnable = bit1(data,5);
|
window.io.bg2.oneEnable = data >> 5 & 1;
|
||||||
window.io.bg2.twoInvert = bit1(data,6);
|
window.io.bg2.twoInvert = data >> 6 & 1;
|
||||||
window.io.bg2.twoEnable = bit1(data,7);
|
window.io.bg2.twoEnable = data >> 7 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//W34SEL
|
//W34SEL
|
||||||
case 0x2124: {
|
case 0x2124: {
|
||||||
window.io.bg3.oneInvert = bit1(data,0);
|
window.io.bg3.oneInvert = data >> 0 & 1;
|
||||||
window.io.bg3.oneEnable = bit1(data,1);
|
window.io.bg3.oneEnable = data >> 1 & 1;
|
||||||
window.io.bg3.twoInvert = bit1(data,2);
|
window.io.bg3.twoInvert = data >> 2 & 1;
|
||||||
window.io.bg3.twoEnable = bit1(data,3);
|
window.io.bg3.twoEnable = data >> 3 & 1;
|
||||||
window.io.bg4.oneInvert = bit1(data,4);
|
window.io.bg4.oneInvert = data >> 4 & 1;
|
||||||
window.io.bg4.oneEnable = bit1(data,5);
|
window.io.bg4.oneEnable = data >> 5 & 1;
|
||||||
window.io.bg4.twoInvert = bit1(data,6);
|
window.io.bg4.twoInvert = data >> 6 & 1;
|
||||||
window.io.bg4.twoEnable = bit1(data,7);
|
window.io.bg4.twoEnable = data >> 7 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//WOBJSEL
|
//WOBJSEL
|
||||||
case 0x2125: {
|
case 0x2125: {
|
||||||
window.io.obj.oneInvert = bit1(data,0);
|
window.io.obj.oneInvert = data >> 0 & 1;
|
||||||
window.io.obj.oneEnable = bit1(data,1);
|
window.io.obj.oneEnable = data >> 1 & 1;
|
||||||
window.io.obj.twoInvert = bit1(data,2);
|
window.io.obj.twoInvert = data >> 2 & 1;
|
||||||
window.io.obj.twoEnable = bit1(data,3);
|
window.io.obj.twoEnable = data >> 3 & 1;
|
||||||
window.io.col.oneInvert = bit1(data,4);
|
window.io.col.oneInvert = data >> 4 & 1;
|
||||||
window.io.col.oneEnable = bit1(data,5);
|
window.io.col.oneEnable = data >> 5 & 1;
|
||||||
window.io.col.twoInvert = bit1(data,6);
|
window.io.col.twoInvert = data >> 6 & 1;
|
||||||
window.io.col.twoEnable = bit1(data,7);
|
window.io.col.twoEnable = data >> 7 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,97 +547,97 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
|
||||||
|
|
||||||
//WBGLOG
|
//WBGLOG
|
||||||
case 0x212a: {
|
case 0x212a: {
|
||||||
window.io.bg1.mask = bits(data,0-1);
|
window.io.bg1.mask = data >> 0 & 3;
|
||||||
window.io.bg2.mask = bits(data,2-3);
|
window.io.bg2.mask = data >> 2 & 3;
|
||||||
window.io.bg3.mask = bits(data,4-5);
|
window.io.bg3.mask = data >> 4 & 3;
|
||||||
window.io.bg4.mask = bits(data,6-7);
|
window.io.bg4.mask = data >> 6 & 3;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//WOBJLOG
|
//WOBJLOG
|
||||||
case 0x212b: {
|
case 0x212b: {
|
||||||
window.io.obj.mask = bits(data,0-1);
|
window.io.obj.mask = data >> 0 & 3;
|
||||||
window.io.col.mask = bits(data,2-3);
|
window.io.col.mask = data >> 2 & 3;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TM
|
//TM
|
||||||
case 0x212c: {
|
case 0x212c: {
|
||||||
bg1.io.aboveEnable = bit1(data,0);
|
bg1.io.aboveEnable = data >> 0 & 1;
|
||||||
bg2.io.aboveEnable = bit1(data,1);
|
bg2.io.aboveEnable = data >> 1 & 1;
|
||||||
bg3.io.aboveEnable = bit1(data,2);
|
bg3.io.aboveEnable = data >> 2 & 1;
|
||||||
bg4.io.aboveEnable = bit1(data,3);
|
bg4.io.aboveEnable = data >> 3 & 1;
|
||||||
obj.io.aboveEnable = bit1(data,4);
|
obj.io.aboveEnable = data >> 4 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TS
|
//TS
|
||||||
case 0x212d: {
|
case 0x212d: {
|
||||||
bg1.io.belowEnable = bit1(data,0);
|
bg1.io.belowEnable = data >> 0 & 1;
|
||||||
bg2.io.belowEnable = bit1(data,1);
|
bg2.io.belowEnable = data >> 1 & 1;
|
||||||
bg3.io.belowEnable = bit1(data,2);
|
bg3.io.belowEnable = data >> 2 & 1;
|
||||||
bg4.io.belowEnable = bit1(data,3);
|
bg4.io.belowEnable = data >> 3 & 1;
|
||||||
obj.io.belowEnable = bit1(data,4);
|
obj.io.belowEnable = data >> 4 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TMW
|
//TMW
|
||||||
case 0x212e: {
|
case 0x212e: {
|
||||||
window.io.bg1.aboveEnable = bit1(data,0);
|
window.io.bg1.aboveEnable = data >> 0 & 1;
|
||||||
window.io.bg2.aboveEnable = bit1(data,1);
|
window.io.bg2.aboveEnable = data >> 1 & 1;
|
||||||
window.io.bg3.aboveEnable = bit1(data,2);
|
window.io.bg3.aboveEnable = data >> 2 & 1;
|
||||||
window.io.bg4.aboveEnable = bit1(data,3);
|
window.io.bg4.aboveEnable = data >> 3 & 1;
|
||||||
window.io.obj.aboveEnable = bit1(data,4);
|
window.io.obj.aboveEnable = data >> 4 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TSW
|
//TSW
|
||||||
case 0x212f: {
|
case 0x212f: {
|
||||||
window.io.bg1.belowEnable = bit1(data,0);
|
window.io.bg1.belowEnable = data >> 0 & 1;
|
||||||
window.io.bg2.belowEnable = bit1(data,1);
|
window.io.bg2.belowEnable = data >> 1 & 1;
|
||||||
window.io.bg3.belowEnable = bit1(data,2);
|
window.io.bg3.belowEnable = data >> 2 & 1;
|
||||||
window.io.bg4.belowEnable = bit1(data,3);
|
window.io.bg4.belowEnable = data >> 3 & 1;
|
||||||
window.io.obj.belowEnable = bit1(data,4);
|
window.io.obj.belowEnable = data >> 4 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//CGWSEL
|
//CGWSEL
|
||||||
case 0x2130: {
|
case 0x2130: {
|
||||||
screen.io.directColor = bit1(data, 0);
|
screen.io.directColor = data >> 0 & 1;
|
||||||
screen.io.blendMode = bit1(data, 1);
|
screen.io.blendMode = data >> 1 & 1;
|
||||||
window.io.col.belowMask = bits(data,4-5);
|
window.io.col.belowMask = data >> 4 & 3;
|
||||||
window.io.col.aboveMask = bits(data,6-7);
|
window.io.col.aboveMask = data >> 6 & 3;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//CGADDSUB
|
//CGADDSUB
|
||||||
case 0x2131: {
|
case 0x2131: {
|
||||||
screen.io.bg1.colorEnable = bit1(data,0);
|
screen.io.bg1.colorEnable = data >> 0 & 1;
|
||||||
screen.io.bg2.colorEnable = bit1(data,1);
|
screen.io.bg2.colorEnable = data >> 1 & 1;
|
||||||
screen.io.bg3.colorEnable = bit1(data,2);
|
screen.io.bg3.colorEnable = data >> 2 & 1;
|
||||||
screen.io.bg4.colorEnable = bit1(data,3);
|
screen.io.bg4.colorEnable = data >> 3 & 1;
|
||||||
screen.io.obj.colorEnable = bit1(data,4);
|
screen.io.obj.colorEnable = data >> 4 & 1;
|
||||||
screen.io.back.colorEnable = bit1(data,5);
|
screen.io.back.colorEnable = data >> 5 & 1;
|
||||||
screen.io.colorHalve = bit1(data,6);
|
screen.io.colorHalve = data >> 6 & 1;
|
||||||
screen.io.colorMode = bit1(data,7);
|
screen.io.colorMode = data >> 7 & 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//COLDATA
|
//COLDATA
|
||||||
case 0x2132: {
|
case 0x2132: {
|
||||||
if(bit1(data,5)) screen.io.colorRed = bits(data,0-4);
|
if(data & 0x20) screen.io.colorRed = data & 0x1f;
|
||||||
if(bit1(data,6)) screen.io.colorGreen = bits(data,0-4);
|
if(data & 0x40) screen.io.colorGreen = data & 0x1f;
|
||||||
if(bit1(data,7)) screen.io.colorBlue = bits(data,0-4);
|
if(data & 0x80) screen.io.colorBlue = data & 0x1f;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//SETINI
|
//SETINI
|
||||||
case 0x2133: {
|
case 0x2133: {
|
||||||
io.interlace = bit1(data,0);
|
io.interlace = data >> 0 & 1;
|
||||||
obj.io.interlace = bit1(data,1);
|
obj.io.interlace = data >> 1 & 1;
|
||||||
io.overscan = bit1(data,2);
|
io.overscan = data >> 2 & 1;
|
||||||
io.pseudoHires = bit1(data,3);
|
io.pseudoHires = data >> 3 & 1;
|
||||||
io.extbg = bit1(data,6);
|
io.extbg = data >> 6 & 1;
|
||||||
updateVideoMode();
|
updateVideoMode();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,8 @@ auto PPU::Background::runMode7() -> void {
|
||||||
case 1:
|
case 1:
|
||||||
px &= 1023;
|
px &= 1023;
|
||||||
py &= 1023;
|
py &= 1023;
|
||||||
tile = bit8(ppu.vram[(py >> 3) * 128 + (px >> 3)],0);
|
tile = ppu.vram[(py >> 3) * 128 + (px >> 3)] >> 0;
|
||||||
palette = bit8(ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)],1);
|
palette = ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)] >> 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//palette color 0 outside of screen area
|
//palette color 0 outside of screen area
|
||||||
|
@ -61,8 +61,8 @@ auto PPU::Background::runMode7() -> void {
|
||||||
} else {
|
} else {
|
||||||
px &= 1023;
|
px &= 1023;
|
||||||
py &= 1023;
|
py &= 1023;
|
||||||
tile = bit8(ppu.vram[(py >> 3) * 128 + (px >> 3)],0);
|
tile = ppu.vram[(py >> 3) * 128 + (px >> 3)] >> 0;
|
||||||
palette = bit8(ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)],1);
|
palette = ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)] >> 8;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -73,9 +73,9 @@ auto PPU::Background::runMode7() -> void {
|
||||||
} else {
|
} else {
|
||||||
px &= 1023;
|
px &= 1023;
|
||||||
py &= 1023;
|
py &= 1023;
|
||||||
tile = bit8(ppu.vram[(py >> 3) * 128 + (px >> 3)],0);
|
tile = ppu.vram[(py >> 3) * 128 + (px >> 3)] >> 0;
|
||||||
}
|
}
|
||||||
palette = bit8(ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)],1);
|
palette = ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)] >> 8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
auto PPU::OAM::read(uint10 address) -> uint8 {
|
auto PPU::OAM::read(uint10 address) -> uint8 {
|
||||||
if(!address.bit(9)) {
|
if(!(address & 0x200)) {
|
||||||
uint n = address >> 2; //object#
|
uint n = address >> 2; //object#
|
||||||
address &= 3;
|
address &= 3;
|
||||||
if(address == 0) return object[n].x & 0xff;
|
if(address == 0) return object[n].x & 0xff;
|
||||||
|
@ -15,40 +15,40 @@ auto PPU::OAM::read(uint10 address) -> uint8 {
|
||||||
} else {
|
} else {
|
||||||
uint n = (address & 0x1f) << 2; //object#
|
uint n = (address & 0x1f) << 2; //object#
|
||||||
return (
|
return (
|
||||||
bit1(object[n + 0].x,8) << 0
|
object[n + 0].x >> 8 << 0
|
||||||
| object[n + 0].size << 1
|
| object[n + 0].size << 1
|
||||||
| bit1(object[n + 1].x,8) << 2
|
| object[n + 1].x >> 8 << 2
|
||||||
| object[n + 1].size << 3
|
| object[n + 1].size << 3
|
||||||
| bit1(object[n + 2].x,8) << 4
|
| object[n + 2].x >> 8 << 4
|
||||||
| object[n + 2].size << 5
|
| object[n + 2].size << 5
|
||||||
| bit1(object[n + 3].x,8) << 6
|
| object[n + 3].x >> 8 << 6
|
||||||
| object[n + 3].size << 7
|
| object[n + 3].size << 7
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::OAM::write(uint10 address, uint8 data) -> void {
|
auto PPU::OAM::write(uint10 address, uint8 data) -> void {
|
||||||
if(!address.bit(9)) {
|
if(!(address & 0x200)) {
|
||||||
uint n = address >> 2; //object#
|
uint n = address >> 2; //object#
|
||||||
address &= 3;
|
address &= 3;
|
||||||
if(address == 0) { bits(object[n].x,0-7) = data; return; }
|
if(address == 0) { object[n].x = object[n].x & 0x100 | data; return; }
|
||||||
if(address == 1) { object[n].y = data; return; }
|
if(address == 1) { object[n].y = data; return; }
|
||||||
if(address == 2) { object[n].character = data; return; }
|
if(address == 2) { object[n].character = data; return; }
|
||||||
object[n].nameselect = bit1(data,0);
|
object[n].nameselect = data >> 0 & 1;
|
||||||
object[n].palette = bits(data,1-3);
|
object[n].palette = data >> 1 & 7;
|
||||||
object[n].priority = bits(data,4-5);
|
object[n].priority = data >> 4 & 3;
|
||||||
object[n].hflip = bit1(data,6);
|
object[n].hflip = data >> 6 & 1;
|
||||||
object[n].vflip = bit1(data,7);
|
object[n].vflip = data >> 7 & 1;
|
||||||
} else {
|
} else {
|
||||||
uint n = (address & 0x1f) << 2; //object#
|
uint n = (address & 0x1f) << 2; //object#
|
||||||
bit1(object[n + 0].x,8) = bit1(data,0);
|
object[n + 0].x = object[n + 0].x & 0xff | bool(data & 0x01) << 8;
|
||||||
object[n + 0].size = bit1(data,1);
|
object[n + 0].size = bool(data & 0x02);
|
||||||
bit1(object[n + 1].x,8) = bit1(data,2);
|
object[n + 1].x = object[n + 1].x & 0xff | bool(data & 0x04) << 8;
|
||||||
object[n + 1].size = bit1(data,3);
|
object[n + 1].size = bool(data & 0x08);
|
||||||
bit1(object[n + 2].x,8) = bit1(data,4);
|
object[n + 2].x = object[n + 2].x & 0xff | bool(data & 0x10) << 8;
|
||||||
object[n + 2].size = bit1(data,5);
|
object[n + 2].size = bool(data & 0x20);
|
||||||
bit1(object[n + 3].x,8) = bit1(data,6);
|
object[n + 3].x = object[n + 3].x & 0xff | bool(data & 0x40) << 8;
|
||||||
object[n + 3].size = bit1(data,7);
|
object[n + 3].size = bool(data & 0x80);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,8 +117,8 @@ auto PPU::Object::tilefetch() -> void {
|
||||||
|
|
||||||
uint16 tiledataAddress = io.tiledataAddress;
|
uint16 tiledataAddress = io.tiledataAddress;
|
||||||
if(sprite.nameselect) tiledataAddress += 1 + io.nameselect << 12;
|
if(sprite.nameselect) tiledataAddress += 1 + io.nameselect << 12;
|
||||||
uint16 chrx = cbits(sprite.character,0-3);
|
uint16 chrx = (sprite.character >> 0 & 15);
|
||||||
uint16 chry = (cbits(sprite.character,4-7) + (y >> 3) & 15) << 4;
|
uint16 chry = ((sprite.character >> 4 & 15) + (y >> 3) & 15) << 4;
|
||||||
|
|
||||||
for(uint tx : range(tileWidth)) {
|
for(uint tx : range(tileWidth)) {
|
||||||
uint sx = x + (tx << 3) & 511;
|
uint sx = x + (tx << 3) & 511;
|
||||||
|
@ -136,8 +136,7 @@ auto PPU::Object::tilefetch() -> void {
|
||||||
uint pos = tiledataAddress + ((chry + (chrx + mx & 15)) << 4);
|
uint pos = tiledataAddress + ((chry + (chrx + mx & 15)) << 4);
|
||||||
uint16 addr = (pos & 0xfff0) + (y & 7);
|
uint16 addr = (pos & 0xfff0) + (y & 7);
|
||||||
|
|
||||||
bits(oamTile[n].data, 0-15) = ppu.vram[addr + 0];
|
oamTile[n].data = ppu.vram[addr + 0] << 0 | ppu.vram[addr + 8] << 16;
|
||||||
bits(oamTile[n].data,16-31) = ppu.vram[addr + 8];
|
|
||||||
ppu.step(2);
|
ppu.step(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,8 +136,8 @@ auto BSMemory::read(uint address, uint8 data) -> uint8 {
|
||||||
if(ROM) return memory.read(bus.mirror(address, size()));
|
if(ROM) return memory.read(bus.mirror(address, size()));
|
||||||
|
|
||||||
if(mode == Mode::Chip) {
|
if(mode == Mode::Chip) {
|
||||||
if(address == 0) return bit8(chip.vendor,0); //only appears once
|
if(address == 0) return chip.vendor; //only appears once
|
||||||
if(address == 1) return bit8(chip.device,0); //only appears once
|
if(address == 1) return chip.device; //only appears once
|
||||||
if((uint3)address == 2) return 0x63; //unknown constant: repeats every eight bytes
|
if((uint3)address == 2) return 0x63; //unknown constant: repeats every eight bytes
|
||||||
return 0x20; //unknown constant: fills in all remaining bytes
|
return 0x20; //unknown constant: fills in all remaining bytes
|
||||||
}
|
}
|
||||||
|
@ -167,8 +167,8 @@ auto BSMemory::write(uint address, uint8 data) -> void {
|
||||||
if(queue.data(0) == 0x0c) {
|
if(queue.data(0) == 0x0c) {
|
||||||
if(queue.size() < 3) return;
|
if(queue.size() < 3) return;
|
||||||
uint16 count; //1 - 65536
|
uint16 count; //1 - 65536
|
||||||
bit8(count,0) = queue.data(!cbit1(queue.address(1),0) ? 1 : 2);
|
count = queue.data(!(queue.address(1) & 1) ? 1 : 2) << 0;
|
||||||
bit8(count,1) = queue.data(!cbit1(queue.address(1),0) ? 2 : 1);
|
count |= queue.data(!(queue.address(1) & 1) ? 2 : 1) << 8;
|
||||||
uint address = queue.address(2);
|
uint address = queue.address(2);
|
||||||
do {
|
do {
|
||||||
block(address >> block.bitCount()).write(address, page.read(address));
|
block(address >> block.bitCount()).write(address, page.read(address));
|
||||||
|
@ -315,13 +315,13 @@ auto BSMemory::write(uint address, uint8 data) -> void {
|
||||||
page.write(0x07, 0x00); //unknown constant
|
page.write(0x07, 0x00); //unknown constant
|
||||||
for(uint6 id : range(block.count())) {
|
for(uint6 id : range(block.count())) {
|
||||||
uint8 address;
|
uint8 address;
|
||||||
address += bits(id,0-1) * 0x08; //verified for LH28F800SUT-ZI
|
address += (id >> 0 & 3) * 0x08; //verified for LH28F800SUT-ZI
|
||||||
address += bits(id,2-3) * 0x40; //verified for LH28F800SUT-ZI
|
address += (id >> 2 & 3) * 0x40; //verified for LH28F800SUT-ZI
|
||||||
address += bit1(id, 4) * 0x20; //guessed for LH28F016SU
|
address += (id >> 4 & 1) * 0x20; //guessed for LH28F016SU
|
||||||
address += bit1(id, 5) * 0x04; //guessed for LH28F032SU; will overwrite unknown constants
|
address += (id >> 5 & 1) * 0x04; //guessed for LH28F032SU; will overwrite unknown constants
|
||||||
uint32 erased = 1 << 31 | block(id).erased; //unknown if d31 is set when erased == 0
|
uint32 erased = 1 << 31 | block(id).erased; //unknown if d31 is set when erased == 0
|
||||||
for(uint2 byte : range(4)) {
|
for(uint2 byte : range(4)) {
|
||||||
page.write(address + byte, bit8(erased,byte)); //little endian
|
page.write(address + byte, erased >> byte * 8); //little endian
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
page.swap();
|
page.swap();
|
||||||
|
@ -350,12 +350,12 @@ auto BSMemory::write(uint address, uint8 data) -> void {
|
||||||
if(queue.data(0) == 0xe0) {
|
if(queue.data(0) == 0xe0) {
|
||||||
if(queue.size() < 4) return; //command length = 3 + count
|
if(queue.size() < 4) return; //command length = 3 + count
|
||||||
uint16 count; //1 - 65536
|
uint16 count; //1 - 65536
|
||||||
bit8(count,0) = queue.data(1); //endian order not affected by queue.address(1).bit(0)
|
count = queue.data(1) << 0; //endian order not affected by queue.address(1).bit(0)
|
||||||
bit8(count,1) = queue.data(2);
|
count |= queue.data(2) << 8;
|
||||||
page.write(queue.address(3), queue.data(3));
|
page.write(queue.address(3), queue.data(3));
|
||||||
if(count--) {
|
if(count--) {
|
||||||
queue.history[1].data = bit8(count,0);
|
queue.history[1].data = count >> 0;
|
||||||
queue.history[2].data = bit8(count,1);
|
queue.history[2].data = count >> 8;
|
||||||
return queue.pop(); //hack to avoid needing a 65539-entry queue
|
return queue.pop(); //hack to avoid needing a 65539-entry queue
|
||||||
} else {
|
} else {
|
||||||
return queue.flush();
|
return queue.flush();
|
||||||
|
@ -374,11 +374,11 @@ auto BSMemory::write(uint address, uint8 data) -> void {
|
||||||
if(queue.data(0) == 0xfb) {
|
if(queue.data(0) == 0xfb) {
|
||||||
if(queue.size() < 3) return;
|
if(queue.size() < 3) return;
|
||||||
uint16 value;
|
uint16 value;
|
||||||
bit8(value,0) = queue.data(!cbit1(queue.address(1),0) ? 1 : 2);
|
value = queue.data(!(queue.address(1) & 1) ? 1 : 2) << 0;
|
||||||
bit8(value,1) = queue.data(!cbit1(queue.address(1),0) ? 2 : 1);
|
value |= queue.data(!(queue.address(1) & 1) ? 2 : 1) << 8;
|
||||||
//writes are always word-aligned: a0 toggles, rather than increments
|
//writes are always word-aligned: a0 toggles, rather than increments
|
||||||
block(queue.address(2) >> block.bitCount()).write(queue.address(2) ^ 0, bit8(value,0));
|
block(queue.address(2) >> block.bitCount()).write(queue.address(2) ^ 0, value >> 0);
|
||||||
block(queue.address(2) >> block.bitCount()).write(queue.address(2) ^ 1, bit8(value,1));
|
block(queue.address(2) >> block.bitCount()).write(queue.address(2) ^ 1, value >> 8);
|
||||||
mode = Mode::CompatibleStatus;
|
mode = Mode::CompatibleStatus;
|
||||||
return queue.flush();
|
return queue.flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,12 +81,12 @@ auto SMP::writeIO(uint16 address, uint8 data) -> void {
|
||||||
case 0xf0: //TEST
|
case 0xf0: //TEST
|
||||||
if(r.p.p) break; //writes only valid when P flag is clear
|
if(r.p.p) break; //writes only valid when P flag is clear
|
||||||
|
|
||||||
io.timersDisable = bit1(data,0);
|
io.timersDisable = data >> 0 & 1;
|
||||||
io.ramWritable = bit1(data,1);
|
io.ramWritable = data >> 1 & 1;
|
||||||
io.ramDisable = bit1(data,2);
|
io.ramDisable = data >> 2 & 1;
|
||||||
io.timersEnable = bit1(data,3);
|
io.timersEnable = data >> 3 & 1;
|
||||||
io.externalWaitStates = bits(data,4-5);
|
io.externalWaitStates = data >> 4 & 3;
|
||||||
io.internalWaitStates = bits(data,6-7);
|
io.internalWaitStates = data >> 6 & 3;
|
||||||
|
|
||||||
timer0.synchronizeStage1();
|
timer0.synchronizeStage1();
|
||||||
timer1.synchronizeStage1();
|
timer1.synchronizeStage1();
|
||||||
|
@ -95,34 +95,34 @@ auto SMP::writeIO(uint16 address, uint8 data) -> void {
|
||||||
|
|
||||||
case 0xf1: //CONTROL
|
case 0xf1: //CONTROL
|
||||||
//0->1 transistion resets timers
|
//0->1 transistion resets timers
|
||||||
if(timer0.enable.raise(bit1(data,0))) {
|
if(timer0.enable.raise(data & 0x01)) {
|
||||||
timer0.stage2 = 0;
|
timer0.stage2 = 0;
|
||||||
timer0.stage3 = 0;
|
timer0.stage3 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(timer1.enable.raise(bit1(data,1))) {
|
if(timer1.enable.raise(data & 0x02)) {
|
||||||
timer1.stage2 = 0;
|
timer1.stage2 = 0;
|
||||||
timer1.stage3 = 0;
|
timer1.stage3 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!timer2.enable.raise(bit1(data,2))) {
|
if(!timer2.enable.raise(data & 0x04)) {
|
||||||
timer2.stage2 = 0;
|
timer2.stage2 = 0;
|
||||||
timer2.stage3 = 0;
|
timer2.stage3 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bit1(data,4)) {
|
if(data & 0x10) {
|
||||||
synchronizeCPU();
|
synchronizeCPU();
|
||||||
io.apu0 = 0x00;
|
io.apu0 = 0x00;
|
||||||
io.apu1 = 0x00;
|
io.apu1 = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bit1(data,5)) {
|
if(data & 0x20) {
|
||||||
synchronizeCPU();
|
synchronizeCPU();
|
||||||
io.apu2 = 0x00;
|
io.apu2 = 0x00;
|
||||||
io.apu3 = 0x00;
|
io.apu3 = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
io.iplromEnable = bit1(data,7);
|
io.iplromEnable = bool(data & 0x80);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xf2: //DSPADDR
|
case 0xf2: //DSPADDR
|
||||||
|
|
Loading…
Reference in New Issue