bsnes/higan/gba/cpu/bus.cpp

86 lines
3.0 KiB
C++
Raw Normal View History

Update to v099r13 release. byuu says: Changelog: - GB core code cleanup completed - GBA core code cleanup completed - some more cleanup on missed processor/arm functions/variables - fixed FC loading icarus bug - "Load ROM File" icarus functionality restored - minor code unification efforts all around (not perfect yet) - MMIO->IO - mmio.cpp->io.cpp - read,write->readIO,writeIO It's been a very long work in progress ... starting all the way back with v094r09, but the major part of the higan code cleanup is now completed! Of course, it's very important to note that this is only for the basic style: - under_score functions and variables are now camelCase - return-type function-name() are now auto function-name() -> return-type - Natural<T>/Integer<T> replace (u)intT_n types where possible - signed/unsigned are now int/uint - most of the x==true,x==false tests changed to x,!x A lot of spot improvements to consistency, simplicity and quality have gone in along the way, of course. But we'll probably never fully finishing beautifying every last line of code in the entire codebase. Still, this is a really great start. Going forward, WIP diffs should start being smaller and of higher quality once again. I know the joke is, "until my coding style changes again", but ... this was way too stressful, way too time consuming, and way too risky. I'm too old and tired now for extreme upheavel like this again. The only major change I'm slowly mulling over would be renaming the using Natural<T>/Integer<T> = (u)intT; shorthand to something that isn't as easily confused with the (u)int_t types ... but we'll see. I'll definitely continue to change small things all the time, but for the larger picture, I need to just accept the style I have and live with it.
2016-06-29 11:10:28 +00:00
auto CPU::_idle() -> void {
prefetchStep(1);
}
Update to v099r13 release. byuu says: Changelog: - GB core code cleanup completed - GBA core code cleanup completed - some more cleanup on missed processor/arm functions/variables - fixed FC loading icarus bug - "Load ROM File" icarus functionality restored - minor code unification efforts all around (not perfect yet) - MMIO->IO - mmio.cpp->io.cpp - read,write->readIO,writeIO It's been a very long work in progress ... starting all the way back with v094r09, but the major part of the higan code cleanup is now completed! Of course, it's very important to note that this is only for the basic style: - under_score functions and variables are now camelCase - return-type function-name() are now auto function-name() -> return-type - Natural<T>/Integer<T> replace (u)intT_n types where possible - signed/unsigned are now int/uint - most of the x==true,x==false tests changed to x,!x A lot of spot improvements to consistency, simplicity and quality have gone in along the way, of course. But we'll probably never fully finishing beautifying every last line of code in the entire codebase. Still, this is a really great start. Going forward, WIP diffs should start being smaller and of higher quality once again. I know the joke is, "until my coding style changes again", but ... this was way too stressful, way too time consuming, and way too risky. I'm too old and tired now for extreme upheavel like this again. The only major change I'm slowly mulling over would be renaming the using Natural<T>/Integer<T> = (u)intT; shorthand to something that isn't as easily confused with the (u)int_t types ... but we'll see. I'll definitely continue to change small things all the time, but for the larger picture, I need to just accept the style I have and live with it.
2016-06-29 11:10:28 +00:00
auto CPU::_read(uint mode, uint32 addr) -> uint32 {
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
uint clocks = _wait(mode, addr);
Update to v098r06 release. byuu says: Changelog: - emulation cores now refresh video from host thread instead of cothreads (fix AMD crash) - SFC: fixed another bug with leap year months in SharpRTC emulation - SFC: cleaned up camelCase on function names for armdsp,epsonrtc,hitachidsp,mcc,nss,sharprtc classes - GB: added MBC1M emulation (requires manually setting mapper=MBC1M in manifest.bml for now, sorry) - audio: implemented Emulator::Audio mixer and effects processor - audio: implemented Emulator::Stream interface - it is now possible to have more than two audio streams: eg SNES + SGB + MSU1 + Voicer-Kun (eventually) - audio: added reverb delay + reverb level settings; exposed balance configuration in UI - video: reworked palette generation to re-enable saturation, gamma, luminance adjustments - higan/emulator.cpp is gone since there was nothing left in it I know you guys are going to say the color adjust/balance/reverb stuff is pointless. And indeed it mostly is. But I like the idea of allowing some fun special effects and configurability that isn't system-wide. Note: there seems to be some kind of added audio lag in the SGB emulation now, and I don't really understand why. The code should be effectively identical to what I had before. The only main thing is that I'm sampling things to 48000hz instead of 32040hz before mixing. There's no point where I'm intentionally introducing added latency though. I'm kind of stumped, so if anyone wouldn't mind taking a look at it, it'd be much appreciated :/ I don't have an MSU1 test ROM, but the latency issue may affect MSU1 as well, and that would be very bad.
2016-04-22 13:35:51 +00:00
uint word = pipeline.fetch.instruction;
if(addr >= 0x1000'0000) {
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
prefetchStep(clocks);
} else if(addr & 0x0800'0000) {
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
if(mode & Prefetch && wait.prefetch) {
Update to v099r13 release. byuu says: Changelog: - GB core code cleanup completed - GBA core code cleanup completed - some more cleanup on missed processor/arm functions/variables - fixed FC loading icarus bug - "Load ROM File" icarus functionality restored - minor code unification efforts all around (not perfect yet) - MMIO->IO - mmio.cpp->io.cpp - read,write->readIO,writeIO It's been a very long work in progress ... starting all the way back with v094r09, but the major part of the higan code cleanup is now completed! Of course, it's very important to note that this is only for the basic style: - under_score functions and variables are now camelCase - return-type function-name() are now auto function-name() -> return-type - Natural<T>/Integer<T> replace (u)intT_n types where possible - signed/unsigned are now int/uint - most of the x==true,x==false tests changed to x,!x A lot of spot improvements to consistency, simplicity and quality have gone in along the way, of course. But we'll probably never fully finishing beautifying every last line of code in the entire codebase. Still, this is a really great start. Going forward, WIP diffs should start being smaller and of higher quality once again. I know the joke is, "until my coding style changes again", but ... this was way too stressful, way too time consuming, and way too risky. I'm too old and tired now for extreme upheavel like this again. The only major change I'm slowly mulling over would be renaming the using Natural<T>/Integer<T> = (u)intT; shorthand to something that isn't as easily confused with the (u)int_t types ... but we'll see. I'll definitely continue to change small things all the time, but for the larger picture, I need to just accept the style I have and live with it.
2016-06-29 11:10:28 +00:00
prefetchSync(addr);
word = prefetchRead();
if(mode & Word) word |= prefetchRead() << 16;
} else {
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
if(!context.dmaActive) prefetchWait();
step(clocks - 1);
word = cartridge.read(mode, addr);
step(1);
}
} else {
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
prefetchStep(clocks - 1);
if(addr < 0x0200'0000) word = bios.read(mode, addr);
Update to v099r13 release. byuu says: Changelog: - GB core code cleanup completed - GBA core code cleanup completed - some more cleanup on missed processor/arm functions/variables - fixed FC loading icarus bug - "Load ROM File" icarus functionality restored - minor code unification efforts all around (not perfect yet) - MMIO->IO - mmio.cpp->io.cpp - read,write->readIO,writeIO It's been a very long work in progress ... starting all the way back with v094r09, but the major part of the higan code cleanup is now completed! Of course, it's very important to note that this is only for the basic style: - under_score functions and variables are now camelCase - return-type function-name() are now auto function-name() -> return-type - Natural<T>/Integer<T> replace (u)intT_n types where possible - signed/unsigned are now int/uint - most of the x==true,x==false tests changed to x,!x A lot of spot improvements to consistency, simplicity and quality have gone in along the way, of course. But we'll probably never fully finishing beautifying every last line of code in the entire codebase. Still, this is a really great start. Going forward, WIP diffs should start being smaller and of higher quality once again. I know the joke is, "until my coding style changes again", but ... this was way too stressful, way too time consuming, and way too risky. I'm too old and tired now for extreme upheavel like this again. The only major change I'm slowly mulling over would be renaming the using Natural<T>/Integer<T> = (u)intT; shorthand to something that isn't as easily confused with the (u)int_t types ... but we'll see. I'll definitely continue to change small things all the time, but for the larger picture, I need to just accept the style I have and live with it.
2016-06-29 11:10:28 +00:00
else if(addr < 0x0300'0000) word = readEWRAM(mode, addr);
else if(addr < 0x0400'0000) word = readIWRAM(mode, addr);
else if(addr >= 0x0700'0000) word = ppu.readOAM(mode, addr);
else if(addr >= 0x0600'0000) word = ppu.readVRAM(mode, addr);
else if(addr >= 0x0500'0000) word = ppu.readPRAM(mode, addr);
else if((addr & 0xffff'fc00) == 0x0400'0000) word = bus.io[addr & 0x3ff]->readIO(mode, addr);
else if((addr & 0xff00'ffff) == 0x0400'0800) word = ((IO*)this)->readIO(mode, 0x0400'0800 | (addr & 3));
prefetchStep(1);
}
return word;
}
Update to v099r13 release. byuu says: Changelog: - GB core code cleanup completed - GBA core code cleanup completed - some more cleanup on missed processor/arm functions/variables - fixed FC loading icarus bug - "Load ROM File" icarus functionality restored - minor code unification efforts all around (not perfect yet) - MMIO->IO - mmio.cpp->io.cpp - read,write->readIO,writeIO It's been a very long work in progress ... starting all the way back with v094r09, but the major part of the higan code cleanup is now completed! Of course, it's very important to note that this is only for the basic style: - under_score functions and variables are now camelCase - return-type function-name() are now auto function-name() -> return-type - Natural<T>/Integer<T> replace (u)intT_n types where possible - signed/unsigned are now int/uint - most of the x==true,x==false tests changed to x,!x A lot of spot improvements to consistency, simplicity and quality have gone in along the way, of course. But we'll probably never fully finishing beautifying every last line of code in the entire codebase. Still, this is a really great start. Going forward, WIP diffs should start being smaller and of higher quality once again. I know the joke is, "until my coding style changes again", but ... this was way too stressful, way too time consuming, and way too risky. I'm too old and tired now for extreme upheavel like this again. The only major change I'm slowly mulling over would be renaming the using Natural<T>/Integer<T> = (u)intT; shorthand to something that isn't as easily confused with the (u)int_t types ... but we'll see. I'll definitely continue to change small things all the time, but for the larger picture, I need to just accept the style I have and live with it.
2016-06-29 11:10:28 +00:00
auto CPU::_write(uint mode, uint32 addr, uint32 word) -> void {
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
uint clocks = _wait(mode, addr);
if(addr >= 0x1000'0000) {
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
prefetchStep(clocks);
} else if(addr & 0x0800'0000) {
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
if(!context.dmaActive) prefetchWait();
step(clocks);
cartridge.write(mode, addr, word);
} else {
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
prefetchStep(clocks);
if(addr < 0x0200'0000);
Update to v099r13 release. byuu says: Changelog: - GB core code cleanup completed - GBA core code cleanup completed - some more cleanup on missed processor/arm functions/variables - fixed FC loading icarus bug - "Load ROM File" icarus functionality restored - minor code unification efforts all around (not perfect yet) - MMIO->IO - mmio.cpp->io.cpp - read,write->readIO,writeIO It's been a very long work in progress ... starting all the way back with v094r09, but the major part of the higan code cleanup is now completed! Of course, it's very important to note that this is only for the basic style: - under_score functions and variables are now camelCase - return-type function-name() are now auto function-name() -> return-type - Natural<T>/Integer<T> replace (u)intT_n types where possible - signed/unsigned are now int/uint - most of the x==true,x==false tests changed to x,!x A lot of spot improvements to consistency, simplicity and quality have gone in along the way, of course. But we'll probably never fully finishing beautifying every last line of code in the entire codebase. Still, this is a really great start. Going forward, WIP diffs should start being smaller and of higher quality once again. I know the joke is, "until my coding style changes again", but ... this was way too stressful, way too time consuming, and way too risky. I'm too old and tired now for extreme upheavel like this again. The only major change I'm slowly mulling over would be renaming the using Natural<T>/Integer<T> = (u)intT; shorthand to something that isn't as easily confused with the (u)int_t types ... but we'll see. I'll definitely continue to change small things all the time, but for the larger picture, I need to just accept the style I have and live with it.
2016-06-29 11:10:28 +00:00
else if(addr < 0x0300'0000) writeEWRAM(mode, addr, word);
else if(addr < 0x0400'0000) writeIWRAM(mode, addr, word);
else if(addr >= 0x0700'0000) ppu.writeOAM(mode, addr, word);
else if(addr >= 0x0600'0000) ppu.writeVRAM(mode, addr, word);
else if(addr >= 0x0500'0000) ppu.writePRAM(mode, addr, word);
else if((addr & 0xffff'fc00) == 0x0400'0000) bus.io[addr & 0x3ff]->writeIO(mode, addr, word);
else if((addr & 0xff00'ffff) == 0x0400'0800) ((IO*)this)->writeIO(mode, 0x0400'0800 | (addr & 3), word);
}
}
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
auto CPU::_wait(uint mode, uint32 addr) -> uint {
if(addr >= 0x1000'0000) return 1; //unmapped
if(addr < 0x0200'0000) return 1;
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
if(addr < 0x0300'0000) return (16 - memory.ewramWait) * (mode & Word ? 2 : 1);
if(addr < 0x0500'0000) return 1;
if(addr < 0x0700'0000) return mode & Word ? 2 : 1;
if(addr < 0x0800'0000) return 1;
Update to v098r06 release. byuu says: Changelog: - emulation cores now refresh video from host thread instead of cothreads (fix AMD crash) - SFC: fixed another bug with leap year months in SharpRTC emulation - SFC: cleaned up camelCase on function names for armdsp,epsonrtc,hitachidsp,mcc,nss,sharprtc classes - GB: added MBC1M emulation (requires manually setting mapper=MBC1M in manifest.bml for now, sorry) - audio: implemented Emulator::Audio mixer and effects processor - audio: implemented Emulator::Stream interface - it is now possible to have more than two audio streams: eg SNES + SGB + MSU1 + Voicer-Kun (eventually) - audio: added reverb delay + reverb level settings; exposed balance configuration in UI - video: reworked palette generation to re-enable saturation, gamma, luminance adjustments - higan/emulator.cpp is gone since there was nothing left in it I know you guys are going to say the color adjust/balance/reverb stuff is pointless. And indeed it mostly is. But I like the idea of allowing some fun special effects and configurability that isn't system-wide. Note: there seems to be some kind of added audio lag in the SGB emulation now, and I don't really understand why. The code should be effectively identical to what I had before. The only main thing is that I'm sampling things to 48000hz instead of 32040hz before mixing. There's no point where I'm intentionally introducing added latency though. I'm kind of stumped, so if anyone wouldn't mind taking a look at it, it'd be much appreciated :/ I don't have an MSU1 test ROM, but the latency issue may affect MSU1 as well, and that would be very bad.
2016-04-22 13:35:51 +00:00
static uint timings[] = {5, 4, 3, 9};
Update to v103r07 release. byuu says: Changelog: - gba/cpu: massive code cleanup effort - gba/cpu: DMA can run in between active instructions¹ - gba/cpu: added two-cycle startup delay between DMA activation and DMA transfers² - processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle - processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle ¹: unfortunately, this causes yet another performance penalty for the poor GBA core =( Also, I think I may have missed disabling DMAs while the CPU is stopped. I'll fix that in the next WIP. ²: I put the waiting counter decrement at the wrong place, so this doesn't actually work. Needs to be more like this:    auto CPU::step(uint clocks) -> void {      for(auto _ : range(clocks)) {        for(auto& timer : this->timer) timer.run();        for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;        context.clock++;      }      ...    auto CPU::DMA::run() -> bool {      if(cpu.stopped() || !active || waiting) return false;      transfer();      if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;      if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;      return true;    } Of course, the real fix will be restructuring how DMA works, so that it's always running in parallel with the CPU instead of this weird design where it tries to run all channels in some kind of loop until no channels are active anymore whenever one channel is activated. Not really sure how to design that yet, however.
2017-07-05 05:29:27 +00:00
uint n = timings[wait.nwait[addr >> 25 & 3]];
uint s = wait.swait[addr >> 25 & 3];
switch(addr & 0x0e00'0000) {
case 0x0800'0000: s = s ? 2 : 3; break;
case 0x0a00'0000: s = s ? 2 : 5; break;
case 0x0c00'0000: s = s ? 2 : 9; break;
case 0x0e00'0000: s = n; break;
}
bool sequential = (mode & Sequential);
if((addr & 0x1fffe) == 0) sequential = false; //N cycle on 16-bit ROM crossing 128KB page boundary (RAM S==N)
Update to v098r06 release. byuu says: Changelog: - emulation cores now refresh video from host thread instead of cothreads (fix AMD crash) - SFC: fixed another bug with leap year months in SharpRTC emulation - SFC: cleaned up camelCase on function names for armdsp,epsonrtc,hitachidsp,mcc,nss,sharprtc classes - GB: added MBC1M emulation (requires manually setting mapper=MBC1M in manifest.bml for now, sorry) - audio: implemented Emulator::Audio mixer and effects processor - audio: implemented Emulator::Stream interface - it is now possible to have more than two audio streams: eg SNES + SGB + MSU1 + Voicer-Kun (eventually) - audio: added reverb delay + reverb level settings; exposed balance configuration in UI - video: reworked palette generation to re-enable saturation, gamma, luminance adjustments - higan/emulator.cpp is gone since there was nothing left in it I know you guys are going to say the color adjust/balance/reverb stuff is pointless. And indeed it mostly is. But I like the idea of allowing some fun special effects and configurability that isn't system-wide. Note: there seems to be some kind of added audio lag in the SGB emulation now, and I don't really understand why. The code should be effectively identical to what I had before. The only main thing is that I'm sampling things to 48000hz instead of 32040hz before mixing. There's no point where I'm intentionally introducing added latency though. I'm kind of stumped, so if anyone wouldn't mind taking a look at it, it'd be much appreciated :/ I don't have an MSU1 test ROM, but the latency issue may affect MSU1 as well, and that would be very bad.
2016-04-22 13:35:51 +00:00
uint clocks = sequential ? s : n;
if(mode & Word) clocks += s; //16-bit bus requires two transfers for words
return clocks;
}