Skip to content

Commit

Permalink
added saving and loading states
Browse files Browse the repository at this point in the history
  • Loading branch information
duysqubix committed Oct 2, 2023
1 parent 671f565 commit 7f6b7e9
Show file tree
Hide file tree
Showing 16 changed files with 673 additions and 135 deletions.
62 changes: 62 additions & 0 deletions internal/cartridge/cartridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package cartridge

import (
"bytes"
"encoding/binary"
"fmt"
"io"
"os"
Expand All @@ -17,6 +19,8 @@ type CartridgeType interface {
SetItem(uint16, uint8)
GetItem(uint16) uint8
Init()
Serialize() *bytes.Buffer
Deserialize(*bytes.Buffer) error
}

var CARTRIDGE_TABLE = map[uint8]func(*Cartridge) CartridgeType{
Expand Down Expand Up @@ -110,6 +114,64 @@ type Cartridge struct {
MemoryModel uint8 // 0 = 16/8, 1 = 4/32
}

func (c *Cartridge) Serialize() *bytes.Buffer {
buf := new(bytes.Buffer)

// ROM
// for _, bank := range c.RomBanks {
// binary.Write(buf, binary.LittleEndian, bank)
// }

binary.Write(buf, binary.LittleEndian, c.RomBanksCount) // ROM Bank Count
binary.Write(buf, binary.LittleEndian, c.RomBankSelected) // ROM Bank Selected

binary.Write(buf, binary.LittleEndian, c.RamBanks) // RAM
binary.Write(buf, binary.LittleEndian, c.RamBankCount) // RAM Bank Count
binary.Write(buf, binary.LittleEndian, c.RamBankSelected) // RAM Bank Selected
binary.Write(buf, binary.LittleEndian, c.RamBankEnabled) // RAM Bank Enabled
binary.Write(buf, binary.LittleEndian, c.MemoryModel) // Memory Model
logger.Debug("Serialized cartridge state")

// seralize MBC State
binary.Write(buf, binary.LittleEndian, c.CartType.Serialize().Bytes())
return buf
}

func (c *Cartridge) Deserialize(data *bytes.Buffer) error {
// Read the data from the buffer

if err := binary.Read(data, binary.LittleEndian, &c.RomBanksCount); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.RomBankSelected); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.RamBanks); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.RamBankCount); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.RamBankSelected); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.RamBankEnabled); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.MemoryModel); err != nil {
return err
}

// deserialize MBC state
return c.CartType.Deserialize(data)
}

func LoadRomBanks(rom_data []byte, dummy_data bool) [][]uint8 {
logger.Infof("Processing ROM file of size %d bytes", len(rom_data))
var rom_banks [][]uint8
Expand Down
35 changes: 35 additions & 0 deletions internal/cartridge/mbc1.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package cartridge

import (
"bytes"
"encoding/binary"
)

type Mbc1Cartridge struct {
parent *Cartridge
romBankSelect uint16
Expand All @@ -8,6 +13,36 @@ type Mbc1Cartridge struct {
hasBattery bool
}

func (c *Mbc1Cartridge) Serialize() *bytes.Buffer {
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, c.romBankSelect) // ROM Bank Select
binary.Write(buf, binary.LittleEndian, c.ramBankSelect) // RAM Bank Select
binary.Write(buf, binary.LittleEndian, c.mode) // Mode
binary.Write(buf, binary.LittleEndian, c.hasBattery) // Has Battery
logger.Debug("Serialized MBC1 state")
return buf
}

func (c *Mbc1Cartridge) Deserialize(data *bytes.Buffer) error {
if err := binary.Read(data, binary.LittleEndian, &c.romBankSelect); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.ramBankSelect); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.mode); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.hasBattery); err != nil {
return err
}

return nil
}

func (c *Mbc1Cartridge) Init() {
if c.hasBattery {
LoadSRAM(c.parent.Filename, &c.parent.RamBanks, c.parent.RamBankCount)
Expand Down
25 changes: 25 additions & 0 deletions internal/cartridge/mbc3.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package cartridge

import (
"bytes"
"encoding/binary"
)

type Mbc3Cartridge struct {
parent *Cartridge
hasBattery bool
Expand All @@ -14,6 +19,26 @@ func (c *Mbc3Cartridge) Init() {
}
}

func (c *Mbc3Cartridge) Serialize() *bytes.Buffer {
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, c.hasBattery) // Has Battery
binary.Write(buf, binary.LittleEndian, c.hasRTC) // Has RTC
logger.Debug("Serialized MBC3 state")
return buf
}

func (c *Mbc3Cartridge) Deserialize(data *bytes.Buffer) error {
if err := binary.Read(data, binary.LittleEndian, &c.hasBattery); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.hasRTC); err != nil {
return err
}

return nil
}

