Skip to content

Commit

Permalink
Allow specifying IO for serial port
Browse files Browse the repository at this point in the history
  • Loading branch information
maxfierke committed Jan 6, 2024
1 parent b054d5b commit 9c994f6
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 13 deletions.
43 changes: 30 additions & 13 deletions devices/serial_port.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package devices

import (
"bytes"
"fmt"
"os"
"io"

"github.com/maxfierke/gogo-gb/mem"
)
Expand Down Expand Up @@ -74,14 +75,27 @@ func (sc *SerialCtrl) SetClockInternal(enabled bool) {
}

type SerialPort struct {
clk uint
ctrl SerialCtrl
recv byte
buf byte
clk uint
ctrl SerialCtrl
recv byte
buf byte
reader io.Reader
writer io.Writer
}

func NewSerialPort() *SerialPort {
return &SerialPort{}
return &SerialPort{
reader: bytes.NewReader([]byte{}),
writer: io.Discard,
}
}

func (sp *SerialPort) SetReader(reader io.Reader) {
sp.reader = reader
}

func (sp *SerialPort) SetWriter(writer io.Writer) {
sp.writer = writer
}

func (sp *SerialPort) Step(cycles uint, ic *InterruptController) {
Expand All @@ -97,9 +111,9 @@ func (sp *SerialPort) Step(cycles uint, ic *InterruptController) {
} else {
sp.clk -= cycles
}
} else {
// TODO: Implement external clock
}

// TODO: Implement external clock
}

func (sp *SerialPort) OnRead(mmu *mem.MMU, addr uint16) mem.MemRead {
Expand All @@ -120,14 +134,17 @@ func (sp *SerialPort) OnWrite(mmu *mem.MMU, addr uint16, value byte) mem.MemWrit
sp.ctrl.Write(value)

if sp.ctrl.IsTransferEnabled() && sp.ctrl.IsClockInternal() {
// TODO: derive this somehow and factor in GBC speeds when relevant
// TODO(GBC): derive this somehow and factor in GBC speeds when relevant
sp.clk = 8192

// TODO: Write this to some IO writer
os.Stderr.Write([]byte{sp.buf})
sp.writer.Write([]byte{sp.buf})

// TODO: Read this from somewhere
sp.recv = 0xFF
readBuf := make([]byte, 1)
if bytesRead, err := sp.reader.Read(readBuf); err != nil || bytesRead == 0 {
sp.recv = 0xFF
} else {
sp.recv = readBuf[0]
}
}

return mem.WriteBlock()
Expand Down
11 changes: 11 additions & 0 deletions hardware/dmg.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package hardware

import (
"io"
"log"

"github.com/maxfierke/gogo-gb/cart"
Expand All @@ -19,6 +20,7 @@ type DMG struct {
cartridge *cart.Cartridge
ic *devices.InterruptController
lcd *devices.LCD
serial *devices.SerialPort

// Non-components
debugger debug.Debugger
Expand Down Expand Up @@ -62,6 +64,7 @@ func NewDMGDebug(debugger debug.Debugger) (*DMG, error) {
debugger: debugger,
ic: ic,
lcd: lcd,
serial: serial,
}, nil
}

Expand Down Expand Up @@ -96,3 +99,11 @@ func (dmg *DMG) Run() {
func (dmg *DMG) SetLogger(logger *log.Logger) {
dmg.logger = logger
}

func (dmg *DMG) SetSerialReader(serial io.Reader) {
dmg.serial.SetReader(serial)
}

func (dmg *DMG) SetSerialWriter(serial io.Writer) {
dmg.serial.SetWriter(serial)
}
18 changes: 18 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type CLIOptions struct {
debugPrint string
logPath string
logger *log.Logger
serialPort string
}

const LOG_PREFIX = ""
Expand Down Expand Up @@ -50,6 +51,7 @@ func main() {

func parseOptions(options *CLIOptions) {
flag.StringVar(&options.cartPath, "cart", "", "Path to cartridge file (.gb, .gbc)")
flag.StringVar(&options.serialPort, "serial-port", "", "Path to serial port IO (could be a file, UNIX socket, etc.)")
flag.StringVar(&options.debugger, "debugger", "none", "Specify debugger to use (\"none\", \"gameboy-doctor\")")
flag.StringVar(&options.debugPrint, "debug-print", "", "Print out something for debugging purposes (\"cart-header\", \"opcodes\")")
flag.StringVar(&options.logPath, "log", "", "Path to log file. Default/empty implies stdout")
Expand Down Expand Up @@ -110,6 +112,22 @@ func initDMG(options *CLIOptions) *hardware.DMG {

dmg.SetLogger(logger)

if options.serialPort != "" {
if options.serialPort == "stdout" || options.serialPort == "/dev/stdout" {
dmg.SetSerialWriter(os.Stdout)
} else if options.serialPort == "stderr" || options.serialPort == "/dev/stderr" {
dmg.SetSerialWriter(os.Stderr)
} else {
serialPort, err := os.Create(options.serialPort)
if err != nil {
logger.Fatalf("Unable to open file '%s' as serial port: %v\n", options.serialPort, err)
}

dmg.SetSerialReader(serialPort)
dmg.SetSerialWriter(serialPort)
}
}

return dmg
}

Expand Down

0 comments on commit 9c994f6

Please sign in to comment.