* removed emulator/bits.hpp dependency
This commit is contained in:
byuu 2019-08-06 13:45:04 +09:00
parent 5757949023
commit 96c381f91f
34 changed files with 517 additions and 585 deletions

View File

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

View File

@ -23,7 +23,6 @@ using namespace nall;
#include <libco/libco.h>
#include <emulator/bits.hpp>
#include <emulator/types.hpp>
#include <emulator/memory/readable.hpp>
#include <emulator/memory/writable.hpp>
@ -31,7 +30,7 @@ using namespace nall;
namespace Emulator {
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 License = "GPLv3";
static const string Website = "https://byuu.org";

View File

@ -65,10 +65,10 @@ struct Random {
if((random() & 1) == 0) hivalue = ~lovalue;
for(uint32 address : range(size)) {
uint8 value = bit1(address,lobit) ? lovalue : hivalue;
if(bit1(address,hibit)) value = ~value;
if((random() & 511) == 0) bit1(value,random() & 7) ^= 1;
if((random() & 2047) == 0) bit1(value,random() & 7) ^= 1;
uint8 value = (address & 1ull << lobit) ? lovalue : hivalue;
if((address & 1ull << hibit)) value = ~value;
if((random() & 511) == 0) value ^= 1 << (random() & 7);
if((random() & 2047) == 0) value ^= 1 << (random() & 7);
data[address] = value;
}
}

View File

@ -1,11 +1,11 @@
auto ARM7TDMI::ADD(uint32 source, uint32 modify, bool carry) -> uint32 {
uint32 result = source + modify + carry;
if(cpsr().t || bit1(opcode,20)) {
if(cpsr().t || (opcode & 1 << 20)) {
uint32 overflow = ~(source ^ modify) & (source ^ result);
cpsr().v = 1 << 31 & (overflow);
cpsr().c = 1 << 31 & (overflow ^ source ^ modify ^ result);
cpsr().z = result == 0;
cpsr().n = bit1(result,31);
cpsr().n = result >> 31;
}
return result;
}
@ -19,10 +19,10 @@ auto ARM7TDMI::ASR(uint32 source, uint8 shift) -> uint32 {
}
auto ARM7TDMI::BIT(uint32 result) -> uint32 {
if(cpsr().t || bit1(opcode,20)) {
if(cpsr().t || (opcode & 1 << 20)) {
cpsr().c = carry;
cpsr().z = result == 0;
cpsr().n = bit1(result,31);
cpsr().n = result >> 31;
}
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 >> 24 && multiplier >> 24 != 0xff) idle();
product += multiplicand * multiplier;
if(cpsr().t || bit1(opcode,20)) {
if(cpsr().t || (opcode & 1 << 20)) {
cpsr().z = product == 0;
cpsr().n = bit1(product,31);
cpsr().n = product >> 31;
}
return product;
}

View File

@ -148,14 +148,14 @@ struct ARM7TDMI {
}
inline auto operator=(uint32 data) -> PSR& {
m = bits(data,0-4);
t = bit1(data,5);
f = bit1(data,6);
i = bit1(data,7);
v = bit1(data,28);
c = bit1(data,29);
z = bit1(data,30);
n = bit1(data,31);
m = data >> 0 & 31;
t = data >> 5 & 1;
f = data >> 6 & 1;
i = data >> 7 & 1;
v = data >> 28 & 1;
c = data >> 29 & 1;
z = data >> 30 & 1;
n = data >> 31 & 1;
return *this;
}

View File

@ -186,7 +186,7 @@ auto ARM7TDMI::armDisassembleMoveMultiple
(uint16 list, uint4 n, uint1 mode, uint1 writeback, uint1 type, uint1 up, uint1 pre) -> string {
string registers;
for(auto index : range(16)) {
if(bit1(list,index)) registers.append(_r[index], ",");
if((list & 1 << index)) registers.append(_r[index], ",");
}
registers.trimRight(",", 1L);
return {mode ? "ldm" : "stm", _c,
@ -358,7 +358,7 @@ auto ARM7TDMI::thumbDisassembleMoveMultiple
(uint8 list, uint3 n, uint1 mode) -> string {
string registers;
for(uint m : range(8)) {
if(bit1(list,m)) registers.append(_r[m], ",");
if((list & 1 << m)) registers.append(_r[m], ",");
}
registers.trimRight(",", 1L);
return {mode ? "ldmia" : "stmia", " ", _r[n], "!,{", registers, "}"};
@ -395,7 +395,7 @@ auto ARM7TDMI::thumbDisassembleStackMultiple
(uint8 list, uint1 lrpc, uint1 mode) -> string {
string registers;
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,");
registers.trimRight(",", 1L);

View File

@ -68,8 +68,11 @@ auto ARM7TDMI::armInitialize() -> void {
#define pattern(s) \
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 \
bits(opcode, 0-23), /* displacement */ \
bits(opcode, 0,23), /* displacement */ \
bit1(opcode,24) /* link */
for(uint4 displacementLo : range(16))
for(uint4 displacementHi : range(16))
@ -81,7 +84,7 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3) /* m */
bits(opcode, 0, 3) /* m */
{
auto opcode = pattern(".... 0001 0010 ---- ---- ---- 0001 ????");
bind(opcode, BranchExchangeRegister);
@ -89,12 +92,12 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 7), /* immediate */ \
bits(opcode, 8-11), /* shift */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode, 0, 7), /* immediate */ \
bits(opcode, 8,11), /* shift */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,20), /* save */ \
bits(opcode,21-24) /* mode */
bits(opcode,21,24) /* mode */
for(uint4 shiftHi : range(16))
for(uint1 save : range(2))
for(uint4 mode : range(16)) {
@ -105,13 +108,13 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3), /* m */ \
bits(opcode, 5- 6), /* type */ \
bits(opcode, 7-11), /* shift */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode, 0, 3), /* m */ \
bits(opcode, 5, 6), /* type */ \
bits(opcode, 7,11), /* shift */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,20), /* save */ \
bits(opcode,21-24) /* mode */
bits(opcode,21,24) /* mode */
for(uint2 type : range(4))
for(uint1 shiftLo : range(2))
for(uint1 save : range(2))
@ -123,13 +126,13 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3), /* m */ \
bits(opcode, 5- 6), /* type */ \
bits(opcode, 8-11), /* s */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode, 0, 3), /* m */ \
bits(opcode, 5, 6), /* type */ \
bits(opcode, 8,11), /* s */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,20), /* save */ \
bits(opcode,21-24) /* mode */
bits(opcode,21,24) /* mode */
for(uint2 type : range(4))
for(uint1 save : range(2))
for(uint4 mode : range(16)) {
@ -140,10 +143,10 @@ auto ARM7TDMI::armInitialize() -> void {
#undef 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 */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,21), /* writeback */ \
bit1(opcode,23), /* up */ \
bit1(opcode,24) /* pre */
@ -157,10 +160,10 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3), /* m */ \
bits(opcode, 0, 3), /* m */ \
bit1(opcode, 5), /* half */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,21), /* writeback */ \
bit1(opcode,23), /* up */ \
bit1(opcode,24) /* pre */
@ -174,9 +177,9 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3), /* m */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode, 0, 3), /* m */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,22) /* byte */
for(uint1 byte : range(2)) {
auto opcode = pattern(".... 0001 0?00 ???? ???? ---- 1001 ????") | byte << 22;
@ -185,9 +188,9 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3) << 0 | bits(opcode, 8-11) << 4, /* immediate */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode, 0, 3) << 0 | bits(opcode, 8,11) << 4, /* immediate */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,20), /* mode */ \
bit1(opcode,21), /* writeback */ \
bit1(opcode,23), /* up */ \
@ -202,9 +205,9 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3), /* m */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode, 0, 3), /* m */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,20), /* mode */ \
bit1(opcode,21), /* writeback */ \
bit1(opcode,23), /* up */ \
@ -219,9 +222,9 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0-11), /* immediate */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode, 0,11), /* immediate */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,20), /* mode */ \
bit1(opcode,21), /* writeback */ \
bit1(opcode,22), /* byte */ \
@ -240,8 +243,8 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0-15), /* list */ \
bits(opcode,16-19), /* n */ \
bits(opcode, 0,15), /* list */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,20), /* mode */ \
bit1(opcode,21), /* writeback */ \
bit1(opcode,22), /* type */ \
@ -260,11 +263,11 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3), /* m */ \
bits(opcode, 5- 6), /* type */ \
bits(opcode, 7-11), /* shift */ \
bits(opcode,12-15), /* d */ \
bits(opcode,16-19), /* n */ \
bits(opcode, 0, 3), /* m */ \
bits(opcode, 5, 6), /* type */ \
bits(opcode, 7,11), /* shift */ \
bits(opcode,12,15), /* d */ \
bits(opcode,16,19), /* n */ \
bit1(opcode,20), /* mode */ \
bit1(opcode,21), /* writeback */ \
bit1(opcode,22), /* byte */ \
@ -284,7 +287,7 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode,12-15), /* d */ \
bits(opcode,12,15), /* d */ \
bit1(opcode,22) /* mode */
for(uint1 mode : range(2)) {
auto opcode = pattern(".... 0001 0?00 ---- ???? ---- 0000 ----") | mode << 22;
@ -293,9 +296,9 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 7), /* immediate */ \
bits(opcode, 8-11), /* rotate */ \
bits(opcode,16-19), /* field */ \
bits(opcode, 0, 7), /* immediate */ \
bits(opcode, 8,11), /* rotate */ \
bits(opcode,16,19), /* field */ \
bit1(opcode,22) /* mode */
for(uint4 immediateHi : range(16))
for(uint1 mode : range(2)) {
@ -305,8 +308,8 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3), /* m */ \
bits(opcode,16-19), /* field */ \
bits(opcode, 0, 3), /* m */ \
bits(opcode,16,19), /* field */ \
bit1(opcode,22) /* mode */
for(uint1 mode : range(2)) {
auto opcode = pattern(".... 0001 0?10 ???? ---- ---- 0000 ????") | mode << 22;
@ -315,10 +318,10 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3), /* m */ \
bits(opcode, 8-11), /* s */ \
bits(opcode,12-15), /* n */ \
bits(opcode,16-19), /* d */ \
bits(opcode, 0, 3), /* m */ \
bits(opcode, 8,11), /* s */ \
bits(opcode,12,15), /* n */ \
bits(opcode,16,19), /* d */ \
bit1(opcode,20), /* save */ \
bit1(opcode,21) /* accumulate */
for(uint1 save : range(2))
@ -329,10 +332,10 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0- 3), /* m */ \
bits(opcode, 8-11), /* s */ \
bits(opcode,12-15), /* l */ \
bits(opcode,16-19), /* h */ \
bits(opcode, 0, 3), /* m */ \
bits(opcode, 8,11), /* s */ \
bits(opcode,12,15), /* l */ \
bits(opcode,16,19), /* h */ \
bit1(opcode,20), /* save */ \
bit1(opcode,21), /* accumulate */ \
bit1(opcode,22) /* sign */
@ -345,7 +348,7 @@ auto ARM7TDMI::armInitialize() -> void {
#undef arguments
#define arguments \
bits(opcode, 0-23) /* immediate */
bits(opcode, 0,23) /* immediate */
for(uint4 immediateLo : range(16))
for(uint4 immediateHi : range(16)) {
auto opcode = pattern(".... 1111 ???? ???? ???? ???? ???? ????") | immediateLo << 4 | immediateHi << 20;
@ -356,7 +359,7 @@ auto ARM7TDMI::armInitialize() -> void {
#define arguments
for(uint12 id : range(4096)) {
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);
}
#undef arguments
@ -386,7 +389,7 @@ auto ARM7TDMI::thumbInitialize() -> void {
for(uint4 m : range(16))
for(uint2 mode : range(4)) {
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);
}
@ -533,6 +536,9 @@ auto ARM7TDMI::thumbInitialize() -> void {
bind(opcode, Undefined);
}
#undef bit1
#undef bits
#undef bind
#undef pattern
}

View File

@ -20,7 +20,7 @@ auto ARM7TDMI::armALU(uint4 mode, uint4 d, uint4 n, uint32 rm) -> void {
case 15: r(d) = BIT(~rm); break; //MVN
}
if(exception() && d == 15 && bit1(opcode,20)) {
if(exception() && d == 15 && (opcode & 1 << 20)) {
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;
PSR& psr = mode ? spsr() : cpsr();
if(field.bit(0)) {
if(field & 1) {
if(mode || privileged()) {
psr.m = bits(data,0-4);
psr.t = bit1(data,5);
psr.f = bit1(data,6);
psr.i = bit1(data,7);
psr.m = data >> 0 & 31;
psr.t = data >> 5 & 1;
psr.f = data >> 6 & 1;
psr.i = data >> 7 & 1;
if(!mode && psr.t) r(15).data += 2;
}
}
if(field.bit(3)) {
psr.v = bit1(data,28);
psr.c = bit1(data,29);
psr.z = bit1(data,30);
psr.n = bit1(data,31);
if(field & 8) {
psr.v = data >> 28 & 1;
psr.c = data >> 29 & 1;
psr.z = data >> 30 & 1;
psr.n = data >> 31 & 1;
}
}
@ -193,13 +193,13 @@ auto ARM7TDMI::armInstructionMoveMultiple
auto cpsrMode = cpsr().m;
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(usr) cpsr().m = PSR::USR;
uint sequential = Nonsequential;
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 == 0) write(Word | sequential, rn, r(m));
rn += 4;
@ -210,7 +210,7 @@ auto ARM7TDMI::armInstructionMoveMultiple
if(mode) {
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();
}
} else {
@ -299,7 +299,7 @@ auto ARM7TDMI::armInstructionMultiplyLong
if(save) {
cpsr().z = rd == 0;
cpsr().n = bit1(rd,63);
cpsr().n = rd >> 63 & 1;
}
}

View File

@ -127,7 +127,7 @@ auto ARM7TDMI::thumbInstructionMoveMultiple
uint32 rn = r(n);
for(uint m : range(8)) {
if(!bit1(list,m)) continue;
if(!(list & 1 << m)) continue;
switch(mode) {
case 0: write(Word | Nonsequential, rn, r(m)); break; //STMIA
case 1: r(m) = read(Word | Nonsequential, rn); break; //LDMIA
@ -135,7 +135,7 @@ auto ARM7TDMI::thumbInstructionMoveMultiple
rn += 4;
}
if(mode == 0 || !bit1(list,n)) r(n) = rn;
if(mode == 0 || !(list & 1 << n)) r(n) = rn;
if(mode == 1) idle();
}
@ -193,7 +193,7 @@ auto ARM7TDMI::thumbInstructionStackMultiple
uint sequential = Nonsequential;
for(uint m : range(8)) {
if(!bit1(list,m)) continue;
if(!(list & 1 << m)) continue;
switch(mode) {
case 0: write(Word | sequential, sp, r(m)); break; //PUSH
case 1: r(m) = read(Word | sequential, sp); break; //POP

View File

@ -84,8 +84,8 @@ auto HG51B::cache() -> bool {
io.cache.address[io.cache.page] = address;
for(uint offset : range(256)) {
step(wait(address)); bit8(programRAM[io.cache.page][offset],0) = read(address++);
step(wait(address)); bit8(programRAM[io.cache.page][offset],1) = read(address++);
step(wait(address)); programRAM[io.cache.page][offset] = read(address++) << 0;
step(wait(address)); programRAM[io.cache.page][offset] |= read(address++) << 8;
}
return io.cache.enable = 0, true;
}

View File

@ -203,11 +203,11 @@ auto HG51B::instructionLD(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 {
bits(out,8-14) = imm;
out = out & 0x00ff | (imm & 0x7f) << 8;
}
auto HG51B::instructionMUL(uint7 reg) -> void {

View File

@ -1,7 +1,7 @@
auto HG51B::readRegister(uint7 address) -> uint24 {
switch(address) {
case 0x01: return bits(r.mul,24-47);
case 0x02: return bits(r.mul, 0-23);
case 0x01: return r.mul >> 24 & 0xffffff;
case 0x02: return r.mul >> 0 & 0xffffff;
case 0x03: return r.mdr;
case 0x08: return r.rom;
case 0x0c: return r.ram;
@ -64,8 +64,8 @@ auto HG51B::readRegister(uint7 address) -> uint24 {
auto HG51B::writeRegister(uint7 address, uint24 data) -> void {
switch(address) {
case 0x01: bits(r.mul,24-47) = data; return;
case 0x02: bits(r.mul, 0-23) = data; return;
case 0x01: r.mul = r.mul & ~0xffffffull | data << 0; return;
case 0x02: r.mul = r.mul & 0xffffffull | data << 24; return;
case 0x03: r.mdr = data; return;
case 0x08: r.rom = data; return;
case 0x0c: r.ram = data; return;

View File

@ -7,32 +7,33 @@ auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void {
switch(mode) {
case 0: //or addr:bit
idle();
CF |= bit1(data,bit);
CF |= bool(data & 1 << bit);
break;
case 1: //or !addr:bit
idle();
CF |= !bit1(data,bit);
CF |= !bool(data & 1 << bit);
break;
case 2: //and addr:bit
CF &= bit1(data,bit);
CF &= bool(data & 1 << bit);
break;
case 3: //and !addr:bit
CF &= !bit1(data,bit);
CF &= !bool(data & 1 << bit);
break;
case 4: //eor addr:bit
idle();
CF ^= bit1(data,bit);
CF ^= bool(data & 1 << bit);
break;
case 5: //ld addr:bit
CF = bit1(data,bit);
CF = bool(data & 1 << bit);
break;
case 6: //st addr:bit
idle();
bit1(data,bit) = CF;
data &= ~(1 << bit);
data |= CF << bit;
write(address, data);
break;
case 7: //not addr:bit
bit1(data,bit) ^= 1;
data ^= 1 << bit;
write(address, data);
break;
}
@ -41,7 +42,8 @@ auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void {
auto SPC700::instructionAbsoluteBitSet(uint3 bit, bool value) -> void {
uint8 address = fetch();
uint8 data = load(address);
bit1(data,bit) = value;
data &= ~(1 << bit);
data |= value << bit;
store(address, data);
}
@ -95,7 +97,7 @@ auto SPC700::instructionBranchBit(uint3 bit, bool match) -> void {
uint8 data = load(address);
idle();
uint8 displacement = fetch();
if(bit1(data,bit) != match) return;
if(bool(data & 1 << bit) != match) return;
idle();
idle();
PC += (int8)displacement;

View File

@ -134,14 +134,14 @@ struct SPC700 {
}
inline auto& operator=(uint8 data) {
c = bit1(data,0);
z = bit1(data,1);
i = bit1(data,2);
h = bit1(data,3);
b = bit1(data,4);
p = bit1(data,5);
v = bit1(data,6);
n = bit1(data,7);
c = data & 0x01;
z = data & 0x02;
i = data & 0x04;
h = data & 0x08;
b = data & 0x10;
p = data & 0x20;
v = data & 0x40;
n = data & 0x80;
return *this;
}
};

View File

@ -37,12 +37,12 @@ struct uPD96050 {
}
inline auto operator=(uint16 data) -> Flag& {
ov0 = bit1(data,0);
ov1 = bit1(data,1);
z = bit1(data,2);
c = bit1(data,3);
s0 = bit1(data,4);
s1 = bit1(data,5);
ov0 = data >> 0 & 1;
ov1 = data >> 1 & 1;
z = data >> 2 & 1;
c = data >> 3 & 1;
s0 = data >> 4 & 1;
s1 = data >> 5 & 1;
return *this;
}
@ -64,17 +64,17 @@ struct uPD96050 {
}
inline auto operator=(uint16 data) -> Status& {
p0 = bit1(data, 0);
p1 = bit1(data, 1);
ei = bit1(data, 7);
sic = bit1(data, 8);
soc = bit1(data, 9);
drc = bit1(data,10);
dma = bit1(data,11);
drs = bit1(data,12);
usf0 = bit1(data,13);
usf1 = bit1(data,14);
rqm = bit1(data,15);
p0 = data >> 0 & 1;
p1 = data >> 1 & 1;
ei = data >> 7 & 1;
sic = data >> 8 & 1;
soc = data >> 9 & 1;
drc = data >> 10 & 1;
dma = data >> 11 & 1;
drs = data >> 12 & 1;
usf0 = data >> 13 & 1;
usf1 = data >> 14 & 1;
rqm = data >> 15 & 1;
return *this;
}

View File

@ -83,9 +83,9 @@ auto ArmDSP::set(uint mode, uint32 addr, uint32 word) -> void {
if(addr == 0x4000'0010) bridge.signal = true;
if(addr == 0x4000'0020) bit8(bridge.timerlatch,0) = word;
if(addr == 0x4000'0024) bit8(bridge.timerlatch,1) = word;
if(addr == 0x4000'0028) bit8(bridge.timerlatch,2) = word;
if(addr == 0x4000'0020) bridge.timerlatch = bridge.timerlatch & 0xffff00 | word << 0;
if(addr == 0x4000'0024) bridge.timerlatch = bridge.timerlatch & 0xff00ff | word << 8;
if(addr == 0x4000'0028) bridge.timerlatch = bridge.timerlatch & 0x00ffff | word << 16;
if(addr == 0x4000'002c) bridge.timer = bridge.timerlatch;
}

View File

@ -48,7 +48,7 @@ auto Event::power() -> void {
create(Event::Enter, 1);
//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 6-7 are not connected

View File

@ -134,21 +134,21 @@ auto HitachiDSP::readIO(uint address, uint8 data) -> uint8 {
//IO
switch(address) {
case 0x7f40: return bit8(io.dma.source,0);
case 0x7f41: return bit8(io.dma.source,1);
case 0x7f42: return bit8(io.dma.source,2);
case 0x7f43: return bit8(io.dma.length,0);
case 0x7f44: return bit8(io.dma.length,1);
case 0x7f45: return bit8(io.dma.target,0);
case 0x7f46: return bit8(io.dma.target,1);
case 0x7f47: return bit8(io.dma.target,2);
case 0x7f40: return io.dma.source >> 0;
case 0x7f41: return io.dma.source >> 8;
case 0x7f42: return io.dma.source >> 16;
case 0x7f43: return io.dma.length >> 0;
case 0x7f44: return io.dma.length >> 8;
case 0x7f45: return io.dma.target >> 0;
case 0x7f46: return io.dma.target >> 8;
case 0x7f47: return io.dma.target >> 16;
case 0x7f48: return io.cache.page;
case 0x7f49: return bit8(io.cache.base,0);
case 0x7f4a: return bit8(io.cache.base,1);
case 0x7f4b: return bit8(io.cache.base,2);
case 0x7f49: return io.cache.base >> 0;
case 0x7f4a: return io.cache.base >> 8;
case 0x7f4b: return io.cache.base >> 16;
case 0x7f4c: return io.cache.lock[0] << 0 | io.cache.lock[1] << 1;
case 0x7f4d: return bit8(io.cache.pb,0);
case 0x7f4e: return bit8(io.cache.pb,1);
case 0x7f4d: return io.cache.pb >> 0;
case 0x7f4e: return io.cache.pb >> 8;
case 0x7f4f: return io.cache.pc;
case 0x7f50: return io.wait.ram << 0 | io.wait.rom << 4;
case 0x7f51: return io.irq;
@ -166,7 +166,11 @@ auto HitachiDSP::readIO(uint address, uint8 data) -> uint8 {
//registers
if((address >= 0x7f80 && address <= 0x7faf) || (address >= 0x7fc0 && address <= 0x7fef)) {
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;
@ -177,16 +181,16 @@ auto HitachiDSP::writeIO(uint address, uint8 data) -> void {
//IO
switch(address) {
case 0x7f40: bit8(io.dma.source,0) = data; return;
case 0x7f41: bit8(io.dma.source,1) = data; return;
case 0x7f42: bit8(io.dma.source,2) = data; return;
case 0x7f40: io.dma.source = io.dma.source & 0xffff00 | data << 0; return;
case 0x7f41: io.dma.source = io.dma.source & 0xff00ff | data << 8; return;
case 0x7f42: io.dma.source = io.dma.source & 0x00ffff | data << 16; return;
case 0x7f43: bit8(io.dma.length,0) = data; return;
case 0x7f44: bit8(io.dma.length,1) = data; return;
case 0x7f43: io.dma.length = io.dma.length & 0xff00 | data << 0; return;
case 0x7f44: io.dma.length = io.dma.length & 0x00ff | data << 8; return;
case 0x7f45: bit8(io.dma.target,0) = data; return;
case 0x7f46: bit8(io.dma.target,1) = data; return;
case 0x7f47: bit8(io.dma.target,2) = data;
case 0x7f45: io.dma.target = io.dma.target & 0xffff00 | data << 0; return;
case 0x7f46: io.dma.target = io.dma.target & 0xff00ff | data << 8; return;
case 0x7f47: io.dma.target = io.dma.target & 0x00ffff | data << 16;
if(io.halt) io.dma.enable = 1;
return;
@ -195,17 +199,17 @@ auto HitachiDSP::writeIO(uint address, uint8 data) -> void {
if(io.halt) io.cache.enable = 1;
return;
case 0x7f49: bit8(io.cache.base,0) = data; return;
case 0x7f4a: bit8(io.cache.base,1) = data; return;
case 0x7f4b: bit8(io.cache.base,2) = data; return;
case 0x7f49: io.cache.base = io.cache.base & 0xffff00 | data << 0; return;
case 0x7f4a: io.cache.base = io.cache.base & 0xff00ff | data << 8; return;
case 0x7f4b: io.cache.base = io.cache.base & 0x00ffff | data << 16; return;
case 0x7f4c:
io.cache.lock[0] = bit1(data,0);
io.cache.lock[1] = bit1(data,1);
io.cache.lock[0] = bool(data & 1);
io.cache.lock[1] = bool(data & 2);
return;
case 0x7f4d: bit8(io.cache.pb,0) = data; return;
case 0x7f4e: bit8(io.cache.pb,1) = data; return;
case 0x7f4d: io.cache.pb = io.cache.pb & 0xff00 | data << 0; return;
case 0x7f4e: io.cache.pb = io.cache.pb & 0x00ff | data << 8; return;
case 0x7f4f:
io.cache.pc = data;
@ -217,8 +221,8 @@ auto HitachiDSP::writeIO(uint address, uint8 data) -> void {
return;
case 0x7f50:
io.wait.ram = bits(data,0-2);
io.wait.rom = bits(data,4-6);
io.wait.ram = data >> 0 & 7;
io.wait.rom = data >> 4 & 7;
return;
case 0x7f51:
@ -259,6 +263,11 @@ auto HitachiDSP::writeIO(uint address, uint8 data) -> void {
//registers
if((address >= 0x7f80 && address <= 0x7faf) || (address >= 0x7fc0 && address <= 0x7fef)) {
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;
}
}

View File

@ -46,8 +46,8 @@ auto ICD::joypWrite(bool p14, bool p15) -> void {
uint4 input = 0xf;
if(p14 == 1 && p15 == 1) input = 0xf - joypID;
if(p14 == 0) input &= bits(joypad,0-3); //d-pad
if(p15 == 0) input &= bits(joypad,4-7); //buttons
if(p14 == 0) input &= (joypad >> 0 & 15); //d-pad
if(p15 == 0) input &= (joypad >> 4 & 15); //buttons
GB_icd_set_joyp(&sameboy, input);

View File

@ -40,8 +40,8 @@ auto MCC::read(uint address, uint8 data) -> uint8 {
case 2: return r.mapping << 7;
case 3: return r.psramEnableLo << 7;
case 4: return r.psramEnableHi << 7;
case 5: return r.psramMapping.bit(0) << 7;
case 6: return r.psramMapping.bit(1) << 7;
case 5: return (r.psramMapping >> 0 & 1) << 7;
case 6: return (r.psramMapping >> 1 & 1) << 7;
case 7: return r.romEnableLo << 7;
case 8: return r.romEnableHi << 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 {
if((address & 0xf0f000) == 0x005000) { //$00-0f:5000-5fff
switch(address >> 16 & 15) {
case 1: irq.enable = bit1(data,7); break;
case 2: w.mapping = bit1(data,7); break;
case 3: w.psramEnableLo = bit1(data,7); break;
case 4: w.psramEnableHi = bit1(data,7); break;
case 5: bit1(w.psramMapping,0) = bit1(data,7); break;
case 6: bit1(w.psramMapping,1) = bit1(data,7); break;
case 7: w.romEnableLo = bit1(data,7); break;
case 8: w.romEnableHi = bit1(data,7); break;
case 9: w.exEnableLo = bit1(data,7); break;
case 10: w.exEnableHi = bit1(data,7); break;
case 11: w.exMapping = bit1(data,7); break;
case 12: w.internallyWritable = bit1(data,7); break;
case 13: w.externallyWritable = bit1(data,7); break;
case 14: if(bit1(data,7)) commit(); break;
case 1: irq.enable = data >> 7; break;
case 2: w.mapping = data >> 7; break;
case 3: w.psramEnableLo = data >> 7; break;
case 4: w.psramEnableHi = data >> 7; break;
case 5: w.psramMapping = w.psramMapping & 2 | data >> 7 << 0; break;
case 6: w.psramMapping = w.psramMapping & 1 | data >> 7 << 1; break;
case 7: w.romEnableLo = data >> 7; break;
case 8: w.romEnableHi = data >> 7; break;
case 9: w.exEnableLo = data >> 7; break;
case 10: w.exEnableHi = data >> 7; break;
case 11: w.exMapping = data >> 7; break;
case 12: w.internallyWritable = data >> 7; break;
case 13: w.externallyWritable = data >> 7; break;
case 14: if(data >> 7) commit(); break;
}
}
}

View File

@ -109,7 +109,7 @@ auto MSU1::audioOpen() -> void {
auto MSU1::readIO(uint addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
switch(0x2000 | (addr & 7)) {
switch(0x2000 | addr & 7) {
case 0x2000:
return (
Revision << 0
@ -139,16 +139,16 @@ auto MSU1::readIO(uint addr, uint8) -> uint8 {
auto MSU1::writeIO(uint addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
switch(0x2000 | (addr & 7)) {
case 0x2000: bit8(io.dataSeekOffset,0) = data; break;
case 0x2001: bit8(io.dataSeekOffset,1) = data; break;
case 0x2002: bit8(io.dataSeekOffset,2) = data; break;
case 0x2003: bit8(io.dataSeekOffset,3) = data;
switch(0x2000 | addr & 7) {
case 0x2000: io.dataSeekOffset = io.dataSeekOffset & 0xffffff00 | data << 0; break;
case 0x2001: io.dataSeekOffset = io.dataSeekOffset & 0xffff00ff | data << 8; break;
case 0x2002: io.dataSeekOffset = io.dataSeekOffset & 0xff00ffff | data << 16; break;
case 0x2003: io.dataSeekOffset = io.dataSeekOffset & 0x00ffffff | data << 24;
io.dataReadOffset = io.dataSeekOffset;
if(dataFile) dataFile->seek(io.dataReadOffset);
break;
case 0x2004: bit8(io.audioTrack,0) = data; break;
case 0x2005: bit8(io.audioTrack,1) = data;
case 0x2004: io.audioTrack = io.audioTrack & 0xff00 | data << 0; break;
case 0x2005: io.audioTrack = io.audioTrack & 0x00ff | data << 8;
io.audioPlay = false;
io.audioRepeat = false;
io.audioPlayOffset = 8;
@ -165,9 +165,9 @@ auto MSU1::writeIO(uint addr, uint8 data) -> void {
case 0x2007:
if(io.audioBusy) break;
if(io.audioError) break;
io.audioPlay = bit1(data,0);
io.audioRepeat = bit1(data,1);
boolean audioResume = bit1(data,2);
io.audioPlay = bool(data & 1);
io.audioRepeat = bool(data & 2);
boolean audioResume = bool(data & 4);
if(!io.audioPlay && audioResume) {
io.audioResumeTrack = io.audioTrack;
io.audioResumeOffset = io.audioPlayOffset;

View File

@ -80,18 +80,18 @@ auto SA1::BWRAM::readBitmap(uint20 address, uint8 data) -> uint8 {
uint shift = address & 1;
address >>= 1;
switch(shift) {
case 0: return cbits(read(address),0-3);
case 1: return cbits(read(address),4-7);
case 0: return read(address) >> 0 & 15;
case 1: return read(address) >> 4 & 15;
}
} else {
//2bpp
uint shift = address & 3;
address >>= 2;
switch(shift) {
case 0: return cbits(read(address),0-1);
case 1: return cbits(read(address),2-3);
case 2: return cbits(read(address),4-5);
case 3: return cbits(read(address),6-7);
case 0: return read(address) >> 0 & 3;
case 1: return read(address) >> 2 & 3;
case 2: return read(address) >> 4 & 3;
case 3: return read(address) >> 6 & 3;
}
}
unreachable;

View File

@ -403,19 +403,19 @@ auto SA1::writeIOSA1(uint address, uint8 data) -> void {
//(MAL) multiplicand / dividend low
case 0x2251: {
bit8(mmio.ma,0) = data;
mmio.ma = mmio.ma & ~0x00ff | data << 0;
return;
}
//(MAH) multiplicand / dividend high
case 0x2252: {
bit8(mmio.ma,1) = data;
mmio.ma = mmio.ma & ~0xff00 | data << 8;
return;
}
//(MBL) multiplier / divisor low
case 0x2253: {
bit8(mmio.mb,0) = data;
mmio.mb = mmio.mb & ~0x00ff | data << 0;
return;
}
@ -423,7 +423,7 @@ auto SA1::writeIOSA1(uint address, uint8 data) -> void {
//multiplication / cumulative sum only resets MB
//division resets both MA and MB
case 0x2254: {
bit8(mmio.mb,1) = data;
mmio.mb = mmio.mb & ~0xff00 | data << 8;
if(mmio.acm == 0) {
if(mmio.md == 0) {

View File

@ -66,11 +66,11 @@ auto SDD1::dmaRead(uint addr, uint8 data) -> uint8 {
auto SDD1::dmaWrite(uint addr, uint8 data) -> void {
uint channel = addr >> 4 & 7;
switch(addr & 15) {
case 2: bit8(dma[channel].addr,0) = data; break;
case 3: bit8(dma[channel].addr,1) = data; break;
case 4: bit8(dma[channel].addr,2) = data; break;
case 5: bit8(dma[channel].size,0) = data; break;
case 6: bit8(dma[channel].size,1) = data; break;
case 2: dma[channel].addr = dma[channel].addr & 0xffff00 | data << 0; break;
case 3: dma[channel].addr = dma[channel].addr & 0xff00ff | data << 8; break;
case 4: dma[channel].addr = dma[channel].addr & 0x00ffff | data << 16; break;
case 5: dma[channel].size = dma[channel].size & 0xff00 | data << 0; break;
case 6: dma[channel].size = dma[channel].size & 0x00ff | data << 8; break;
}
return cpu.writeDMA(addr, data);
}
@ -100,7 +100,7 @@ auto SDD1::mcuRead(uint addr, uint8 data) -> uint8 {
if(r4800 & r4801) {
//at least one channel has S-DD1 decompression enabled ...
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
if(addr == dma[n].addr) {
if(!dmaReady) {
@ -113,7 +113,7 @@ auto SDD1::mcuRead(uint addr, uint8 data) -> uint8 {
data = decompressor.read();
if(--dma[n].size == 0) {
dmaReady = false;
bit1(r4801,n) = 0;
r4801 &= ~(1 << n);
}
return data;

View File

@ -175,6 +175,6 @@ auto CPU::Channel::hdmaTransfer() -> void {
auto CPU::Channel::hdmaAdvance() -> void {
if(!hdmaActive()) return;
lineCounter--;
hdmaDoTransfer = bit1(lineCounter,7);
hdmaDoTransfer = bool(lineCounter & 0x80);
hdmaReload();
}

View File

@ -41,21 +41,21 @@ auto CPU::readCPU(uint addr, uint8 data) -> uint8 {
data |= (vcounter() >= ppu.vdisp()) << 7; //vblank
return data;
case 0x4213: return io.pio; //RDIO
case 0x4213: return io.pio; //RDIO
case 0x4214: return bit8(io.rddiv,0); //RDDIVL
case 0x4215: return bit8(io.rddiv,1); //RDDIVH
case 0x4216: return bit8(io.rdmpy,0); //RDMPYL
case 0x4217: return bit8(io.rdmpy,1); //RDMPYH
case 0x4214: return io.rddiv >> 0; //RDDIVL
case 0x4215: return io.rddiv >> 8; //RDDIVH
case 0x4216: return io.rdmpy >> 0; //RDMPYL
case 0x4217: return io.rdmpy >> 8; //RDMPYH
case 0x4218: return bit8(io.joy1,0); //JOY1L
case 0x4219: return bit8(io.joy1,1); //JOY1H
case 0x421a: return bit8(io.joy2,0); //JOY2L
case 0x421b: return bit8(io.joy2,1); //JOY2H
case 0x421c: return bit8(io.joy3,0); //JOY3L
case 0x421d: return bit8(io.joy3,1); //JOY3H
case 0x421e: return bit8(io.joy4,0); //JOY4L
case 0x421f: return bit8(io.joy4,1); //JOY4H
case 0x4218: return io.joy1 >> 0; //JOY1L
case 0x4219: return io.joy1 >> 8; //JOY1H
case 0x421a: return io.joy2 >> 0; //JOY2L
case 0x421b: return io.joy2 >> 8; //JOY2H
case 0x421c: return io.joy3 >> 0; //JOY3L
case 0x421d: return io.joy3 >> 8; //JOY3H
case 0x421e: return io.joy4 >> 0; //JOY4L
case 0x421f: return io.joy4 >> 8; //JOY4H
}
@ -77,18 +77,18 @@ auto CPU::readDMA(uint addr, uint8 data) -> uint8 {
| channel.direction << 7
);
case 0x4301: return channel.targetAddress; //BBADx
case 0x4302: return bit8(channel.sourceAddress,0); //A1TxL
case 0x4303: return bit8(channel.sourceAddress,1); //A1TxH
case 0x4304: return channel.sourceBank; //A1Bx
case 0x4305: return bit8(channel.transferSize,0); //DASxL
case 0x4306: return bit8(channel.transferSize,1); //DASxH
case 0x4307: return channel.indirectBank; //DASBx
case 0x4308: return bit8(channel.hdmaAddress,0); //A2AxL
case 0x4309: return bit8(channel.hdmaAddress,1); //A2AxH
case 0x430a: return channel.lineCounter; //NTRLx
case 0x430b: return channel.unknown; //???x
case 0x430f: return channel.unknown; //???x ($43xb mirror)
case 0x4301: return channel.targetAddress; //BBADx
case 0x4302: return channel.sourceAddress >> 0; //A1TxL
case 0x4303: return channel.sourceAddress >> 8; //A1TxH
case 0x4304: return channel.sourceBank; //A1Bx
case 0x4305: return channel.transferSize >> 0; //DASxL
case 0x4306: return channel.transferSize >> 8; //DASxH
case 0x4307: return channel.indirectBank; //DASBx
case 0x4308: return channel.hdmaAddress >> 0; //A2AxL
case 0x4309: return channel.hdmaAddress >> 8; //A2AxH
case 0x430a: return channel.lineCounter; //NTRLx
case 0x430b: return channel.unknown; //???x
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);
case 0x2181: //WMADDL
bits(io.wramAddress,0-7) = data;
io.wramAddress = io.wramAddress & 0x1ff00 | data << 0;
return;
case 0x2182: //WMADDM
bits(io.wramAddress,8-15) = data;
io.wramAddress = io.wramAddress & 0x100ff | data << 8;
return;
case 0x2183: //WMADDH
bit1(io.wramAddress,16) = bit1(data,0);
io.wramAddress = io.wramAddress & 0x0ffff | (data & 1) << 16;
return;
case 0x4016: //JOYSER0
@ -136,7 +136,7 @@ auto CPU::writeCPU(uint addr, uint8 data) -> void {
return;
case 0x4201: //WRIO
if(bit1(io.pio,7) && !bit1(data,7)) ppu.latchCounters();
if((io.pio & 0x80) && !(data & 0x80)) ppu.latchCounters();
io.pio = data;
return;
@ -149,18 +149,18 @@ auto CPU::writeCPU(uint addr, uint8 data) -> void {
if(alu.mpyctr || alu.divctr) return;
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.shift = io.wrmpyb;
return;
case 0x4204: //WRDIVL
bit8(io.wrdiva,0) = data;
io.wrdiva = io.wrdiva & 0xff00 | data << 0;
return;
case 0x4205: //WRDIVH
bit8(io.wrdiva,1) = data;
io.wrdiva = io.wrdiva & 0x00ff | data << 8;
return;
case 0x4206: //WRDIVB
@ -175,31 +175,31 @@ auto CPU::writeCPU(uint addr, uint8 data) -> void {
case 0x4207: //HTIMEL
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;
return;
case 0x4208: //HTIMEH
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;
return;
case 0x4209: //VTIMEL
bits(io.vtime,0-7) = data;
io.vtime = io.vtime & 0x100 | data << 0;
return;
case 0x420a: //VTIMEH
bit1(io.vtime,8) = data & 1;
io.vtime = io.vtime & 0x0ff | (data & 1) << 8;
return;
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;
return;
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;
case 0x420d: //MEMSEL
@ -215,12 +215,12 @@ auto CPU::writeDMA(uint addr, uint8 data) -> void {
switch(addr & 0xff8f) {
case 0x4300: //DMAPx
channel.transferMode = bits(data,0-2);
channel.fixedTransfer = bit1(data,3);
channel.reverseTransfer = bit1(data,4);
channel.unused = bit1(data,5);
channel.indirect = bit1(data,6);
channel.direction = bit1(data,7);
channel.transferMode = data >> 0 & 7;
channel.fixedTransfer = data >> 3 & 1;
channel.reverseTransfer = data >> 4 & 1;
channel.unused = data >> 5 & 1;
channel.indirect = data >> 6 & 1;
channel.direction = data >> 7 & 1;
return;
case 0x4301: //BBADx
@ -228,11 +228,11 @@ auto CPU::writeDMA(uint addr, uint8 data) -> void {
return;
case 0x4302: //A1TxL
bit8(channel.sourceAddress,0) = data;
channel.sourceAddress = channel.sourceAddress & 0xff00 | data << 0;
return;
case 0x4303: //A1TxH
bit8(channel.sourceAddress,1) = data;
channel.sourceAddress = channel.sourceAddress & 0x00ff | data << 8;
return;
case 0x4304: //A1Bx
@ -240,11 +240,11 @@ auto CPU::writeDMA(uint addr, uint8 data) -> void {
return;
case 0x4305: //DASxL
bit8(channel.transferSize,0) = data;
channel.transferSize = channel.transferSize & 0xff00 | data << 0;
return;
case 0x4306: //DASxH
bit8(channel.transferSize,1) = data;
channel.transferSize = channel.transferSize & 0x00ff | data << 8;
return;
case 0x4307: //DASBx
@ -252,11 +252,11 @@ auto CPU::writeDMA(uint addr, uint8 data) -> void {
return;
case 0x4308: //A2AxL
bit8(channel.hdmaAddress,0) = data;
channel.hdmaAddress = channel.hdmaAddress & 0xff00 | data << 0;
return;
case 0x4309: //A2AxH
bit8(channel.hdmaAddress,1) = data;
channel.hdmaAddress = channel.hdmaAddress & 0x00ff | data << 8;
return;
case 0x430a: //NTRLx

View File

@ -27,10 +27,10 @@ auto Interface::display() -> Display {
}
auto Interface::color(uint32 color) -> uint64 {
uint r = bits(color, 0- 4);
uint g = bits(color, 5- 9);
uint b = bits(color,10-14);
uint l = bits(color,15-18);
uint r = color >> 0 & 31;
uint g = color >> 5 & 31;
uint b = color >> 10 & 31;
uint l = color >> 15 & 15;
//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

View File

@ -84,19 +84,19 @@ auto PPU::Background::getTile() -> void {
if(offsetX >= 8) {
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);
uint valid = 13 + id;
uint valid = 1 << 13 + id;
if(ppu.io.bgMode == 4) {
if(bit1(hlookup,valid)) {
if(!bit1(hlookup,15)) {
if(hlookup & valid) {
if(!(hlookup & 0x8000)) {
hoffset = offsetX + (hlookup & ~7);
} else {
voffset = py + hlookup;
}
}
} else {
if(bit1(hlookup,valid)) hoffset = offsetX + (hlookup & ~7);
if(bit1(vlookup,valid)) voffset = py + vlookup;
if(hlookup & valid) hoffset = offsetX + (hlookup & ~7);
if(vlookup & valid) voffset = py + vlookup;
}
}
}
@ -116,27 +116,30 @@ auto PPU::Background::getTile() -> void {
uint16 address = io.screenAddress + offset;
tile = ppu.vram[address];
bool mirrorY = bit1(tile,15);
bool mirrorX = bit1(tile,14);
priority = io.priority[bit1(tile,13)];
paletteNumber = bits(tile,10-12);
bool mirrorY = tile & 0x8000;
bool mirrorX = tile & 0x4000;
priority = io.priority[bool(tile & 0x2000)];
paletteNumber = tile >> 10 & 7;
paletteIndex = paletteOffset + (paletteNumber << paletteSize);
if(tileWidth == 4 && (bool)(hoffset & 8) != mirrorX) tile += 1;
if(tileHeight == 4 && (bool)(voffset & 8) != mirrorY) tile += 16;
uint16 character = bits(tile,0-9) + tiledataIndex & tileMask;
if(tileWidth == 4 && bool(hoffset & 8) != mirrorX) tile += 1;
if(tileHeight == 4 && bool(voffset & 8) != mirrorY) tile += 16;
uint16 character = (tile & 0x03ff) + tiledataIndex & tileMask;
if(mirrorY) voffset ^= 7;
offset = (character << 3 + io.mode) + (voffset & 7);
switch(io.mode) {
case Mode::BPP8:
bits(data[1],16-31) = ppu.vram[offset + 24];
bits(data[1], 0-15) = ppu.vram[offset + 16];
data[0] = ppu.vram[offset + 0] << 0 | ppu.vram[offset + 8] << 16;
data[1] = ppu.vram[offset + 16] << 0 | ppu.vram[offset + 24] << 16;
break;
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:
bits(data[0], 0-15) = ppu.vram[offset + 0];
data[0] = ppu.vram[offset + 0] << 0;
break;
}
if(mirrorX) for(auto n : range(2)) {

View File

@ -23,9 +23,9 @@ auto PPU::addressVRAM() const -> uint16 {
uint16 address = io.vramAddress;
switch(io.vramMapping) {
case 0: return address;
case 1: return bits(address, 8-15) << 8 | bits(address,0-4) << 3 | bits(address,5-7);
case 2: return bits(address, 9-15) << 9 | bits(address,0-5) << 3 | bits(address,6-8);
case 3: return bits(address,10-15) << 10 | bits(address,0-6) << 3 | bits(address,7-9);
case 1: return address & 0xff00 | address << 3 & 0x00f8 | address >> 5 & 7;
case 2: return address & 0xfe00 | address << 3 & 0x01f8 | address >> 6 & 7;
case 3: return address & 0xfc00 | address << 3 & 0x03f8 | address >> 7 & 7;
}
unreachable;
}
@ -39,7 +39,8 @@ auto PPU::readVRAM() -> uint16 {
auto PPU::writeVRAM(bool byte, uint8 data) -> void {
if(!io.displayDisable && vcounter() < vdisp()) return;
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 {
@ -101,7 +102,7 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
//SLHV
case 0x2137: {
if(cbit1(cpu.pio(),7)) latchCounters();
if(cpu.pio() & 0x80) latchCounters();
return data; //CPU MDR
}
@ -114,7 +115,7 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
//VMDATALREAD
case 0x2139: {
ppu1.mdr = bit8(latch.vram,0);
ppu1.mdr = latch.vram >> 0;
if(io.vramIncrementMode == 0) {
latch.vram = readVRAM();
io.vramAddress += io.vramIncrementSize;
@ -124,7 +125,7 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
//VMDATAHREAD
case 0x213a: {
ppu1.mdr = bit8(latch.vram,1);
ppu1.mdr = latch.vram >> 8;
if(io.vramIncrementMode == 1) {
latch.vram = readVRAM();
io.vramAddress += io.vramIncrementSize;
@ -135,9 +136,10 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
//CGDATAREAD
case 0x213b: {
if(io.cgramAddressLatch++ == 0) {
bits(ppu2.mdr,0-7) = readCGRAM(0, io.cgramAddress);
ppu2.mdr = readCGRAM(0, io.cgramAddress);
} else {
bits(ppu2.mdr,0-6) = readCGRAM(1, io.cgramAddress++);
ppu2.mdr &= 0x80;
ppu2.mdr |= readCGRAM(1, io.cgramAddress++) & 0x7f;
}
return ppu2.mdr;
}
@ -145,9 +147,10 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
//OPHCT
case 0x213c: {
if(latch.hcounter++ == 0) {
bits(ppu2.mdr,0-7) = bits(io.hcounter,0-7);
ppu2.mdr = io.hcounter >> 0;
} else {
bit1(ppu2.mdr,0 ) = bit1(io.hcounter,8 );
ppu2.mdr &= 0xfe;
ppu2.mdr |= io.hcounter >> 8 & 1;
}
return ppu2.mdr;
}
@ -155,19 +158,20 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
//OPVCT
case 0x213d: {
if(latch.vcounter++ == 0) {
bits(ppu2.mdr,0-7) = bits(io.vcounter,0-7);
ppu2.mdr = io.vcounter >> 0;
} else {
bit1(ppu2.mdr,0 ) = bit1(io.vcounter,8 );
ppu2.mdr &= 0xfe;
ppu2.mdr |= io.vcounter >> 8 & 1;
}
return ppu2.mdr;
}
//STAT77
case 0x213e: {
bits(ppu1.mdr,0-3) = ppu1.version;
bit1(ppu1.mdr, 5) = 0;
bit1(ppu1.mdr, 6) = obj.io.rangeOver;
bit1(ppu1.mdr, 7) = obj.io.timeOver;
ppu1.mdr &= 1 << 4;
ppu1.mdr |= ppu1.version << 0;
ppu1.mdr |= obj.io.rangeOver << 6;
ppu1.mdr |= obj.io.timeOver << 7;
return ppu1.mdr;
}
@ -175,15 +179,16 @@ auto PPU::readIO(uint addr, uint8 data) -> uint8 {
case 0x213f: {
latch.hcounter = 0;
latch.vcounter = 0;
bits(ppu2.mdr,0-3) = ppu2.version;
bit1(ppu2.mdr, 4) = Region::PAL(); //0 = NTSC, 1 = PAL
if(!cbit1(cpu.pio(),7)) {
bit1(ppu2.mdr, 6) = 1;
ppu2.mdr &= 1 << 5;
ppu2.mdr |= ppu2.version;
ppu2.mdr |= Region::PAL() << 4; //0 = NTSC, 1 = PAL
if(!(cpu.pio() & 0x80)) {
ppu2.mdr |= 1 << 6;;
} else {
bit1(ppu2.mdr, 6) = latch.counters;
ppu2.mdr |= latch.counters << 6;
latch.counters = 0;
}
bit1(ppu2.mdr, 7) = field();
ppu2.mdr |= field() << 7;
return ppu2.mdr;
}
@ -200,16 +205,16 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
//INIDISP
case 0x2100: {
if(io.displayDisable && vcounter() == vdisp()) obj.addressReset();
io.displayBrightness = bits(data,0-3);
io.displayDisable = bit1(data,7);
io.displayBrightness = data >> 0 & 15;
io.displayDisable = data >> 7 & 1;
return;
}
//OBSEL
case 0x2101: {
obj.io.tiledataAddress = bits(data,0-2) << 13;
obj.io.nameselect = bits(data,3-4);
obj.io.baseSize = bits(data,5-7);
obj.io.tiledataAddress = (data & 7) << 13;
obj.io.nameselect = data >> 3 & 3;
obj.io.baseSize = data >> 5 & 7;
return;
}
@ -222,18 +227,18 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
//OAMADDH
case 0x2103: {
io.oamBaseAddress = bit1(data,0) << 9 | (io.oamBaseAddress & 0x01fe);
io.oamPriority = bit1(data,7);
io.oamBaseAddress = (data & 1) << 9 | (io.oamBaseAddress & 0x01fe);
io.oamPriority = bool(data & 0x80);
obj.addressReset();
return;
}
//OAMDATA
case 0x2104: {
uint1 latchBit = bit1(io.oamAddress,0);
uint1 latchBit = io.oamAddress & 1;
uint10 address = io.oamAddress++;
if(latchBit == 0) latch.oam = data;
if(bit1(address,9)) {
if(address & 0x200) {
writeOAM(address, data);
} else if(latchBit == 1) {
writeOAM((address & ~1) + 0, latch.oam);
@ -245,65 +250,65 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
//BGMODE
case 0x2105: {
io.bgMode = bits(data,0-2);
io.bgPriority = bit1(data, 3);
bg1.io.tileSize = bit1(data, 4);
bg2.io.tileSize = bit1(data, 5);
bg3.io.tileSize = bit1(data, 6);
bg4.io.tileSize = bit1(data, 7);
io.bgMode = data >> 0 & 7;
io.bgPriority = data >> 3 & 1;
bg1.io.tileSize = data >> 4 & 1;
bg2.io.tileSize = data >> 5 & 1;
bg3.io.tileSize = data >> 6 & 1;
bg4.io.tileSize = data >> 7 & 1;
updateVideoMode();
return;
}
//MOSAIC
case 0x2106: {
bg1.mosaic.enable = bit1(data,0);
bg2.mosaic.enable = bit1(data,1);
bg3.mosaic.enable = bit1(data,2);
bg4.mosaic.enable = bit1(data,3);
Background::Mosaic::size = bits(data,4-7);
bg1.mosaic.enable = data >> 0 & 1;
bg2.mosaic.enable = data >> 1 & 1;
bg3.mosaic.enable = data >> 2 & 1;
bg4.mosaic.enable = data >> 3 & 1;
Background::Mosaic::size = data >> 4 & 15;
return;
}
//BG1SC
case 0x2107: {
bg1.io.screenSize = bits(data,0-1);
bg1.io.screenAddress = bits(data,2-7) << 10;
bg1.io.screenSize = data & 3;
bg1.io.screenAddress = data >> 2 << 10;
return;
}
//BG2SC
case 0x2108: {
bg2.io.screenSize = bits(data,0-1);
bg2.io.screenAddress = bits(data,2-7) << 10;
bg2.io.screenSize = data & 3;
bg2.io.screenAddress = data >> 2 << 10;
return;
}
//BG3SC
case 0x2109: {
bg3.io.screenSize = bits(data,0-1);
bg3.io.screenAddress = bits(data,2-7) << 10;
bg3.io.screenSize = data & 3;
bg3.io.screenAddress = data >> 2 << 10;
return;
}
//BG4SC
case 0x210a: {
bg4.io.screenSize = bits(data,0-1);
bg4.io.screenAddress = bits(data,2-7) << 10;
bg4.io.screenSize = data & 3;
bg4.io.screenAddress = data >> 2 << 10;
return;
}
//BG12NBA
case 0x210b: {
bg1.io.tiledataAddress = bits(data,0-3) << 12;
bg2.io.tiledataAddress = bits(data,4-7) << 12;
bg1.io.tiledataAddress = (data >> 0 & 15) << 12;
bg2.io.tiledataAddress = (data >> 4 & 15) << 12;
return;
}
//BG34NBA
case 0x210c: {
bg3.io.tiledataAddress = bits(data,0-3) << 12;
bg4.io.tiledataAddress = bits(data,4-7) << 12;
bg3.io.tiledataAddress = (data >> 0 & 15) << 12;
bg4.io.tiledataAddress = (data >> 4 & 15) << 12;
return;
}
@ -377,21 +382,21 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
case 0x2115: {
static const uint size[4] = {1, 32, 128, 128};
io.vramIncrementSize = size[data & 3];
io.vramMapping = bits(data,2-3);
io.vramIncrementMode = bit1(data, 7);
io.vramMapping = data >> 2 & 3;
io.vramIncrementMode = data >> 7 & 1;
return;
}
//VMADDL
case 0x2116: {
bit8(io.vramAddress,0) = data;
io.vramAddress = io.vramAddress & 0xff00 | data << 0;
latch.vram = readVRAM();
return;
}
//VMADDH
case 0x2117: {
bit8(io.vramAddress,1) = data;
io.vramAddress = io.vramAddress & 0x00ff | data << 8;
latch.vram = readVRAM();
return;
}
@ -412,9 +417,9 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
//M7SEL
case 0x211a: {
io.hflipMode7 = bit1(data, 0);
io.vflipMode7 = bit1(data, 1);
io.repeatMode7 = bits(data,6-7);
io.hflipMode7 = data >> 0 & 1;
io.vflipMode7 = data >> 1 & 1;
io.repeatMode7 = data >> 6 & 3;
return;
}
@ -472,47 +477,47 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
if(io.cgramAddressLatch++ == 0) {
latch.cgram = data;
} else {
writeCGRAM(io.cgramAddress++, bits(data,0-6) << 8 | latch.cgram);
writeCGRAM(io.cgramAddress++, (data & 0x7f) << 8 | latch.cgram);
}
return;
}
//W12SEL
case 0x2123: {
window.io.bg1.oneInvert = bit1(data,0);
window.io.bg1.oneEnable = bit1(data,1);
window.io.bg1.twoInvert = bit1(data,2);
window.io.bg1.twoEnable = bit1(data,3);
window.io.bg2.oneInvert = bit1(data,4);
window.io.bg2.oneEnable = bit1(data,5);
window.io.bg2.twoInvert = bit1(data,6);
window.io.bg2.twoEnable = bit1(data,7);
window.io.bg1.oneInvert = data >> 0 & 1;
window.io.bg1.oneEnable = data >> 1 & 1;
window.io.bg1.twoInvert = data >> 2 & 1;
window.io.bg1.twoEnable = data >> 3 & 1;
window.io.bg2.oneInvert = data >> 4 & 1;
window.io.bg2.oneEnable = data >> 5 & 1;
window.io.bg2.twoInvert = data >> 6 & 1;
window.io.bg2.twoEnable = data >> 7 & 1;
return;
}
//W34SEL
case 0x2124: {
window.io.bg3.oneInvert = bit1(data,0);
window.io.bg3.oneEnable = bit1(data,1);
window.io.bg3.twoInvert = bit1(data,2);
window.io.bg3.twoEnable = bit1(data,3);
window.io.bg4.oneInvert = bit1(data,4);
window.io.bg4.oneEnable = bit1(data,5);
window.io.bg4.twoInvert = bit1(data,6);
window.io.bg4.twoEnable = bit1(data,7);
window.io.bg3.oneInvert = data >> 0 & 1;
window.io.bg3.oneEnable = data >> 1 & 1;
window.io.bg3.twoInvert = data >> 2 & 1;
window.io.bg3.twoEnable = data >> 3 & 1;
window.io.bg4.oneInvert = data >> 4 & 1;
window.io.bg4.oneEnable = data >> 5 & 1;
window.io.bg4.twoInvert = data >> 6 & 1;
window.io.bg4.twoEnable = data >> 7 & 1;
return;
}
//WOBJSEL
case 0x2125: {
window.io.obj.oneInvert = bit1(data,0);
window.io.obj.oneEnable = bit1(data,1);
window.io.obj.twoInvert = bit1(data,2);
window.io.obj.twoEnable = bit1(data,3);
window.io.col.oneInvert = bit1(data,4);
window.io.col.oneEnable = bit1(data,5);
window.io.col.twoInvert = bit1(data,6);
window.io.col.twoEnable = bit1(data,7);
window.io.obj.oneInvert = data >> 0 & 1;
window.io.obj.oneEnable = data >> 1 & 1;
window.io.obj.twoInvert = data >> 2 & 1;
window.io.obj.twoEnable = data >> 3 & 1;
window.io.col.oneInvert = data >> 4 & 1;
window.io.col.oneEnable = data >> 5 & 1;
window.io.col.twoInvert = data >> 6 & 1;
window.io.col.twoEnable = data >> 7 & 1;
return;
}
@ -542,97 +547,97 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
//WBGLOG
case 0x212a: {
window.io.bg1.mask = bits(data,0-1);
window.io.bg2.mask = bits(data,2-3);
window.io.bg3.mask = bits(data,4-5);
window.io.bg4.mask = bits(data,6-7);
window.io.bg1.mask = data >> 0 & 3;
window.io.bg2.mask = data >> 2 & 3;
window.io.bg3.mask = data >> 4 & 3;
window.io.bg4.mask = data >> 6 & 3;
return;
}
//WOBJLOG
case 0x212b: {
window.io.obj.mask = bits(data,0-1);
window.io.col.mask = bits(data,2-3);
window.io.obj.mask = data >> 0 & 3;
window.io.col.mask = data >> 2 & 3;
return;
}
//TM
case 0x212c: {
bg1.io.aboveEnable = bit1(data,0);
bg2.io.aboveEnable = bit1(data,1);
bg3.io.aboveEnable = bit1(data,2);
bg4.io.aboveEnable = bit1(data,3);
obj.io.aboveEnable = bit1(data,4);
bg1.io.aboveEnable = data >> 0 & 1;
bg2.io.aboveEnable = data >> 1 & 1;
bg3.io.aboveEnable = data >> 2 & 1;
bg4.io.aboveEnable = data >> 3 & 1;
obj.io.aboveEnable = data >> 4 & 1;
return;
}
//TS
case 0x212d: {
bg1.io.belowEnable = bit1(data,0);
bg2.io.belowEnable = bit1(data,1);
bg3.io.belowEnable = bit1(data,2);
bg4.io.belowEnable = bit1(data,3);
obj.io.belowEnable = bit1(data,4);
bg1.io.belowEnable = data >> 0 & 1;
bg2.io.belowEnable = data >> 1 & 1;
bg3.io.belowEnable = data >> 2 & 1;
bg4.io.belowEnable = data >> 3 & 1;
obj.io.belowEnable = data >> 4 & 1;
return;
}
//TMW
case 0x212e: {
window.io.bg1.aboveEnable = bit1(data,0);
window.io.bg2.aboveEnable = bit1(data,1);
window.io.bg3.aboveEnable = bit1(data,2);
window.io.bg4.aboveEnable = bit1(data,3);
window.io.obj.aboveEnable = bit1(data,4);
window.io.bg1.aboveEnable = data >> 0 & 1;
window.io.bg2.aboveEnable = data >> 1 & 1;
window.io.bg3.aboveEnable = data >> 2 & 1;
window.io.bg4.aboveEnable = data >> 3 & 1;
window.io.obj.aboveEnable = data >> 4 & 1;
return;
}
//TSW
case 0x212f: {
window.io.bg1.belowEnable = bit1(data,0);
window.io.bg2.belowEnable = bit1(data,1);
window.io.bg3.belowEnable = bit1(data,2);
window.io.bg4.belowEnable = bit1(data,3);
window.io.obj.belowEnable = bit1(data,4);
window.io.bg1.belowEnable = data >> 0 & 1;
window.io.bg2.belowEnable = data >> 1 & 1;
window.io.bg3.belowEnable = data >> 2 & 1;
window.io.bg4.belowEnable = data >> 3 & 1;
window.io.obj.belowEnable = data >> 4 & 1;
return;
}
//CGWSEL
case 0x2130: {
screen.io.directColor = bit1(data, 0);
screen.io.blendMode = bit1(data, 1);
window.io.col.belowMask = bits(data,4-5);
window.io.col.aboveMask = bits(data,6-7);
screen.io.directColor = data >> 0 & 1;
screen.io.blendMode = data >> 1 & 1;
window.io.col.belowMask = data >> 4 & 3;
window.io.col.aboveMask = data >> 6 & 3;
return;
}
//CGADDSUB
case 0x2131: {
screen.io.bg1.colorEnable = bit1(data,0);
screen.io.bg2.colorEnable = bit1(data,1);
screen.io.bg3.colorEnable = bit1(data,2);
screen.io.bg4.colorEnable = bit1(data,3);
screen.io.obj.colorEnable = bit1(data,4);
screen.io.back.colorEnable = bit1(data,5);
screen.io.colorHalve = bit1(data,6);
screen.io.colorMode = bit1(data,7);
screen.io.bg1.colorEnable = data >> 0 & 1;
screen.io.bg2.colorEnable = data >> 1 & 1;
screen.io.bg3.colorEnable = data >> 2 & 1;
screen.io.bg4.colorEnable = data >> 3 & 1;
screen.io.obj.colorEnable = data >> 4 & 1;
screen.io.back.colorEnable = data >> 5 & 1;
screen.io.colorHalve = data >> 6 & 1;
screen.io.colorMode = data >> 7 & 1;
return;
}
//COLDATA
case 0x2132: {
if(bit1(data,5)) screen.io.colorRed = bits(data,0-4);
if(bit1(data,6)) screen.io.colorGreen = bits(data,0-4);
if(bit1(data,7)) screen.io.colorBlue = bits(data,0-4);
if(data & 0x20) screen.io.colorRed = data & 0x1f;
if(data & 0x40) screen.io.colorGreen = data & 0x1f;
if(data & 0x80) screen.io.colorBlue = data & 0x1f;
return;
}
//SETINI
case 0x2133: {
io.interlace = bit1(data,0);
obj.io.interlace = bit1(data,1);
io.overscan = bit1(data,2);
io.pseudoHires = bit1(data,3);
io.extbg = bit1(data,6);
io.interlace = data >> 0 & 1;
obj.io.interlace = data >> 1 & 1;
io.overscan = data >> 2 & 1;
io.pseudoHires = data >> 3 & 1;
io.extbg = data >> 6 & 1;
updateVideoMode();
return;
}

View File

@ -50,8 +50,8 @@ auto PPU::Background::runMode7() -> void {
case 1:
px &= 1023;
py &= 1023;
tile = bit8(ppu.vram[(py >> 3) * 128 + (px >> 3)],0);
palette = bit8(ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)],1);
tile = ppu.vram[(py >> 3) * 128 + (px >> 3)] >> 0;
palette = ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)] >> 8;
break;
//palette color 0 outside of screen area
@ -61,8 +61,8 @@ auto PPU::Background::runMode7() -> void {
} else {
px &= 1023;
py &= 1023;
tile = bit8(ppu.vram[(py >> 3) * 128 + (px >> 3)],0);
palette = bit8(ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)],1);
tile = ppu.vram[(py >> 3) * 128 + (px >> 3)] >> 0;
palette = ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)] >> 8;
}
break;
@ -73,9 +73,9 @@ auto PPU::Background::runMode7() -> void {
} else {
px &= 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;
}

View File

@ -1,5 +1,5 @@
auto PPU::OAM::read(uint10 address) -> uint8 {
if(!address.bit(9)) {
if(!(address & 0x200)) {
uint n = address >> 2; //object#
address &= 3;
if(address == 0) return object[n].x & 0xff;
@ -15,40 +15,40 @@ auto PPU::OAM::read(uint10 address) -> uint8 {
} else {
uint n = (address & 0x1f) << 2; //object#
return (
bit1(object[n + 0].x,8) << 0
| object[n + 0].size << 1
| bit1(object[n + 1].x,8) << 2
| object[n + 1].size << 3
| bit1(object[n + 2].x,8) << 4
| object[n + 2].size << 5
| bit1(object[n + 3].x,8) << 6
| object[n + 3].size << 7
object[n + 0].x >> 8 << 0
| object[n + 0].size << 1
| object[n + 1].x >> 8 << 2
| object[n + 1].size << 3
| object[n + 2].x >> 8 << 4
| object[n + 2].size << 5
| object[n + 3].x >> 8 << 6
| object[n + 3].size << 7
);
}
}
auto PPU::OAM::write(uint10 address, uint8 data) -> void {
if(!address.bit(9)) {
if(!(address & 0x200)) {
uint n = address >> 2; //object#
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 == 2) { object[n].character = data; return; }
object[n].nameselect = bit1(data,0);
object[n].palette = bits(data,1-3);
object[n].priority = bits(data,4-5);
object[n].hflip = bit1(data,6);
object[n].vflip = bit1(data,7);
object[n].nameselect = data >> 0 & 1;
object[n].palette = data >> 1 & 7;
object[n].priority = data >> 4 & 3;
object[n].hflip = data >> 6 & 1;
object[n].vflip = data >> 7 & 1;
} else {
uint n = (address & 0x1f) << 2; //object#
bit1(object[n + 0].x,8) = bit1(data,0);
object[n + 0].size = bit1(data,1);
bit1(object[n + 1].x,8) = bit1(data,2);
object[n + 1].size = bit1(data,3);
bit1(object[n + 2].x,8) = bit1(data,4);
object[n + 2].size = bit1(data,5);
bit1(object[n + 3].x,8) = bit1(data,6);
object[n + 3].size = bit1(data,7);
object[n + 0].x = object[n + 0].x & 0xff | bool(data & 0x01) << 8;
object[n + 0].size = bool(data & 0x02);
object[n + 1].x = object[n + 1].x & 0xff | bool(data & 0x04) << 8;
object[n + 1].size = bool(data & 0x08);
object[n + 2].x = object[n + 2].x & 0xff | bool(data & 0x10) << 8;
object[n + 2].size = bool(data & 0x20);
object[n + 3].x = object[n + 3].x & 0xff | bool(data & 0x40) << 8;
object[n + 3].size = bool(data & 0x80);
}
}

View File

@ -117,8 +117,8 @@ auto PPU::Object::tilefetch() -> void {
uint16 tiledataAddress = io.tiledataAddress;
if(sprite.nameselect) tiledataAddress += 1 + io.nameselect << 12;
uint16 chrx = cbits(sprite.character,0-3);
uint16 chry = (cbits(sprite.character,4-7) + (y >> 3) & 15) << 4;
uint16 chrx = (sprite.character >> 0 & 15);
uint16 chry = ((sprite.character >> 4 & 15) + (y >> 3) & 15) << 4;
for(uint tx : range(tileWidth)) {
uint sx = x + (tx << 3) & 511;
@ -136,8 +136,7 @@ auto PPU::Object::tilefetch() -> void {
uint pos = tiledataAddress + ((chry + (chrx + mx & 15)) << 4);
uint16 addr = (pos & 0xfff0) + (y & 7);
bits(oamTile[n].data, 0-15) = ppu.vram[addr + 0];
bits(oamTile[n].data,16-31) = ppu.vram[addr + 8];
oamTile[n].data = ppu.vram[addr + 0] << 0 | ppu.vram[addr + 8] << 16;
ppu.step(2);
}
}

View File

@ -136,8 +136,8 @@ auto BSMemory::read(uint address, uint8 data) -> uint8 {
if(ROM) return memory.read(bus.mirror(address, size()));
if(mode == Mode::Chip) {
if(address == 0) return bit8(chip.vendor,0); //only appears once
if(address == 1) return bit8(chip.device,0); //only appears once
if(address == 0) return chip.vendor; //only appears once
if(address == 1) return chip.device; //only appears once
if((uint3)address == 2) return 0x63; //unknown constant: repeats every eight 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.size() < 3) return;
uint16 count; //1 - 65536
bit8(count,0) = queue.data(!cbit1(queue.address(1),0) ? 1 : 2);
bit8(count,1) = queue.data(!cbit1(queue.address(1),0) ? 2 : 1);
count = queue.data(!(queue.address(1) & 1) ? 1 : 2) << 0;
count |= queue.data(!(queue.address(1) & 1) ? 2 : 1) << 8;
uint address = queue.address(2);
do {
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
for(uint6 id : range(block.count())) {
uint8 address;
address += bits(id,0-1) * 0x08; //verified for LH28F800SUT-ZI
address += bits(id,2-3) * 0x40; //verified for LH28F800SUT-ZI
address += bit1(id, 4) * 0x20; //guessed for LH28F016SU
address += bit1(id, 5) * 0x04; //guessed for LH28F032SU; will overwrite unknown constants
address += (id >> 0 & 3) * 0x08; //verified for LH28F800SUT-ZI
address += (id >> 2 & 3) * 0x40; //verified for LH28F800SUT-ZI
address += (id >> 4 & 1) * 0x20; //guessed for LH28F016SU
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
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();
@ -350,12 +350,12 @@ auto BSMemory::write(uint address, uint8 data) -> void {
if(queue.data(0) == 0xe0) {
if(queue.size() < 4) return; //command length = 3 + count
uint16 count; //1 - 65536
bit8(count,0) = queue.data(1); //endian order not affected by queue.address(1).bit(0)
bit8(count,1) = queue.data(2);
count = queue.data(1) << 0; //endian order not affected by queue.address(1).bit(0)
count |= queue.data(2) << 8;
page.write(queue.address(3), queue.data(3));
if(count--) {
queue.history[1].data = bit8(count,0);
queue.history[2].data = bit8(count,1);
queue.history[1].data = count >> 0;
queue.history[2].data = count >> 8;
return queue.pop(); //hack to avoid needing a 65539-entry queue
} else {
return queue.flush();
@ -374,11 +374,11 @@ auto BSMemory::write(uint address, uint8 data) -> void {
if(queue.data(0) == 0xfb) {
if(queue.size() < 3) return;
uint16 value;
bit8(value,0) = queue.data(!cbit1(queue.address(1),0) ? 1 : 2);
bit8(value,1) = queue.data(!cbit1(queue.address(1),0) ? 2 : 1);
value = queue.data(!(queue.address(1) & 1) ? 1 : 2) << 0;
value |= queue.data(!(queue.address(1) & 1) ? 2 : 1) << 8;
//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) ^ 1, bit8(value,1));
block(queue.address(2) >> block.bitCount()).write(queue.address(2) ^ 0, value >> 0);
block(queue.address(2) >> block.bitCount()).write(queue.address(2) ^ 1, value >> 8);
mode = Mode::CompatibleStatus;
return queue.flush();
}

View File

@ -81,12 +81,12 @@ auto SMP::writeIO(uint16 address, uint8 data) -> void {
case 0xf0: //TEST
if(r.p.p) break; //writes only valid when P flag is clear
io.timersDisable = bit1(data,0);
io.ramWritable = bit1(data,1);
io.ramDisable = bit1(data,2);
io.timersEnable = bit1(data,3);
io.externalWaitStates = bits(data,4-5);
io.internalWaitStates = bits(data,6-7);
io.timersDisable = data >> 0 & 1;
io.ramWritable = data >> 1 & 1;
io.ramDisable = data >> 2 & 1;
io.timersEnable = data >> 3 & 1;
io.externalWaitStates = data >> 4 & 3;
io.internalWaitStates = data >> 6 & 3;
timer0.synchronizeStage1();
timer1.synchronizeStage1();
@ -95,34 +95,34 @@ auto SMP::writeIO(uint16 address, uint8 data) -> void {
case 0xf1: //CONTROL
//0->1 transistion resets timers
if(timer0.enable.raise(bit1(data,0))) {
if(timer0.enable.raise(data & 0x01)) {
timer0.stage2 = 0;
timer0.stage3 = 0;
}
if(timer1.enable.raise(bit1(data,1))) {
if(timer1.enable.raise(data & 0x02)) {
timer1.stage2 = 0;
timer1.stage3 = 0;
}
if(!timer2.enable.raise(bit1(data,2))) {
if(!timer2.enable.raise(data & 0x04)) {
timer2.stage2 = 0;
timer2.stage3 = 0;
}
if(bit1(data,4)) {
if(data & 0x10) {
synchronizeCPU();
io.apu0 = 0x00;
io.apu1 = 0x00;
}
if(bit1(data,5)) {
if(data & 0x20) {
synchronizeCPU();
io.apu2 = 0x00;
io.apu3 = 0x00;
}
io.iplromEnable = bit1(data,7);
io.iplromEnable = bool(data & 0x80);
break;
case 0xf2: //DSPADDR