func (c *Mbc3Cartridge) SetItem(addr uint16, value uint8) {
switch {
case addr < 0x2000:
Expand Down
35 changes: 35 additions & 0 deletions internal/cartridge/mbc5.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package cartridge

import (
"bytes"
"encoding/binary"
)

type Mbc5Cartridge struct {
parent *Cartridge
hasBattery bool
Expand All @@ -15,6 +20,36 @@ func (c *Mbc5Cartridge) Init() {
c.romBankHi = 0
}

func (c *Mbc5Cartridge) Serialize() *bytes.Buffer {
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, c.hasBattery) // Has Battery
binary.Write(buf, binary.LittleEndian, c.hasRumble) // Has Rumble
binary.Write(buf, binary.LittleEndian, c.romBankLow) // ROM Bank Low
binary.Write(buf, binary.LittleEndian, c.romBankHi) // ROM Bank Hi
return buf

}

func (c *Mbc5Cartridge) Deserialize(data *bytes.Buffer) error {
if err := binary.Read(data, binary.LittleEndian, &c.hasBattery); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.hasRumble); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.romBankLow); err != nil {
return err
}

if err := binary.Read(data, binary.LittleEndian, &c.romBankHi); err != nil {
return err
}

return nil
}

func (c *Mbc5Cartridge) GetRomBank() uint16 {
return uint16(c.romBankLow) | (uint16(c.romBankHi) << 8)
}
Expand Down
11 changes: 11 additions & 0 deletions internal/cartridge/rom_only.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
package cartridge

import "bytes"

type RomOnlyCartridge struct {
parent *Cartridge
}

func (c *RomOnlyCartridge) Init() {
}

func (c *RomOnlyCartridge) Serialize() *bytes.Buffer {
buf := new(bytes.Buffer)
return buf
}

func (c *RomOnlyCartridge) Deserialize(data *bytes.Buffer) error {
return nil
}

func (c *RomOnlyCartridge) SetItem(addr uint16, value uint8) {
// do nothing
// can't write to ROM and RAM doesn't exist on these carts
Expand Down
69 changes: 69 additions & 0 deletions internal/motherboard/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package motherboard

import (
"bufio"
"bytes"
"container/list"
"encoding/binary"
"fmt"
"io"
"math/rand"
Expand Down Expand Up @@ -43,6 +45,73 @@ type CPU struct {
PcHist *list.List // records last 16 PC values
}

func (c *CPU) Serialize() *bytes.Buffer {
buf := new(bytes.Buffer)

binary.Write(buf, binary.LittleEndian, c.Registers.A)
binary.Write(buf, binary.LittleEndian, c.Registers.B)
binary.Write(buf, binary.LittleEndian, c.Registers.C)
binary.Write(buf, binary.LittleEndian, c.Registers.D)
binary.Write(buf, binary.LittleEndian, c.Registers.E)
binary.Write(buf, binary.LittleEndian, c.Registers.F)
binary.Write(buf, binary.LittleEndian, c.Registers.H)
binary.Write(buf, binary.LittleEndian, c.Registers.L)
binary.Write(buf, binary.LittleEndian, c.Registers.SP)
binary.Write(buf, binary.LittleEndian, c.Registers.PC)
binary.Write(buf, binary.LittleEndian, c.Interrupts.InterruptsEnabling)
binary.Write(buf, binary.LittleEndian, c.Interrupts.InterruptsOn)
binary.Write(buf, binary.LittleEndian, c.Interrupts.IE)
binary.Write(buf, binary.LittleEndian, c.Interrupts.IF)
logger.Debug("Serializing CPU state")
return buf
}

func (c *CPU) Deserialize(data *bytes.Buffer) error {
if err := binary.Read(data, binary.LittleEndian, &c.Registers.A); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Registers.B); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Registers.C); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Registers.D); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Registers.E); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Registers.F); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Registers.H); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Registers.L); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Registers.SP); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Registers.PC); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Interrupts.InterruptsEnabling); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Interrupts.InterruptsOn); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Interrupts.IE); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &c.Interrupts.IF); err != nil {
return err
}
return nil
}

func NewCpu(mb *Motherboard) *CPU {
return &CPU{
Registers: &Registers{
Expand Down
26 changes: 25 additions & 1 deletion internal/motherboard/input.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package motherboard

import "github.com/duysqubix/gobc/internal"
import (
"bytes"
"encoding/binary"

"github.com/duysqubix/gobc/internal"
)

const (
P10 uint8 = iota
Expand Down Expand Up @@ -36,6 +41,25 @@ type Input struct {
Mb *Motherboard
}

func (i *Input) Serialize() *bytes.Buffer {
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, i.directional)
binary.Write(buf, binary.LittleEndian, i.standard)
return buf
}

func (i *Input) Deserialize(data *bytes.Buffer) error {
// Read the data from the buffer
if err := binary.Read(data, binary.LittleEndian, &i.directional); err != nil {
return err
}
if err := binary.Read(data, binary.LittleEndian, &i.standard); err != nil {
return err
}

return nil
}

func NewInput(mb *Motherboard) *Input {
return &Input{
directional: 0x0F,
Expand Down
Loading

0 comments on commit 7f6b7e9

Please sign in to comment.