Skip to content

Commit

Permalink
perf: display optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
rkdud007 committed Nov 15, 2024
1 parent 3fa5a48 commit 53febd5
Show file tree
Hide file tree
Showing 6 changed files with 447 additions and 241 deletions.
37 changes: 37 additions & 0 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
EmuTest:testExecuteADD_I_VX() (gas: 112007)
EmuTest:testExecuteADD_VX_NN() (gas: 87897)
EmuTest:testExecuteADD_VX_VY() (gas: 92135)
EmuTest:testExecuteAND_VX_VY() (gas: 89401)
EmuTest:testExecuteCALL_ADDR() (gas: 112333)
EmuTest:testExecuteCLS() (gas: 86080)
EmuTest:testExecuteDRW_VX_VY_N() (gas: 342323)
EmuTest:testExecuteJP_ADDR() (gas: 63925)
EmuTest:testExecuteJP_V0_ADDR() (gas: 88069)
EmuTest:testExecuteLD_B_VX() (gas: 139587)
EmuTest:testExecuteLD_DT_VX() (gas: 110533)
EmuTest:testExecuteLD_F_VX() (gas: 111000)
EmuTest:testExecuteLD_I_ADDR() (gas: 86549)
EmuTest:testExecuteLD_I_VX() (gas: 183907)
EmuTest:testExecuteLD_ST_VX() (gas: 110648)
EmuTest:testExecuteLD_VX_DT() (gas: 110262)
EmuTest:testExecuteLD_VX_I() (gas: 183325)
EmuTest:testExecuteLD_VX_K() (gas: 125347)
EmuTest:testExecuteLD_VX_NN() (gas: 86280)
EmuTest:testExecuteLD_VX_VY() (gas: 87927)
EmuTest:testExecuteNOP() (gas: 47714)
EmuTest:testExecuteOR_VX_VY() (gas: 89529)
EmuTest:testExecuteRET() (gas: 95008)
EmuTest:testExecuteRND_VX_NN() (gas: 87591)
EmuTest:testExecuteSE_VX_NN() (gas: 89440)
EmuTest:testExecuteSE_VX_VY() (gas: 91089)
EmuTest:testExecuteSHL_VX_VY() (gas: 90803)
EmuTest:testExecuteSHR_VX_VY() (gas: 90570)
EmuTest:testExecuteSKNP_VX() (gas: 92714)
EmuTest:testExecuteSKP_VX() (gas: 113723)
EmuTest:testExecuteSNE_VX_NN() (gas: 89513)
EmuTest:testExecuteSNE_VX_VY() (gas: 91675)
EmuTest:testExecuteSUBN_VX_VY() (gas: 92777)
EmuTest:testExecuteSUB_VX_VY() (gas: 92393)
EmuTest:testExecuteUnknownOpcode() (gas: 64227)
EmuTest:testExecuteXOR_VX_VY() (gas: 89448)
EmuTest:testReset() (gas: 130454)
1 change: 1 addition & 0 deletions desktop/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions desktop/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
bitvec = "1.0.1"
sdl2 = "^0.34.3"
alloy = { version = "=0.5.4", features = [
"full",
Expand Down
192 changes: 116 additions & 76 deletions desktop/src/main.rs

Large diffs are not rendered by default.

163 changes: 145 additions & 18 deletions src/Emu.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,105 @@ contract Emu {
// Display
// -------------------------------------------------------------------------

/// @notice fontset size
uint8 constant FONTSET_SIZE = 80;

/// @notice fontset
/// @dev Most modern emulators will use that space to store the sprite data for font characters of all the
/// hexadecimal digits, that is characters of 0-9 and A-F. We could store this data at any fixed position in RAM, but this
/// space is already defined as empty anyway. Each character is made up of eight rows of five pixels, with each row using
/// a byte of data, meaning that each letter altogether takes up five bytes of data. The following diagram illustrates how
/// a character is stored as bytes
uint8[FONTSET_SIZE] FONTSET = [
0xF0,
0x90,
0x90,
0x90,
0xF0, // 0
0x20,
0x60,
0x20,
0x20,
0x70, // 1
0xF0,
0x10,
0xF0,
0x80,
0xF0, // 2
0xF0,
0x10,
0xF0,
0x10,
0xF0, // 3
0x90,
0x90,
0xF0,
0x10,
0x10, // 4
0xF0,
0x80,
0xF0,
0x10,
0xF0, // 5
0xF0,
0x80,
0xF0,
0x90,
0xF0, // 6
0xF0,
0x10,
0x20,
0x40,
0x40, // 7
0xF0,
0x90,
0xF0,
0x90,
0xF0, // 8
0xF0,
0x90,
0xF0,
0x10,
0xF0, // 9
0xF0,
0x90,
0xF0,
0x90,
0x90, // A
0xE0,
0x90,
0xE0,
0x90,
0xE0, // B
0xF0,
0x80,
0x80,
0x80,
0xF0, // C
0xE0,
0x90,
0x90,
0x90,
0xE0, // D
0xF0,
0x80,
0xF0,
0x80,
0xF0, // E
0xF0,
0x80,
0xF0,
0x80,
0x80 // F
];

struct Emulator {
/// @notice 16-bit program counter
uint16 pc;
/// @notice 4KB RAM
uint8[RAM_SIZE] ram;
/// @notice A 64x32 monochrome display
bool[SCREEN_WIDTH * SCREEN_HEIGHT] screen;
/// @notice A 64x32 monochrome display = 2048 bit = 256 * 8 bits
uint256[8] screen;
/// @notice Sixteen 8-bit general purpose registers, referred to as V0 thru VF
uint8[NUM_REGS] v_reg;
/// @notice Single 16-bit register used as a pointer for memory access, called the I Register
Expand Down Expand Up @@ -63,13 +155,16 @@ contract Emu {

constructor() {
emu.pc = START_ADDR;
for (uint256 i = 0; i < FONTSET_SIZE; i++) {
emu.ram[i] = FONTSET[i];
}
}

/// @notice Reset the emulator
function reset() public {
emu.pc = START_ADDR;
for (uint256 i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++) {
emu.screen[i] = false;
for (uint256 i = 0; i < 8; i++) {
emu.screen[i] = 0;
}
for (uint256 i = 0; i < NUM_REGS; i++) {
emu.v_reg[i] = 0;
Expand All @@ -84,6 +179,10 @@ contract Emu {
}
emu.dt = 0;
emu.st = 0;
// Copy FONTSET
for (uint256 i = 0; i < FONTSET_SIZE; i++) {
emu.ram[i] = FONTSET[i];
}
}

// -------------------------------------------------------------------------
Expand Down Expand Up @@ -159,8 +258,8 @@ contract Emu {

// 00E0 - CLS
if (digit1 == 0x0 && digit2 == 0x0 && digit3 == 0xE && digit4 == 0) {
for (uint256 i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++) {
emu.screen[i] = false;
for (uint256 i = 0; i < 8; i++) {
emu.screen[i] = 0;
}
return;
}
Expand Down Expand Up @@ -321,17 +420,39 @@ contract Emu {
for (uint8 row = 0; row < height; row++) {
uint8 sprite_byte = emu.ram[emu.i_reg + row];
for (uint8 col = 0; col < 8; col++) {
// Get the sprite pixel (bit) at the current column
uint8 sprite_pixel = (sprite_byte >> (7 - col)) & 0x1;

// Calculate the screen coordinates, wrapping around if necessary
uint32 screen_x = uint32((x + col) % SCREEN_WIDTH);
uint32 screen_y = uint32((y + row) % SCREEN_HEIGHT);
uint256 index = screen_y * SCREEN_WIDTH + screen_x;

bool pixel_before = emu.screen[index];
// Calculate the index in the display buffer
uint32 pixel_index = screen_y * SCREEN_WIDTH + screen_x; // Range: 0 to 2047

// Calculate the display array index and bit position
uint256 display_index = pixel_index / 256; // Index in emu.screen[]
uint256 bit_position = pixel_index % 256; // Bit position within emu.screen[display_index]

// Get the current pixel value from the display
bool pixel_before = ((emu.screen[display_index] >> (255 - bit_position)) & 0x1) != 0;

// Calculate the new pixel value using XOR (as per CHIP-8 drawing behavior)
bool new_pixel = pixel_before != (sprite_pixel == 1);

// Update the collision flag VF if a pixel is erased
if (pixel_before && !new_pixel) {
emu.v_reg[0xF] = 1;
}
emu.screen[index] = new_pixel;

// Update the display with the new pixel value
if (new_pixel) {
// Set the bit to 1
emu.screen[display_index] |= (1 << (255 - bit_position));
} else {
// Set the bit to 0
emu.screen[display_index] &= ~(1 << (255 - bit_position));
}
}
}
return;
Expand Down Expand Up @@ -438,7 +559,7 @@ contract Emu {
// -------------------------------------------------------------------------

/// @notice Get display
function getDisplay() public view returns (bool[SCREEN_WIDTH * SCREEN_HEIGHT] memory) {
function getDisplay() public view returns (uint256[8] memory) {
return emu.screen;
}

Expand Down Expand Up @@ -530,16 +651,22 @@ contract Emu {
}

function setScreenPixel(uint256 index, bool value) public {
require(index < SCREEN_WIDTH * SCREEN_HEIGHT, "Index out of bounds");
emu.screen[index] = value;
unchecked {
require(index < SCREEN_WIDTH * SCREEN_HEIGHT, "Index out of bounds");
if (value) {
// Set the bit to 1
emu.screen[index >> 8] |= 1 << (index & 255);
} else {
// Set the bit to 0
emu.screen[index >> 8] &= ~(1 << (index & 255));
}
}
}

function isDisplayCleared() public view returns (bool) {
for (uint256 i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++) {
if (emu.screen[i]) {
return false;
}
}
return true;
return (
emu.screen[0] == 0 && emu.screen[1] == 0 && emu.screen[2] == 0 && emu.screen[3] == 0 && emu.screen[4] == 0
&& emu.screen[5] == 0 && emu.screen[6] == 0 && emu.screen[7] == 0
);
}
}
Loading

0 comments on commit 53febd5

Please sign in to comment.