mirror of https://github.com/bsnes-emu/bsnes.git
Update to v104r08 release.
byuu says: Changelog: - processor/upd96050: code cleanups - processor/upd96050: improved emulation of S1/OV1 flags [thanks to Cydrak, Lord Nightmare] - tomoko/settings/audio: reduced the size of the frequency/latency combo boxes to show longer device driver names Errata: I need to clear regs.sr in uPD96050::power() Note: the S1/OV1 emulation is likely not 100% correct yet, but it's a step in the right direction. No SNES games actually use S1/OV1, so this shouldn't result in any issues, I'd just like to have this part of the chip emulated correctly.
This commit is contained in:
parent
d8a8f06c35
commit
25bda4f159
|
@ -12,7 +12,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "104.07";
|
static const string Version = "104.08";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
|
@ -31,7 +31,7 @@ auto uPD96050::execOP(uint24 opcode) -> void {
|
||||||
case 4: idb = regs.dp; break;
|
case 4: idb = regs.dp; break;
|
||||||
case 5: idb = regs.rp; break;
|
case 5: idb = regs.rp; break;
|
||||||
case 6: idb = dataROM[regs.rp]; break;
|
case 6: idb = dataROM[regs.rp]; break;
|
||||||
case 7: idb = 0x8000 - regs.flaga.s1; break;
|
case 7: idb = 0x8000 - flags.a.s1; break;
|
||||||
case 8: idb = regs.dr; regs.sr.rqm = 1; break;
|
case 8: idb = regs.dr; regs.sr.rqm = 1; break;
|
||||||
case 9: idb = regs.dr; break;
|
case 9: idb = regs.dr; break;
|
||||||
case 10: idb = regs.sr; break;
|
case 10: idb = regs.sr; break;
|
||||||
|
@ -45,7 +45,7 @@ auto uPD96050::execOP(uint24 opcode) -> void {
|
||||||
if(alu) {
|
if(alu) {
|
||||||
uint16 p, q, r;
|
uint16 p, q, r;
|
||||||
Flag flag;
|
Flag flag;
|
||||||
bool c;
|
boolean c;
|
||||||
|
|
||||||
switch(pselect) {
|
switch(pselect) {
|
||||||
case 0: p = dataRAM[regs.dp]; break;
|
case 0: p = dataRAM[regs.dp]; break;
|
||||||
|
@ -55,8 +55,8 @@ auto uPD96050::execOP(uint24 opcode) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(asl) {
|
switch(asl) {
|
||||||
case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break;
|
case 0: q = regs.a; flag = flags.a; c = flags.b.c; break;
|
||||||
case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break;
|
case 1: q = regs.b; flag = flags.b; c = flags.a.c; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(alu) {
|
switch(alu) {
|
||||||
|
@ -70,46 +70,68 @@ auto uPD96050::execOP(uint24 opcode) -> void {
|
||||||
case 8: r = q - 1; p = 1; break; //DEC
|
case 8: r = q - 1; p = 1; break; //DEC
|
||||||
case 9: r = q + 1; p = 1; break; //INC
|
case 9: r = q + 1; p = 1; break; //INC
|
||||||
case 10: r = ~q; break; //CMP
|
case 10: r = ~q; break; //CMP
|
||||||
case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR)
|
case 11: r = q >> 1 | q & 0x8000; break; //SHR1 (ASR)
|
||||||
case 12: r = (q << 1) | c; break; //SHL1 (ROL)
|
case 12: r = q << 1 | c; break; //SHL1 (ROL)
|
||||||
case 13: r = (q << 2) | 3; break; //SHL2
|
case 13: r = q << 2 | 3; break; //SHL2
|
||||||
case 14: r = (q << 4) | 15; break; //SHL4
|
case 14: r = q << 4 | 15; break; //SHL4
|
||||||
case 15: r = (q << 8) | (q >> 8); break; //XCHG
|
case 15: r = q << 8 | q >> 8; break; //XCHG
|
||||||
}
|
}
|
||||||
|
|
||||||
flag.s0 = (r & 0x8000);
|
flag.s0 = r & 0x8000;
|
||||||
flag.z = (r == 0);
|
flag.z = r == 0;
|
||||||
|
|
||||||
switch(alu) {
|
switch(alu) {
|
||||||
case 1: case 2: case 3: case 10: case 13: case 14: case 15: {
|
case 1: //OR
|
||||||
|
case 2: //AND
|
||||||
|
case 3: //XOR
|
||||||
|
case 10: //CMP
|
||||||
|
case 13: //SHL2
|
||||||
|
case 14: //SHL4
|
||||||
|
case 15: { //XCHG
|
||||||
flag.c = 0;
|
flag.c = 0;
|
||||||
flag.ov0 = 0;
|
flag.ov0 = 0;
|
||||||
flag.ov1 = 0;
|
flag.ov1 = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: case 5: case 6: case 7: case 8: case 9: {
|
case 4: //SUB
|
||||||
|
case 5: //ADD
|
||||||
|
case 6: //SBB
|
||||||
|
case 7: //ADC
|
||||||
|
case 8: //DEC
|
||||||
|
case 9: { //INC
|
||||||
|
if(!flag.ov1) {
|
||||||
|
flag.s1 = flag.s0;
|
||||||
|
}
|
||||||
|
|
||||||
if(alu & 1) {
|
if(alu & 1) {
|
||||||
//addition
|
//addition
|
||||||
flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000;
|
flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000;
|
||||||
flag.c = (r < q);
|
flag.c = r < q;
|
||||||
} else {
|
} else {
|
||||||
//subtraction
|
//subtraction
|
||||||
flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;
|
flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;
|
||||||
flag.c = (r > q);
|
flag.c = r > q;
|
||||||
}
|
|
||||||
if(flag.ov0) {
|
|
||||||
flag.s1 = flag.ov1 ^ !(r & 0x8000);
|
|
||||||
flag.ov1 = !flag.ov1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ovh[] = last three overflow flags (0 = most recent result)
|
||||||
|
flag.ovh[2] = flag.ovh[1];
|
||||||
|
flag.ovh[1] = flag.ovh[0];
|
||||||
|
flag.ovh[0] = flag.ov0;
|
||||||
|
|
||||||
|
flag.ov1 = (
|
||||||
|
(flag.ovh[0] ^ flag.ovh[1] ^ flag.ovh[2])
|
||||||
|
| (flag.ovh[0] & !flag.ovh[1] & flag.ovh[2] & flag.s0 == flag.s1)
|
||||||
|
);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 11: {
|
case 11: { //SHR1 (ASR)
|
||||||
flag.c = q & 1;
|
flag.c = q & 1;
|
||||||
flag.ov0 = 0;
|
flag.ov0 = 0;
|
||||||
flag.ov1 = 0;
|
flag.ov1 = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 12: {
|
case 12: { //SHL1 (ROL)
|
||||||
flag.c = q >> 15;
|
flag.c = q >> 15;
|
||||||
flag.ov0 = 0;
|
flag.ov0 = 0;
|
||||||
flag.ov1 = 0;
|
flag.ov1 = 0;
|
||||||
|
@ -118,16 +140,16 @@ auto uPD96050::execOP(uint24 opcode) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(asl) {
|
switch(asl) {
|
||||||
case 0: regs.a = r; regs.flaga = flag; break;
|
case 0: regs.a = r; flags.a = flag; break;
|
||||||
case 1: regs.b = r; regs.flagb = flag; break;
|
case 1: regs.b = r; flags.b = flag; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
execLD((idb << 6) + dst);
|
execLD((idb << 6) + dst);
|
||||||
|
|
||||||
switch(dpl) {
|
switch(dpl) {
|
||||||
case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
|
case 1: regs.dp = (regs.dp & 0xf0) + (regs.dp + 1 & 0x0f); break; //DPINC
|
||||||
case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC
|
case 2: regs.dp = (regs.dp & 0xf0) + (regs.dp - 1 & 0x0f); break; //DPDEC
|
||||||
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
|
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,46 +168,52 @@ auto uPD96050::execJP(uint24 opcode) -> void {
|
||||||
uint11 na = opcode >> 2; //next address
|
uint11 na = opcode >> 2; //next address
|
||||||
uint2 bank = opcode >> 0; //bank address
|
uint2 bank = opcode >> 0; //bank address
|
||||||
|
|
||||||
uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
|
uint14 jp = regs.pc & 0x2000 | bank << 11 | na << 0;
|
||||||
|
|
||||||
switch(brch) {
|
switch(brch) {
|
||||||
case 0x000: regs.pc = regs.so; return; //JMPSO
|
case 0x000: regs.pc = regs.so; return; //JMPSO
|
||||||
|
|
||||||
case 0x080: if(regs.flaga.c == 0) regs.pc = jp; return; //JNCA
|
case 0x080: if(flags.a.c == 0) regs.pc = jp; return; //JNCA
|
||||||
case 0x082: if(regs.flaga.c == 1) regs.pc = jp; return; //JCA
|
case 0x082: if(flags.a.c == 1) regs.pc = jp; return; //JCA
|
||||||
case 0x084: if(regs.flagb.c == 0) regs.pc = jp; return; //JNCB
|
case 0x084: if(flags.b.c == 0) regs.pc = jp; return; //JNCB
|
||||||
case 0x086: if(regs.flagb.c == 1) regs.pc = jp; return; //JCB
|
case 0x086: if(flags.b.c == 1) regs.pc = jp; return; //JCB
|
||||||
|
|
||||||
case 0x088: if(regs.flaga.z == 0) regs.pc = jp; return; //JNZA
|
case 0x088: if(flags.a.z == 0) regs.pc = jp; return; //JNZA
|
||||||
case 0x08a: if(regs.flaga.z == 1) regs.pc = jp; return; //JZA
|
case 0x08a: if(flags.a.z == 1) regs.pc = jp; return; //JZA
|
||||||
case 0x08c: if(regs.flagb.z == 0) regs.pc = jp; return; //JNZB
|
case 0x08c: if(flags.b.z == 0) regs.pc = jp; return; //JNZB
|
||||||
case 0x08e: if(regs.flagb.z == 1) regs.pc = jp; return; //JZB
|
case 0x08e: if(flags.b.z == 1) regs.pc = jp; return; //JZB
|
||||||
|
|
||||||
case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jp; return; //JNOVA0
|
case 0x090: if(flags.a.ov0 == 0) regs.pc = jp; return; //JNOVA0
|
||||||
case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jp; return; //JOVA0
|
case 0x092: if(flags.a.ov0 == 1) regs.pc = jp; return; //JOVA0
|
||||||
case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jp; return; //JNOVB0
|
case 0x094: if(flags.b.ov0 == 0) regs.pc = jp; return; //JNOVB0
|
||||||
case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jp; return; //JOVB0
|
case 0x096: if(flags.b.ov0 == 1) regs.pc = jp; return; //JOVB0
|
||||||
|
|
||||||
case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jp; return; //JNOVA1
|
case 0x098: if(flags.a.ov1 == 0) regs.pc = jp; return; //JNOVA1
|
||||||
case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jp; return; //JOVA1
|
case 0x09a: if(flags.a.ov1 == 1) regs.pc = jp; return; //JOVA1
|
||||||
case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jp; return; //JNOVB1
|
case 0x09c: if(flags.b.ov1 == 0) regs.pc = jp; return; //JNOVB1
|
||||||
case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jp; return; //JOVB1
|
case 0x09e: if(flags.b.ov1 == 1) regs.pc = jp; return; //JOVB1
|
||||||
|
|
||||||
case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jp; return; //JNSA0
|
case 0x0a0: if(flags.a.s0 == 0) regs.pc = jp; return; //JNSA0
|
||||||
case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jp; return; //JSA0
|
case 0x0a2: if(flags.a.s0 == 1) regs.pc = jp; return; //JSA0
|
||||||
case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jp; return; //JNSB0
|
case 0x0a4: if(flags.b.s0 == 0) regs.pc = jp; return; //JNSB0
|
||||||
case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jp; return; //JSB0
|
case 0x0a6: if(flags.b.s0 == 1) regs.pc = jp; return; //JSB0
|
||||||
|
|
||||||
case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jp; return; //JNSA1
|
case 0x0a8: if(flags.a.s1 == 0) regs.pc = jp; return; //JNSA1
|
||||||
case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jp; return; //JSA1
|
case 0x0aa: if(flags.a.s1 == 1) regs.pc = jp; return; //JSA1
|
||||||
case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jp; return; //JNSB1
|
case 0x0ac: if(flags.b.s1 == 0) regs.pc = jp; return; //JNSB1
|
||||||
case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jp; return; //JSB1
|
case 0x0ae: if(flags.b.s1 == 1) regs.pc = jp; return; //JSB1
|
||||||
|
|
||||||
case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jp; return; //JDPL0
|
case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jp; return; //JDPL0
|
||||||
case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jp; return; //JDPLN0
|
case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jp; return; //JDPLN0
|
||||||
case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jp; return; //JDPLF
|
case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jp; return; //JDPLF
|
||||||
case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jp; return; //JDPLNF
|
case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jp; return; //JDPLNF
|
||||||
|
|
||||||
|
//serial input/output acknowledge not emulated
|
||||||
|
case 0x0b4: if(0) regs.pc = jp; return; //JNSIAK
|
||||||
|
case 0x0b6: if(0) regs.pc = jp; return; //JSIAK
|
||||||
|
case 0x0b8: if(0) regs.pc = jp; return; //JNSOAK
|
||||||
|
case 0x0ba: if(0) regs.pc = jp; return; //JSOAK
|
||||||
|
|
||||||
case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jp; return; //JNRQM
|
case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jp; return; //JNRQM
|
||||||
case 0x0be: if(regs.sr.rqm == 1) regs.pc = jp; return; //JRQM
|
case 0x0be: if(regs.sr.rqm == 1) regs.pc = jp; return; //JRQM
|
||||||
|
|
||||||
|
@ -209,7 +237,7 @@ auto uPD96050::execLD(uint24 opcode) -> void {
|
||||||
case 4: regs.dp = id; break;
|
case 4: regs.dp = id; break;
|
||||||
case 5: regs.rp = id; break;
|
case 5: regs.rp = id; break;
|
||||||
case 6: regs.dr = id; regs.sr.rqm = 1; break;
|
case 6: regs.dr = id; regs.sr.rqm = 1; break;
|
||||||
case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); break;
|
case 7: regs.sr = regs.sr & 0x907c | id & ~0x907c; break;
|
||||||
case 8: regs.so = id; break; //LSB
|
case 8: regs.so = id; break; //LSB
|
||||||
case 9: regs.so = id; break; //MSB
|
case 9: regs.so = id; break; //MSB
|
||||||
case 10: regs.k = id; break;
|
case 10: regs.k = id; break;
|
||||||
|
|
|
@ -1,27 +1,50 @@
|
||||||
auto uPD96050::serialize(serializer& s) -> void {
|
auto uPD96050::serialize(serializer& s) -> void {
|
||||||
s.array(dataRAM);
|
s.array(dataRAM);
|
||||||
|
regs.serialize(s);
|
||||||
s.array(regs.stack);
|
flags.a.serialize(s);
|
||||||
s.integer(regs.pc);
|
flags.b.serialize(s);
|
||||||
s.integer(regs.rp);
|
}
|
||||||
s.integer(regs.dp);
|
|
||||||
s.integer(regs.sp);
|
auto uPD96050::Flag::serialize(serializer& s) -> void {
|
||||||
|
s.boolean(ov0);
|
||||||
s.integer(regs.k);
|
s.boolean(ov1);
|
||||||
s.integer(regs.l);
|
s.boolean(z);
|
||||||
s.integer(regs.m);
|
s.boolean(c);
|
||||||
s.integer(regs.n);
|
s.boolean(s0);
|
||||||
s.integer(regs.a);
|
s.boolean(s1);
|
||||||
s.integer(regs.b);
|
s.array(ovh);
|
||||||
|
}
|
||||||
s.integer(regs.flaga.data);
|
|
||||||
s.integer(regs.flagb.data);
|
auto uPD96050::Status::serialize(serializer& s) -> void {
|
||||||
|
s.boolean(p0);
|
||||||
s.integer(regs.tr);
|
s.boolean(p1);
|
||||||
s.integer(regs.trb);
|
s.boolean(ei);
|
||||||
|
s.boolean(sic);
|
||||||
s.integer(regs.sr.data);
|
s.boolean(soc);
|
||||||
s.integer(regs.dr);
|
s.boolean(drc);
|
||||||
s.integer(regs.si);
|
s.boolean(dma);
|
||||||
s.integer(regs.so);
|
s.boolean(drs);
|
||||||
|
s.boolean(uf0);
|
||||||
|
s.boolean(uf1);
|
||||||
|
s.boolean(rqm);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto uPD96050::Registers::serialize(serializer& s) -> void {
|
||||||
|
s.array(stack);
|
||||||
|
s.integer(pc);
|
||||||
|
s.integer(rp);
|
||||||
|
s.integer(dp);
|
||||||
|
s.integer(sp);
|
||||||
|
s.integer(si);
|
||||||
|
s.integer(so);
|
||||||
|
s.integer(k);
|
||||||
|
s.integer(l);
|
||||||
|
s.integer(m);
|
||||||
|
s.integer(n);
|
||||||
|
s.integer(a);
|
||||||
|
s.integer(b);
|
||||||
|
s.integer(tr);
|
||||||
|
s.integer(trb);
|
||||||
|
s.integer(dr);
|
||||||
|
sr.serialize(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,14 +32,14 @@ auto uPD96050::power() -> void {
|
||||||
regs.n = 0x0000;
|
regs.n = 0x0000;
|
||||||
regs.a = 0x0000;
|
regs.a = 0x0000;
|
||||||
regs.b = 0x0000;
|
regs.b = 0x0000;
|
||||||
regs.flaga = 0x00;
|
|
||||||
regs.flagb = 0x00;
|
|
||||||
regs.tr = 0x0000;
|
regs.tr = 0x0000;
|
||||||
regs.trb = 0x0000;
|
regs.trb = 0x0000;
|
||||||
regs.sr = 0x0000;
|
|
||||||
regs.dr = 0x0000;
|
regs.dr = 0x0000;
|
||||||
regs.si = 0x0000;
|
regs.si = 0x0000;
|
||||||
regs.so = 0x0000;
|
regs.so = 0x0000;
|
||||||
|
|
||||||
|
flags.a = 0x0000;
|
||||||
|
flags.b = 0x0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
//NEC uPD7720 (not supported)
|
|
||||||
//NEC uPD7725
|
//NEC uPD7725
|
||||||
//NEC uPD96050
|
//NEC uPD96050
|
||||||
|
|
||||||
|
@ -33,62 +32,95 @@ struct uPD96050 {
|
||||||
uint16 dataRAM[2048];
|
uint16 dataRAM[2048];
|
||||||
|
|
||||||
struct Flag {
|
struct Flag {
|
||||||
union {
|
inline operator uint() const {
|
||||||
uint8_t data = 0;
|
return ov0 << 0 | ov1 << 1 | z << 2 | c << 3 | s0 << 4 | s1 << 5;
|
||||||
BooleanBitField<uint8_t, 5> s1;
|
}
|
||||||
BooleanBitField<uint8_t, 4> s0;
|
|
||||||
BooleanBitField<uint8_t, 3> c;
|
|
||||||
BooleanBitField<uint8_t, 2> z;
|
|
||||||
BooleanBitField<uint8_t, 1> ov1;
|
|
||||||
BooleanBitField<uint8_t, 0> ov0;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline operator uint() const { return data & 0x3f; }
|
inline auto operator=(uint16 data) -> Flag& {
|
||||||
inline auto& operator=(uint value) { return data = value, *this; }
|
ov0 = data.bit(0);
|
||||||
inline auto& operator=(const Flag& value) { return data = value.data, *this; }
|
ov1 = data.bit(1);
|
||||||
|
z = data.bit(2);
|
||||||
|
c = data.bit(3);
|
||||||
|
s0 = data.bit(4);
|
||||||
|
s1 = data.bit(5);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
|
boolean ov0; //overflow 0
|
||||||
|
boolean ov1; //overflow 1
|
||||||
|
boolean z; //zero
|
||||||
|
boolean c; //carry
|
||||||
|
boolean s0; //sign 0
|
||||||
|
boolean s1; //sign 1
|
||||||
|
|
||||||
|
boolean ovh[3]; //overflow history (internal)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Status {
|
struct Status {
|
||||||
union {
|
inline operator uint() const {
|
||||||
uint16_t data = 0;
|
bool _drs = drs & !drc; //when DRC=1, DRS=0
|
||||||
BooleanBitField<uint16_t, 15> rqm;
|
return p0 << 0 | p1 << 1 | ei << 7 | sic << 8 | soc << 9 | drc << 10
|
||||||
BooleanBitField<uint16_t, 14> usf1;
|
| dma << 11 | _drs << 12 | uf0 << 13 | uf1 << 14 | rqm << 15;
|
||||||
BooleanBitField<uint16_t, 13> usf0;
|
}
|
||||||
BooleanBitField<uint16_t, 12> drs;
|
|
||||||
BooleanBitField<uint16_t, 11> dma;
|
inline auto operator=(uint16 data) -> Status& {
|
||||||
BooleanBitField<uint16_t, 10> drc;
|
p0 = data.bit( 0);
|
||||||
BooleanBitField<uint16_t, 9> soc;
|
p1 = data.bit( 1);
|
||||||
BooleanBitField<uint16_t, 8> sic;
|
ei = data.bit( 7);
|
||||||
BooleanBitField<uint16_t, 7> ei;
|
sic = data.bit( 8);
|
||||||
BooleanBitField<uint16_t, 1> p1;
|
soc = data.bit( 9);
|
||||||
BooleanBitField<uint16_t, 0> p0;
|
drc = data.bit(10);
|
||||||
|
dma = data.bit(11);
|
||||||
|
drs = data.bit(12);
|
||||||
|
uf0 = data.bit(13);
|
||||||
|
uf1 = data.bit(14);
|
||||||
|
rqm = data.bit(15);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
|
boolean p0; //output port 0
|
||||||
|
boolean p1; //output port 1
|
||||||
|
boolean ei; //enable interrupts
|
||||||
|
boolean sic; //serial input control (0 = 16-bit; 1 = 8-bit)
|
||||||
|
boolean soc; //serial output control (0 = 16-bit; 1 = 8-bit)
|
||||||
|
boolean drc; //data register size (0 = 16-bit; 1 = 8-bit)
|
||||||
|
boolean dma; //data register DMA mode
|
||||||
|
boolean drs; //data register status (1 = active; 0 = stopped)
|
||||||
|
boolean uf0; //user flag 0
|
||||||
|
boolean uf1; //user flag 1
|
||||||
|
boolean rqm; //request mode (=1 on internal access; =0 on external access)
|
||||||
};
|
};
|
||||||
|
|
||||||
inline operator uint() const { return data & 0xff83; }
|
struct Registers {
|
||||||
inline auto& operator=(uint value) { return data = value, *this; }
|
auto serialize(serializer&) -> void;
|
||||||
};
|
|
||||||
|
|
||||||
struct Regs {
|
|
||||||
uint16 stack[16]; //LIFO
|
uint16 stack[16]; //LIFO
|
||||||
VariadicNatural pc; //program counter
|
VariadicNatural pc; //program counter
|
||||||
VariadicNatural rp; //ROM pointer
|
VariadicNatural rp; //ROM pointer
|
||||||
VariadicNatural dp; //data pointer
|
VariadicNatural dp; //data pointer
|
||||||
uint4 sp; //stack pointer
|
uint4 sp; //stack pointer
|
||||||
|
uint16 si; //serial input
|
||||||
|
uint16 so; //serial output
|
||||||
int16 k;
|
int16 k;
|
||||||
int16 l;
|
int16 l;
|
||||||
int16 m;
|
int16 m;
|
||||||
int16 n;
|
int16 n;
|
||||||
int16 a; //accumulator
|
int16 a; //accumulator
|
||||||
int16 b; //accumulator
|
int16 b; //accumulator
|
||||||
Flag flaga;
|
|
||||||
Flag flagb;
|
|
||||||
uint16 tr; //temporary register
|
uint16 tr; //temporary register
|
||||||
uint16 trb; //temporary register
|
uint16 trb; //temporary register
|
||||||
Status sr; //status register
|
|
||||||
uint16 dr; //data register
|
uint16 dr; //data register
|
||||||
uint16 si;
|
Status sr; //status register
|
||||||
uint16 so;
|
|
||||||
} regs;
|
} regs;
|
||||||
|
|
||||||
|
struct Flags {
|
||||||
|
Flag a;
|
||||||
|
Flag b;
|
||||||
|
} flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) {
|
||||||
auto AudioSettings::updateDevice() -> void {
|
auto AudioSettings::updateDevice() -> void {
|
||||||
frequencyList.reset();
|
frequencyList.reset();
|
||||||
for(auto& frequency : audio->availableFrequencies()) {
|
for(auto& frequency : audio->availableFrequencies()) {
|
||||||
frequencyList.append(ComboButtonItem().setText(frequency));
|
frequencyList.append(ComboButtonItem().setText((uint)frequency));
|
||||||
if(frequency == settings["Audio/Frequency"].real()) {
|
if(frequency == settings["Audio/Frequency"].real()) {
|
||||||
frequencyList.item(frequencyList.itemCount() - 1).setSelected();
|
frequencyList.item(frequencyList.itemCount() - 1).setSelected();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,9 @@ struct AudioSettings : TabFrameItem {
|
||||||
Label deviceLabel{&controlLayout, Size{0, 0}};
|
Label deviceLabel{&controlLayout, Size{0, 0}};
|
||||||
ComboButton deviceList{&controlLayout, Size{~0, 0}};
|
ComboButton deviceList{&controlLayout, Size{~0, 0}};
|
||||||
Label frequencyLabel{&controlLayout, Size{0, 0}};
|
Label frequencyLabel{&controlLayout, Size{0, 0}};
|
||||||
ComboButton frequencyList{&controlLayout, Size{~0, 0}};
|
ComboButton frequencyList{&controlLayout, Size{80, 0}};
|
||||||
Label latencyLabel{&controlLayout, Size{0, 0}};
|
Label latencyLabel{&controlLayout, Size{0, 0}};
|
||||||
ComboButton latencyList{&controlLayout, Size{~0, 0}};
|
ComboButton latencyList{&controlLayout, Size{80, 0}};
|
||||||
CheckLabel exclusiveMode{&layout, Size{~0, 0}};
|
CheckLabel exclusiveMode{&layout, Size{~0, 0}};
|
||||||
Label effectsLabel{&layout, Size{~0, 0}, 2};
|
Label effectsLabel{&layout, Size{~0, 0}, 2};
|
||||||
HorizontalLayout volumeLayout{&layout, Size{~0, 0}};
|
HorizontalLayout volumeLayout{&layout, Size{~0, 0}};
|
||||||
|
|
Loading…
Reference in New Issue