Skip to content

Serial (Link Cable) support #232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions pyboy/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ def valid_sample_rate(freq):
help="Add GameShark cheats on start-up. Add multiple by comma separation (i.e. '010138CD, 01033CD1')",
)

parser.add_argument("--serial-bind", action="store_true", help="Bind to this TCP addres for using Link Cable")
parser.add_argument(
"--serial-address", default=None, type=str, help="Connect (or bind) to this TCP address for using Link Cable"
)
parser.add_argument(
"--serial-interrupt-based", action="store_true", help="Use only interrupt-based transfers for using Link Cable"
)

gameboy_type_parser = parser.add_mutually_exclusive_group()
gameboy_type_parser.add_argument(
"--dmg", action="store_const", const=False, dest="cgb", help="Force emulator to run as original Game Boy (DMG)"
Expand Down Expand Up @@ -160,6 +168,9 @@ def valid_sample_rate(freq):
def main():
argv = parser.parse_args()

if (argv.serial_bind or argv.serial_interrupt_based) and not argv.serial_address:
parser.error("--serial-bind and --serial-interrupt-based requires --serial-address")

print(
"""
The Game Boy controls are as follows:
Expand Down
2 changes: 1 addition & 1 deletion pyboy/core/cartridge/cartridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def load_romfile(filename):

logger.debug("Loading ROM file: %d bytes", len(romdata))
if len(romdata) == 0:
logger.error("ROM file is empty!")
logger.critical("ROM file is empty!")
raise PyBoyException("Empty ROM file")

banksize = 16 * 1024
Expand Down
2 changes: 1 addition & 1 deletion pyboy/core/cartridge/mbc1.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def setitem(self, address, value):
def getitem(self, address):
if 0xA000 <= address < 0xC000:
if not self.rambank_initialized:
logger.error("RAM banks not initialized: %0.4x", address)
logger.warning("RAM banks not initialized: %0.4x", address)

if not self.rambank_enabled:
return 0xFF
Expand Down
2 changes: 1 addition & 1 deletion pyboy/core/cartridge/mbc2.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def getitem(self, address):
return self.rombanks[self.rombank_selected, address - 0x4000]
elif 0xA000 <= address < 0xC000:
if not self.rambank_initialized:
logger.error("RAM banks not initialized: %0.4x", address)
logger.warning("RAM banks not initialized: %0.4x", address)

if not self.rambank_enabled:
return 0xFF
Expand Down
2 changes: 1 addition & 1 deletion pyboy/core/cartridge/rtc.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __init__(self, filename):
self.halt = 0

if not os.path.exists(self.filename):
logger.info("No RTC file found. Skipping.")
logger.debug("No RTC file found. Skipping.")
else:
with open(self.filename, "rb") as f:
self.load_state(IntIOWrapper(f), STATE_VERSION)
Expand Down
13 changes: 10 additions & 3 deletions pyboy/core/mb.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
PyBoyException,
PyBoyOutOfBoundsException,
INTR_TIMER,
INTR_SERIAL,
INTR_HIGHTOLOW,
INTR_SERIAL,
OPCODE_BRK,
MAX_CYCLES,
)
Expand All @@ -32,9 +32,12 @@ def __init__(
sound_sample_rate,
cgb,
randomize=False,
serial_address=None,
serial_bind=None,
serial_interrupt_based=False,
):
if bootrom_file is not None:
logger.info("Boot-ROM file provided")
logger.debug("Boot-ROM file provided")

self.cartridge = cartridge.load_cartridge(gamerom)
logger.debug("Cartridge started:\n%s", str(self.cartridge))
Expand All @@ -49,7 +52,7 @@ def __init__(
logger.debug("Cartridge type auto-detected to %s", ("CGB" if self.cartridge.cgb else "DMG"))

self.timer = timer.Timer()
self.serial = serial.Serial()
self.serial = serial.Serial(serial_address, serial_bind, serial_interrupt_based)
self.interaction = interaction.Interaction()
self.ram = ram.RAM(cgb, randomize=randomize)
self.cpu = cpu.CPU(self)
Expand Down Expand Up @@ -228,6 +231,7 @@ def buttonevent(self, key):

def stop(self, save):
self.sound.stop()
self.serial.stop()
if save:
self.cartridge.stop()

Expand Down Expand Up @@ -394,6 +398,9 @@ def getitem(self, i):
if self.serial.tick(self.cpu.cycles):
self.cpu.set_interruptflag(INTR_SERIAL)
if i == 0xFF01:
# logger.debug(("Master " if self.serial.is_master else "Slave ") + "Read SB: %02x", self.serial.SB)
assert self.serial.sending_state == 2 # PASSIVE
assert self.serial.SC & 0x80 == 0 # No transfer active
return self.serial.SB
elif i == 0xFF02:
return self.serial.SC
Expand Down
16 changes: 13 additions & 3 deletions pyboy/core/serial.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,37 @@
# GitHub: https://github.com/Baekalfen/PyBoy
#

cimport cython
from libc.stdint cimport int64_t, uint8_t, uint16_t, uint32_t, uint64_t

from pyboy.logging.logging cimport Logger
from pyboy.utils cimport IntIOInterface

import cython

from pyboy.logging.logging cimport Logger

cdef uint64_t MAX_CYCLES, CYCLES_8192HZ
cdef Logger logger

cdef uint64_t SENDING, RECEIVING, PASSIVE

cdef class Serial:
cdef uint64_t SB, SC
cdef int64_t _cycles_to_interrupt
cdef uint64_t last_cycles, clock, clock_target
cdef bint transfer_enabled, double_speed, internal_clock
cdef bint serial_connected, is_master
cdef uint64_t sending_state

cdef bint tick(self, uint64_t) noexcept nogil
cdef void stop(self) noexcept

cdef void set_SB(self, uint8_t) noexcept nogil
cdef void set_SC(self, uint8_t) noexcept nogil

cdef int save_state(self, IntIOInterface) except -1
cdef int load_state(self, IntIOInterface, int) except -1

cdef object connection, binding_connection
cdef uint8_t trans_bits
cdef bint serial_interrupt_based

cdef void disconnect(self) noexcept nogil
Loading
Loading