Skip to content

Commit

Permalink
more elaborate memory access, prevents OOB but without wrapping, some…
Browse files Browse the repository at this point in the history
… branch prediction favoritism to single-pixel dxyn (mwhaha) and overall performance boost, now clocking at nearly 6.5m
  • Loading branch information
coornio committed Aug 20, 2024
1 parent e237cd6 commit e80ca8a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 27 deletions.
24 changes: 11 additions & 13 deletions src/GuestClass/EmuCores/CHIP8_MODERN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <utility>

#include "CHIP8_MODERN.hpp"

#include "../../HostClass/HomeDirManager.hpp"
#include "../../HostClass/BasicVideoSpec.hpp"
#include "../../HostClass/BasicAudioSpec.hpp"



CHIP8_MODERN::~CHIP8_MODERN() = default;
CHIP8_MODERN::CHIP8_MODERN(
HomeDirManager& ref_HDM,
Expand All @@ -23,7 +19,7 @@ CHIP8_MODERN::CHIP8_MODERN(
: EmuCores{ ref_HDM, ref_BVS, ref_BAS }
{
copyGameToMemory(mMemoryBank.data(), cGameLoadPos);
copyFontToMemory(mMemoryBank.data(), 0, 80);
copyFontToMemory(mMemoryBank.data(), 0x0, 0x50);

mProgCounter = cStartOffset;
mFramerate = cRefreshRate;
Expand Down Expand Up @@ -110,10 +106,10 @@ void CHIP8_MODERN::instructionLoop() {
}
break;
case 0x1:
instruction_1NNN((HI << 8 | LO) & 0xFFF);
instruction_1NNN(HI << 8 | LO);
break;
case 0x2:
instruction_2NNN((HI << 8 | LO) & 0xFFF);
instruction_2NNN(HI << 8 | LO);
break;
case 0x3:
instruction_3xNN(HI & 0xF, LO);
Expand Down Expand Up @@ -175,14 +171,15 @@ void CHIP8_MODERN::instructionLoop() {
}
break;
case 0xA:
instruction_ANNN((HI << 8 | LO) & 0xFFF);
instruction_ANNN(HI << 8 | LO);
break;
case 0xB:
instruction_BNNN((HI << 8 | LO) & 0xFFF);
instruction_BNNN(HI << 8 | LO);
break;
case 0xC:
instruction_CxNN(HI & 0xF, LO);
break;
[[likely]]
case 0xD:
instruction_DxyN(HI & 0xF, LO >> 4, LO & 0xF);
break;
Expand Down Expand Up @@ -243,13 +240,14 @@ f32 CHIP8_MODERN::calcAudioTone() const {
}

void CHIP8_MODERN::nextInstruction() {
mProgCounter = mProgCounter + 2;
mProgCounter += 2;
}

void CHIP8_MODERN::jumpProgramTo(const s32 next) {
if (mProgCounter - 2 == next) [[unlikely]] {
void CHIP8_MODERN::jumpProgramTo(const u32 next) {
const auto NNN{ next & 0xFFF };
if (mProgCounter - 2u == NNN) [[unlikely]] {
setInterrupt(Interrupt::SOUND);
} else { mProgCounter = static_cast<u16>(next); }
} else { mProgCounter = NNN & 0xFFF; }
}

void CHIP8_MODERN::renderAudioData() {
Expand Down
40 changes: 26 additions & 14 deletions src/GuestClass/EmuCores/CHIP8_MODERN.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#pragma once

#include <array>
#include <utility>

#include "EmuCores.hpp"

Expand Down Expand Up @@ -55,17 +56,17 @@ class CHIP8_MODERN final : public EmuCores {
std::array<u8, cTotalMemory + 31>
mMemoryBank{};

//bool constexpr in_range(const usz pos) const noexcept { return pos < cTotalMemory; }

// Write memory at saved index + offset, using given value
void writeMemoryI(const u32 value, const u32 pos) noexcept {
mMemoryBank[mRegisterI + pos & cTotalMemory - 1u] = static_cast<u8>(value);
//if (in_range(mRegisterI + pos)) { mMemoryBank[mRegisterI + pos] = static_cast<u8>(value); }
//mMemoryBank[mRegisterI + pos & cTotalMemory - 1u] = value & 0xFF;
const auto index{ mRegisterI + pos };
if (!(index & cTotalMemory)) [[likely]]
{ mMemoryBank[index] = value & 0xFF; }
}

// Read memory at saved index + offset
auto readMemoryI(const u32 pos) const noexcept {
//return (in_range(mRegisterI + pos)) ? mMemoryBank[mRegisterI + pos] : 0xFF;
//return mMemoryBank[mRegisterI + pos & cTotalMemory - 1u];
return mMemoryBank[mRegisterI + pos];
}

Expand All @@ -82,7 +83,7 @@ class CHIP8_MODERN final : public EmuCores {
void handleEndFrameInterrupt() noexcept;

f32 calcAudioTone() const;
void jumpProgramTo(s32);
void jumpProgramTo(u32);

/*==================================================================*/
#pragma region 0 instruction branch
Expand Down Expand Up @@ -276,7 +277,7 @@ class CHIP8_MODERN final : public EmuCores {

// ANNN - set I = NNN
void instruction_ANNN(const s32 NNN) {
mRegisterI = static_cast<u16>(NNN);
mRegisterI = NNN & 0xFFF;
}

/*ΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛ*/
Expand Down Expand Up @@ -318,15 +319,20 @@ class CHIP8_MODERN final : public EmuCores {
const usz DATA
) {
switch (DATA) {
[[unlikely]]
case 0b00000000:
return;

[[likely]]
case 0b10000000:
if (Quirk.wrapSprite) { X &= mDisplayWb; }
if (X < mDisplayW) {
if (!(mDisplayBuffer[Y * mDisplayW + X] ^= 1))
{ mRegisterV[0xF] = 1; }
}
return;

[[unlikely]]
default:
if (Quirk.wrapSprite) { X &= mDisplayWb; }
else if (X >= mDisplayW) { return; }
Expand All @@ -353,17 +359,23 @@ class CHIP8_MODERN final : public EmuCores {
mRegisterV[0xF] = 0;

switch (N) {
[[likely]]
case 1:
drawByte(pX, pY, readMemoryI(0));
break;

[[unlikely]]
case 0:
for (auto H{ 0 }, I{ 0 }; H < 16; ++H, ++pY &= mDisplayHb)
for (auto H{ 0 }, I{ 0 }; H < 16; ++H, I += 2, ++pY &= mDisplayHb)
{
drawByte(pX + 0, pY, readMemoryI(I++));
drawByte(pX + 8, pY, readMemoryI(I++));
drawByte(pX + 0, pY, readMemoryI(I + 0));
drawByte(pX + 8, pY, readMemoryI(I + 1));

if (!Quirk.wrapSprite && pY == mDisplayHb) { break; }
}
break;

[[unlikely]]
default:
for (auto H{ 0 }; H < N; ++H, ++pY &= mDisplayHb)
{
Expand Down Expand Up @@ -419,7 +431,7 @@ class CHIP8_MODERN final : public EmuCores {
}
// FX1E - set I = I + VX
void instruction_Fx1E(const s32 X) {
mRegisterI += mRegisterV[X];
(mRegisterI += mRegisterV[X]) &= 0xFFF;
}
// FX29 - point I to 5 byte hex sprite from value in VX
void instruction_Fx29(const s32 X) {
Expand All @@ -436,14 +448,14 @@ class CHIP8_MODERN final : public EmuCores {
for (auto idx{ 0 }; idx <= X; ++idx)
{ writeMemoryI(mRegisterV[idx], idx); }
if (!Quirk.idxRegNoInc) [[likely]]
{ mRegisterI += static_cast<u16>(X + 1); }
{ (mRegisterI += X + 1 & 0xFF) &= 0xFFF; }
}
// FX65 - load V0..VX from RAM at I..I+X
void instruction_Fx65(const s32 X) {
for (auto idx{ 0 }; idx <= X; ++idx)
{ mRegisterV[idx] = static_cast<u8>(readMemoryI(idx)); }
{ mRegisterV[idx] = readMemoryI(idx); }
if (!Quirk.idxRegNoInc) [[likely]]
{ mRegisterI += static_cast<u16>(X + 1); }
{ (mRegisterI += X + 1 & 0xFF) &= 0xFFF; }
}

/*ΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛΛ*/
Expand Down

0 comments on commit e80ca8a

Please sign in to comment.