diff --git a/bsnes/base/base.hpp b/bsnes/base/base.hpp index 0088df18..9ccfe02a 100755 --- a/bsnes/base/base.hpp +++ b/bsnes/base/base.hpp @@ -1,7 +1,7 @@ #ifndef BASE_HPP #define BASE_HPP -const char Version[] = "086.12"; +const char Version[] = "086.13"; #include #include @@ -121,6 +121,7 @@ typedef uint29_t uint29; typedef uint30_t uint30; typedef uint31_t uint31; typedef uint32_t uint32; +typedef uint_t<33> uint33; typedef uint64_t uint64; typedef varuint_t varuint; diff --git a/bsnes/nall/bit.hpp b/bsnes/nall/bit.hpp index d5e5e1bd..2732efce 100755 --- a/bsnes/nall/bit.hpp +++ b/bsnes/nall/bit.hpp @@ -1,45 +1,56 @@ #ifndef NALL_BIT_HPP #define NALL_BIT_HPP +#include + namespace nall { - template constexpr inline unsigned uclamp(const unsigned x) { - enum { y = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) }; + template + constexpr inline type_t uclamp(const type_t x) { + enum : type_t { b = 1ull << (bits - 1), y = b * 2 - 1 }; return y + ((x - y) & -(x < y)); //min(x, y); } - template constexpr inline unsigned uclip(const unsigned x) { - enum { m = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) }; + template + constexpr inline type_t uclip(const type_t x) { + enum : type_t { b = 1ull << (bits - 1), m = b * 2 - 1 }; return (x & m); } - template constexpr inline signed sclamp(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << (bits - 1)) - 1 }; + template + constexpr inline type_t sclamp(const type_t x) { + enum : type_t { b = 1ull << (bits - 1), m = b - 1 }; return (x > m) ? m : (x < -b) ? -b : x; } - template constexpr inline signed sclip(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << bits) - 1 }; + template + constexpr inline type_t sclip(const type_t x) { + typedef typename type_if::value, unsigned, uintmax_t>::type cast_t; + enum : cast_t { b = 1ull << (bits - 1), m = b * 2 - 1 }; return ((x & m) ^ b) - b; } namespace bit { //lowest(0b1110) == 0b0010 - template constexpr inline T lowest(const T x) { + template + constexpr inline T lowest(const T x) { return x & -x; } //clear_lowest(0b1110) == 0b1100 - template constexpr inline T clear_lowest(const T x) { + template + constexpr inline T clear_lowest(const T x) { return x & (x - 1); } //set_lowest(0b0101) == 0b0111 - template constexpr inline T set_lowest(const T x) { + template + constexpr inline T set_lowest(const T x) { return x | (x + 1); } //count number of bits set in a byte - inline unsigned count(unsigned x) { + template + inline unsigned count(T x) { unsigned count = 0; do count += x & 1; while(x >>= 1); return count; @@ -47,7 +58,8 @@ namespace nall { //round up to next highest single bit: //round(15) == 16, round(16) == 16, round(17) == 32 - inline unsigned round(unsigned x) { + template + inline T round(T x) { if((x & (x - 1)) == 0) return x; while(x & (x - 1)) x &= x - 1; return x << 1; diff --git a/bsnes/nall/platform.hpp b/bsnes/nall/platform.hpp index f3e4b3f5..e775ab8f 100755 --- a/bsnes/nall/platform.hpp +++ b/bsnes/nall/platform.hpp @@ -64,8 +64,8 @@ #define mkdir(n, m) _wmkdir(nall::utf16_t(n)) #define putenv _putenv #define rmdir _rmdir - #define usleep(n) Sleep(n / 1000) #define vsnprintf _vsnprintf + inline void usleep(unsigned milliseconds) { Sleep(milliseconds / 1000); } #endif //================ diff --git a/bsnes/nall/varint.hpp b/bsnes/nall/varint.hpp index be954c62..20f579b6 100755 --- a/bsnes/nall/varint.hpp +++ b/bsnes/nall/varint.hpp @@ -2,61 +2,67 @@ #define NALL_VARINT_HPP #include +#include namespace nall { template class uint_t { private: - unsigned data; + typedef typename type_if::type type_t; + type_t data; public: - inline operator unsigned() const { return data; } - inline unsigned operator ++(int) { unsigned r = data; data = uclip(data + 1); return r; } - inline unsigned operator --(int) { unsigned r = data; data = uclip(data - 1); return r; } - inline unsigned operator ++() { return data = uclip(data + 1); } - inline unsigned operator --() { return data = uclip(data - 1); } - inline unsigned operator =(const unsigned i) { return data = uclip(i); } - inline unsigned operator |=(const unsigned i) { return data = uclip(data | i); } - inline unsigned operator ^=(const unsigned i) { return data = uclip(data ^ i); } - inline unsigned operator &=(const unsigned i) { return data = uclip(data & i); } - inline unsigned operator<<=(const unsigned i) { return data = uclip(data << i); } - inline unsigned operator>>=(const unsigned i) { return data = uclip(data >> i); } - inline unsigned operator +=(const unsigned i) { return data = uclip(data + i); } - inline unsigned operator -=(const unsigned i) { return data = uclip(data - i); } - inline unsigned operator *=(const unsigned i) { return data = uclip(data * i); } - inline unsigned operator /=(const unsigned i) { return data = uclip(data / i); } - inline unsigned operator %=(const unsigned i) { return data = uclip(data % i); } + inline operator type_t() const { return data; } + inline type_t operator ++(int) { type_t r = data; data = uclip(data + 1); return r; } + inline type_t operator --(int) { type_t r = data; data = uclip(data - 1); return r; } + inline type_t operator ++() { return data = uclip(data + 1); } + inline type_t operator --() { return data = uclip(data - 1); } + inline type_t operator =(const type_t i) { return data = uclip(i); } + inline type_t operator |=(const type_t i) { return data = uclip(data | i); } + inline type_t operator ^=(const type_t i) { return data = uclip(data ^ i); } + inline type_t operator &=(const type_t i) { return data = uclip(data & i); } + inline type_t operator<<=(const type_t i) { return data = uclip(data << i); } + inline type_t operator>>=(const type_t i) { return data = uclip(data >> i); } + inline type_t operator +=(const type_t i) { return data = uclip(data + i); } + inline type_t operator -=(const type_t i) { return data = uclip(data - i); } + inline type_t operator *=(const type_t i) { return data = uclip(data * i); } + inline type_t operator /=(const type_t i) { return data = uclip(data / i); } + inline type_t operator %=(const type_t i) { return data = uclip(data % i); } inline uint_t() : data(0) {} - inline uint_t(const unsigned i) : data(uclip(i)) {} + inline uint_t(const type_t i) : data(uclip(i)) {} - template inline unsigned operator=(const uint_t &i) { return data = uclip((unsigned)i); } - template inline uint_t(const uint_t &i) : data(uclip(i)) {} + template inline type_t operator=(const uint_t &i) { return data = uclip((type_t)i); } + template inline uint_t(const uint_t &i) : data(uclip(i)) {} }; template class int_t { private: - signed data; + typedef typename type_if::type type_t; + type_t data; public: - inline operator signed() const { return data; } - inline signed operator ++(int) { signed r = data; data = sclip(data + 1); return r; } - inline signed operator --(int) { signed r = data; data = sclip(data - 1); return r; } - inline signed operator ++() { return data = sclip(data + 1); } - inline signed operator --() { return data = sclip(data - 1); } - inline signed operator =(const signed i) { return data = sclip(i); } - inline signed operator |=(const signed i) { return data = sclip(data | i); } - inline signed operator ^=(const signed i) { return data = sclip(data ^ i); } - inline signed operator &=(const signed i) { return data = sclip(data & i); } - inline signed operator<<=(const signed i) { return data = sclip(data << i); } - inline signed operator>>=(const signed i) { return data = sclip(data >> i); } - inline signed operator +=(const signed i) { return data = sclip(data + i); } - inline signed operator -=(const signed i) { return data = sclip(data - i); } - inline signed operator *=(const signed i) { return data = sclip(data * i); } - inline signed operator /=(const signed i) { return data = sclip(data / i); } - inline signed operator %=(const signed i) { return data = sclip(data % i); } + inline operator type_t() const { return data; } + inline type_t operator ++(int) { type_t r = data; data = sclip(data + 1); return r; } + inline type_t operator --(int) { type_t r = data; data = sclip(data - 1); return r; } + inline type_t operator ++() { return data = sclip(data + 1); } + inline type_t operator --() { return data = sclip(data - 1); } + inline type_t operator =(const type_t i) { return data = sclip(i); } + inline type_t operator |=(const type_t i) { return data = sclip(data | i); } + inline type_t operator ^=(const type_t i) { return data = sclip(data ^ i); } + inline type_t operator &=(const type_t i) { return data = sclip(data & i); } + inline type_t operator<<=(const type_t i) { return data = sclip(data << i); } + inline type_t operator>>=(const type_t i) { return data = sclip(data >> i); } + inline type_t operator +=(const type_t i) { return data = sclip(data + i); } + inline type_t operator -=(const type_t i) { return data = sclip(data - i); } + inline type_t operator *=(const type_t i) { return data = sclip(data * i); } + inline type_t operator /=(const type_t i) { return data = sclip(data / i); } + inline type_t operator %=(const type_t i) { return data = sclip(data % i); } inline int_t() : data(0) {} - inline int_t(const signed i) : data(sclip(i)) {} + inline int_t(const type_t i) : data(sclip(i)) {} + + template inline type_t operator=(const int_t &i) { return data = sclip((type_t)i); } + template inline int_t(const int_t &i) : data(sclip(i)) {} }; class varuint_t { diff --git a/bsnes/nes/video/video.cpp b/bsnes/nes/video/video.cpp index f90626a3..910b3c1e 100755 --- a/bsnes/nes/video/video.cpp +++ b/bsnes/nes/video/video.cpp @@ -46,9 +46,10 @@ unsigned Video::palette30( q *= saturation; auto gammaAdjust = [=](double f) { return f < 0.0 ? 0.0 : std::pow(f, 2.2 / gamma); }; - return (uclamp<10>(1023.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q)) << 20) - + (uclamp<10>(1023.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q)) << 10) - + (uclamp<10>(1023.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q)) << 0); + unsigned r = 1023.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q); + unsigned g = 1023.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q); + unsigned b = 1023.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q); + return (uclamp<10>(r) << 20) + (uclamp<10>(g) << 10) + (uclamp<10>(b) << 0); } void Video::generate(Format format) { diff --git a/bsnes/snes/chip/armdsp/armdsp.cpp b/bsnes/snes/chip/armdsp/armdsp.cpp index 4fde7ee4..37f3060f 100755 --- a/bsnes/snes/chip/armdsp/armdsp.cpp +++ b/bsnes/snes/chip/armdsp/armdsp.cpp @@ -44,7 +44,7 @@ void ArmDSP::enter() { pipeline.prefetch.opcode = bus_read<4>(r[15]); r[15].step(); - //if(pipeline.instruction.address == 0x00000208) trace = 1; + //if(pipeline.instruction.address == 0x0000ef5c) trace = 1; if(trace) { print("\n", disassemble_registers(), "\n"); print(disassemble_opcode(pipeline.instruction.address), "\n"); @@ -52,6 +52,7 @@ void ArmDSP::enter() { } instruction = pipeline.instruction.opcode; + if(!condition()) continue; if((instruction & 0x0fc000f0) == 0x00000090) { op_multiply(); continue; } if((instruction & 0x0fb000f0) == 0x01000000) { op_move_to_register_from_status_register(); continue; } if((instruction & 0x0fb000f0) == 0x01200000) { op_move_to_status_register_from_register(); continue; } diff --git a/bsnes/snes/chip/armdsp/armdsp.hpp b/bsnes/snes/chip/armdsp/armdsp.hpp index 7718a345..50fc2e9b 100755 --- a/bsnes/snes/chip/armdsp/armdsp.hpp +++ b/bsnes/snes/chip/armdsp/armdsp.hpp @@ -1,4 +1,4 @@ -//ARM v3 (ARM6?) +//ARMv3 (ARM6) struct ArmDSP : public Coprocessor { uint8 programROM[128 * 1024]; @@ -22,6 +22,11 @@ struct ArmDSP : public Coprocessor { //opcodes.cpp bool condition(); void opcode(uint32 data); + void lsl(bool &c, uint32 &rm, uint32 rs); + void lsr(bool &c, uint32 &rm, uint32 rs); + void asr(bool &c, uint32 &rm, uint32 rs); + void ror(bool &c, uint32 &rm, uint32 rs); + void rrx(bool &c, uint32 &rm); void op_multiply(); void op_move_to_status_register_from_register(); diff --git a/bsnes/snes/chip/armdsp/disassembler.cpp b/bsnes/snes/chip/armdsp/disassembler.cpp index 71a94fcb..8a7f046b 100755 --- a/bsnes/snes/chip/armdsp/disassembler.cpp +++ b/bsnes/snes/chip/armdsp/disassembler.cpp @@ -15,24 +15,49 @@ string ArmDSP::disassemble_opcode(uint32 pc) { uint32 instruction = bus_read<4>(pc); output.append(hex<8>(instruction), " "); + //multiply + if((instruction & 0x0fc000f0) == 0x00000090) { + uint4 condition = instruction >> 28; + uint1 accumulate = instruction >> 21; + uint1 save = instruction >> 20; + uint4 rd = instruction >> 16; + uint4 rn = instruction >> 12; + uint4 rs = instruction >> 8; + uint4 rm = instruction >> 0; + + output.append(accumulate ? "mla" : "mul", condition[conditions], save ? "s " : " "); + output.append(registers[rd], ",", registers[rm], ",", registers[rs]); + if(accumulate) output.append(",", registers[rn]); + + return output; + } + //move to register from status register if((instruction & 0x0fb000f0) == 0x01000000) { + uint4 condition = instruction >> 28; uint1 psr = instruction >> 22; uint4 rd = instruction >> 12; - output.append("mrs ", registers[rd], ",", psr ? "spsr" : "cpsr"); + + output.append("mrs", condition[conditions], " "); + output.append(registers[rd], ",", psr ? "spsr" : "cpsr"); + return output; } //move to status register from register if((instruction & 0x0fb000f0) == 0x01200000) { + uint4 condition = instruction >> 28; uint1 psr = instruction >> 22; uint4 field = instruction >> 16; - output.append("msr ", psr ? "spsr:" : "cpsr:", + + output.append("msr", conditions[condition], " "); + output.append(psr ? "spsr:" : "cpsr:", field & 1 ? "c" : "", field & 2 ? "x" : "", field & 4 ? "s" : "", field & 8 ? "f" : "", ",", registers[(uint4)instruction]); + return output; } diff --git a/bsnes/snes/chip/armdsp/opcodes.cpp b/bsnes/snes/chip/armdsp/opcodes.cpp index 8ff6b1e7..3fda67b6 100755 --- a/bsnes/snes/chip/armdsp/opcodes.cpp +++ b/bsnes/snes/chip/armdsp/opcodes.cpp @@ -1,7 +1,8 @@ #ifdef ARMDSP_CPP bool ArmDSP::condition() { - switch((uint4)(instruction >> 28)) { + uint4 condition = instruction >> 28; + switch(condition) { case 0: return cpsr.z == 1; //EQ (equal) case 1: return cpsr.z == 0; //NE (not equal) case 2: return cpsr.c == 1; //CS (carry set) @@ -29,33 +30,36 @@ bool ArmDSP::condition() { void ArmDSP::opcode(uint32 rm) { uint4 opcode = instruction >> 21; uint1 s = instruction >> 20; - auto &rn = r[(uint4)(instruction >> 16)]; - auto &rd = r[(uint4)(instruction >> 12)]; + uint4 n = instruction >> 16; + uint4 d = instruction >> 12; + + uint32 rn = r[n]; + auto &rd = r[d]; uint32 ri = rd, ro; //comparison opcodes always update flags if(opcode >= 8 && opcode <= 11) assert(s == 1); - static auto bit = [&](uint32 ro) { + auto bit = [&](uint32 ro) { if(!s) return; - cpsr.n = ro & 0x80000000; + cpsr.n = ro >> 31; cpsr.z = ro == 0; }; - static auto add = [&](uint32 ro) { + auto add = [&](uint32 ro) { if(!s) return; - cpsr.n = ro & 0x80000000; + cpsr.n = ro >> 31; cpsr.z = ro == 0; cpsr.c = ro < ri; - cpsr.v = ~(ri ^ rm) & (ri ^ ro) & 0x80000000; + cpsr.v = ~(ri ^ rm) & (ri ^ ro) & (1u << 31); }; - static auto sub = [&](uint32 ro) { + auto sub = [&](uint32 ro) { if(!s) return; - cpsr.n = ro & 0x80000000; + cpsr.n = ro >> 31; cpsr.z = ro == 0; cpsr.c = ro > ri; - cpsr.v = (ri ^ rm) & (ri ^ ro) & 0x80000000; + cpsr.v = (ri ^ rm) & (ri ^ ro) & (1u << 31); }; switch(opcode) { @@ -78,7 +82,46 @@ void ArmDSP::opcode(uint32 rm) { } } -//(mul,mla){condition}{s} +//logical shift left +void ArmDSP::lsl(bool &c, uint32 &rm, uint32 rs) { + while(rs--) { + c = rm >> 31; + rm <<= 1; + } +} + +//logical shift right +void ArmDSP::lsr(bool &c, uint32 &rm, uint32 rs) { + while(rs--) { + c = rm & 1; + rm >>= 1; + } +} + +//arithmetic shift right +void ArmDSP::asr(bool &c, uint32 &rm, uint32 rs) { + while(rs--) { + c = rm & 1; + rm = (int32)rm >> 1; + } +} + +//rotate right +void ArmDSP::ror(bool &c, uint32 &rm, uint32 rs) { + while(rs--) { + c = rm & 1; + rm = (rm << 31) | (rm >> 1); + } +} + +//rotate right with extend +void ArmDSP::rrx(bool &c, uint32 &rm) { + bool carry = c; + c = rm & 1; + rm = (carry << 31) | (rm >> 1); +} + +//(mul,mla){condition}{s} rd,rm,rs,rn //cccc 0000 00as dddd nnnn ssss 1001 mmmm //c = condition //a = accumulate @@ -88,8 +131,6 @@ void ArmDSP::opcode(uint32 rm) { //s = rs //n = rm void ArmDSP::op_multiply() { - if(!condition()) return; - uint1 accumulate = instruction >> 21; uint1 save = instruction >> 20; uint4 d = instruction >> 16; @@ -100,7 +141,7 @@ void ArmDSP::op_multiply() { r[d] = r[m] * r[s]; if(accumulate) r[d] += r[n]; if(save) { - cpsr.n = r[d] & 0x80000000; + cpsr.n = r[d] >> 31; cpsr.z = r[d] == 0; } } @@ -111,8 +152,6 @@ void ArmDSP::op_multiply() { //r = SPSR (0 = CPSR) //d = rd void ArmDSP::op_move_to_register_from_status_register() { - if(!condition()) return; - uint1 source = instruction >> 22; uint4 d = instruction >> 12; @@ -126,8 +165,6 @@ void ArmDSP::op_move_to_register_from_status_register() { //f = field mask //m = rm void ArmDSP::op_move_to_status_register_from_register() { - if(!condition()) return; - uint1 source = instruction >> 22; uint4 field = instruction >> 16; uint4 m = instruction; @@ -152,44 +189,27 @@ void ArmDSP::op_move_to_status_register_from_register() { //s = shift //m = rm void ArmDSP::op_data_immediate_shift() { - if(!condition()) return; - uint1 save = instruction >> 20; uint5 shift = instruction >> 7; uint2 mode = instruction >> 5; uint4 m = instruction; - bool carry = cpsr.c; uint32 rs = shift; uint32 rm = r[m]; + bool c = cpsr.c; - switch(mode) { - case 0: //LSL - rm = rm << rs; - if(rs) carry = rm & (1 << (32 - rs)); - break; + if(mode == 0) lsl(c, rm, rs); + if(mode == 1) lsr(c, rm, rs ? rs : 32); + if(mode == 2) asr(c, rm, rs ? rs : 32); + if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm); - case 1: //LSR - if(rs == 0) rs = 32; - rm = rm >> rs; - carry = rm & (1 << (rs - 1)); - break; - - case 2: //ASR - if(rs == 0) rs = 32; - rm = (int32)rm >> rs; - break; - - case 3: //ROR + RRX - if(rs == 0) rm = (cpsr.c << 31) | (rm >> 1); //RRX - if(rs != 0) rm = (rm >> rs) + (rm << (32 - rs)); //ROR - break; - } - - if(save) cpsr.c = carry; + if(save) cpsr.c = c; opcode(rm); } +//{opcode}{condition}{s} rd,rm {shift} rs +//{opcode}{condition} rn,rm {shift} rs +//{opcode}{condition}{s} rd,rn,rm {shift} rs //cccc 000o ooos nnnn dddd ssss 0ss1 mmmm //c = condition //o = opcode @@ -200,39 +220,21 @@ void ArmDSP::op_data_immediate_shift() { //s = shift //m = rm void ArmDSP::op_data_register_shift() { - if(!condition()) return; - uint1 save = instruction >> 20; uint4 s = instruction >> 8; uint2 mode = instruction >> 5; uint4 m = instruction >> 0; - bool carry = cpsr.c; - uint32 rs = (uint8)r[s]; + uint8 rs = r[s]; uint32 rm = r[m]; + bool c = cpsr.c; - switch(mode) { - case 0: //LSL - rm = rm << rs; - if(rs) carry = rm & (1 << (32 - rs)); - break; + if(mode == 0) lsl(c, rm, rs < 33 ? rs : 33); + if(mode == 1) lsr(c, rm, rs < 33 ? rs : 33); + if(mode == 2) asr(c, rm, rs < 32 ? rs : 32); + if(mode == 3) ror(c, rm, rs < 32 ? rs : 32); - case 1: //LSR - if(rs == 0) break; - rm = rm >> rs; - carry = rm & (1 << (rs - 1)); - break; - - case 2: //ASR - rm = (int32)rm >> rs; - break; - - case 3: //ROR - rm = (rm >> rs) + (rm << (32 - rs)); - break; - } - - if(save) cpsr.c = carry; + if(save) cpsr.c = c; opcode(rm); } @@ -248,18 +250,17 @@ void ArmDSP::op_data_register_shift() { //l = shift immediate //i = immediate void ArmDSP::op_data_immediate() { - if(!condition()) return; - uint1 save = instruction >> 20; uint4 shift = instruction >> 8; uint8 immediate = instruction; - bool carry = cpsr.c; + bool c = cpsr.c; + uint32 rs = shift << 1; uint32 rm = (immediate >> rs) | (immediate << (32 - rs)); - if(rs) carry = immediate & 0x80000000; + if(rs) c = immediate >> 31; - if(save) cpsr.c = carry; + if(save) cpsr.c = c; opcode(rm); } @@ -275,8 +276,6 @@ void ArmDSP::op_data_immediate() { //d = rd //i = immediate void ArmDSP::op_move_immediate_offset() { - if(!condition()) return; - uint1 p = instruction >> 24; uint1 u = instruction >> 23; uint1 b = instruction >> 22; @@ -318,8 +317,6 @@ void ArmDSP::op_move_immediate_offset() { //s = shift mode //m = rm void ArmDSP::op_move_register_offset() { - if(!condition()) return; - uint1 p = instruction >> 24; uint1 u = instruction >> 23; uint1 b = instruction >> 22; @@ -335,27 +332,12 @@ void ArmDSP::op_move_register_offset() { auto &rd = r[d]; uint32 rs = immediate; uint32 rm = r[m]; + bool c = cpsr.c; - switch(mode) { - case 0: //LSL - rm = rm << rs; - break; - - case 1: //LSR - if(rs == 0) rs = 32; - rm = rm >> rs; - break; - - case 2: //ASR - if(rs == 0) rs = 32; - rm = (int32)rm >> rs; - break; - - case 3: //ROR + RRX - if(rs == 0) rm = (cpsr.c << 31) | (rm >> 1); //RRX - if(rs != 0) rm = (rm >> rs) + (rm << (32 - rs)); //ROR - break; - } + if(mode == 0) lsl(c, rm, rs); + if(mode == 1) lsr(c, rm, rs ? rs : 32); + if(mode == 2) asr(c, rm, rs ? rs : 32); + if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm); if(l) { if(p == 1) rn = u ? rn + rm : rn - rm; @@ -372,6 +354,7 @@ void ArmDSP::op_move_register_offset() { if(p == 0 || w == 1) r[n] = rn; } +//(ldm,stm){condition}{mode} rn{!},{r...} //cccc 100p uswl nnnn llll llll llll llll //c = condition //p = pre (0 = post-indexed addressing) @@ -382,8 +365,6 @@ void ArmDSP::op_move_register_offset() { //n = rn //l = register list void ArmDSP::op_move_multiple() { - if(!condition()) return; - uint1 p = instruction >> 24; uint1 u = instruction >> 23; uint1 s = instruction >> 22; @@ -426,8 +407,6 @@ void ArmDSP::op_move_multiple() { //l = link //d = displacement (24-bit signed) void ArmDSP::op_branch() { - if(!condition()) return; - uint1 l = instruction >> 24; int24 displacement = instruction; diff --git a/bsnes/snes/chip/armdsp/registers.hpp b/bsnes/snes/chip/armdsp/registers.hpp index d9600e04..6f3d28ba 100755 --- a/bsnes/snes/chip/armdsp/registers.hpp +++ b/bsnes/snes/chip/armdsp/registers.hpp @@ -16,7 +16,7 @@ struct Bridge { Buffer armtocpu; uint8 status() const { - return 0x80 | (cputoarm.ready << 3) | (armtocpu.ready << 0); + return 0x84 | (cputoarm.ready << 3) | (armtocpu.ready << 0); } } bridge; diff --git a/bsnes/snes/chip/msu1/msu1.cpp b/bsnes/snes/chip/msu1/msu1.cpp index f12a9102..b1695e65 100755 --- a/bsnes/snes/chip/msu1/msu1.cpp +++ b/bsnes/snes/chip/msu1/msu1.cpp @@ -36,8 +36,10 @@ void MSU1::enter() { } } - left = sclamp<16>((double)left * (double)mmio.audio_volume / 255.0); - right = sclamp<16>((double)right * (double)mmio.audio_volume / 255.0); + signed lchannel = (double)left * (double)mmio.audio_volume / 255.0; + signed rchannel = (double)right * (double)mmio.audio_volume / 255.0; + left = sclamp<16>(lchannel); + right = sclamp<16>(rchannel); audio.coprocessor_sample(left, right); step(1);