Skip to content

Commit

Permalink
Merge pull request #32 from Kautenja/backup_restore_memory_leak
Browse files Browse the repository at this point in the history
Backup restore memory leak
  • Loading branch information
Kautenja authored Aug 13, 2018
2 parents 75f89ee + ff4a79e commit 035321b
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 50 deletions.
4 changes: 4 additions & 0 deletions nes_py/laines/cartridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Cartridge::Cartridge(const char* file_name) {
}
}

Cartridge::Cartridge(Cartridge* cart) {
mapper = cart->mapper->copy();
};

Cartridge::~Cartridge() {
delete this->mapper;
}
Expand Down
21 changes: 21 additions & 0 deletions nes_py/laines/gamestate.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
#include "gamestate.hpp"

GameState::GameState() {
ppu_state = new PPUState();
cpu_state = new CPUState();
};

GameState::~GameState() {
delete cartridge;
delete joypad;
delete gui;
delete ppu_state;
delete cpu_state;
}

GameState::GameState(GameState* state) {
cartridge = new Cartridge(state->cartridge);
joypad = new Joypad(state->joypad);
Expand All @@ -8,6 +21,14 @@ GameState::GameState(GameState* state) {
ppu_state = new PPUState(state->ppu_state);
}

GameState::GameState(GameState* state, CPUState* cpu, PPUState* ppu) {
cartridge = new Cartridge(state->cartridge);
joypad = new Joypad(state->joypad);
gui = new GUI(state->gui);
cpu_state = cpu;
ppu_state = ppu;
}

void GameState::load() {
// setup the CPU up
CPU::set_state(cpu_state);
Expand Down
18 changes: 16 additions & 2 deletions nes_py/laines/gui.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
#include "gui.hpp"

unsigned GUI::get_width() { return GUI::WIDTH; }
GUI::GUI() {

unsigned GUI::get_height() { return GUI::HEIGHT; }
};

GUI::GUI(GUI* gui) {
// copy the screen from the other GUI into this GUI
memcpy(screen, gui->screen, WIDTH * HEIGHT * sizeof(u32));
};

unsigned GUI::get_width() {
return GUI::WIDTH;
}

unsigned GUI::get_height() {
return GUI::HEIGHT;
}

void GUI::new_frame(u32* pixels) {
// copy the pixels into the screen array (pointer)
memcpy(this->screen, pixels, this->WIDTH * this->HEIGHT * sizeof(u32));
}

void GUI::copy_screen(unsigned char *output_buffer) {
// copy the screen into the output buffer
memcpy(output_buffer, this->screen, this->WIDTH * this->HEIGHT * sizeof(u32));
}
4 changes: 1 addition & 3 deletions nes_py/laines/include/cartridge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ class Cartridge {
Cartridge(const char* file_name);

/// Initialize a cartridge as a copy of another
Cartridge(Cartridge* cart) {
mapper = cart->mapper->copy();
};
Cartridge(Cartridge* cart);

/// Delete an instance of cartridge
~Cartridge();
Expand Down
9 changes: 5 additions & 4 deletions nes_py/laines/include/gamestate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ class GameState {
CPUState* cpu_state;

/// Initialize a new game-state
GameState() {
ppu_state = new PPUState();
cpu_state = new CPUState();
};
GameState();
/// Delete a game-state
~GameState();
/// create a new game-state as a copy of another
GameState(GameState* state);
/// create a new game-state as a copy of another with different states
GameState(GameState* state, CPUState* new_cpu_state, PPUState* new_ppu_state);
/// Load the game-state's data into the machine
void load();
};
4 changes: 2 additions & 2 deletions nes_py/laines/include/gui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ class GUI {

public:
/// Initialize a new GUI.
GUI() { };
GUI();

/// Initialize a new GUI as a copy of another GUI.
GUI(GUI* gui) { memcpy(screen, gui->screen, WIDTH * HEIGHT * sizeof(u32)); };
GUI(GUI* gui);

/// Return the width of the screen.
static unsigned get_width();
Expand Down
22 changes: 2 additions & 20 deletions nes_py/laines/include/joypad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,10 @@ class Joypad {
public:

/// Initialize a new joy-pad instance
Joypad() {
for (int i = 0; i < NUM_JOYPADS; i++) {
joypad_buttons[i] = 0;
joypad_bits[i] = 0;
}
strobe = false;
};
Joypad();

/// Initialize a new joy-pad as a copy of another
Joypad(Joypad* joypad) {
std::copy(
std::begin(joypad->joypad_buttons),
std::end(joypad->joypad_buttons),
std::begin(joypad_buttons)
);
std::copy(
std::begin(joypad->joypad_bits),
std::end(joypad->joypad_bits),
std::begin(joypad_bits)
);
strobe = joypad->strobe;
};
Joypad(Joypad* joypad);

/**
Write a button state to the given joy-pad.
Expand Down
5 changes: 5 additions & 0 deletions nes_py/laines/include/mapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
#include <cstring>
#include "common.hpp"

/// An abstract base class for a Mapper module on a Cartridge
class Mapper {
/// the ROM this mapper is loading from
u8* rom;
/// the size of the ROM in bytes
int romSize;
/// whether this mapper has CHR RAM
bool chrRam = false;

protected:
Expand Down
22 changes: 22 additions & 0 deletions nes_py/laines/joypad.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
#include "joypad.hpp"

Joypad::Joypad() {
for (int i = 0; i < NUM_JOYPADS; i++) {
joypad_buttons[i] = 0;
joypad_bits[i] = 0;
}
strobe = false;
};

Joypad::Joypad(Joypad* joypad) {
std::copy(
std::begin(joypad->joypad_buttons),
std::end(joypad->joypad_buttons),
std::begin(joypad_buttons)
);
std::copy(
std::begin(joypad->joypad_bits),
std::end(joypad->joypad_bits),
std::begin(joypad_bits)
);
strobe = joypad->strobe;
};

void Joypad::write_buttons(int n, u8 buttons) {
this->joypad_buttons[n] = buttons;
}
Expand Down
48 changes: 33 additions & 15 deletions nes_py/laines/mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,57 @@

Mapper::Mapper(u8* rom) : rom(rom) {
// Read infos from header:
prgSize = rom[4] * 0x4000;
chrSize = rom[5] * 0x2000;
prgRamSize = rom[8] ? rom[8] * 0x2000 : 0x2000;
prgSize = rom[4] * 0x4000;
chrSize = rom[5] * 0x2000;
prgRamSize = rom[8] ? rom[8] * 0x2000 : 0x2000;
PPU::set_mirroring((rom[6] & 1) ? VERTICAL : HORIZONTAL);

this->prg = rom + 16;
this->prgRam = new u8[prgRamSize];
prg = rom + 16;
prgRam = new u8[prgRamSize];

// CHR ROM:
if (chrSize)
this->chr = rom + 16 + prgSize;
if (chrSize) {
chr = rom + 16 + prgSize;
// calculate the ROM size
romSize = (chr + chrSize) - rom;
}
// CHR RAM:
else {
chrRam = true;
chrSize = 0x2000;
this->chr = new u8[chrSize];
chr = new u8[chrSize];
// calculate the ROM size
romSize = (rom + 16 + prgSize) - rom;
}
}

Mapper::Mapper(Mapper* mapper) {
rom = mapper->rom;
// copy the ROM size and create a new array to store its data in
romSize = mapper->romSize;
rom = new u8[romSize];
// copy the ROM data
memcpy(rom, mapper->rom, romSize * sizeof(u8));
// copy the flag for whether the mapper has CHR RAM
chrRam = mapper->chrRam;

// setup the PRG ROM
prgSize = mapper->prgSize;
prg = mapper->prg;

prg = rom + 16;
// setup the CHR ROM/RAM
chrSize = mapper->chrSize;
chr = mapper->chr;

// CHR RAM:
if (chrRam) {
chr = new u8[chrSize];
memcpy(chr, mapper->chr, chrSize * sizeof(u8));
}
// CHR ROM:
else {
chr = rom + 16 + prgSize;
}
// setup the PRG RAM
prgRamSize = mapper->prgRamSize;
prgRam = new u8[prgRamSize];
memcpy(prgRam, mapper->prgRam, prgRamSize * sizeof(u8));

// copy the maps
std::copy(std::begin(mapper->prgMap), std::end(mapper->prgMap), std::begin(prgMap));
std::copy(std::begin(mapper->chrMap), std::end(mapper->chrMap), std::begin(chrMap));
}
Expand Down
6 changes: 3 additions & 3 deletions nes_py/laines/nes_env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ void NESEnv::step(unsigned char action) {

void NESEnv::backup() {
// copy the current state with the backup state
backup_state = new GameState(current_state);
backup_state->cpu_state = CPU::get_state();
backup_state->ppu_state = PPU::get_state();
delete backup_state;
backup_state = new GameState(current_state, CPU::get_state(), PPU::get_state());
}

void NESEnv::restore() {
// copy the backup state into the current state and load the machine
delete current_state;
current_state = new GameState(backup_state);
current_state->load();
}
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def README():

setup(
name='nes_py',
version='0.10.2',
version='0.10.3',
description='An NES Emulator and OpenAI Gym interface',
long_description=README(),
long_description_content_type='text/markdown',
Expand Down

0 comments on commit 035321b

Please sign in to comment.