def execute(self, motherboard: Motherboard):
     value = motherboard.reg.get(self.register_pair)
     if value >= 256**2:
         raise ValueError(
             f"Tried to push {value} from {self.register_pair}")
     motherboard.push_to_stack(value)
     return 16
    def execute(self, motherboard: Motherboard):

        if self.cc is not None:
            if motherboard.reg.get_flag_condition(self.cc):
                return_address = motherboard.pop_from_stack()
                motherboard.program_counter = return_address
                return 20
            else:
                return 8
        else:
            return_address = motherboard.pop_from_stack()
            motherboard.program_counter = return_address
            return 16
 def execute(self, motherboard: Motherboard):
     if self.cc is None or motherboard.reg.get_flag_condition(self.cc):
         if type(self.destination) == Addr:
             motherboard.program_counter = self.destination.address
             return 16
         elif type(self.destination) == AddrReg:
             motherboard.program_counter = motherboard.reg.get(
                 self.destination.register)
             return 4
         else:
             raise ValueError(
                 f"Unhandled jump destination: {self.destination}")
     else:
         return 12
    def execute(self, motherboard: Motherboard):
        motherboard.stopped = True
        motherboard.memory.write(0xFF04, 0)  # Write to DIV
        # TODO Timer should stop running here (https://gbdev.io/pandocs/#ff04-div-divider-register-r-w)
        logger.info("Stopping CPU and LCD")

        return 4
    def execute(self, motherboard: Motherboard):
        popped = motherboard.pop_from_stack()
        if popped >= 256**2:
            raise ValueError(f"Popped {popped} from stack. [{self}]")
        motherboard.reg.set(self.register_pair, popped)

        return 12
Exemple #6
0
def _handle_header_and_entrypoint(motherboard: Motherboard) -> CartridgeHeader:
    motherboard.program_counter = 0x100
    b = b""
    for i in range(0x0100, 0x0150):
        b += bytes([motherboard.memory.read(i)])
    logger.debug("Cartridge bytes to parse:")
    logger.debug(str(b))
    logger.debug("")
    logger.debug(str(motherboard.memory._cartridge))

    header = CartridgeHeader.parse(b)
    logger.debug(str(header))

    if header.cartridge_type in [CartridgeType.ROM_ONLY, CartridgeType.MBC1]:
        # This should be handled correctly
        pass
    else:
        logger.warn(
            f"We may not handle cartridge correctly: {header.cartridge_type}")

    logger.debug("Will load instruction from " +
                 str(motherboard.program_counter))
    instruction_decoding.fetch_decode_execute(motherboard)
    instruction_decoding.fetch_decode_execute(motherboard)
    return header
Exemple #7
0
def run_game_from_file(filename: str):
    with open(filename, "rb") as file:
        cartridge_data = list(file.read())
        logger.info(f"Loaded game ROM ({len(cartridge_data)} bytes)")

    with open("DMG_ROM.bin", "rb") as boot_file:
        boot_rom_buffer = list(boot_file.read())
        logger.info(f"Loaded boot ROM ({len(boot_rom_buffer)} bytes)")

    joypad = JoyPad()
    timer = Timer()
    display = Display(joypad)

    ram_size_enum = RAM_Size(cartridge_data[0x149])
    if ram_size_enum == RAM_Size.NONE:
        ram_size = 0
    elif ram_size_enum == RAM_Size.RAM_32KB:
        ram_size = 32 * 1024
    elif ram_size_enum == RAM_Size.RAM_8KB:
        ram_size = 8 * 1024
    else:
        raise ValueError(f"TODO Handle RAM size: {ram_size_enum}")

    escaped_title = bytes(
        cartridge_data[0x134:0x134 + 11]).decode("utf-8").replace("\x00", "")
    save_file_name = f"savefiles/__{escaped_title.replace(' ', '_')}__"
    if os.path.exists(save_file_name):
        logger.info(f"Savefile found: {save_file_name}")
        with open(save_file_name, "rb") as save_file:
            ram_data = list(save_file.read())
            logger.debug(f"Loaded RAM data ({len(ram_data)} bytes)")
            if len(ram_data) != ram_size:
                raise ValueError(
                    f"Expected RAM size {ram_size} but savefile has size {len(ram_data)}"
                )
    else:
        ram_data = [0] * ram_size
        logger.info(
            f"Savefile not found: {save_file_name}. Created new RAM data with size {ram_size}"
        )

    cartridge = Cartridge(cartridge_data, ram_data)
    memory = Memory(cartridge, joypad, timer, display)
    motherboard = Motherboard(memory, 0)

    cartridge_header = _handle_header_and_entrypoint(motherboard)

    display.set_title(cartridge_header.title)

    _run_game(motherboard, display, timer, cartridge, save_file_name)
    logger.info("Exiting emulator")
 def execute(self, motherboard: Motherboard):
     motherboard.halted = True
     logger.debug("HALTING...")
     return 4
 def execute(self, motherboard: Motherboard):
     motherboard.push_to_stack(motherboard.program_counter)
     motherboard.program_counter = self.address
     return 16
 def execute(self, motherboard: Motherboard):
     return_address = motherboard.pop_from_stack()
     motherboard.program_counter = return_address
     motherboard.IME_flag = True
     return 16
 def execute(self, motherboard: Motherboard):
     if self.cc is None or motherboard.reg.get_flag_condition(self.cc):
         motherboard.push_to_stack(motherboard.program_counter)
         motherboard.program_counter = self.address
         return 24
     return 12
 def execute(self, motherboard: Motherboard):
     motherboard.enable_interrupts_after_next_instruction()
     logger.debug("Enabling interrupts (after next instruction)")
     return 4