[pypy-svn] r52621 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test
cami at codespeak.net
cami at codespeak.net
Sun Mar 16 20:42:45 CET 2008
Author: cami
Date: Sun Mar 16 20:42:44 2008
New Revision: 52621
Modified:
pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py
Log:
replaced all tabs with spaces.
added skip skiptest
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sun Mar 16 20:42:44 2008
@@ -4,30 +4,30 @@
from pypy.lang.gameboy import constants
-def hasCartridgeBattery(self, cartridgeType):
- return (cartridgeType == constants.TYPE_MBC1_RAM_BATTERY \
- or cartridgeType == constants.TYPE_MBC2_BATTERY \
- or cartridgeType == constants.TYPE_MBC3_RTC_BATTERY \
- or cartridgeType == constants.TYPE_MBC3_RTC_RAM_BATTERY \
- or cartridgeType == constants.TYPE_MBC3_RAM_BATTERY \
- or cartridgeType == constants.TYPE_MBC5_RAM_BATTERY \
- or cartridgeType == constants.TYPE_MBC5_RUMBLE_RAM_BATTERY \
- or cartridgeType == constants.TYPE_HUC1_RAM_BATTERY);
+def hasCartridgeBattery(self, cartridgeType):
+ return (cartridgeType == constants.TYPE_MBC1_RAM_BATTERY \
+ or cartridgeType == constants.TYPE_MBC2_BATTERY \
+ or cartridgeType == constants.TYPE_MBC3_RTC_BATTERY \
+ or cartridgeType == constants.TYPE_MBC3_RTC_RAM_BATTERY \
+ or cartridgeType == constants.TYPE_MBC3_RAM_BATTERY \
+ or cartridgeType == constants.TYPE_MBC5_RAM_BATTERY \
+ or cartridgeType == constants.TYPE_MBC5_RUMBLE_RAM_BATTERY \
+ or cartridgeType == constants.TYPE_HUC1_RAM_BATTERY);
def hasCartridgeType(self, catridgeType):
- return constants.CATRIDGE_TYPE_MAPPING.has_key(cartridgeType);
+ return constants.CATRIDGE_TYPE_MAPPING.has_key(cartridgeType);
def createBankController(self, cartridgeType, rom, ram, clock):
- if hasCartridgeType(cartridgeType):
- return constants.CATRIDGE_TYPE_MAPPING[cartridgeType](rom, ram, clock);
- else:
- raise InvalidMemoryBankTypeError("Unsupported memory bank controller (0x"+hex(cartridgeType)+")")
+ if hasCartridgeType(cartridgeType):
+ return constants.CATRIDGE_TYPE_MAPPING[cartridgeType](rom, ram, clock);
+ else:
+ raise InvalidMemoryBankTypeError("Unsupported memory bank controller (0x"+hex(cartridgeType)+")")
class InvalidMemoryBankTypeError(Exception):
- pass
+ pass
@@ -35,128 +35,128 @@
# CARTRIDGE
class Cartridge(object):
-
- def __init__(self, storeDriver, clockDriver):
- self.store = storeDriver
- self.clock = clockDriver
-
-
- def initialize(self):
- pass
-
-
- def getTitle(self):
- pass
-
-
- def getCartridgeType(self):
- return self.rom[constants.CARTRIDGE_TYPE_ADDRESS] & 0xFF
-
-
- def getRom(self):
- return self.rom
-
-
- def getROMSize(self):
- romSize = self.rom[constants.CARTRIDGE_SIZE_ADDRESS] & 0xFF
- if romSize>=0x00 and romSize<=0x07:
- return 32768 << romSize
- return -1
-
-
- def getRAMSize(self):
- return constants.RAM_SIZE_MAPPING[self.rom[constants.RAM_SIZE_ADDRESS]]
-
-
- def getDestinationCode(self):
- return self.rom[constants.DESTINATION_CODE_ADDRESS] & 0xFF;
-
-
- def getLicenseeCode():
- return self.rom[constants.LICENSEE_ADDRESS] & 0xFF;
-
-
- def getROMVersion(self):
- return self.rom[constants.ROM_VERSION_ADDRESS] & 0xFF;
-
-
- def getHeaderChecksum(self):
- return self.rom[constants.HEADER_CHECKSUM_ADDRESS] & 0xFF;
-
-
- def getChecksum(self):
- return ((rom[constants.CHECKSUM_A_ADDRESS] & 0xFF) << 8) + (rom[constants.CHECKSUM_B_ADDRESS] & 0xFF);
-
-
- def hasBattery(self):
- return hasCartridgeBattery(self.getCartridgeType())
-
-
- def reset(self):
- if not self.hasBattery():
- self.ram[0:len(self.ram):1] = 0xFF;
- self.mbc.reset();
-
-
- def read(self, address):
- return self.mbc.read(address);
-
-
- def write(self, address, data):
- self.mbc.write(address, data);
-
-
- def load(self, cartridgeName):
- romSize = self.store.getCartridgeSize(cartridgeName);
- self.rom = range(0, romSize)
- for i in range(0, romSize):
- self.rom[i] = 0
-
- self.store.readCartridge(cartridgeName, self.rom)
-
- if not self.verifyHeader():
- raise Exeption("Cartridge header is corrupted")
-
- if romSize < self.getROMSize():
- raise Exeption("Cartridge is truncated")
-
- ramSize = self.getRAMSize()
-
- if (getCartridgeType() >= constants.TYPE_MBC2
- and getCartridgeType() <= constants.TYPE_MBC2_BATTERY):
- ramSize = 512;
-
- self.ram = []
-
- for i in range(0, ramSize):
- self.ram[i] = 0xFF
-
- if self.store.hasBattery(cartridgeName):
- self.store.readBattery(cartridgeName, ram)
-
- self.mbc = createBankController(self.getCartridgeType(), rom, ram, clock)
-
-
- def save(self, cartridgeName):
- if self.hasBattery():
- self.store.writeBattery(cartridgeName, self.ram)
-
-
- def verify(self):
- checksum = 0;
- for address in range(len(self.rom)):
- if address is not 0x014E and address is not 0x014F:
- checksum = (checksum + (self.rom[address] & 0xFF)) & 0xFFFF
- return (checksum == self.getChecksum());
-
-
- def verifyHeader(self):
- if self.rom.length < 0x0150:
- return false;
- checksum = 0xE7;
- for address in range(0x0134, 0x014C):
- checksum = (checksum - (rom[address] & 0xFF)) & 0xFF;
- return (checksum == self.getHeaderChecksum())
+
+ def __init__(self, storeDriver, clockDriver):
+ self.store = storeDriver
+ self.clock = clockDriver
+
+
+ def initialize(self):
+ pass
+
+
+ def getTitle(self):
+ pass
+
+
+ def getCartridgeType(self):
+ return self.rom[constants.CARTRIDGE_TYPE_ADDRESS] & 0xFF
+
+
+ def getRom(self):
+ return self.rom
+
+
+ def getROMSize(self):
+ romSize = self.rom[constants.CARTRIDGE_SIZE_ADDRESS] & 0xFF
+ if romSize>=0x00 and romSize<=0x07:
+ return 32768 << romSize
+ return -1
+
+
+ def getRAMSize(self):
+ return constants.RAM_SIZE_MAPPING[self.rom[constants.RAM_SIZE_ADDRESS]]
+
+
+ def getDestinationCode(self):
+ return self.rom[constants.DESTINATION_CODE_ADDRESS] & 0xFF;
+
+
+ def getLicenseeCode():
+ return self.rom[constants.LICENSEE_ADDRESS] & 0xFF;
+
+
+ def getROMVersion(self):
+ return self.rom[constants.ROM_VERSION_ADDRESS] & 0xFF;
+
+
+ def getHeaderChecksum(self):
+ return self.rom[constants.HEADER_CHECKSUM_ADDRESS] & 0xFF;
+
+
+ def getChecksum(self):
+ return ((rom[constants.CHECKSUM_A_ADDRESS] & 0xFF) << 8) + (rom[constants.CHECKSUM_B_ADDRESS] & 0xFF);
+
+
+ def hasBattery(self):
+ return hasCartridgeBattery(self.getCartridgeType())
+
+
+ def reset(self):
+ if not self.hasBattery():
+ self.ram[0:len(self.ram):1] = 0xFF;
+ self.mbc.reset();
+
+
+ def read(self, address):
+ return self.mbc.read(address);
+
+
+ def write(self, address, data):
+ self.mbc.write(address, data);
+
+
+ def load(self, cartridgeName):
+ romSize = self.store.getCartridgeSize(cartridgeName);
+ self.rom = range(0, romSize)
+ for i in range(0, romSize):
+ self.rom[i] = 0
+
+ self.store.readCartridge(cartridgeName, self.rom)
+
+ if not self.verifyHeader():
+ raise Exeption("Cartridge header is corrupted")
+
+ if romSize < self.getROMSize():
+ raise Exeption("Cartridge is truncated")
+
+ ramSize = self.getRAMSize()
+
+ if (getCartridgeType() >= constants.TYPE_MBC2
+ and getCartridgeType() <= constants.TYPE_MBC2_BATTERY):
+ ramSize = 512;
+
+ self.ram = []
+
+ for i in range(0, ramSize):
+ self.ram[i] = 0xFF
+
+ if self.store.hasBattery(cartridgeName):
+ self.store.readBattery(cartridgeName, ram)
+
+ self.mbc = createBankController(self.getCartridgeType(), rom, ram, clock)
+
+
+ def save(self, cartridgeName):
+ if self.hasBattery():
+ self.store.writeBattery(cartridgeName, self.ram)
+
+
+ def verify(self):
+ checksum = 0;
+ for address in range(len(self.rom)):
+ if address is not 0x014E and address is not 0x014F:
+ checksum = (checksum + (self.rom[address] & 0xFF)) & 0xFFFF
+ return (checksum == self.getChecksum());
+
+
+ def verifyHeader(self):
+ if self.rom.length < 0x0150:
+ return false;
+ checksum = 0xE7;
+ for address in range(0x0134, 0x014C):
+ checksum = (checksum - (rom[address] & 0xFF)) & 0xFF;
+ return (checksum == self.getHeaderChecksum())
# ==============================================================================
@@ -164,171 +164,171 @@
class MBC(object):
- ramEnable = False
-
- rom = []
- ram = []
-
- romSize = 0;
- ramSize = 0;
-
- minRomBankSize = 0
- maxRomBankSize = 0
-
- minRamBankSize = 0
- maxRamBankSize = 0
-
- romBank = constants.ROM_BANK_SIZE
- ramBank = 0
-
-
- def reset(self):
- self.romBank = constants.ROM_BANK_SIZE;
- self.ramBank = 0;
- self.ramEnable = False;
-
- def setROM(self, buffer):
- banks = len(buffer) / constants.ROM_BANK_SIZE;
- if (banks < minRomBankSize or banks > maxRomBankSize):
- raise Exception("Invalid constants.ROM size");
- self.rom = buffer;
- self.romSize = constants.ROM_BANK_SIZE*banks - 1;
-
-
- def setRAM(buffer):
- banks = len(buffer) / constants.RAM_BANK_SIZE;
- if (banks < minRamBankSize or banks > maxRamBankSize):
- raise Exception("Invalid constants.RAM size");
- self.ram = buffer;
- self.ramSize = constants.RAM_BANK_SIZE*banks - 1;
-
+ ramEnable = False
+
+ rom = []
+ ram = []
+
+ romSize = 0;
+ ramSize = 0;
+
+ minRomBankSize = 0
+ maxRomBankSize = 0
+
+ minRamBankSize = 0
+ maxRamBankSize = 0
+
+ romBank = constants.ROM_BANK_SIZE
+ ramBank = 0
+
+
+ def reset(self):
+ self.romBank = constants.ROM_BANK_SIZE;
+ self.ramBank = 0;
+ self.ramEnable = False;
+
+ def setROM(self, buffer):
+ banks = len(buffer) / constants.ROM_BANK_SIZE;
+ if (banks < minRomBankSize or banks > maxRomBankSize):
+ raise Exception("Invalid constants.ROM size");
+ self.rom = buffer;
+ self.romSize = constants.ROM_BANK_SIZE*banks - 1;
+
+
+ def setRAM(buffer):
+ banks = len(buffer) / constants.RAM_BANK_SIZE;
+ if (banks < minRamBankSize or banks > maxRamBankSize):
+ raise Exception("Invalid constants.RAM size");
+ self.ram = buffer;
+ self.ramSize = constants.RAM_BANK_SIZE*banks - 1;
+
"""
Mario GameBoy (TM) Emulator
Memory Bank Controller 1 (2MB constants.ROM, 32KB constants.RAM)
-0000-3FFF ROM Bank 0 (16KB)
-4000-7FFF ROM Bank 1-127 (16KB)
-A000-BFFF RAM Bank 0-3 (8KB)
+0000-3FFF ROM Bank 0 (16KB)
+4000-7FFF ROM Bank 1-127 (16KB)
+A000-BFFF RAM Bank 0-3 (8KB)
"""
class MBC1(MBC):
-
- def __init__(self, rom, ram):
- self.minRamBankSize = 0
- self.maxRamBankSize = 4
- self.minRomBankSize = 2
- self.maxRomBankSize = 128
-
- self.setRom(rom)
- self.serRam(ram)
-
-
- def reset(self):
- super.reset()
-
- self.memoryModel = 0
-
-
- def read(self, address):
- if address <= 0x3FFF:
- # 0000-3FFF
- return self.rom[address] & 0xFF
- elif (address <= 0x7FFF):
- # 4000-7FFF
- return self.rom[romBank + (address & 0x3FFF)] & 0xFF;
- elif (address >= 0xA000 and address <= 0xBFFF):
- # A000-BFFF
- if (self.ramEnable):
- return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF;
- return 0xFF;
-
-
- def write(self, address, data):
- if (address <= 0x1FFF):
- # 0000-1FFF
- if (self.ramSize > 0):
- self.ramEnable = ((data & 0x0A) == 0x0A)
- elif (address <= 0x3FFF):
- # 2000-3FFF
- if ((data & 0x1F) == 0):
- data = 1;
- if (self.memoryModel == 0):
- self.romBank = ((self.romBank & 0x180000) + ((data & 0x1F) << 14)) & self.romSize;
- else:
- self.romBank = ((data & 0x1F) << 14) & self.romSize;
- elif (address <= 0x5FFF):
- # 4000-5FFF
- if (self.memoryModel == 0):
- self.romBank = ((self.romBank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize;
- else:
- self.ramBank = ((data & 0x03) << 13) & self.ramSize;
- elif (address <= 0x7FFF):
- # 6000-7FFF
- self.memoryModel = data & 0x01
- elif (address >= 0xA000 and address <= 0xBFFF):
- # A000-BFFF
- if (self.ramEnable):
- self.ram[self.ramBank + (address & 0x1FFF)] = data;
-
-
-
-
+
+ def __init__(self, rom, ram):
+ self.minRamBankSize = 0
+ self.maxRamBankSize = 4
+ self.minRomBankSize = 2
+ self.maxRomBankSize = 128
+
+ self.setRom(rom)
+ self.serRam(ram)
+
+
+ def reset(self):
+ super.reset()
+
+ self.memoryModel = 0
+
+
+ def read(self, address):
+ if address <= 0x3FFF:
+ # 0000-3FFF
+ return self.rom[address] & 0xFF
+ elif (address <= 0x7FFF):
+ # 4000-7FFF
+ return self.rom[romBank + (address & 0x3FFF)] & 0xFF;
+ elif (address >= 0xA000 and address <= 0xBFFF):
+ # A000-BFFF
+ if (self.ramEnable):
+ return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF;
+ return 0xFF;
+
+
+ def write(self, address, data):
+ if (address <= 0x1FFF):
+ # 0000-1FFF
+ if (self.ramSize > 0):
+ self.ramEnable = ((data & 0x0A) == 0x0A)
+ elif (address <= 0x3FFF):
+ # 2000-3FFF
+ if ((data & 0x1F) == 0):
+ data = 1;
+ if (self.memoryModel == 0):
+ self.romBank = ((self.romBank & 0x180000) + ((data & 0x1F) << 14)) & self.romSize;
+ else:
+ self.romBank = ((data & 0x1F) << 14) & self.romSize;
+ elif (address <= 0x5FFF):
+ # 4000-5FFF
+ if (self.memoryModel == 0):
+ self.romBank = ((self.romBank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize;
+ else:
+ self.ramBank = ((data & 0x03) << 13) & self.ramSize;
+ elif (address <= 0x7FFF):
+ # 6000-7FFF
+ self.memoryModel = data & 0x01
+ elif (address >= 0xA000 and address <= 0xBFFF):
+ # A000-BFFF
+ if (self.ramEnable):
+ self.ram[self.ramBank + (address & 0x1FFF)] = data;
+
+
+
+
"""
Mario GameBoy (TM) Emulator
Memory Bank Controller 2 (256KB constants.ROM, 512x4bit constants.RAM)
-0000-3FFF ROM Bank 0 (16KB)
-4000-7FFF ROM Bank 1-15 (16KB)
-A000-A1FF RAM Bank (512x4bit)
+0000-3FFF ROM Bank 0 (16KB)
+4000-7FFF ROM Bank 1-15 (16KB)
+A000-A1FF RAM Bank (512x4bit)
"""
class MBC2(MBC):
- RAM_BANK_SIZE = 512;
+ RAM_BANK_SIZE = 512;
- def __init__(self, rom, ram):
- self.minRamBankSize = constants.RAM_BANK_SIZE
- self.maxRamBankSize = constants.RAM_BANK_SIZE
- self.minRomBankSize = 2
- self.maxRomBankSize = 16
-
- self.setROM(rom);
- self.setRAM(ram);
-
-
- def reset(self):
- super.reset()
-
-
- def read(self, address):
- if (address <= 0x3FFF):
- # 0000-3FFF
- return self.rom[address] & 0xFF;
- elif (address <= 0x7FFF):
- # 4000-7FFF
- return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF;
- elif (address >= 0xA000 and address <= 0xA1FF):
- # A000-A1FF
- return self.ram[address & 0x01FF] & 0x0F;
- return 0xFF;
-
-
- def write(self, address, data):
- if (address <= 0x1FFF):
- # 0000-1FFF
- if ((address & 0x0100) == 0):
- self.ramEnable = ((data & 0x0A) == 0x0A);
- elif (address <= 0x3FFF):
- # 2000-3FFF
- if ((address & 0x0100) != 0):
- if ((data & 0x0F) == 0):
- data = 1;
- self.romBank = ((data & 0x0F) << 14) & self.romSize;
- elif (address >= 0xA000 and address <= 0xA1FF):
- # A000-A1FF
- if (self.ramEnable):
- self.ram[address & 0x01FF] = (byte) (data & 0x0F);
+ def __init__(self, rom, ram):
+ self.minRamBankSize = constants.RAM_BANK_SIZE
+ self.maxRamBankSize = constants.RAM_BANK_SIZE
+ self.minRomBankSize = 2
+ self.maxRomBankSize = 16
+
+ self.setROM(rom);
+ self.setRAM(ram);
+
+
+ def reset(self):
+ super.reset()
+
+
+ def read(self, address):
+ if (address <= 0x3FFF):
+ # 0000-3FFF
+ return self.rom[address] & 0xFF;
+ elif (address <= 0x7FFF):
+ # 4000-7FFF
+ return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF;
+ elif (address >= 0xA000 and address <= 0xA1FF):
+ # A000-A1FF
+ return self.ram[address & 0x01FF] & 0x0F;
+ return 0xFF;
+
+
+ def write(self, address, data):
+ if (address <= 0x1FFF):
+ # 0000-1FFF
+ if ((address & 0x0100) == 0):
+ self.ramEnable = ((data & 0x0A) == 0x0A);
+ elif (address <= 0x3FFF):
+ # 2000-3FFF
+ if ((address & 0x0100) != 0):
+ if ((data & 0x0F) == 0):
+ data = 1;
+ self.romBank = ((data & 0x0F) << 14) & self.romSize;
+ elif (address >= 0xA000 and address <= 0xA1FF):
+ # A000-A1FF
+ if (self.ramEnable):
+ self.ram[address & 0x01FF] = (byte) (data & 0x0F);
"""
@@ -336,171 +336,171 @@
Memory Bank Controller 3 (2MB constants.ROM, 32KB constants.RAM, Real Time Clock)
-0000-3FFF ROM Bank 0 (16KB)
-4000-7FFF ROM Bank 1-127 (16KB)
-A000-BFFF RAM Bank 0-3 (8KB)
+0000-3FFF ROM Bank 0 (16KB)
+4000-7FFF ROM Bank 1-127 (16KB)
+A000-BFFF RAM Bank 0-3 (8KB)
"""
class MBC3(MBC):
- #ClockDriver
- clock = None;
+ #ClockDriver
+ clock = None;
- romBank = 0;
- ramBank = 0;
+ romBank = 0;
+ ramBank = 0;
- clockRegister = 0;
- clockLatch = 0;
- clockTime = 0;
-
- clockSeconds = 0
- clockMinutes = 0
- clockHours = 0
- clockDays = 0
- clockControl = None
- clockLSeconds = 0
- clockLMinutes = 0
- clockLHours = 0
- clockLDaysclockLControl = None
-
- def __init__(self, rom, ram, clock):
- self.minRamBankSize = 0
- self.maxRamBankSize = 4
- self.minRomBankSize = 2
- self.maxRomBankSize = 128
-
- self.clock = clock;
-
- self.setROM(rom);
- self.setRAM(ram);
-
-
- def reset():
- super.reset()
-
- self.clockTime = self.clock.getTime();
-
- self.clockLatch = self.clockRegister = 0;
-
- self.clockSeconds = self.clockMinutes = self.clockHours = self.clockDays = self.clockControl = 0;
- self.clockLSeconds = self.clockLMinutes = self.clockLHours = self.clockLDays = self.clockLControl = 0;
-
-
- def read(self, address):
- if (address <= 0x3FFF):
- # 0000-3FFF
- return self.rom[address] & 0xFF;
- elif (address <= 0x7FFF):
- # 4000-5FFF
- return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF;
- elif (address >= 0xA000 and address <= 0xBFFF):
- # A000-BFFF
- if (self.ramBank >= 0):
- return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF;
- else:
- if (self.clockRegister == 0x08):
- return self.clockLSeconds;
- if (self.clockRegister == 0x09):
- return self.clockLMinutes;
- if (self.clockRegister == 0x0A):
- return self.clockLHours;
- if (self.clockRegister == 0x0B):
- return self.clockLDays;
- if (self.clockRegister == 0x0C):
- return self.clockLControl;
- return 0xFF;
-
-
- def write(self, address, data):
- if (address <= 0x1FFF):
- # 0000-1FFF
- if (self.ramSize > 0):
- self.ramEnable = ((data & 0x0A) == 0x0A);
- elif (address <= 0x3FFF):
- # 2000-3FFF
- if (data == 0):
- data = 1;
- self.romBank = ((data & 0x7F) << 14) & self.romSize;
- elif (address <= 0x5FFF):
- # 4000-5FFF
- if (data >= 0x00 and data <= 0x03):
- self.ramBank = (data << 13) & self.ramSize;
- else:
- self.ramBank = -1;
- self.clockRegister = data;
- elif (address <= 0x7FFF):
- # 6000-7FFF
- if (self.clockLatch == 0 and data == 1):
- self.latchClock();
- if (data == 0 or data == 1):
- self.clockLatch = data;
- elif (address >= 0xA000 and address <= 0xBFFF):
- # A000-BFFF
- if (self.ramEnable):
- if (self.ramBank >= 0):
- # constants.TODO conversion to byte
- self.ram[self.ramBank + (address & 0x1FFF)] = data;
- else:
- self.updateClock();
-
- if (self.clockRegister == 0x08):
- self.clockSeconds = data;
- if (self.clockRegister == 0x09):
- self.clockMinutes = data;
- if (self.clockRegister == 0x0A):
- self.clockHours = data;
- if (self.clockRegister == 0x0B):
- self.clockDays = data;
- if (self.clockRegister == 0x0C):
- self.clockControl = (self.clockControl & 0x80) | data;
-
-
- def latchClock(self):
- self.updateClock();
-
- self.clockLSeconds = self.clockSeconds;
- self.clockLMinutes = self.clockMinutes;
- self.clockLHours = self.clockHours;
- self.clockLDays = self.clockDays & 0xFF;
- self.clockLControl = (self.clockControl & 0xFE) | ((self.clockDays >> 8) & 0x01);
-
-
- def updateClock():
- now = self.clock.getTime();
-
- if ((self.clockControl & 0x40) == 0):
- elapsed = now - self.clockTime;
-
- while (elapsed >= 246060):
- elapsed -= 246060
- self.clockDays+=1
-
- while (elapsed >= 6060):
- elapsed -= 6060;
- self.clockHours+=1
-
- while (elapsed >= 60):
- elapsed -= 60;
- self.clockMinutes+=1
-
- self.clockSeconds += elapsed;
-
- while (self.clockSeconds >= 60):
- self.clockSeconds -= 60;
- self.clockMinutes+=1
-
- while (self.clockMinutes >= 60):
- self.clockMinutes -= 60;
- self.clockHours+=1
-
- while (self.clockHours >= 24):
- self.clockHours -= 24;
- self.clockDays+=1
-
- while (self.clockDays >= 512):
- self.clockDays -= 512;
- self.clockControl |= 0x80;
+ clockRegister = 0;
+ clockLatch = 0;
+ clockTime = 0;
+
+ clockSeconds = 0
+ clockMinutes = 0
+ clockHours = 0
+ clockDays = 0
+ clockControl = None
+ clockLSeconds = 0
+ clockLMinutes = 0
+ clockLHours = 0
+ clockLDaysclockLControl = None
+
+ def __init__(self, rom, ram, clock):
+ self.minRamBankSize = 0
+ self.maxRamBankSize = 4
+ self.minRomBankSize = 2
+ self.maxRomBankSize = 128
+
+ self.clock = clock;
+
+ self.setROM(rom);
+ self.setRAM(ram);
+
+
+ def reset():
+ super.reset()
+
+ self.clockTime = self.clock.getTime();
+
+ self.clockLatch = self.clockRegister = 0;
+
+ self.clockSeconds = self.clockMinutes = self.clockHours = self.clockDays = self.clockControl = 0;
+ self.clockLSeconds = self.clockLMinutes = self.clockLHours = self.clockLDays = self.clockLControl = 0;
+
+
+ def read(self, address):
+ if (address <= 0x3FFF):
+ # 0000-3FFF
+ return self.rom[address] & 0xFF;
+ elif (address <= 0x7FFF):
+ # 4000-5FFF
+ return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF;
+ elif (address >= 0xA000 and address <= 0xBFFF):
+ # A000-BFFF
+ if (self.ramBank >= 0):
+ return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF;
+ else:
+ if (self.clockRegister == 0x08):
+ return self.clockLSeconds;
+ if (self.clockRegister == 0x09):
+ return self.clockLMinutes;
+ if (self.clockRegister == 0x0A):
+ return self.clockLHours;
+ if (self.clockRegister == 0x0B):
+ return self.clockLDays;
+ if (self.clockRegister == 0x0C):
+ return self.clockLControl;
+ return 0xFF;
+
+
+ def write(self, address, data):
+ if (address <= 0x1FFF):
+ # 0000-1FFF
+ if (self.ramSize > 0):
+ self.ramEnable = ((data & 0x0A) == 0x0A);
+ elif (address <= 0x3FFF):
+ # 2000-3FFF
+ if (data == 0):
+ data = 1;
+ self.romBank = ((data & 0x7F) << 14) & self.romSize;
+ elif (address <= 0x5FFF):
+ # 4000-5FFF
+ if (data >= 0x00 and data <= 0x03):
+ self.ramBank = (data << 13) & self.ramSize;
+ else:
+ self.ramBank = -1;
+ self.clockRegister = data;
+ elif (address <= 0x7FFF):
+ # 6000-7FFF
+ if (self.clockLatch == 0 and data == 1):
+ self.latchClock();
+ if (data == 0 or data == 1):
+ self.clockLatch = data;
+ elif (address >= 0xA000 and address <= 0xBFFF):
+ # A000-BFFF
+ if (self.ramEnable):
+ if (self.ramBank >= 0):
+ # constants.TODO conversion to byte
+ self.ram[self.ramBank + (address & 0x1FFF)] = data;
+ else:
+ self.updateClock();
+
+ if (self.clockRegister == 0x08):
+ self.clockSeconds = data;
+ if (self.clockRegister == 0x09):
+ self.clockMinutes = data;
+ if (self.clockRegister == 0x0A):
+ self.clockHours = data;
+ if (self.clockRegister == 0x0B):
+ self.clockDays = data;
+ if (self.clockRegister == 0x0C):
+ self.clockControl = (self.clockControl & 0x80) | data;
+
+
+ def latchClock(self):
+ self.updateClock();
+
+ self.clockLSeconds = self.clockSeconds;
+ self.clockLMinutes = self.clockMinutes;
+ self.clockLHours = self.clockHours;
+ self.clockLDays = self.clockDays & 0xFF;
+ self.clockLControl = (self.clockControl & 0xFE) | ((self.clockDays >> 8) & 0x01);
+
+
+ def updateClock():
+ now = self.clock.getTime();
+
+ if ((self.clockControl & 0x40) == 0):
+ elapsed = now - self.clockTime;
+
+ while (elapsed >= 246060):
+ elapsed -= 246060
+ self.clockDays+=1
+
+ while (elapsed >= 6060):
+ elapsed -= 6060;
+ self.clockHours+=1
+
+ while (elapsed >= 60):
+ elapsed -= 60;
+ self.clockMinutes+=1
+
+ self.clockSeconds += elapsed;
+
+ while (self.clockSeconds >= 60):
+ self.clockSeconds -= 60;
+ self.clockMinutes+=1
+
+ while (self.clockMinutes >= 60):
+ self.clockMinutes -= 60;
+ self.clockHours+=1
+
+ while (self.clockHours >= 24):
+ self.clockHours -= 24;
+ self.clockDays+=1
+
+ while (self.clockDays >= 512):
+ self.clockDays -= 512;
+ self.clockControl |= 0x80;
- self.clockTime = now;
+ self.clockTime = now;
@@ -509,73 +509,73 @@
Memory Bank Controller 5 (8MB constants.ROM, 128KB constants.RAM)
*
-0000-3FFF ROM Bank 0 (16KB)
-4000-7FFF ROM Bank 1-511 (16KB)
-A000-BFFF RAM Bank 0-15 (8KB)
+0000-3FFF ROM Bank 0 (16KB)
+4000-7FFF ROM Bank 1-511 (16KB)
+A000-BFFF RAM Bank 0-15 (8KB)
"""
class MBC5(MBC):
- romBank = 0;
+ romBank = 0;
- rumble = False;
+ rumble = False;
- def __init__(self, rom, ram, rumble):
- self.minRamBankSize = 0
- self.maxRamBankSize = 16
- self.minRomBankSize = 2
- self.maxRomBankSize = 512
-
- self.rumble = rumble;
- self.setROM(rom);
- self.setRAM(ram);
-
-
- def reset():
- super.reset()
-
-
- def read(self, address):
- if (address <= 0x3FFF):
- # 0000-3FFF
- return self.rom[address] & 0xFF;
- elif (address <= 0x7FFF):
- # 4000-7FFF
- return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF;
- elif (address >= 0xA000 and address <= 0xBFFF):
- # A000-BFFF
- return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF;
- return 0xFF;
-
-
- def write(self, address, data):
- if (address <= 0x1FFF):
- # 0000-1FFF
- if (self.ramSize > 0):
- self.ramEnable = ((data & 0x0A) == 0x0A);
- elif (address <= 0x2FFF):
- # 2000-2FFF
- self.romBank = ((self.romBank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.romSize;
- elif (address <= 0x3FFF):
- # 3000-3FFF
- self.romBank = ((self.romBank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.romSize;
- elif (address <= 0x4FFF):
- # 4000-4FFF
- if (self.rumble):
- self.ramBank = ((data & 0x07) << 13) & self.ramSize;
- else:
- self.ramBank = ((data & 0x0F) << 13) & self.ramSize;
- elif (address >= 0xA000 and address <= 0xBFFF):
- # A000-BFFF
- if (self.ramEnable):
- #TODO byte conversion
- self.ram[self.ramBank + (address & 0x1FFF)] = data;
+ def __init__(self, rom, ram, rumble):
+ self.minRamBankSize = 0
+ self.maxRamBankSize = 16
+ self.minRomBankSize = 2
+ self.maxRomBankSize = 512
+
+ self.rumble = rumble;
+ self.setROM(rom);
+ self.setRAM(ram);
+
+
+ def reset():
+ super.reset()
+
+
+ def read(self, address):
+ if (address <= 0x3FFF):
+ # 0000-3FFF
+ return self.rom[address] & 0xFF;
+ elif (address <= 0x7FFF):
+ # 4000-7FFF
+ return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF;
+ elif (address >= 0xA000 and address <= 0xBFFF):
+ # A000-BFFF
+ return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF;
+ return 0xFF;
+
+
+ def write(self, address, data):
+ if (address <= 0x1FFF):
+ # 0000-1FFF
+ if (self.ramSize > 0):
+ self.ramEnable = ((data & 0x0A) == 0x0A);
+ elif (address <= 0x2FFF):
+ # 2000-2FFF
+ self.romBank = ((self.romBank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.romSize;
+ elif (address <= 0x3FFF):
+ # 3000-3FFF
+ self.romBank = ((self.romBank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.romSize;
+ elif (address <= 0x4FFF):
+ # 4000-4FFF
+ if (self.rumble):
+ self.ramBank = ((data & 0x07) << 13) & self.ramSize;
+ else:
+ self.ramBank = ((data & 0x0F) << 13) & self.ramSize;
+ elif (address >= 0xA000 and address <= 0xBFFF):
+ # A000-BFFF
+ if (self.ramEnable):
+ #TODO byte conversion
+ self.ram[self.ramBank + (address & 0x1FFF)] = data;
class HuC1(MBC):
- def __init__(self, ram, rom):
- super.__init__(self, ram, rom)
+ def __init__(self, ram, rom):
+ super.__init__(self, ram, rom)
"""
@@ -583,130 +583,130 @@
Hudson Memory Bank Controller 3 (2MB constants.ROM, 128KB constants.RAM, constants.RTC)
-0000-3FFF ROM Bank 0 (16KB)
-4000-7FFF ROM Bank 1-127 (16KB)
-A000-BFFF RAM Bank 0-15 (8KB)
+0000-3FFF ROM Bank 0 (16KB)
+4000-7FFF ROM Bank 1-127 (16KB)
+A000-BFFF RAM Bank 0-15 (8KB)
"""
class HuC3(MBC):
- clock = None;
-
- romBank = 0;
-
- ramFlag = 0;
-
- ramValue = 0;
-
- clockRegister = 0;
- clockShift = 0;
- clockTime = 0;
-
- def __init__(self, rom, ram, clock):
- self.minRamBankSize = 0
- self.maxRamBankSize = 4
- self.minRomBankSize = 2
- self.maxRomBankSize = 128
- self.clock = clock;
- self.setROM(rom);
- self.setRAM(ram);
-
-
- def reset():
- super.reset()
-
- self.ramFlag = 0;
- self.ramValue = 0;
-
- self.clockRegister = 0;
- self.clockShift = 0;
-
- self.clockTime = self.clock.getTime();
-
-
- def read(self, address):
- if (address <= 0x3FFF):
- # 0000-3FFF
- return self.rom[address] & 0xFF;
- elif (address <= 0x7FFF):
- # 4000-5FFF
- return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF;
- elif (address >= 0xA000 and address <= 0xBFFF):
- # A000-BFFF
- if (self.ramFlag == 0x0C):
- return self.ramValue;
- elif (self.ramFlag == 0x0D):
- return 0x01;
- elif (self.ramFlag == 0x0A or self.ramFlag == 0x00):
- if (self.ramSize > 0):
- return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF;
- return 0xFF;
-
-
- def write(self, address, data):
- if (address <= 0x1FFF):
- # 0000-1FFF
- self.ramFlag = data;
- elif (address <= 0x3FFF):
- # 2000-3FFF
- if ((data & 0x7F) == 0):
- data = 1;
- self.romBank = ((data & 0x7F) << 14) & self.romSize;
- elif (address <= 0x5FFF):
- # 4000-5FFF
- self.ramBank = ((data & 0x0F) << 13) & self.ramSize;
- elif (address >= 0xA000 and address <= 0xBFFF):
- # A000-BFFF
- if (self.ramFlag == 0x0B):
- if ((data & 0xF0) == 0x10):
- if (self.clockShift <= 24):
- self.ramValue = (self.clockRegister >> self.clockShift) & 0x0F;
- self.clockShift += 4;
- elif ((data & 0xF0) == 0x30):
- if (self.clockShift <= 24):
- self.clockRegister &= ~(0x0F << self.clockShift);
- self.clockRegister |= ((data & 0x0F) << self.clockShift);
- self.clockShift += 4;
- elif ((data & 0xF0) == 0x40):
- self.updateClock();
- if ((data & 0x0F) == 0x00):
- self.clockShift = 0;
- elif ((data & 0x0F) == 0x03):
- self.clockShift = 0;
- elif ((data & 0x0F) == 0x07):
- self.clockShift = 0;
- elif ((data & 0xF0) == 0x50):
- pass
- elif ((data & 0xF0) == 0x60):
- self.ramValue = 0x01;
- elif (self.ramFlag >= 0x0C and self.ramFlag <= 0x0E):
- pass
- elif (self.ramFlag == 0x0A):
- if (self.ramSize > 0):
- #TODO byte conversion
- self.ram[self.ramBank + (address & 0x1FFF)] = data;
-
-
- def updateClock(self):
- now = self.clock.getTime();
- elapsed = now - self.clockTime;
- # years (4 bits)
- while (elapsed >= 365246060):
- self.clockRegister += 1 << 24;
- elapsed -= 365246060;
- # days (12 bits)
- while (elapsed >= 246060):
- self.clockRegister += 1 << 12;
- elapsed -= 246060;
- # minutes (12 bits)
- while (elapsed >= 60):
- self.clockRegister += 1;
- elapsed -= 60;
-
- if ((self.clockRegister & 0x0000FFF) >= 2460):
- self.clockRegister += (1 << 12) - 2460;
- if ((self.clockRegister & 0x0FFF000) >= (365 << 12)):
- self.clockRegister += (1 << 24) - (365 << 12);
+ clock = None;
+
+ romBank = 0;
+
+ ramFlag = 0;
+
+ ramValue = 0;
+
+ clockRegister = 0;
+ clockShift = 0;
+ clockTime = 0;
+
+ def __init__(self, rom, ram, clock):
+ self.minRamBankSize = 0
+ self.maxRamBankSize = 4
+ self.minRomBankSize = 2
+ self.maxRomBankSize = 128
+ self.clock = clock;
+ self.setROM(rom);
+ self.setRAM(ram);
+
+
+ def reset():
+ super.reset()
+
+ self.ramFlag = 0;
+ self.ramValue = 0;
+
+ self.clockRegister = 0;
+ self.clockShift = 0;
+
+ self.clockTime = self.clock.getTime();
+
+
+ def read(self, address):
+ if (address <= 0x3FFF):
+ # 0000-3FFF
+ return self.rom[address] & 0xFF;
+ elif (address <= 0x7FFF):
+ # 4000-5FFF
+ return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF;
+ elif (address >= 0xA000 and address <= 0xBFFF):
+ # A000-BFFF
+ if (self.ramFlag == 0x0C):
+ return self.ramValue;
+ elif (self.ramFlag == 0x0D):
+ return 0x01;
+ elif (self.ramFlag == 0x0A or self.ramFlag == 0x00):
+ if (self.ramSize > 0):
+ return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF;
+ return 0xFF;
+
+
+ def write(self, address, data):
+ if (address <= 0x1FFF):
+ # 0000-1FFF
+ self.ramFlag = data;
+ elif (address <= 0x3FFF):
+ # 2000-3FFF
+ if ((data & 0x7F) == 0):
+ data = 1;
+ self.romBank = ((data & 0x7F) << 14) & self.romSize;
+ elif (address <= 0x5FFF):
+ # 4000-5FFF
+ self.ramBank = ((data & 0x0F) << 13) & self.ramSize;
+ elif (address >= 0xA000 and address <= 0xBFFF):
+ # A000-BFFF
+ if (self.ramFlag == 0x0B):
+ if ((data & 0xF0) == 0x10):
+ if (self.clockShift <= 24):
+ self.ramValue = (self.clockRegister >> self.clockShift) & 0x0F;
+ self.clockShift += 4;
+ elif ((data & 0xF0) == 0x30):
+ if (self.clockShift <= 24):
+ self.clockRegister &= ~(0x0F << self.clockShift);
+ self.clockRegister |= ((data & 0x0F) << self.clockShift);
+ self.clockShift += 4;
+ elif ((data & 0xF0) == 0x40):
+ self.updateClock();
+ if ((data & 0x0F) == 0x00):
+ self.clockShift = 0;
+ elif ((data & 0x0F) == 0x03):
+ self.clockShift = 0;
+ elif ((data & 0x0F) == 0x07):
+ self.clockShift = 0;
+ elif ((data & 0xF0) == 0x50):
+ pass
+ elif ((data & 0xF0) == 0x60):
+ self.ramValue = 0x01;
+ elif (self.ramFlag >= 0x0C and self.ramFlag <= 0x0E):
+ pass
+ elif (self.ramFlag == 0x0A):
+ if (self.ramSize > 0):
+ #TODO byte conversion
+ self.ram[self.ramBank + (address & 0x1FFF)] = data;
+
+
+ def updateClock(self):
+ now = self.clock.getTime();
+ elapsed = now - self.clockTime;
+ # years (4 bits)
+ while (elapsed >= 365246060):
+ self.clockRegister += 1 << 24;
+ elapsed -= 365246060;
+ # days (12 bits)
+ while (elapsed >= 246060):
+ self.clockRegister += 1 << 12;
+ elapsed -= 246060;
+ # minutes (12 bits)
+ while (elapsed >= 60):
+ self.clockRegister += 1;
+ elapsed -= 60;
+
+ if ((self.clockRegister & 0x0000FFF) >= 2460):
+ self.clockRegister += (1 << 12) - 2460;
+ if ((self.clockRegister & 0x0FFF000) >= (365 << 12)):
+ self.clockRegister += (1 << 24) - (365 << 12);
- self.clockTime = now - elapsed;
+ self.clockTime = now - elapsed;
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py Sun Mar 16 20:42:44 2008
@@ -54,7 +54,7 @@
# constants.RAM Bank Size (8KB)
RAM_BANK_SIZE = 0x2000
-
+
# ___________________________________________________________________________
# CPU FLAGS
# ___________________________________________________________________________
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Sun Mar 16 20:42:44 2008
@@ -8,61 +8,61 @@
class Interrupt(object):
- # Registers
- enable = 0;
- flag = 0;
+ # Registers
+ enable = 0;
+ flag = 0;
- def __init__(self):
- self.reset();
+ def __init__(self):
+ self.reset();
- def reset(self):
- self.enable = 0;
- self.flag = VBLANK;
+ def reset(self):
+ self.enable = 0;
+ self.flag = VBLANK;
- def isPending(self):
- return (self.enable & self.flag) != 0;
+ def isPending(self):
+ return (self.enable & self.flag) != 0;
- def isPending(self, mask):
- return (self.enable & self.flag & mask) != 0;
+ def isPending(self, mask):
+ return (self.enable & self.flag & mask) != 0;
- def raiseInterrupt(self, mask):
- self.flag |= mask;
+ def raiseInterrupt(self, mask):
+ self.flag |= mask;
- def lower(self, mask):
- self.flag &= ~mask;
+ def lower(self, mask):
+ self.flag &= ~mask;
- def write(self, address, data):
- if address == constants.IE:
- self.setInterruptEnable(data);
- elif address == constants.IF:
- self.setInterruptFlag(data);
+ def write(self, address, data):
+ if address == constants.IE:
+ self.setInterruptEnable(data);
+ elif address == constants.IF:
+ self.setInterruptFlag(data);
- def read(self, address):
- if address == constants.IE:
- return self.getInterruptEnable();
- elif address == constants.IF:
- return self.getInterruptFlag();
- return 0xFF;
+ def read(self, address):
+ if address == constants.IE:
+ return self.getInterruptEnable();
+ elif address == constants.IF:
+ return self.getInterruptFlag();
+ return 0xFF;
- def getInterruptEnable(self):
- return self.enable;
+ def getInterruptEnable(self):
+ return self.enable;
- def getInterruptFlag(self):
- return 0xE0 | self.flag;
+ def getInterruptFlag(self):
+ return 0xE0 | self.flag;
- def setInterruptEnable(self, data):
- self.enable = data;
+ def setInterruptEnable(self, data):
+ self.enable = data;
- def setInterruptFlag(self, data):
- self.flag = data;
+ def setInterruptFlag(self, data):
+ self.flag = data;
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Sun Mar 16 20:42:44 2008
@@ -6,65 +6,65 @@
class Joypad(object):
- # Registers
- joyp = 0;
- cycles = 0;
+ # Registers
+ joyp = 0;
+ cycles = 0;
- # Interrupt Controller
- interrupt = None;
+ # Interrupt Controller
+ interrupt = None;
- # Driver JoypadDriver
- driver = None;
+ # Driver JoypadDriver
+ driver = None;
- def __init__(self, joypadDriver, interrupt):
- self.driver = joypadDriver;
- self.interrupt = interrupt;
- self.reset();
+ def __init__(self, joypadDriver, interrupt):
+ self.driver = joypadDriver;
+ self.interrupt = interrupt;
+ self.reset();
- def reset(self):
- self.joyp = 0xFF;
- self.cycles = constants.JOYPAD_CLOCK;
+ def reset(self):
+ self.joyp = 0xFF;
+ self.cycles = constants.JOYPAD_CLOCK;
- def cycles(self):
- return self.cycles;
+ def cycles(self):
+ return self.cycles;
- def emulate(self, ticks):
- self.cycles -= ticks;
- if (self.cycles <= 0):
- if (self.driver.isRaised()):
- self.update();
+ def emulate(self, ticks):
+ self.cycles -= ticks;
+ if (self.cycles <= 0):
+ if (self.driver.isRaised()):
+ self.update();
- self.cycles = constants.JOYPAD_CLOCK;
+ self.cycles = constants.JOYPAD_CLOCK;
- def write(self, address, data):
- if (address == constants.JOYP):
- self.joyp = (self.joyp & 0xCF) + (data & 0x30);
- self.update();
+ def write(self, address, data):
+ if (address == constants.JOYP):
+ self.joyp = (self.joyp & 0xCF) + (data & 0x30);
+ self.update();
- def read(self, address):
- if (address == constants.JOYP):
- return self.joyp;
- return 0xFF;
+ def read(self, address):
+ if (address == constants.JOYP):
+ return self.joyp;
+ return 0xFF;
- def update(self):
- data = self.joyp & 0xF0;
+ def update(self):
+ data = self.joyp & 0xF0;
- switch = (data & 0x30)
- if switch==0x10:
- data |= self.driver.getButtons();
- elif switch==0x20:
- data |= self.driver.getDirections();
- elif switch==0x30:
- data |= 0x0F;
+ switch = (data & 0x30)
+ if switch==0x10:
+ data |= self.driver.getButtons();
+ elif switch==0x20:
+ data |= self.driver.getDirections();
+ elif switch==0x30:
+ data |= 0x0F;
- if ((self.joyp & ~data & 0x0F) != 0):
- self.interrupt.raiseInterrupt(constants.JOYPAD);
+ if ((self.joyp & ~data & 0x0F) != 0):
+ self.interrupt.raiseInterrupt(constants.JOYPAD);
- self.joyp = data;
+ self.joyp = data;
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py Sun Mar 16 20:42:44 2008
@@ -7,44 +7,44 @@
from pypy.lang.gameboy import constants
class RAM(object):
-
- # Work RAM
- wram = []
-
- # High RAM
- hram = []
-
- def __init__(self):
- self.reset();
-
- def reset(self):
- self.wram = range(0, constants.WRAM_SIZE)
- for index in range(0, constants.WRAM_SIZE):
- #TODO convert to byte
- self.wram[index] = 0x00;
-
- self.hram = range(0, constants.HIGH_SIZE)
- for index in range(0, constants.HIGH_SIZE):
- #TODO convert to byte
- self.hram[index] = 0x00;
-
- def write(self, address, data):
- if (address >= 0xC000 and address <= 0xFDFF):
- # C000-DFFF Work RAM (8KB)
- # E000-FDFF Echo RAM
- #TODO convert to byte
- self.wram[address & 0x1FFF] = data;
- elif (address >= 0xFF80 and address <= 0xFFFE):
- # FF80-FFFE High RAM
- #TODO convert to byte
- self.hram[address & 0x7F] = data;
-
- def read(self, address):
- if (address >= 0xC000 and address <= 0xFDFF):
- # C000-DFFF Work RAM
- # E000-FDFF Echo RAM
- return self.wram[address & 0x1FFF] & 0xFF;
- elif (address >= 0xFF80 and address <= 0xFFFE):
- # FF80-FFFE High RAM
- return self.hram[address & 0x7F] & 0xFF;
- return 0xFF;
+
+ # Work RAM
+ wram = []
+
+ # High RAM
+ hram = []
+
+ def __init__(self):
+ self.reset();
+
+ def reset(self):
+ self.wram = range(0, constants.WRAM_SIZE)
+ for index in range(0, constants.WRAM_SIZE):
+ #TODO convert to byte
+ self.wram[index] = 0x00;
+
+ self.hram = range(0, constants.HIGH_SIZE)
+ for index in range(0, constants.HIGH_SIZE):
+ #TODO convert to byte
+ self.hram[index] = 0x00;
+
+ def write(self, address, data):
+ if (address >= 0xC000 and address <= 0xFDFF):
+ # C000-DFFF Work RAM (8KB)
+ # E000-FDFF Echo RAM
+ #TODO convert to byte
+ self.wram[address & 0x1FFF] = data;
+ elif (address >= 0xFF80 and address <= 0xFFFE):
+ # FF80-FFFE High RAM
+ #TODO convert to byte
+ self.hram[address & 0x7F] = data;
+
+ def read(self, address):
+ if (address >= 0xC000 and address <= 0xFDFF):
+ # C000-DFFF Work RAM
+ # E000-FDFF Echo RAM
+ return self.wram[address & 0x1FFF] & 0xFF;
+ elif (address >= 0xFF80 and address <= 0xFFFE):
+ # FF80-FFFE High RAM
+ return self.hram[address & 0x7F] & 0xFF;
+ return 0xFF;
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Sun Mar 16 20:42:44 2008
@@ -6,50 +6,50 @@
class Serial(object):
- # Registers
- sb = 0
- sc = 0
- cycles = 0
+ # Registers
+ sb = 0
+ sc = 0
+ cycles = 0
- # Interrupt Controller #Interrupt
- interrupt = None
+ # Interrupt Controller #Interrupt
+ interrupt = None
- def __init__(self, interrupt):
- self.interrupt = interrupt
- self.reset()
+ def __init__(self, interrupt):
+ self.interrupt = interrupt
+ self.reset()
- def reset(self):
- self.cycles = constants.SERIAL_CLOCK
- self.sb = 0x00
- self.sc = 0x00
+ def reset(self):
+ self.cycles = constants.SERIAL_CLOCK
+ self.sb = 0x00
+ self.sc = 0x00
- def cycles(self):
- return self.cycles
+ def cycles(self):
+ return self.cycles
- def emulate(self, ticks):
- if ((self.sc & 0x81) == 0x81):
- self.cycles -= ticks
+ def emulate(self, ticks):
+ if ((self.sc & 0x81) == 0x81):
+ self.cycles -= ticks
- if (self.cycles <= 0):
- self.sb = 0xFF
- self.sc &= 0x7F
- self.cycles = constants.SERIAL_IDLE_CLOCK
+ if (self.cycles <= 0):
+ self.sb = 0xFF
+ self.sc &= 0x7F
+ self.cycles = constants.SERIAL_IDLE_CLOCK
- self.interrupt.raiseInterrupt(constants.SERIAL)
+ self.interrupt.raiseInterrupt(constants.SERIAL)
- def setSerialData(self, data):
- self.sb = data
+ def setSerialData(self, data):
+ self.sb = data
- def setSerialControl(self, data):
- self.sc = data
+ def setSerialControl(self, data):
+ self.sc = data
- # HACK: delay the serial interrupt (Shin Nihon Pro Wrestling)
- self.cycles = constants.SERIAL_IDLE_CLOCK + constants.SERIAL_CLOCK
+ # HACK: delay the serial interrupt (Shin Nihon Pro Wrestling)
+ self.cycles = constants.SERIAL_IDLE_CLOCK + constants.SERIAL_CLOCK
- def getSerialData(self):
- return self.sb
+ def getSerialData(self):
+ return self.sb
- def getSerialControl(self):
- return self.sc
+ def getSerialControl(self):
+ return self.sc
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sun Mar 16 20:42:44 2008
@@ -8,738 +8,738 @@
class Sound(object):
- # Audio Channel 1 int
- nr10=0;
- nr11=0;
- nr12=0;
- nr13=0;
- nr14=0;
- audio1Index=0;
- audio1Length=0;
- audio1Volume=0;
- audio1EnvelopeLength=0;
- audio1SweepLength=0;
- audio1Frequency=0;
-
-
- # Audio Channel 2 int
- nr21=0;
- nr22=0;
- nr23=0;
- nr24=0;
- audio2Index=0;
- audio2Length=0;
- audio2Volume=0;
- audio2EnvelopeLength=0;
- audio2Frequency=0;
-
-
- # Audio Channel 3 int
- nr30=0;
- nr31=0;
- nr32=0;
- nr33=0;
- nr34=0;
- audio3Index=0;
- audio3Length=0;
- audio3Frequency=0;
- audio3WavePattern = []# = new byte[16];
-
- # Audio Channel 4 int
- nr41=0;
- nr42=0;
- nr43=0;
- nr44=0;
- audio4Index=0;
- audio4Length=0;
- audio4Volume=0;
- audio4EnvelopeLength=0;
- audio4Frequency=0;
-
- # Output Control int
- nr50=0;
- nr51=0;
- nr52=0;
-
- # Sound DriverSoundDriver
- #driver;
- buffer = []# = new byte[512];
- #int
- #frames;
- #cycles;
-
- # Frequency Table
- frequencyTable = []#= new int[2048];
- noiseFreqRatioTable = [] #= new int[8];
-
- # Noise Tables
- noiseStep7Table = [] #= new int[128 / 32];
- noiseStep15Table = [] #= new int[32768 / 32];
-
- def __init__(self, soundDriver):
- self.driver = soundDriver;
- self.generateFrequencyTables();
- self.generateNoiseTables();
- self.reset();
-
-
- def start(self):
- self.driver.start();
-
-
- def stop(self):
- self.driver.stop();
-
-
- def cycles(self):
- return self.cycles;
-
-
- def emulate(self, ticks):
- self.cycles -= ticks;
- while (self.cycles <= 0):
- self.updateAudio();
- if (self.driver.isEnabled()):
- self.frames += self.driver.getSampleRate();
- length = (self.frames / constants.SOUND_CLOCK) << 1;
- self.mixAudio(self.buffer, length);
- self.driver.write(self.buffer, length);
- self.frames %= constants.SOUND_CLOCK;
-
- self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK;
-
-
-
- def reset(self):
- self.cycles = constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK;
- self.frames = 0;
- self.audio1Index = self.audio2Index = self.audio3Index = self.audio4Index = 0;
- self.write(constants.NR10, 0x80);
- self.write(constants.NR11, 0x3F); # 0xBF
- self.write(constants.NR12, 0x00); # 0xF3
- self.write(constants.NR13, 0xFF);
- self.write(constants.NR14, 0xBF);
-
- self.write(constants.NR21, 0x3F);
- self.write(constants.NR22, 0x00);
- self.write(constants.NR23, 0xFF);
- self.write(constants.NR24, 0xBF);
-
- self.write(constants.NR30, 0x7F);
- self.write(constants.NR31, 0xFF);
- self.write(constants.NR32, 0x9F);
- self.write(constants.NR33, 0xFF);
- self.write(constants.NR34, 0xBF);
-
- self.write(constants.NR41, 0xFF);
- self.write(constants.NR42, 0x00);
- self.write(constants.NR43, 0x00);
- self.write(constants.NR44, 0xBF);
-
- self.write(constants.NR50, 0x00); # 0x77
- self.write(constants.NR51, 0xF0);
- self.write(constants.NR52, 0xFF); # 0xF0
-
- for address in range(0xFF30, 0xFF3F):
- write = 0xFF
- if (address & 1) == 0:
- write = 0x00
- self.write(address, write);
-
-
- def read(self, address):
- if address==constants.NR10:
- return self.getAudio1Sweep();
- elif address == constants.NR11:
- return self.getAudio1Length();
- elif address == constants.NR12:
- return self.getAudio1Envelope();
- elif address == constants.NR13:
- return self.getAudio1Frequency();
- elif address == constants.NR14:
- return self.getAudio1Playback();
-
- elif address == constants.NR21:
- return self.getAudio2Length();
- elif address == constants.NR22:
- return self.getAudio2Envelope();
- elif address==constants.NR23:
- return self.getAudio2Frequency();
- elif address==constants.NR24:
- return self.getAudio2Playback();
-
- elif address==constants.NR30:
- return self.getAudio3Enable();
- elif address==constants.NR31:
- return self.getAudio3Length();
- elif address==constants.NR32:
- return self.getAudio3Level();
- elif address==constants.NR33:
- return self.getAudio4Frequency();
- elif address==constants.NR34:
- return self.getAudio3Playback();
-
- elif address==constants.NR41:
- return self.getAudio4Length();
- elif address==constants.NR42:
- return self.getAudio4Envelope();
- elif address==constants.NR43:
- return self.getAudio4Polynomial();
- elif address==constants.NR44:
- return self.getAudio4Playback();
-
- elif address==constants.NR50:
- return self.getOutputLevel();
- elif address==constants.NR51:
- return self.getOutputTerminal();
- elif address==constants.NR52:
- return self.getOutputEnable();
-
- elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F):
- return self.getAudio3WavePattern(address);
-
- return 0xFF;
-
-
- def write(self, address, data):
- if address==constants.NR10:
- self.setAudio1Sweep(data);
- elif address == constants.NR11:
- self.setAudio1Length(data);
- elif address == constants.NR12:
- self.setAudio1Envelope(data);
- elif address == constants.NR13:
- self.setAudio1Frequency(data);
- elif address == constants.NR14:
- self.setAudio1Playback(data);
-
- elif address == constants.NR21:
- self.setAudio2Length(data);
- elif address == constants.NR22:
- self.setAudio2Envelope(data);
- elif address == constants.NR23:
- self.setAudio2Frequency(data);
- elif address == constants.NR24:
- self.setAudio2Playback(data);
-
- elif address == constants.NR30:
- self.setAudio3Enable(data);
- elif address == constants.NR31:
- self.setAudio3Length(data);
- elif address == constants.NR32:
- self.setAudio3Level(data);
- elif address == constants.NR33:
- self.setAudio3Frequency(data);
- elif address == constants.NR34:
- self.setAudio3Playback(data);
-
- elif address == constants.NR41:
- self.setAudio4Length(data);
- elif address == constants.NR42:
- self.setAudio4Envelope(data);
- elif address == constants.NR43:
- self.setAudio4Polynomial(data);
- elif address == constants.NR44:
- self.setAudio4Playback(data);
-
- elif address == constants.NR50:
- self.setOutputLevel(data);
- elif address == constants.NR51:
- self.setOutputTerminal(data);
- elif address == constants.NR52:
- self.setOutputEnable(data);
-
- elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F):
- self.setAudio3WavePattern(address, data);
-
-
- def updateAudio(self):
- if ((self.nr52 & 0x80) == 0):
- return
- if ((self.nr52 & 0x01) != 0):
- self.updateAudio1();
- if ((self.nr52 & 0x02) != 0):
- self.updateAudio2();
- if ((self.nr52 & 0x04) != 0):
- self.updateAudio3();
- if ((self.nr52 & 0x08) != 0):
- self.updateAudio4();
-
-
- def mixAudio(self,buffer, length):
- for index in range(0, length):
- buffer[index] = 0;
- if ((self.nr52 & 0x80) == 0):
- return
- if ((self.nr52 & 0x01) != 0):
- self.mixAudio1(buffer, length);
- if ((self.nr52 & 0x02) != 0):
- self.mixAudio2(buffer, length);
- if ((self.nr52 & 0x04) != 0):
- self.mixAudio3(buffer, length);
- if ((self.nr52 & 0x08) != 0):
- self.mixAudio4(buffer, length);
-
-
- # Audio Channel 1
- def getAudio1Sweep(self):
- return self.nr10;
-
-
- def getAudio1Length(self):
- return self.nr11;
-
-
- def getAudio1Envelope(self):
- return self.nr12;
-
-
- def getAudio1Frequency(self):
- return self.nr13;
-
-
- def getAudio1Playback(self):
- return self.nr14;
-
-
- def setAudio1Sweep(self, data):
- self.nr10 = data;
- self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07);
-
-
- def setAudio1Length(self, data):
- self.nr11 = data;
- self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr11 & 0x3F));
-
-
- def setAudio1Envelope(self, data):
- self.nr12 = data;
- if ((self.nr14 & 0x40) != 0):
- return
- if ((self.nr12 >> 4) == 0):
- self.audio1Volume = 0;
- elif (self.audio1EnvelopeLength == 0 and (self.nr12 & 0x07) == 0):
- self.audio1Volume = (self.audio1Volume + 1) & 0x0F;
- else:
- self.audio1Volume = (self.audio1Volume + 2) & 0x0F;
-
-
- def setAudio1Frequency(self, data):
- self.nr13 = data;
- self.audio1Frequency = self.frequencyTable[self.nr13 + ((self.nr14 & 0x07) << 8)];
-
-
- def setAudio1Playback(self, data):
- self.nr14 = data;
- self.audio1Frequency = self.frequencyTable[self.nr13
- + ((self.nr14 & 0x07) << 8)];
- if ((self.nr14 & 0x80) != 0):
- self.nr52 |= 0x01;
- if ((self.nr14 & 0x40) != 0 and self.audio1Length == 0):
- self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr11 & 0x3F));
- self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07);
- self.audio1Volume = self.nr12 >> 4;
- self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr12 & 0x07);
-
-
- def updateAudio1(self):
- if ((self.nr14 & 0x40) != 0 and self.audio1Length > 0):
- self.audio1Length-=1;
- if (self.audio1Length <= 0):
- self.nr52 &= ~0x01;
- if (self.audio1EnvelopeLength > 0):
- self.audio1EnvelopeLength-=1;
- if (self.audio1EnvelopeLength <= 0):
- if ((self.nr12 & 0x08) != 0):
- if (self.audio1Volume < 15):
- self.audio1Volume+=1;
- elif (self.audio1Volume > 0):
- self.audio1Volume-=1;
- self.audio1EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr12 & 0x07);
- if (self.audio1SweepLength > 0):
- self.audio1SweepLength-=1;
- if (self.audio1SweepLength <= 0):
- sweepSteps = (self.nr10 & 0x07);
- if (sweepSteps != 0):
- frequency = ((self.nr14 & 0x07) << 8) + self.nr13;
- if ((self.nr10 & 0x08) != 0):
- frequency -= frequency >> sweepSteps;
- else:
- frequency += frequency >> sweepSteps;
- if (frequency < 2048):
- self.audio1Frequency = self.frequencyTable[frequency];
- self.nr13 = frequency & 0xFF;
- self.nr14 = (self.nr14 & 0xF8) + ((frequency >> 8) & 0x07);
- else:
- self.audio1Frequency = 0;
- self.nr52 &= ~0x01;
-
- self.audio1SweepLength += (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07);
-
-
- def mixAudio1(self, buffer, length):
- wavePattern = 0x18
- if (self.nr11 & 0xC0) == 0x00:
- wavePattern = 0x04
- elif (self.nr11 & 0xC0) == 0x40:
- wavePattern = 0x08
- elif (self.nr11 & 0xC0) == 0x80:
- wavePattern = 0x10
- wavePattern << 22;
- for index in range(0, length, 3):
- self.audio1Index += self.audio1Frequency;
- if ((self.audio1Index & (0x1F << 22)) >= wavePattern):
- if ((self.nr51 & 0x10) != 0):
- buffer[index + 0] -= self.audio1Volume;
- if ((self.nr51 & 0x01) != 0):
- buffer[index + 1] -= self.audio1Volume;
- else:
- if ((self.nr51 & 0x10) != 0):
- buffer[index + 0] += self.audio1Volume;
- if ((self.nr51 & 0x01) != 0):
- buffer[index + 1] += self.audio1Volume;
-
-
- # Audio Channel 2
- def getAudio2Length(self):
- return self.nr21;
-
-
- def getAudio2Envelope(self):
- return self.nr22;
-
-
- def getAudio2Frequency(self):
- return self.nr23;
-
-
- def getAudio2Playback(self):
- return self.nr24;
-
-
- def setAudio2Length(self, data):
- self.nr21 = data;
- self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr21 & 0x3F));
-
-
- def setAudio2Envelope(self, data):
- self.nr22 = data;
- if ((self.nr24 & 0x40) == 0):
- if ((self.nr22 >> 4) == 0):
- self.audio2Volume = 0;
- elif (self.audio2EnvelopeLength == 0 and (self.nr22 & 0x07) == 0):
- self.audio2Volume = (self.audio2Volume + 1) & 0x0F;
- else:
- self.audio2Volume = (self.audio2Volume + 2) & 0x0F;
-
-
- def setAudio2Frequency(self, data):
- self.nr23 = data;
- self.audio2Frequency = self.frequencyTable[self.nr23\
- + ((self.nr24 & 0x07) << 8)];
-
-
- def setAudio2Playback(self, data):
- self.nr24 = data;
- self.audio2Frequency = self.frequencyTable[self.nr23\
- + ((self.nr24 & 0x07) << 8)];
- if ((self.nr24 & 0x80) != 0):
- self.nr52 |= 0x02;
- if ((self.nr24 & 0x40) != 0 and self.audio2Length == 0):
- self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr21 & 0x3F));
- self.audio2Volume = self.nr22 >> 4;
- self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr22 & 0x07);
-
-
-
- def updateAudio2(self):
- if ((self.nr24 & 0x40) != 0 and self.audio2Length > 0):
- self.audio2Length-=1;
- if (self.audio2Length <= 0):
- self.nr52 &= ~0x02;
- if (self.audio2EnvelopeLength > 0):
- self.audio2EnvelopeLength-=1;
-
- if (self.audio2EnvelopeLength <= 0):
- if ((self.nr22 & 0x08) != 0):
- if (self.audio2Volume < 15):
- self.audio2Volume+=1;
- elif (self.audio2Volume > 0):
- self.audio2Volume-=1;
- self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr22 & 0x07);
-
-
- def mixAudio2(self, buffer, length):
- wavePattern = 0x18
- if (self.nr21 & 0xC0) == 0x00:
- wavePattern = 0x04
- elif (self.nr21 & 0xC0) == 0x40:
- wavePattern = 0x08
- elif (self.nr21 & 0xC0) == 0x80:
- wavePattern = 0x10
- wavePattern << 22;
- for index in range(0, length):
- self.audio2Index += self.audio2Frequency;
- if ((self.audio2Index & (0x1F << 22)) >= wavePattern):
- if ((self.nr51 & 0x20) != 0):
- buffer[index + 0] -= self.audio2Volume;
- if ((self.nr51 & 0x02) != 0):
- buffer[index + 1] -= self.audio2Volume;
- else:
- if ((self.nr51 & 0x20) != 0):
- buffer[index + 0] += self.audio2Volume;
- if ((self.nr51 & 0x02) != 0):
- buffer[index + 1] += self.audio2Volume;
-
-
- # Audio Channel 3
- def getAudio3Enable(self):
- return self.nr30;
-
-
- def getAudio3Length(self):
- return self.nr31;
-
-
- def getAudio3Level(self):
- return self.nr32;
-
-
- def getAudio4Frequency(self):
- return self.nr33;
-
-
- def getAudio3Playback(self):
- return self.nr34;
-
-
- def setAudio3Enable(self, data):
- self.nr30 = data & 0x80;
- if ((self.nr30 & 0x80) == 0):
- self.nr52 &= ~0x04;
-
-
- def setAudio3Length(self, data):
- self.nr31 = data;
- self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.nr31);
-
-
- def setAudio3Level(self, data):
- self.nr32 = data;
-
-
- def setAudio3Frequency(self, data):
- self.nr33 = data;
- self.audio3Frequency = self.frequencyTable[((self.nr34 & 0x07) << 8) + self.nr33] >> 1;
-
-
- def setAudio3Playback(self, data):
- self.nr34 = data;
- self.audio3Frequency = self.frequencyTable[((self.nr34 & 0x07) << 8) + self.nr33] >> 1;
- if ((self.nr34 & 0x80) != 0 and (self.nr30 & 0x80) != 0):
- self.nr52 |= 0x04;
- if ((self.nr34 & 0x40) != 0 and self.audio3Length == 0):
- self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.nr31);
-
-
-
- def setAudio3WavePattern(self, address, data):
- #TODO convert to byte
- self.audio3WavePattern[address & 0x0F] = data;
-
-
- def getAudio3WavePattern(self, address):
- return self.audio3WavePattern[address & 0x0F] & 0xFF;
-
-
- def updateAudio3(self):
- if ((self.nr34 & 0x40) != 0 and self.audio3Length > 0):
- self.audio3Length-=1;
- if (self.audio3Length <= 0):
- self.nr52 &= ~0x04;
-
-
- def mixAudio3(self, buffer, length):
- wavePattern = 2
- if (self.nr32 & 0x60) == 0x00:
- wavePattern = 8
- elif (self.nr32 & 0x60) == 0x40:
- wavePattern = 0
- elif (self.nr32 & 0x60) == 0x80:
- wavePattern = 1
-
- for index in range(0, length, 2):
- self.audio3Index += self.audio3Frequency;
- sample = self.audio3WavePattern[(self.audio3Index >> 23) & 0x0F];
- if ((self.audio3Index & (1 << 22)) != 0):
- sample = (sample >> 0) & 0x0F;
- else:
- sample = (sample >> 4) & 0x0F;
-
- sample = ((sample - 8) << 1) >> level;
-
- if ((self.nr51 & 0x40) != 0):
- buffer[index + 0] += sample;
- if ((self.nr51 & 0x04) != 0):
- buffer[index + 1] += sample;
-
-
- # Audio Channel 4
- def getAudio4Length(self):
- return self.nr41;
-
-
- def getAudio4Envelope(self):
- return self.nr42;
-
-
- def getAudio4Polynomial(self):
- return self.nr43;
-
-
- def getAudio4Playback(self):
- return self.nr44;
-
-
- def setAudio4Length(self, data):
- self.nr41 = data;
- self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr41 & 0x3F));
-
-
- def setAudio4Envelope(self, data):
- self.nr42 = data;
- if ((self.nr44 & 0x40) == 0):
- if ((self.nr42 >> 4) == 0):
- self.audio4Volume = 0;
- elif (self.audio4EnvelopeLength == 0 and (self.nr42 & 0x07) == 0):
- self.audio4Volume = (self.audio4Volume + 1) & 0x0F;
- else:
- self.audio4Volume = (self.audio4Volume + 2) & 0x0F;
-
-
- def setAudio4Polynomial(self, data):
- self.nr43 = data;
- if ((self.nr43 >> 4) <= 12):
- self.audio4Frequency = self.noiseFreqRatioTable[self.nr43 & 0x07] >> ((self.nr43 >> 4) + 1);
- else:
- self.audio4Frequency = 0;
-
-
- def setAudio4Playback(self, data):
- self.nr44 = data;
- if ((self.nr44 & 0x80) != 0):
- self.nr52 |= 0x08;
- if ((self.nr44 & 0x40) != 0 and self.audio4Length == 0):
- self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr41 & 0x3F));
- self.audio4Volume = self.nr42 >> 4;
- self.audio4EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr42 & 0x07);
- self.audio4Index = 0;
-
-
-
- def updateAudio4(self):
- if ((self.nr44 & 0x40) != 0 and self.audio4Length > 0):
- self.audio4Length-=1;
- if (self.audio4Length <= 0):
- self.nr52 &= ~0x08;
- if (self.audio4EnvelopeLength > 0):
- self.audio4EnvelopeLength-=1;
- if (self.audio4EnvelopeLength <= 0):
- if ((self.nr42 & 0x08) != 0):
- if (self.audio4Volume < 15):
- self.audio4Volume+=1;
- elif (self.audio4Volume > 0):
- self.audio4Volume-=1;
- self.audio4EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr42 & 0x07);
-
-
- def mixAudio4(self, buffer, length):
- for index in range(0, length, 2):
- self.audio4Index += self.audio4Frequency;
- polynomial;
- if ((self.nr43 & 0x08) != 0):
- # 7 steps
- self.audio4Index &= 0x7FFFFF;
- polynomial = self.noiseStep7Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31);
- else:
- # 15 steps
- self.audio4Index &= 0x7FFFFFFF;
- polynomial = self.noiseStep15Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31);
- if ((polynomial & 1) != 0):
- if ((self.nr51 & 0x80) != 0):
- buffer[index + 0] -= self.audio4Volume;
- if ((self.nr51 & 0x08) != 0):
- buffer[index + 1] -= self.audio4Volume;
- else:
- if ((self.nr51 & 0x80) != 0):
- buffer[index + 0] += self.audio4Volume;
- if ((self.nr51 & 0x08) != 0):
- buffer[index + 1] += self.audio4Volume;
-
-
- # Output Control
- def getOutputLevel(self):
- return self.nr50;
-
-
- def getOutputTerminal(self):
- return self.nr51;
-
-
- def getOutputEnable(self):
- return self.nr52;
-
-
- def setOutputLevel(self, data):
- self.nr50 = data;
-
-
- def setOutputTerminal(self, data):
- self.nr51 = data;
-
-
- def setOutputEnable(self, data):
- self.nr52 = (self.nr52 & 0x7F) | (data & 0x80);
- if ((self.nr52 & 0x80) == 0x00):
- self.nr52 &= 0xF0;
-
-
- # Frequency Table Generation
- def generateFrequencyTables(self):
- sampleRate = self.driver.getSampleRate();
- # frequency = (4194304 / 32) / (2048 - period) Hz
- for period in range(0, 2048):
- skip = (((constants.GAMEBOY_CLOCK << 10) / sampleRate) << (22 - 8)) / (2048 - period);
- if (skip >= (32 << 22)):
- self.frequencyTable[period] = 0;
- else:
- self.frequencyTable[period] = skip;
- # Polynomial Noise Frequency Ratios
- #
- # 4194304 Hz * 1/2^3 * 2 4194304 Hz * 1/2^3 * 1 4194304 Hz * 1/2^3 *
- # 1/2 4194304 Hz * 1/2^3 * 1/3 4194304 Hz * 1/2^3 * 1/4 4194304 Hz *
- # 1/2^3 * 1/5 4194304 Hz * 1/2^3 * 1/6 4194304 Hz * 1/2^3 * 1/7
- for ratio in range(0, 8):
- divider = 1
- if ratio != 0:
- divider = 2 * ratio
- self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / divider) * ((1 << 16) / sampleRate);
-
-
-
- # Noise Generation
- def generateNoiseTables(self):
- polynomial = 0x7F
- # 7 steps
- for index in range(0, 0x7F):
- polynomial = (((polynomial << 6) ^ (polynomial << 5)) & 0x40) | (polynomial >> 1);
- if ((index & 31) == 0):
- self.noiseStep7Table[index >> 5] = 0;
- self.noiseStep7Table[index >> 5] |= (polynomial & 1) << (index & 31);
- # 15 steps&
- polynomial = 0x7FFF
- for index in range(0, 0x7FFF):
- polynomial = (((polynomial << 14) ^ (polynomial << 13)) & 0x4000) | (polynomial >> 1);
- if ((index & 31) == 0):
- self.noiseStep15Table[index >> 5] = 0;
- self.noiseStep15Table[index >> 5] |= (polynomial & 1) << (index & 31);
+ # Audio Channel 1 int
+ nr10=0;
+ nr11=0;
+ nr12=0;
+ nr13=0;
+ nr14=0;
+ audio1Index=0;
+ audio1Length=0;
+ audio1Volume=0;
+ audio1EnvelopeLength=0;
+ audio1SweepLength=0;
+ audio1Frequency=0;
+
+
+ # Audio Channel 2 int
+ nr21=0;
+ nr22=0;
+ nr23=0;
+ nr24=0;
+ audio2Index=0;
+ audio2Length=0;
+ audio2Volume=0;
+ audio2EnvelopeLength=0;
+ audio2Frequency=0;
+
+
+ # Audio Channel 3 int
+ nr30=0;
+ nr31=0;
+ nr32=0;
+ nr33=0;
+ nr34=0;
+ audio3Index=0;
+ audio3Length=0;
+ audio3Frequency=0;
+ audio3WavePattern = []# = new byte[16];
+
+ # Audio Channel 4 int
+ nr41=0;
+ nr42=0;
+ nr43=0;
+ nr44=0;
+ audio4Index=0;
+ audio4Length=0;
+ audio4Volume=0;
+ audio4EnvelopeLength=0;
+ audio4Frequency=0;
+
+ # Output Control int
+ nr50=0;
+ nr51=0;
+ nr52=0;
+
+ # Sound DriverSoundDriver
+ #driver;
+ buffer = []# = new byte[512];
+ #int
+ #frames;
+ #cycles;
+
+ # Frequency Table
+ frequencyTable = []#= new int[2048];
+ noiseFreqRatioTable = [] #= new int[8];
+
+ # Noise Tables
+ noiseStep7Table = [] #= new int[128 / 32];
+ noiseStep15Table = [] #= new int[32768 / 32];
+
+ def __init__(self, soundDriver):
+ self.driver = soundDriver;
+ self.generateFrequencyTables();
+ self.generateNoiseTables();
+ self.reset();
+
+
+ def start(self):
+ self.driver.start();
+
+
+ def stop(self):
+ self.driver.stop();
+
+
+ def cycles(self):
+ return self.cycles;
+
+
+ def emulate(self, ticks):
+ self.cycles -= ticks;
+ while (self.cycles <= 0):
+ self.updateAudio();
+ if (self.driver.isEnabled()):
+ self.frames += self.driver.getSampleRate();
+ length = (self.frames / constants.SOUND_CLOCK) << 1;
+ self.mixAudio(self.buffer, length);
+ self.driver.write(self.buffer, length);
+ self.frames %= constants.SOUND_CLOCK;
+
+ self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK;
+
+
+
+ def reset(self):
+ self.cycles = constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK;
+ self.frames = 0;
+ self.audio1Index = self.audio2Index = self.audio3Index = self.audio4Index = 0;
+ self.write(constants.NR10, 0x80);
+ self.write(constants.NR11, 0x3F); # 0xBF
+ self.write(constants.NR12, 0x00); # 0xF3
+ self.write(constants.NR13, 0xFF);
+ self.write(constants.NR14, 0xBF);
+
+ self.write(constants.NR21, 0x3F);
+ self.write(constants.NR22, 0x00);
+ self.write(constants.NR23, 0xFF);
+ self.write(constants.NR24, 0xBF);
+
+ self.write(constants.NR30, 0x7F);
+ self.write(constants.NR31, 0xFF);
+ self.write(constants.NR32, 0x9F);
+ self.write(constants.NR33, 0xFF);
+ self.write(constants.NR34, 0xBF);
+
+ self.write(constants.NR41, 0xFF);
+ self.write(constants.NR42, 0x00);
+ self.write(constants.NR43, 0x00);
+ self.write(constants.NR44, 0xBF);
+
+ self.write(constants.NR50, 0x00); # 0x77
+ self.write(constants.NR51, 0xF0);
+ self.write(constants.NR52, 0xFF); # 0xF0
+
+ for address in range(0xFF30, 0xFF3F):
+ write = 0xFF
+ if (address & 1) == 0:
+ write = 0x00
+ self.write(address, write);
+
+
+ def read(self, address):
+ if address==constants.NR10:
+ return self.getAudio1Sweep();
+ elif address == constants.NR11:
+ return self.getAudio1Length();
+ elif address == constants.NR12:
+ return self.getAudio1Envelope();
+ elif address == constants.NR13:
+ return self.getAudio1Frequency();
+ elif address == constants.NR14:
+ return self.getAudio1Playback();
+
+ elif address == constants.NR21:
+ return self.getAudio2Length();
+ elif address == constants.NR22:
+ return self.getAudio2Envelope();
+ elif address==constants.NR23:
+ return self.getAudio2Frequency();
+ elif address==constants.NR24:
+ return self.getAudio2Playback();
+
+ elif address==constants.NR30:
+ return self.getAudio3Enable();
+ elif address==constants.NR31:
+ return self.getAudio3Length();
+ elif address==constants.NR32:
+ return self.getAudio3Level();
+ elif address==constants.NR33:
+ return self.getAudio4Frequency();
+ elif address==constants.NR34:
+ return self.getAudio3Playback();
+
+ elif address==constants.NR41:
+ return self.getAudio4Length();
+ elif address==constants.NR42:
+ return self.getAudio4Envelope();
+ elif address==constants.NR43:
+ return self.getAudio4Polynomial();
+ elif address==constants.NR44:
+ return self.getAudio4Playback();
+
+ elif address==constants.NR50:
+ return self.getOutputLevel();
+ elif address==constants.NR51:
+ return self.getOutputTerminal();
+ elif address==constants.NR52:
+ return self.getOutputEnable();
+
+ elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F):
+ return self.getAudio3WavePattern(address);
+
+ return 0xFF;
+
+
+ def write(self, address, data):
+ if address==constants.NR10:
+ self.setAudio1Sweep(data);
+ elif address == constants.NR11:
+ self.setAudio1Length(data);
+ elif address == constants.NR12:
+ self.setAudio1Envelope(data);
+ elif address == constants.NR13:
+ self.setAudio1Frequency(data);
+ elif address == constants.NR14:
+ self.setAudio1Playback(data);
+
+ elif address == constants.NR21:
+ self.setAudio2Length(data);
+ elif address == constants.NR22:
+ self.setAudio2Envelope(data);
+ elif address == constants.NR23:
+ self.setAudio2Frequency(data);
+ elif address == constants.NR24:
+ self.setAudio2Playback(data);
+
+ elif address == constants.NR30:
+ self.setAudio3Enable(data);
+ elif address == constants.NR31:
+ self.setAudio3Length(data);
+ elif address == constants.NR32:
+ self.setAudio3Level(data);
+ elif address == constants.NR33:
+ self.setAudio3Frequency(data);
+ elif address == constants.NR34:
+ self.setAudio3Playback(data);
+
+ elif address == constants.NR41:
+ self.setAudio4Length(data);
+ elif address == constants.NR42:
+ self.setAudio4Envelope(data);
+ elif address == constants.NR43:
+ self.setAudio4Polynomial(data);
+ elif address == constants.NR44:
+ self.setAudio4Playback(data);
+
+ elif address == constants.NR50:
+ self.setOutputLevel(data);
+ elif address == constants.NR51:
+ self.setOutputTerminal(data);
+ elif address == constants.NR52:
+ self.setOutputEnable(data);
+
+ elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F):
+ self.setAudio3WavePattern(address, data);
+
+
+ def updateAudio(self):
+ if ((self.nr52 & 0x80) == 0):
+ return
+ if ((self.nr52 & 0x01) != 0):
+ self.updateAudio1();
+ if ((self.nr52 & 0x02) != 0):
+ self.updateAudio2();
+ if ((self.nr52 & 0x04) != 0):
+ self.updateAudio3();
+ if ((self.nr52 & 0x08) != 0):
+ self.updateAudio4();
+
+
+ def mixAudio(self,buffer, length):
+ for index in range(0, length):
+ buffer[index] = 0;
+ if ((self.nr52 & 0x80) == 0):
+ return
+ if ((self.nr52 & 0x01) != 0):
+ self.mixAudio1(buffer, length);
+ if ((self.nr52 & 0x02) != 0):
+ self.mixAudio2(buffer, length);
+ if ((self.nr52 & 0x04) != 0):
+ self.mixAudio3(buffer, length);
+ if ((self.nr52 & 0x08) != 0):
+ self.mixAudio4(buffer, length);
+
+
+ # Audio Channel 1
+ def getAudio1Sweep(self):
+ return self.nr10;
+
+
+ def getAudio1Length(self):
+ return self.nr11;
+
+
+ def getAudio1Envelope(self):
+ return self.nr12;
+
+
+ def getAudio1Frequency(self):
+ return self.nr13;
+
+
+ def getAudio1Playback(self):
+ return self.nr14;
+
+
+ def setAudio1Sweep(self, data):
+ self.nr10 = data;
+ self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07);
+
+
+ def setAudio1Length(self, data):
+ self.nr11 = data;
+ self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr11 & 0x3F));
+
+
+ def setAudio1Envelope(self, data):
+ self.nr12 = data;
+ if ((self.nr14 & 0x40) != 0):
+ return
+ if ((self.nr12 >> 4) == 0):
+ self.audio1Volume = 0;
+ elif (self.audio1EnvelopeLength == 0 and (self.nr12 & 0x07) == 0):
+ self.audio1Volume = (self.audio1Volume + 1) & 0x0F;
+ else:
+ self.audio1Volume = (self.audio1Volume + 2) & 0x0F;
+
+
+ def setAudio1Frequency(self, data):
+ self.nr13 = data;
+ self.audio1Frequency = self.frequencyTable[self.nr13 + ((self.nr14 & 0x07) << 8)];
+
+
+ def setAudio1Playback(self, data):
+ self.nr14 = data;
+ self.audio1Frequency = self.frequencyTable[self.nr13
+ + ((self.nr14 & 0x07) << 8)];
+ if ((self.nr14 & 0x80) != 0):
+ self.nr52 |= 0x01;
+ if ((self.nr14 & 0x40) != 0 and self.audio1Length == 0):
+ self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr11 & 0x3F));
+ self.audio1SweepLength = (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07);
+ self.audio1Volume = self.nr12 >> 4;
+ self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr12 & 0x07);
+
+
+ def updateAudio1(self):
+ if ((self.nr14 & 0x40) != 0 and self.audio1Length > 0):
+ self.audio1Length-=1;
+ if (self.audio1Length <= 0):
+ self.nr52 &= ~0x01;
+ if (self.audio1EnvelopeLength > 0):
+ self.audio1EnvelopeLength-=1;
+ if (self.audio1EnvelopeLength <= 0):
+ if ((self.nr12 & 0x08) != 0):
+ if (self.audio1Volume < 15):
+ self.audio1Volume+=1;
+ elif (self.audio1Volume > 0):
+ self.audio1Volume-=1;
+ self.audio1EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr12 & 0x07);
+ if (self.audio1SweepLength > 0):
+ self.audio1SweepLength-=1;
+ if (self.audio1SweepLength <= 0):
+ sweepSteps = (self.nr10 & 0x07);
+ if (sweepSteps != 0):
+ frequency = ((self.nr14 & 0x07) << 8) + self.nr13;
+ if ((self.nr10 & 0x08) != 0):
+ frequency -= frequency >> sweepSteps;
+ else:
+ frequency += frequency >> sweepSteps;
+ if (frequency < 2048):
+ self.audio1Frequency = self.frequencyTable[frequency];
+ self.nr13 = frequency & 0xFF;
+ self.nr14 = (self.nr14 & 0xF8) + ((frequency >> 8) & 0x07);
+ else:
+ self.audio1Frequency = 0;
+ self.nr52 &= ~0x01;
+
+ self.audio1SweepLength += (constants.SOUND_CLOCK / 128) * ((self.nr10 >> 4) & 0x07);
+
+
+ def mixAudio1(self, buffer, length):
+ wavePattern = 0x18
+ if (self.nr11 & 0xC0) == 0x00:
+ wavePattern = 0x04
+ elif (self.nr11 & 0xC0) == 0x40:
+ wavePattern = 0x08
+ elif (self.nr11 & 0xC0) == 0x80:
+ wavePattern = 0x10
+ wavePattern << 22;
+ for index in range(0, length, 3):
+ self.audio1Index += self.audio1Frequency;
+ if ((self.audio1Index & (0x1F << 22)) >= wavePattern):
+ if ((self.nr51 & 0x10) != 0):
+ buffer[index + 0] -= self.audio1Volume;
+ if ((self.nr51 & 0x01) != 0):
+ buffer[index + 1] -= self.audio1Volume;
+ else:
+ if ((self.nr51 & 0x10) != 0):
+ buffer[index + 0] += self.audio1Volume;
+ if ((self.nr51 & 0x01) != 0):
+ buffer[index + 1] += self.audio1Volume;
+
+
+ # Audio Channel 2
+ def getAudio2Length(self):
+ return self.nr21;
+
+
+ def getAudio2Envelope(self):
+ return self.nr22;
+
+
+ def getAudio2Frequency(self):
+ return self.nr23;
+
+
+ def getAudio2Playback(self):
+ return self.nr24;
+
+
+ def setAudio2Length(self, data):
+ self.nr21 = data;
+ self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr21 & 0x3F));
+
+
+ def setAudio2Envelope(self, data):
+ self.nr22 = data;
+ if ((self.nr24 & 0x40) == 0):
+ if ((self.nr22 >> 4) == 0):
+ self.audio2Volume = 0;
+ elif (self.audio2EnvelopeLength == 0 and (self.nr22 & 0x07) == 0):
+ self.audio2Volume = (self.audio2Volume + 1) & 0x0F;
+ else:
+ self.audio2Volume = (self.audio2Volume + 2) & 0x0F;
+
+
+ def setAudio2Frequency(self, data):
+ self.nr23 = data;
+ self.audio2Frequency = self.frequencyTable[self.nr23\
+ + ((self.nr24 & 0x07) << 8)];
+
+
+ def setAudio2Playback(self, data):
+ self.nr24 = data;
+ self.audio2Frequency = self.frequencyTable[self.nr23\
+ + ((self.nr24 & 0x07) << 8)];
+ if ((self.nr24 & 0x80) != 0):
+ self.nr52 |= 0x02;
+ if ((self.nr24 & 0x40) != 0 and self.audio2Length == 0):
+ self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr21 & 0x3F));
+ self.audio2Volume = self.nr22 >> 4;
+ self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr22 & 0x07);
+
+
+
+ def updateAudio2(self):
+ if ((self.nr24 & 0x40) != 0 and self.audio2Length > 0):
+ self.audio2Length-=1;
+ if (self.audio2Length <= 0):
+ self.nr52 &= ~0x02;
+ if (self.audio2EnvelopeLength > 0):
+ self.audio2EnvelopeLength-=1;
+
+ if (self.audio2EnvelopeLength <= 0):
+ if ((self.nr22 & 0x08) != 0):
+ if (self.audio2Volume < 15):
+ self.audio2Volume+=1;
+ elif (self.audio2Volume > 0):
+ self.audio2Volume-=1;
+ self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr22 & 0x07);
+
+
+ def mixAudio2(self, buffer, length):
+ wavePattern = 0x18
+ if (self.nr21 & 0xC0) == 0x00:
+ wavePattern = 0x04
+ elif (self.nr21 & 0xC0) == 0x40:
+ wavePattern = 0x08
+ elif (self.nr21 & 0xC0) == 0x80:
+ wavePattern = 0x10
+ wavePattern << 22;
+ for index in range(0, length):
+ self.audio2Index += self.audio2Frequency;
+ if ((self.audio2Index & (0x1F << 22)) >= wavePattern):
+ if ((self.nr51 & 0x20) != 0):
+ buffer[index + 0] -= self.audio2Volume;
+ if ((self.nr51 & 0x02) != 0):
+ buffer[index + 1] -= self.audio2Volume;
+ else:
+ if ((self.nr51 & 0x20) != 0):
+ buffer[index + 0] += self.audio2Volume;
+ if ((self.nr51 & 0x02) != 0):
+ buffer[index + 1] += self.audio2Volume;
+
+
+ # Audio Channel 3
+ def getAudio3Enable(self):
+ return self.nr30;
+
+
+ def getAudio3Length(self):
+ return self.nr31;
+
+
+ def getAudio3Level(self):
+ return self.nr32;
+
+
+ def getAudio4Frequency(self):
+ return self.nr33;
+
+
+ def getAudio3Playback(self):
+ return self.nr34;
+
+
+ def setAudio3Enable(self, data):
+ self.nr30 = data & 0x80;
+ if ((self.nr30 & 0x80) == 0):
+ self.nr52 &= ~0x04;
+
+
+ def setAudio3Length(self, data):
+ self.nr31 = data;
+ self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.nr31);
+
+
+ def setAudio3Level(self, data):
+ self.nr32 = data;
+
+
+ def setAudio3Frequency(self, data):
+ self.nr33 = data;
+ self.audio3Frequency = self.frequencyTable[((self.nr34 & 0x07) << 8) + self.nr33] >> 1;
+
+
+ def setAudio3Playback(self, data):
+ self.nr34 = data;
+ self.audio3Frequency = self.frequencyTable[((self.nr34 & 0x07) << 8) + self.nr33] >> 1;
+ if ((self.nr34 & 0x80) != 0 and (self.nr30 & 0x80) != 0):
+ self.nr52 |= 0x04;
+ if ((self.nr34 & 0x40) != 0 and self.audio3Length == 0):
+ self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.nr31);
+
+
+
+ def setAudio3WavePattern(self, address, data):
+ #TODO convert to byte
+ self.audio3WavePattern[address & 0x0F] = data;
+
+
+ def getAudio3WavePattern(self, address):
+ return self.audio3WavePattern[address & 0x0F] & 0xFF;
+
+
+ def updateAudio3(self):
+ if ((self.nr34 & 0x40) != 0 and self.audio3Length > 0):
+ self.audio3Length-=1;
+ if (self.audio3Length <= 0):
+ self.nr52 &= ~0x04;
+
+
+ def mixAudio3(self, buffer, length):
+ wavePattern = 2
+ if (self.nr32 & 0x60) == 0x00:
+ wavePattern = 8
+ elif (self.nr32 & 0x60) == 0x40:
+ wavePattern = 0
+ elif (self.nr32 & 0x60) == 0x80:
+ wavePattern = 1
+
+ for index in range(0, length, 2):
+ self.audio3Index += self.audio3Frequency;
+ sample = self.audio3WavePattern[(self.audio3Index >> 23) & 0x0F];
+ if ((self.audio3Index & (1 << 22)) != 0):
+ sample = (sample >> 0) & 0x0F;
+ else:
+ sample = (sample >> 4) & 0x0F;
+
+ sample = ((sample - 8) << 1) >> level;
+
+ if ((self.nr51 & 0x40) != 0):
+ buffer[index + 0] += sample;
+ if ((self.nr51 & 0x04) != 0):
+ buffer[index + 1] += sample;
+
+
+ # Audio Channel 4
+ def getAudio4Length(self):
+ return self.nr41;
+
+
+ def getAudio4Envelope(self):
+ return self.nr42;
+
+
+ def getAudio4Polynomial(self):
+ return self.nr43;
+
+
+ def getAudio4Playback(self):
+ return self.nr44;
+
+
+ def setAudio4Length(self, data):
+ self.nr41 = data;
+ self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr41 & 0x3F));
+
+
+ def setAudio4Envelope(self, data):
+ self.nr42 = data;
+ if ((self.nr44 & 0x40) == 0):
+ if ((self.nr42 >> 4) == 0):
+ self.audio4Volume = 0;
+ elif (self.audio4EnvelopeLength == 0 and (self.nr42 & 0x07) == 0):
+ self.audio4Volume = (self.audio4Volume + 1) & 0x0F;
+ else:
+ self.audio4Volume = (self.audio4Volume + 2) & 0x0F;
+
+
+ def setAudio4Polynomial(self, data):
+ self.nr43 = data;
+ if ((self.nr43 >> 4) <= 12):
+ self.audio4Frequency = self.noiseFreqRatioTable[self.nr43 & 0x07] >> ((self.nr43 >> 4) + 1);
+ else:
+ self.audio4Frequency = 0;
+
+
+ def setAudio4Playback(self, data):
+ self.nr44 = data;
+ if ((self.nr44 & 0x80) != 0):
+ self.nr52 |= 0x08;
+ if ((self.nr44 & 0x40) != 0 and self.audio4Length == 0):
+ self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.nr41 & 0x3F));
+ self.audio4Volume = self.nr42 >> 4;
+ self.audio4EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.nr42 & 0x07);
+ self.audio4Index = 0;
+
+
+
+ def updateAudio4(self):
+ if ((self.nr44 & 0x40) != 0 and self.audio4Length > 0):
+ self.audio4Length-=1;
+ if (self.audio4Length <= 0):
+ self.nr52 &= ~0x08;
+ if (self.audio4EnvelopeLength > 0):
+ self.audio4EnvelopeLength-=1;
+ if (self.audio4EnvelopeLength <= 0):
+ if ((self.nr42 & 0x08) != 0):
+ if (self.audio4Volume < 15):
+ self.audio4Volume+=1;
+ elif (self.audio4Volume > 0):
+ self.audio4Volume-=1;
+ self.audio4EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.nr42 & 0x07);
+
+
+ def mixAudio4(self, buffer, length):
+ for index in range(0, length, 2):
+ self.audio4Index += self.audio4Frequency;
+ polynomial;
+ if ((self.nr43 & 0x08) != 0):
+ # 7 steps
+ self.audio4Index &= 0x7FFFFF;
+ polynomial = self.noiseStep7Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31);
+ else:
+ # 15 steps
+ self.audio4Index &= 0x7FFFFFFF;
+ polynomial = self.noiseStep15Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31);
+ if ((polynomial & 1) != 0):
+ if ((self.nr51 & 0x80) != 0):
+ buffer[index + 0] -= self.audio4Volume;
+ if ((self.nr51 & 0x08) != 0):
+ buffer[index + 1] -= self.audio4Volume;
+ else:
+ if ((self.nr51 & 0x80) != 0):
+ buffer[index + 0] += self.audio4Volume;
+ if ((self.nr51 & 0x08) != 0):
+ buffer[index + 1] += self.audio4Volume;
+
+
+ # Output Control
+ def getOutputLevel(self):
+ return self.nr50;
+
+
+ def getOutputTerminal(self):
+ return self.nr51;
+
+
+ def getOutputEnable(self):
+ return self.nr52;
+
+
+ def setOutputLevel(self, data):
+ self.nr50 = data;
+
+
+ def setOutputTerminal(self, data):
+ self.nr51 = data;
+
+
+ def setOutputEnable(self, data):
+ self.nr52 = (self.nr52 & 0x7F) | (data & 0x80);
+ if ((self.nr52 & 0x80) == 0x00):
+ self.nr52 &= 0xF0;
+
+
+ # Frequency Table Generation
+ def generateFrequencyTables(self):
+ sampleRate = self.driver.getSampleRate();
+ # frequency = (4194304 / 32) / (2048 - period) Hz
+ for period in range(0, 2048):
+ skip = (((constants.GAMEBOY_CLOCK << 10) / sampleRate) << (22 - 8)) / (2048 - period);
+ if (skip >= (32 << 22)):
+ self.frequencyTable[period] = 0;
+ else:
+ self.frequencyTable[period] = skip;
+ # Polynomial Noise Frequency Ratios
+ #
+ # 4194304 Hz * 1/2^3 * 2 4194304 Hz * 1/2^3 * 1 4194304 Hz * 1/2^3 *
+ # 1/2 4194304 Hz * 1/2^3 * 1/3 4194304 Hz * 1/2^3 * 1/4 4194304 Hz *
+ # 1/2^3 * 1/5 4194304 Hz * 1/2^3 * 1/6 4194304 Hz * 1/2^3 * 1/7
+ for ratio in range(0, 8):
+ divider = 1
+ if ratio != 0:
+ divider = 2 * ratio
+ self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / divider) * ((1 << 16) / sampleRate);
+
+
+
+ # Noise Generation
+ def generateNoiseTables(self):
+ polynomial = 0x7F
+ # 7 steps
+ for index in range(0, 0x7F):
+ polynomial = (((polynomial << 6) ^ (polynomial << 5)) & 0x40) | (polynomial >> 1);
+ if ((index & 31) == 0):
+ self.noiseStep7Table[index >> 5] = 0;
+ self.noiseStep7Table[index >> 5] |= (polynomial & 1) << (index & 31);
+ # 15 steps&
+ polynomial = 0x7FFF
+ for index in range(0, 0x7FFF):
+ polynomial = (((polynomial << 14) ^ (polynomial << 13)) & 0x4000) | (polynomial >> 1);
+ if ((index & 31) == 0):
+ self.noiseStep15Table[index >> 5] = 0;
+ self.noiseStep15Table[index >> 5] |= (polynomial & 1) << (index & 31);
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Sun Mar 16 20:42:44 2008
@@ -1,3 +1,4 @@
+import py
from pypy.lang.gameboy.cpu import CPU, Register, DoubleRegister
from pypy.lang.gameboy import constants
@@ -111,17 +112,18 @@
]
def test_cycles():
+ py.test.skip("opCode mapping in CPU is still missing.")
cpu = get_cpu()
for entry in OPCODE_CYCLES:
if len(entry) == 2:
- cycletest(cpu, entry[0], entry[1])
+ cycle_test(cpu, entry[0], entry[1])
elif len(entry) == 4:
for opCode in range(entry[0], entry[1], entry[2]):
- cycletest(cpu, opCode, entry[3])
+ cycle_test(cpu, opCode, entry[3])
-def cycletest(cpu, opCode, cycles):
+def cycle_test(cpu, opCode, cycles):
oldCycles = cpu.cycles
cpu.execute(opCode)
assert oldCycles - cpu.cycles == cycles
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Sun Mar 16 20:42:44 2008
@@ -6,120 +6,120 @@
class Timer(object):
- # Registers
- #int
- div = 0;
- tima = 0;
- tma = 0;
- tac = 0;
+ # Registers
+ #int
+ div = 0;
+ tima = 0;
+ tma = 0;
+ tac = 0;
- dividerCycles = 0;
- timerCycles = 0;
- timerClock = 0;
+ dividerCycles = 0;
+ timerCycles = 0;
+ timerClock = 0;
- # Interrupt Controller Interrupt
- interrupt = None;
+ # Interrupt Controller Interrupt
+ interrupt = None;
- def __init__(self, interrupt):
- self.interrupt = interrupt;
- self.reset();
+ def __init__(self, interrupt):
+ self.interrupt = interrupt;
+ self.reset();
- def reset(self):
- self.div = 0;
- self.dividerCycles = constants.DIV_CLOCK;
- self.tima = self.tma = self.tac = 0x00;
- self.timerCycles = self.timerClock = constants.TIMER_CLOCK[self.tac & 0x03];
+ def reset(self):
+ self.div = 0;
+ self.dividerCycles = constants.DIV_CLOCK;
+ self.tima = self.tma = self.tac = 0x00;
+ self.timerCycles = self.timerClock = constants.TIMER_CLOCK[self.tac & 0x03];
- def write(self, address, data):
- if address==constants.DIV:
- self.setDivider(data);
- elif address==constants.TIMA:
- self.setTimerCounter(data);
- elif address==constants.TMA:
- self.setTimerModulo(data);
- elif address==constants.TAC:
- self.setTimerControl(data);
-
+ def write(self, address, data):
+ if address==constants.DIV:
+ self.setDivider(data);
+ elif address==constants.TIMA:
+ self.setTimerCounter(data);
+ elif address==constants.TMA:
+ self.setTimerModulo(data);
+ elif address==constants.TAC:
+ self.setTimerControl(data);
+
- def read(self, address):
- if address==constants.DIV:
- return self.getDivider();
- elif address==constants.TIMA:
- return self.getTimerCounter();
- elif address==constants.TMA:
- return self.getTimerModulo();
- elif address==constants.TAC:
- return self.getTimerControl();
- return 0xFF;
+ def read(self, address):
+ if address==constants.DIV:
+ return self.getDivider();
+ elif address==constants.TIMA:
+ return self.getTimerCounter();
+ elif address==constants.TMA:
+ return self.getTimerModulo();
+ elif address==constants.TAC:
+ return self.getTimerControl();
+ return 0xFF;
- def setDivider(self, data):
- #DIV register resets on write
- self.div = 0;
+ def setDivider(self, data):
+ #DIV register resets on write
+ self.div = 0;
- def setTimerCounter(self, data):
- self.tima = data;
+ def setTimerCounter(self, data):
+ self.tima = data;
- def setTimerModulo(self, data):
- self.tma = data;
+ def setTimerModulo(self, data):
+ self.tma = data;
- def setTimerControl(self, data):
- if ((self.tac & 0x03) != (data & 0x03)):
- self.timerCycles = self.timerClock = constants.TIMER_CLOCK[data & 0x03];
- self.tac = data;
+ def setTimerControl(self, data):
+ if ((self.tac & 0x03) != (data & 0x03)):
+ self.timerCycles = self.timerClock = constants.TIMER_CLOCK[data & 0x03];
+ self.tac = data;
- def getDivider(self):
- return self.div;
+ def getDivider(self):
+ return self.div;
- def getTimerCounter(self):
- return self.tima;
+ def getTimerCounter(self):
+ return self.tima;
- def getTimerModulo(self):
- return self.tma;
+ def getTimerModulo(self):
+ return self.tma;
- def getTimerControl(self):
- return 0xF8 | self.tac;
+ def getTimerControl(self):
+ return 0xF8 | self.tac;
- def cycles(self):
- if ((self.tac & 0x04) != 0 and self.timerCycles < self.dividerCycles):
- return self.timerCycles;
- return self.dividerCycles;
+ def cycles(self):
+ if ((self.tac & 0x04) != 0 and self.timerCycles < self.dividerCycles):
+ return self.timerCycles;
+ return self.dividerCycles;
- def emulate(self, ticks):
- self.emulateDivider(ticks);
- self.emulateTimer(ticks);
+ def emulate(self, ticks):
+ self.emulateDivider(ticks);
+ self.emulateTimer(ticks);
- def emulateDivider(self, ticks):
- self.dividerCycles -= ticks;
- while (self.dividerCycles <= 0):
- self.div = (self.div + 1) & 0xFF;
- self.dividerCycles += constants.DIV_CLOCK;
-
+ def emulateDivider(self, ticks):
+ self.dividerCycles -= ticks;
+ while (self.dividerCycles <= 0):
+ self.div = (self.div + 1) & 0xFF;
+ self.dividerCycles += constants.DIV_CLOCK;
+
- def emulateTimer(self, ticks):
- if ((self.tac & 0x04) != 0):
- self.timerCycles -= ticks;
+ def emulateTimer(self, ticks):
+ if ((self.tac & 0x04) != 0):
+ self.timerCycles -= ticks;
- while (self.timerCycles <= 0):
- self.tima = (self.tima + 1) & 0xFF;
- self.timerCycles += self.timerClock;
+ while (self.timerCycles <= 0):
+ self.tima = (self.tima + 1) & 0xFF;
+ self.timerCycles += self.timerClock;
- if (self.tima == 0x00):
- self.tima = self.tma;
- self.interrupt.raiseInterrupt(constants.TIMER);
-
+ if (self.tima == 0x00):
+ self.tima = self.tma;
+ self.interrupt.raiseInterrupt(constants.TIMER);
+
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sun Mar 16 20:42:44 2008
@@ -7,709 +7,709 @@
class Video(object):
- # constants.OAM Registers
- oam = [] #= new byte[OAM_SIZE]
+ # constants.OAM Registers
+ oam = [] #= new byte[OAM_SIZE]
- # Video constants.RAM
- vram = []#= new byte[VRAM_SIZE]
+ # Video constants.RAM
+ vram = []#= new byte[VRAM_SIZE]
- # constants.LCD Registers int
- lcdc = 0
- stat = 0
- scy = 0
- scx = 0
- ly = 0
- lyc = 0
- dma = 0
- bgp = 0
- obp0 = 0
- obp1 = 0
- wy = 0
- wx = 0
- wly = 0
-
- cycles = 0
-
- frames = 0
- frameSkip = 0
-
- #boolean
- transfer = False
- display = False
- vblank = False
- dirty = False
-
- # Line Buffer, constants.OAM Cache and Color Palette
- line = []#= new int[8 + 160 + 8]
- objects = []#= new int[OBJECTS_PER_LINE]
- palette = []#= new int[1024]
-
- # Video Driver VideoDriver
- driver = None
-
- # Interrupt Controller Interrupt
- interrupt = None
-
- # Memory Interface Memory
- memory = None
-
-
- def __init__(self, videDriver, interrupt, memory):
- self.driver = videoDriver
- self.interrupt = interrupt
- self.memory = memory
- self.reset()
-
-
- def getFrameSkip(self):
- return self.frameSkip
-
-
- def setFrameSkip(self, frameSkip):
- self.frameSkip = frameSkip
-
-
- def reset(self):
- self.cycles = constants.MODE_2_TICKS
-
- self.lcdc = 0x91
- self.stat = 2
- self.ly = 0
- self.lyc = 0
- self.dma = 0xFF
- self.scy = 0
- self.scx = 0
- self.wy = self.wly = 0
- self.wx = 0
- self.bgp = 0xFC
- self.obp0 = self.obp1 = 0xFF
-
- self.transfer = True
- self.display = True
- self.vblank = True
- self.dirty = True
-
- for index in range(0, constants.VRAM_SIZE):
- self.vram[index] = 0x00
-
- for index in range(0, constants.OAM_SIZE):
- self.oam[index] = 0x00
-
-
- def write(self, address, data):
- # assert data >= 0x00 and data <= 0xFF
- if address == constants.LCDC :
- self.setControl(data)
- elif address == constants.STAT:
- self.setStatus(data)
- elif address == constants.SCY:
- self.setScrollY(data)
- elif address == constants.SCX:
- self.setScrollX(data)
- elif address == constants.LY:
- # Read Only
- pass
- elif address == constants.LYC:
- self.setLYCompare(data)
- elif address == constants.DMA:
- self.setDMA(data)
- elif address == constants.BGP:
- self.setBackgroundPalette(data)
- elif address == constants.OBP0:
- self.setObjectPalette0(data)
- elif address == constants.OBP1:
- self.setObjectPalette1(data)
- elif address == constants.WY:
- self.setWindowY(data)
- elif address == constants.WX:
- self.setWindowX(data)
- else:
- if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE):
- #TODO convert to byte
- self.oam[address - constants.OAM_ADDR] = data
- elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE):
- #TODO convert to byte
- self.vram[address - constants.VRAM_ADDR] =data
-
-
- def read(self, address):
- if address == constants.LCDC:
- return self.getControl()
- elif address == constants.STAT:
- return self.getStatus()
- elif address == constants.SCY:
- return self.getScrollY()
- elif address == constants.SCX:
- return self.getScrollX()
- elif address == constants.LY:
- return self.getLineY()
- elif address == constants.LYC:
- return self.getLineYCompare()
- elif address == constants.DMA:
- return self.getDMA()
- elif address == constants.BGP:
- return self.getBackgroundPalette()
- elif address == constants.OBP0:
- return self.getObjectPalette0()
- elif address == constants.OBP1:
- return self.getObjectPalette1()
- elif address == constants.WY:
- return self.getWindowY()
- elif address == constants.WX:
- return self.getWindowX()
- else:
- if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE):
- return self.oam[address - constants.OAM_ADDR] & 0xFF
- elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE):
- return self.vram[address - constants.VRAM_ADDR] & 0xFF
- return 0xFF
-
-
- def cycles(self):
- return self.cycles
-
-
- def emulate(self, ticks):
- if ((self.lcdc & 0x80) != 0):
- self.cycles -= ticks
- while (self.cycles <= 0):
- switch = self.stat & 0x03
- if switch == 0:
- self.emulateHBlank()
- elif switch == 1:
- self.emulateVBlank()
- elif switch == 2:
- self.emulateOAM()
- elif switch == 3:
- self.emulateTransfer()
-
-
- def getControl(self):
- return self.lcdc
-
-
- def getStatus(self):
- return 0x80 | self.stat
-
-
- def getScrollY(self):
- return self.scy
-
-
- def getScrollX(self):
- return self.scx
-
-
- def getLineY(self):
- return self.ly
-
-
- def getLineYCompare(self):
- return self.lyc
-
-
- def getDMA(self):
- return self.dma
-
-
- def getBackgroundPalette(self):
- return self.bgp
-
-
- def getObjectPalette0(self):
- return self.obp0
-
-
- def getObjectPalette1(self):
- return self.obp1
-
-
- def getWindowY(self):
- return self.wy
-
-
- def getWindowX(self):
- return self.wx
-
-
- def setControl(self, data):
- if ((self.lcdc & 0x80) != (data & 0x80)):
- # constants.NOTE: do not reset constants.LY=LYC flag (bit 2) of the constants.STAT register (Mr.
- # Do!)
- if ((data & 0x80) != 0):
- self.stat = (self.stat & 0xFC) | 0x02
- self.cycles = constants.MODE_2_TICKS
- self.ly = 0
- self.display = False
- else:
- self.stat = (self.stat & 0xFC) | 0x00
- self.cycles = constants.MODE_1_TICKS
- self.ly = 0
-
- self.clearFrame()
- # don't draw window if it was not enabled and not being drawn before
- if ((self.lcdc & 0x20) == 0 and (data & 0x20) != 0 and self.wly == 0 and self.ly > self.wy):
- self.wly = 144
- self.lcdc = data
-
-
- def setStatus(self, data):
- self.stat = (self.stat & 0x87) | (data & 0x78)
- # Gameboy Bug
- if ((self.lcdc & 0x80) != 0 and (self.stat & 0x03) == 0x01 and (self.stat & 0x44) != 0x44):
- self.interrupt.raiseInterrupt(constants.LCD)
-
-
- def setScrollY(self, data):
- self.scy = data
-
-
- def setScrollX(self, data):
- self.scx = data
-
-
- def setLYCompare(self, data):
- self.lyc = data
- if ((self.lcdc & 0x80) != 0):
- if (self.ly == self.lyc):
- # constants.NOTE: raise interrupt once per line (Prehistorik Man, The
- # Jetsons, Muhammad Ali)
- if ((self.stat & 0x04) == 0):
- # constants.LYC=LY interrupt
- self.stat |= 0x04
- if ((self.stat & 0x40) != 0):
- self.interrupt.raiseInterrupt(constants.LCD)
- else:
- self.stat &= 0xFB
-
-
- def setDMA(self, data):
- self.dma = data
- for index in range(0, constants.OAM_SIZE):
- #TODO convert to byte
- self.oam[index] = self.memory.read((self.dma << 8) + index)
-
-
- def setBackgroundPalette(self, data):
- if (self.bgp != data):
- self.bgp = data
- self.dirty = True
-
-
- def setObjectPalette0(self, data):
- if (self.obp0 != data):
- self.obp0 = data
- self.dirty = True
-
-
- def setObjectPalette1(self, data):
- if (self.obp1 != data):
- self.obp1 = data
- self.dirty = True
-
-
- def setWindowY(self, data):
- self.wy = data
-
-
- def setWindowX(self, data):
- self.wx = data
-
-
- def emulateOAM(self):
- self.stat = (self.stat & 0xFC) | 0x03
- self.cycles += constants.MODE_3_BEGIN_TICKS
- self.transfer = True
-
-
- def emulateTransfer(self):
- if (self.transfer):
- if (self.display):
- self.drawLine()
- self.stat = (self.stat & 0xFC) | 0x03
- self.cycles += constants.MODE_3_END_TICKS
- self.transfer = False
- else:
- self.stat = (self.stat & 0xFC) | 0x00
- self.cycles += constants.MODE_0_TICKS
- # H-Blank interrupt
- if ((self.stat & 0x08) != 0 and (self.stat & 0x44) != 0x44):
- self.interrupt.raiseInterrupt(constants.LCD)
-
-
- def emulateHBlank(self):
- self.ly+=1
- if (self.ly == self.lyc):
- # constants.LYC=LY interrupt
- self.stat |= 0x04
- if ((self.stat & 0x40) != 0):
- self.interrupt.raiseInterrupt(constants.LCD)
- else:
- self.stat &= 0xFB
- if (self.ly < 144):
- self.stat = (self.stat & 0xFC) | 0x02
- self.cycles += constants.MODE_2_TICKS
- # constants.OAM interrupt
- if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44):
- self.interrupt.raiseInterrupt(constants.LCD)
- else:
- if (self.display):
- self.drawFrame()
- self.frames += 1
- if (self.frames >= self.frameSkip):
- self.display = True
- self.frames = 0
- else:
- self.display = False
-
- self.stat = (self.stat & 0xFC) | 0x01
- self.cycles += constants.MODE_1_BEGIN_TICKS
- self.vblank = True
-
-
- def emulateVBlank(self):
- if (self.vblank):
- self.vblank = False
- self.stat = (self.stat & 0xFC) | 0x01
- self.cycles += constants.MODE_1_TICKS - constants.MODE_1_BEGIN_TICKS
- # V-Blank interrupt
- if ((self.stat & 0x10) != 0):
- self.interrupt.raiseInterrupt(constants.LCD)
- # V-Blank interrupt
- self.interrupt.raiseInterrupt(constants.VBLANK)
- elif (self.ly == 0):
- self.stat = (self.stat & 0xFC) | 0x02
- self.cycles += constants.MODE_2_TICKS
- # constants.OAM interrupt
- if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44):
- self.interrupt.raiseInterrupt(constants.LCD)
- else:
- if (self.ly < 153):
- self.ly+=1
- self.stat = (self.stat & 0xFC) | 0x01
- if (self.ly == 153):
- self.cycles += constants.MODE_1_END_TICKS
- else:
- self.cycles += constants.MODE_1_TICKS
- else:
- self.ly = self.wly = 0
- self.stat = (self.stat & 0xFC) | 0x01
- self.cycles += constants.MODE_1_TICKS - constants.MODE_1_END_TICKS
- if (self.ly == self.lyc):
- # constants.LYC=LY interrupt
- self.stat |= 0x04
- if ((self.stat & 0x40) != 0):
- self.interrupt.raiseInterrupt(constants.LCD)
- else:
- self.stat &= 0xFB
-
-
- def drawFrame(self):
- self.driver.display()
-
-
- def clearFrame(self):
- self.clearPixels()
- self.driver.display()
-
-
- def drawLine(self):
- if ((self.lcdc & 0x01) != 0):
- self.drawBackground()
- else:
- self.drawCleanBackground()
- if ((self.lcdc & 0x20) != 0):
- self.drawWindow()
- if ((self.lcdc & 0x02) != 0):
- self.drawObjects()
- self.drawPixels()
-
-
- def drawCleanBackground(self):
- for x in range(0, 8+160+8):
- self.line[x] = 0x00
-
-
- def drawBackground(self):
- y = (self.scy + self.ly) & 0xFF
- x = self.scx & 0xFF
- tileMap = constants.VRAM_MAP_A
- if (self.lcdc & 0x08) != 0:
- tileMap = constants.VRAM_MAP_B
- tileData = constants.VRAM_DATA_B
- if (self.lcdc & 0x10) != 0:
- tileData = constants.VRAM_DATA_A
- tileMap += ((y >> 3) << 5) + (x >> 3)
- tileData += (y & 7) << 1
- self.drawTiles(8 - (x & 7), tileMap, tileData)
-
-
- def drawWindow(self):
- if (self.ly >= self.wy and self.wx < 167 and self.wly < 144):
- tileMap = constants.VRAM_MAP_A
- if (self.lcdc & 0x40) != 0:
- tileMap = constants.VRAM_MAP_B
- tileData = constants.VRAM_DATA_B
- if (self.lcdc & 0x10) != 0:
- tileData = constants.VRAM_DATA_A
- tileMap += (self.wly >> 3) << 5
- tileData += (self.wly & 7) << 1
- self.drawTiles(self.wx + 1, tileMap, tileData)
- self.wly+=1
-
-
- def drawObjects(self):
- count = self.scanObjects()
- lastx = 176
- for index in range(176, count):
- data = self.objects[index]
- x = (data >> 24) & 0xFF
- flags = (data >> 12) & 0xFF
- address = data & 0xFFF
- if (x + 8 <= lastx):
- self.drawObjectTile(x, address, flags)
- else:
- self.drawOverlappedObjectTile(x, address, flags)
- lastx = x
-
-
- def scanObjects(self):
- count = 0
- # search active objects
- for offset in range(0, 4*40, 4):
- y = self.oam[offset + 0] & 0xFF
- x = self.oam[offset + 1] & 0xFF
- if (y <= 0 or y >= 144 + 16 or x <= 0 or x >= 168):
- continue
- tile = self.oam[offset + 2] & 0xFF
- flags = self.oam[offset + 3] & 0xFF
-
- y = self.ly - y + 16
-
- if ((self.lcdc & 0x04) != 0):
- # 8x16 tile size
- if (y < 0 or y > 15):
- continue
- # Y flip
- if ((flags & 0x40) != 0):
- y = 15 - y
- tile &= 0xFE
- else:
- # 8x8 tile size
- if (y < 0 or y > 7):
- continue
- # Y flip
- if ((flags & 0x40) != 0):
- y = 7 - y
- self.objects[count] = (x << 24) + (count << 20) + (flags << 12) + ((tile << 4) + (y << 1))
- if (++count >= constants.OBJECTS_PER_LINE):
- break
- self.sortScanObject(count)
- return count
-
- def sortScanObject(self, count):
- # sort objects from lower to higher priority
- for index in range(0, count):
- rightmost = index
- for number in range(index+1, count):
- if ((self.objects[number] >> 20) > (self.objects[rightmost] >> 20)):
- rightmost = number
- if (rightmost != index):
- data = self.objects[index]
- self.objects[index] = self.objects[rightmost]
- self.objects[rightmost] = data
-
-
- def drawTiles(self, x, tileMap, tileData):
- if ((self.lcdc & 0x10) != 0):
- while (x < 168):
- tile = self.vram[tileMap] & 0xFF
- self.drawTile(x, tileData + (tile << 4))
- tileMap = (tileMap & 0x1FE0) + ((tileMap + 1) & 0x001F)
- x += 8
- else:
- while (x < 168):
- tile = (self.vram[tileMap] ^ 0x80) & 0xFF
- self.drawTile(x, tileData + (tile << 4))
- tileMap = (tileMap & 0x1FE0) + ((tileMap + 1) & 0x001F)
- x += 8
-
-
- def drawTile(self, x, address):
- pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8)
- self.line[x + 0] = (pattern >> 7) & 0x0101
- self.line[x + 1] = (pattern >> 6) & 0x0101
- self.line[x + 2] = (pattern >> 5) & 0x0101
- self.line[x + 3] = (pattern >> 4) & 0x0101
- self.line[x + 4] = (pattern >> 3) & 0x0101
- self.line[x + 5] = (pattern >> 2) & 0x0101
- self.line[x + 6] = (pattern >> 1) & 0x0101
- self.line[x + 7] = (pattern >> 0) & 0x0101
-
-
- def drawObjectTile(self, x, address, flags):
- pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8)
- mask = 0
- # priority
- if (flags & 0x80) != 0:
- mask |= 0x0008
- # palette
- if (flags & 0x10) != 0:
- mask |= 0x0004
- # X flip
- if (flags & 0x20) != 0:
- color = (pattern << 1)
- if ((color & 0x0202) != 0):
- self.line[x + 0] |= color | mask
- color = (pattern >> 0)
- if ((color & 0x0202) != 0):
- self.line[x + 1] |= color | mask
- color = (pattern >> 1)
- if ((color & 0x0202) != 0):
- self.line[x + 2] |= color | mask
- color = (pattern >> 2)
- if ((color & 0x0202) != 0):
- self.line[x + 3] |= color | mask
- color = (pattern >> 3)
- if ((color & 0x0202) != 0):
- self.line[x + 4] |= color | mask
- color = (pattern >> 4)
- if ((color & 0x0202) != 0):
- self.line[x + 5] |= color | mask
- color = (pattern >> 5)
- if ((color & 0x0202) != 0):
- self.line[x + 6] |= color | mask
- color = (pattern >> 6)
- if ((color & 0x0202) != 0):
- self.line[x + 7] |= color | mask
- else:
- color = (pattern >> 6)
- if ((color & 0x0202) != 0):
- self.line[x + 0] |= color | mask
- color = (pattern >> 5)
- if ((color & 0x0202) != 0):
- self.line[x + 1] |= color | mask
- color = (pattern >> 4)
- if ((color & 0x0202) != 0):
- self.line[x + 2] |= color | mask
- color = (pattern >> 3)
- if ((color & 0x0202) != 0):
- self.line[x + 3] |= color | mask
- color = (pattern >> 2)
- if ((color & 0x0202) != 0):
- self.line[x + 4] |= color | mask
- color = (pattern >> 1)
- if ((color & 0x0202) != 0):
- self.line[x + 5] |= color | mask
- color = (pattern >> 0)
- if ((color & 0x0202) != 0):
- self.line[x + 6] |= color | mask
- color = (pattern << 1)
- if ((color & 0x0202) != 0):
- self.line[x + 7] |= color | mask
-
-
- def drawOverlappedObjectTile(self, x, address, flags):
- pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8)
- mask = 0
- # priority
- if ((flags & 0x80) != 0):
- mask |= 0x0008
- # palette
- if ((flags & 0x10) != 0):
- mask |= 0x0004
- # X flip
- if ((flags & 0x20) != 0):
- color = (pattern << 1)
- if ((color & 0x0202) != 0):
- self.line[x + 0] = (self.line[x + 0] & 0x0101) | color | mask
- color = (pattern >> 0)
- if ((color & 0x0202) != 0):
- self.line[x + 1] = (self.line[x + 1] & 0x0101) | color | mask
- color = (pattern >> 1)
- if ((color & 0x0202) != 0):
- self.line[x + 2] = (self.line[x + 2] & 0x0101) | color | mask
- color = (pattern >> 2)
- if ((color & 0x0202) != 0):
- self.line[x + 3] = (self.line[x + 3] & 0x0101) | color | mask
- color = (pattern >> 3)
- if ((color & 0x0202) != 0):
- self.line[x + 4] = (self.line[x + 4] & 0x0101) | color | mask
- color = (pattern >> 4)
- if ((color & 0x0202) != 0):
- self.line[x + 5] = (self.line[x + 5] & 0x0101) | color | mask
- color = (pattern >> 6)
- if ((color & 0x0202) != 0):
- self.line[x + 7] = (self.line[x + 7] & 0x0101) | color | mask
- color = (pattern >> 5)
- if ((color & 0x0202) != 0):
- self.line[x + 6] = (self.line[x + 6] & 0x0101) | color | mask
- else:
- color = (pattern >> 6)
- if ((color & 0x0202) != 0):
- self.line[x + 0] = (self.line[x + 0] & 0x0101) | color | mask
- color = (pattern >> 5)
- if ((color & 0x0202) != 0):
- self.line[x + 1] = (self.line[x + 1] & 0x0101) | color | mask
- color = (pattern >> 4)
- if ((color & 0x0202) != 0):
- self.line[x + 2] = (self.line[x + 2] & 0x0101) | color | mask
- color = (pattern >> 3)
- if ((color & 0x0202) != 0):
- self.line[x + 3] = (self.line[x + 3] & 0x0101) | color | mask
- color = (pattern >> 2)
- if ((color & 0x0202) != 0):
- self.line[x + 4] = (self.line[x + 4] & 0x0101) | color | mask
- color = (pattern >> 1)
- if ((color & 0x0202) != 0):
- self.line[x + 5] = (self.line[x + 5] & 0x0101) | color | mask
- color = (pattern >> 0)
- if ((color & 0x0202) != 0):
- self.line[x + 6] = (self.line[x + 6] & 0x0101) | color | mask
- color = (pattern << 1)
- if ((color & 0x0202) != 0):
- self.line[x + 7] = (self.line[x + 7] & 0x0101) | color | mask
-
-
- def drawPixels(self):
- self.updatePalette()
- pixels = self.driver.getPixels()
- offset = self.ly * self.driver.getWidth()
- for x in range(8, 168, 4):
- pattern0 = self.line[x + 0]
- pattern1 = self.line[x + 1]
- pattern2 = self.line[x + 2]
- pattern3 = self.line[x + 3]
- pixels[offset + 0] = self.palette[pattern0]
- pixels[offset + 1] = self.palette[pattern1]
- pixels[offset + 2] = self.palette[pattern2]
- pixels[offset + 3] = self.palette[pattern3]
- offset += 4
-
-
- def clearPixels(self):
- pixels = self.driver.getPixels()
- length = self.driver.getWidth() * self.driver.getHeight()
- for offset in range(0, length):
- pixels[offset] = constants.COLOR_MAP[0]
-
-
- def updatePalette(self):
- if (not self.dirty):
- return
- # bit 4/0 = constants.BG color, bit 5/1 = constants.OBJ color, bit 2 = constants.OBJ palette, bit
- # 3 = constants.OBJ priority
- for pattern in range(0, 64):
- #color
- if ((pattern & 0x22) == 0 or ((pattern & 0x08) != 0 and (pattern & 0x11) != 0)):
- # constants.OBJ behind constants.BG color 1-3
- color = (self.bgp >> ((((pattern >> 3) & 0x02) + (pattern & 0x01)) << 1)) & 0x03
- # constants.OBJ above constants.BG
- elif ((pattern & 0x04) == 0):
- color = (self.obp0 >> ((((pattern >> 4) & 0x02) + ((pattern >> 1) & 0x01)) << 1)) & 0x03
- else:
- color = (self.obp1 >> ((((pattern >> 4) & 0x02) + ((pattern >> 1) & 0x01)) << 1)) & 0x03
+ # constants.LCD Registers int
+ lcdc = 0
+ stat = 0
+ scy = 0
+ scx = 0
+ ly = 0
+ lyc = 0
+ dma = 0
+ bgp = 0
+ obp0 = 0
+ obp1 = 0
+ wy = 0
+ wx = 0
+ wly = 0
+
+ cycles = 0
+
+ frames = 0
+ frameSkip = 0
+
+ #boolean
+ transfer = False
+ display = False
+ vblank = False
+ dirty = False
+
+ # Line Buffer, constants.OAM Cache and Color Palette
+ line = []#= new int[8 + 160 + 8]
+ objects = []#= new int[OBJECTS_PER_LINE]
+ palette = []#= new int[1024]
+
+ # Video Driver VideoDriver
+ driver = None
+
+ # Interrupt Controller Interrupt
+ interrupt = None
+
+ # Memory Interface Memory
+ memory = None
+
+
+ def __init__(self, videDriver, interrupt, memory):
+ self.driver = videoDriver
+ self.interrupt = interrupt
+ self.memory = memory
+ self.reset()
+
+
+ def getFrameSkip(self):
+ return self.frameSkip
+
+
+ def setFrameSkip(self, frameSkip):
+ self.frameSkip = frameSkip
+
+
+ def reset(self):
+ self.cycles = constants.MODE_2_TICKS
+
+ self.lcdc = 0x91
+ self.stat = 2
+ self.ly = 0
+ self.lyc = 0
+ self.dma = 0xFF
+ self.scy = 0
+ self.scx = 0
+ self.wy = self.wly = 0
+ self.wx = 0
+ self.bgp = 0xFC
+ self.obp0 = self.obp1 = 0xFF
+
+ self.transfer = True
+ self.display = True
+ self.vblank = True
+ self.dirty = True
+
+ for index in range(0, constants.VRAM_SIZE):
+ self.vram[index] = 0x00
+
+ for index in range(0, constants.OAM_SIZE):
+ self.oam[index] = 0x00
+
+
+ def write(self, address, data):
+ # assert data >= 0x00 and data <= 0xFF
+ if address == constants.LCDC :
+ self.setControl(data)
+ elif address == constants.STAT:
+ self.setStatus(data)
+ elif address == constants.SCY:
+ self.setScrollY(data)
+ elif address == constants.SCX:
+ self.setScrollX(data)
+ elif address == constants.LY:
+ # Read Only
+ pass
+ elif address == constants.LYC:
+ self.setLYCompare(data)
+ elif address == constants.DMA:
+ self.setDMA(data)
+ elif address == constants.BGP:
+ self.setBackgroundPalette(data)
+ elif address == constants.OBP0:
+ self.setObjectPalette0(data)
+ elif address == constants.OBP1:
+ self.setObjectPalette1(data)
+ elif address == constants.WY:
+ self.setWindowY(data)
+ elif address == constants.WX:
+ self.setWindowX(data)
+ else:
+ if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE):
+ #TODO convert to byte
+ self.oam[address - constants.OAM_ADDR] = data
+ elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE):
+ #TODO convert to byte
+ self.vram[address - constants.VRAM_ADDR] =data
+
+
+ def read(self, address):
+ if address == constants.LCDC:
+ return self.getControl()
+ elif address == constants.STAT:
+ return self.getStatus()
+ elif address == constants.SCY:
+ return self.getScrollY()
+ elif address == constants.SCX:
+ return self.getScrollX()
+ elif address == constants.LY:
+ return self.getLineY()
+ elif address == constants.LYC:
+ return self.getLineYCompare()
+ elif address == constants.DMA:
+ return self.getDMA()
+ elif address == constants.BGP:
+ return self.getBackgroundPalette()
+ elif address == constants.OBP0:
+ return self.getObjectPalette0()
+ elif address == constants.OBP1:
+ return self.getObjectPalette1()
+ elif address == constants.WY:
+ return self.getWindowY()
+ elif address == constants.WX:
+ return self.getWindowX()
+ else:
+ if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE):
+ return self.oam[address - constants.OAM_ADDR] & 0xFF
+ elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE):
+ return self.vram[address - constants.VRAM_ADDR] & 0xFF
+ return 0xFF
+
+
+ def cycles(self):
+ return self.cycles
+
+
+ def emulate(self, ticks):
+ if ((self.lcdc & 0x80) != 0):
+ self.cycles -= ticks
+ while (self.cycles <= 0):
+ switch = self.stat & 0x03
+ if switch == 0:
+ self.emulateHBlank()
+ elif switch == 1:
+ self.emulateVBlank()
+ elif switch == 2:
+ self.emulateOAM()
+ elif switch == 3:
+ self.emulateTransfer()
+
+
+ def getControl(self):
+ return self.lcdc
+
+
+ def getStatus(self):
+ return 0x80 | self.stat
+
+
+ def getScrollY(self):
+ return self.scy
+
+
+ def getScrollX(self):
+ return self.scx
+
+
+ def getLineY(self):
+ return self.ly
+
+
+ def getLineYCompare(self):
+ return self.lyc
+
+
+ def getDMA(self):
+ return self.dma
+
+
+ def getBackgroundPalette(self):
+ return self.bgp
+
+
+ def getObjectPalette0(self):
+ return self.obp0
+
+
+ def getObjectPalette1(self):
+ return self.obp1
+
+
+ def getWindowY(self):
+ return self.wy
+
+
+ def getWindowX(self):
+ return self.wx
+
+
+ def setControl(self, data):
+ if ((self.lcdc & 0x80) != (data & 0x80)):
+ # constants.NOTE: do not reset constants.LY=LYC flag (bit 2) of the constants.STAT register (Mr.
+ # Do!)
+ if ((data & 0x80) != 0):
+ self.stat = (self.stat & 0xFC) | 0x02
+ self.cycles = constants.MODE_2_TICKS
+ self.ly = 0
+ self.display = False
+ else:
+ self.stat = (self.stat & 0xFC) | 0x00
+ self.cycles = constants.MODE_1_TICKS
+ self.ly = 0
+
+ self.clearFrame()
+ # don't draw window if it was not enabled and not being drawn before
+ if ((self.lcdc & 0x20) == 0 and (data & 0x20) != 0 and self.wly == 0 and self.ly > self.wy):
+ self.wly = 144
+ self.lcdc = data
+
+
+ def setStatus(self, data):
+ self.stat = (self.stat & 0x87) | (data & 0x78)
+ # Gameboy Bug
+ if ((self.lcdc & 0x80) != 0 and (self.stat & 0x03) == 0x01 and (self.stat & 0x44) != 0x44):
+ self.interrupt.raiseInterrupt(constants.LCD)
+
+
+ def setScrollY(self, data):
+ self.scy = data
+
+
+ def setScrollX(self, data):
+ self.scx = data
+
+
+ def setLYCompare(self, data):
+ self.lyc = data
+ if ((self.lcdc & 0x80) != 0):
+ if (self.ly == self.lyc):
+ # constants.NOTE: raise interrupt once per line (Prehistorik Man, The
+ # Jetsons, Muhammad Ali)
+ if ((self.stat & 0x04) == 0):
+ # constants.LYC=LY interrupt
+ self.stat |= 0x04
+ if ((self.stat & 0x40) != 0):
+ self.interrupt.raiseInterrupt(constants.LCD)
+ else:
+ self.stat &= 0xFB
+
+
+ def setDMA(self, data):
+ self.dma = data
+ for index in range(0, constants.OAM_SIZE):
+ #TODO convert to byte
+ self.oam[index] = self.memory.read((self.dma << 8) + index)
+
+
+ def setBackgroundPalette(self, data):
+ if (self.bgp != data):
+ self.bgp = data
+ self.dirty = True
+
+
+ def setObjectPalette0(self, data):
+ if (self.obp0 != data):
+ self.obp0 = data
+ self.dirty = True
+
+
+ def setObjectPalette1(self, data):
+ if (self.obp1 != data):
+ self.obp1 = data
+ self.dirty = True
+
+
+ def setWindowY(self, data):
+ self.wy = data
+
+
+ def setWindowX(self, data):
+ self.wx = data
+
+
+ def emulateOAM(self):
+ self.stat = (self.stat & 0xFC) | 0x03
+ self.cycles += constants.MODE_3_BEGIN_TICKS
+ self.transfer = True
+
+
+ def emulateTransfer(self):
+ if (self.transfer):
+ if (self.display):
+ self.drawLine()
+ self.stat = (self.stat & 0xFC) | 0x03
+ self.cycles += constants.MODE_3_END_TICKS
+ self.transfer = False
+ else:
+ self.stat = (self.stat & 0xFC) | 0x00
+ self.cycles += constants.MODE_0_TICKS
+ # H-Blank interrupt
+ if ((self.stat & 0x08) != 0 and (self.stat & 0x44) != 0x44):
+ self.interrupt.raiseInterrupt(constants.LCD)
+
+
+ def emulateHBlank(self):
+ self.ly+=1
+ if (self.ly == self.lyc):
+ # constants.LYC=LY interrupt
+ self.stat |= 0x04
+ if ((self.stat & 0x40) != 0):
+ self.interrupt.raiseInterrupt(constants.LCD)
+ else:
+ self.stat &= 0xFB
+ if (self.ly < 144):
+ self.stat = (self.stat & 0xFC) | 0x02
+ self.cycles += constants.MODE_2_TICKS
+ # constants.OAM interrupt
+ if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44):
+ self.interrupt.raiseInterrupt(constants.LCD)
+ else:
+ if (self.display):
+ self.drawFrame()
+ self.frames += 1
+ if (self.frames >= self.frameSkip):
+ self.display = True
+ self.frames = 0
+ else:
+ self.display = False
+
+ self.stat = (self.stat & 0xFC) | 0x01
+ self.cycles += constants.MODE_1_BEGIN_TICKS
+ self.vblank = True
+
+
+ def emulateVBlank(self):
+ if (self.vblank):
+ self.vblank = False
+ self.stat = (self.stat & 0xFC) | 0x01
+ self.cycles += constants.MODE_1_TICKS - constants.MODE_1_BEGIN_TICKS
+ # V-Blank interrupt
+ if ((self.stat & 0x10) != 0):
+ self.interrupt.raiseInterrupt(constants.LCD)
+ # V-Blank interrupt
+ self.interrupt.raiseInterrupt(constants.VBLANK)
+ elif (self.ly == 0):
+ self.stat = (self.stat & 0xFC) | 0x02
+ self.cycles += constants.MODE_2_TICKS
+ # constants.OAM interrupt
+ if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44):
+ self.interrupt.raiseInterrupt(constants.LCD)
+ else:
+ if (self.ly < 153):
+ self.ly+=1
+ self.stat = (self.stat & 0xFC) | 0x01
+ if (self.ly == 153):
+ self.cycles += constants.MODE_1_END_TICKS
+ else:
+ self.cycles += constants.MODE_1_TICKS
+ else:
+ self.ly = self.wly = 0
+ self.stat = (self.stat & 0xFC) | 0x01
+ self.cycles += constants.MODE_1_TICKS - constants.MODE_1_END_TICKS
+ if (self.ly == self.lyc):
+ # constants.LYC=LY interrupt
+ self.stat |= 0x04
+ if ((self.stat & 0x40) != 0):
+ self.interrupt.raiseInterrupt(constants.LCD)
+ else:
+ self.stat &= 0xFB
+
+
+ def drawFrame(self):
+ self.driver.display()
+
+
+ def clearFrame(self):
+ self.clearPixels()
+ self.driver.display()
+
+
+ def drawLine(self):
+ if ((self.lcdc & 0x01) != 0):
+ self.drawBackground()
+ else:
+ self.drawCleanBackground()
+ if ((self.lcdc & 0x20) != 0):
+ self.drawWindow()
+ if ((self.lcdc & 0x02) != 0):
+ self.drawObjects()
+ self.drawPixels()
+
+
+ def drawCleanBackground(self):
+ for x in range(0, 8+160+8):
+ self.line[x] = 0x00
+
+
+ def drawBackground(self):
+ y = (self.scy + self.ly) & 0xFF
+ x = self.scx & 0xFF
+ tileMap = constants.VRAM_MAP_A
+ if (self.lcdc & 0x08) != 0:
+ tileMap = constants.VRAM_MAP_B
+ tileData = constants.VRAM_DATA_B
+ if (self.lcdc & 0x10) != 0:
+ tileData = constants.VRAM_DATA_A
+ tileMap += ((y >> 3) << 5) + (x >> 3)
+ tileData += (y & 7) << 1
+ self.drawTiles(8 - (x & 7), tileMap, tileData)
+
+
+ def drawWindow(self):
+ if (self.ly >= self.wy and self.wx < 167 and self.wly < 144):
+ tileMap = constants.VRAM_MAP_A
+ if (self.lcdc & 0x40) != 0:
+ tileMap = constants.VRAM_MAP_B
+ tileData = constants.VRAM_DATA_B
+ if (self.lcdc & 0x10) != 0:
+ tileData = constants.VRAM_DATA_A
+ tileMap += (self.wly >> 3) << 5
+ tileData += (self.wly & 7) << 1
+ self.drawTiles(self.wx + 1, tileMap, tileData)
+ self.wly+=1
+
+
+ def drawObjects(self):
+ count = self.scanObjects()
+ lastx = 176
+ for index in range(176, count):
+ data = self.objects[index]
+ x = (data >> 24) & 0xFF
+ flags = (data >> 12) & 0xFF
+ address = data & 0xFFF
+ if (x + 8 <= lastx):
+ self.drawObjectTile(x, address, flags)
+ else:
+ self.drawOverlappedObjectTile(x, address, flags)
+ lastx = x
+
+
+ def scanObjects(self):
+ count = 0
+ # search active objects
+ for offset in range(0, 4*40, 4):
+ y = self.oam[offset + 0] & 0xFF
+ x = self.oam[offset + 1] & 0xFF
+ if (y <= 0 or y >= 144 + 16 or x <= 0 or x >= 168):
+ continue
+ tile = self.oam[offset + 2] & 0xFF
+ flags = self.oam[offset + 3] & 0xFF
+
+ y = self.ly - y + 16
+
+ if ((self.lcdc & 0x04) != 0):
+ # 8x16 tile size
+ if (y < 0 or y > 15):
+ continue
+ # Y flip
+ if ((flags & 0x40) != 0):
+ y = 15 - y
+ tile &= 0xFE
+ else:
+ # 8x8 tile size
+ if (y < 0 or y > 7):
+ continue
+ # Y flip
+ if ((flags & 0x40) != 0):
+ y = 7 - y
+ self.objects[count] = (x << 24) + (count << 20) + (flags << 12) + ((tile << 4) + (y << 1))
+ if (++count >= constants.OBJECTS_PER_LINE):
+ break
+ self.sortScanObject(count)
+ return count
+
+ def sortScanObject(self, count):
+ # sort objects from lower to higher priority
+ for index in range(0, count):
+ rightmost = index
+ for number in range(index+1, count):
+ if ((self.objects[number] >> 20) > (self.objects[rightmost] >> 20)):
+ rightmost = number
+ if (rightmost != index):
+ data = self.objects[index]
+ self.objects[index] = self.objects[rightmost]
+ self.objects[rightmost] = data
+
+
+ def drawTiles(self, x, tileMap, tileData):
+ if ((self.lcdc & 0x10) != 0):
+ while (x < 168):
+ tile = self.vram[tileMap] & 0xFF
+ self.drawTile(x, tileData + (tile << 4))
+ tileMap = (tileMap & 0x1FE0) + ((tileMap + 1) & 0x001F)
+ x += 8
+ else:
+ while (x < 168):
+ tile = (self.vram[tileMap] ^ 0x80) & 0xFF
+ self.drawTile(x, tileData + (tile << 4))
+ tileMap = (tileMap & 0x1FE0) + ((tileMap + 1) & 0x001F)
+ x += 8
+
+
+ def drawTile(self, x, address):
+ pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8)
+ self.line[x + 0] = (pattern >> 7) & 0x0101
+ self.line[x + 1] = (pattern >> 6) & 0x0101
+ self.line[x + 2] = (pattern >> 5) & 0x0101
+ self.line[x + 3] = (pattern >> 4) & 0x0101
+ self.line[x + 4] = (pattern >> 3) & 0x0101
+ self.line[x + 5] = (pattern >> 2) & 0x0101
+ self.line[x + 6] = (pattern >> 1) & 0x0101
+ self.line[x + 7] = (pattern >> 0) & 0x0101
+
+
+ def drawObjectTile(self, x, address, flags):
+ pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8)
+ mask = 0
+ # priority
+ if (flags & 0x80) != 0:
+ mask |= 0x0008
+ # palette
+ if (flags & 0x10) != 0:
+ mask |= 0x0004
+ # X flip
+ if (flags & 0x20) != 0:
+ color = (pattern << 1)
+ if ((color & 0x0202) != 0):
+ self.line[x + 0] |= color | mask
+ color = (pattern >> 0)
+ if ((color & 0x0202) != 0):
+ self.line[x + 1] |= color | mask
+ color = (pattern >> 1)
+ if ((color & 0x0202) != 0):
+ self.line[x + 2] |= color | mask
+ color = (pattern >> 2)
+ if ((color & 0x0202) != 0):
+ self.line[x + 3] |= color | mask
+ color = (pattern >> 3)
+ if ((color & 0x0202) != 0):
+ self.line[x + 4] |= color | mask
+ color = (pattern >> 4)
+ if ((color & 0x0202) != 0):
+ self.line[x + 5] |= color | mask
+ color = (pattern >> 5)
+ if ((color & 0x0202) != 0):
+ self.line[x + 6] |= color | mask
+ color = (pattern >> 6)
+ if ((color & 0x0202) != 0):
+ self.line[x + 7] |= color | mask
+ else:
+ color = (pattern >> 6)
+ if ((color & 0x0202) != 0):
+ self.line[x + 0] |= color | mask
+ color = (pattern >> 5)
+ if ((color & 0x0202) != 0):
+ self.line[x + 1] |= color | mask
+ color = (pattern >> 4)
+ if ((color & 0x0202) != 0):
+ self.line[x + 2] |= color | mask
+ color = (pattern >> 3)
+ if ((color & 0x0202) != 0):
+ self.line[x + 3] |= color | mask
+ color = (pattern >> 2)
+ if ((color & 0x0202) != 0):
+ self.line[x + 4] |= color | mask
+ color = (pattern >> 1)
+ if ((color & 0x0202) != 0):
+ self.line[x + 5] |= color | mask
+ color = (pattern >> 0)
+ if ((color & 0x0202) != 0):
+ self.line[x + 6] |= color | mask
+ color = (pattern << 1)
+ if ((color & 0x0202) != 0):
+ self.line[x + 7] |= color | mask
+
+
+ def drawOverlappedObjectTile(self, x, address, flags):
+ pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8)
+ mask = 0
+ # priority
+ if ((flags & 0x80) != 0):
+ mask |= 0x0008
+ # palette
+ if ((flags & 0x10) != 0):
+ mask |= 0x0004
+ # X flip
+ if ((flags & 0x20) != 0):
+ color = (pattern << 1)
+ if ((color & 0x0202) != 0):
+ self.line[x + 0] = (self.line[x + 0] & 0x0101) | color | mask
+ color = (pattern >> 0)
+ if ((color & 0x0202) != 0):
+ self.line[x + 1] = (self.line[x + 1] & 0x0101) | color | mask
+ color = (pattern >> 1)
+ if ((color & 0x0202) != 0):
+ self.line[x + 2] = (self.line[x + 2] & 0x0101) | color | mask
+ color = (pattern >> 2)
+ if ((color & 0x0202) != 0):
+ self.line[x + 3] = (self.line[x + 3] & 0x0101) | color | mask
+ color = (pattern >> 3)
+ if ((color & 0x0202) != 0):
+ self.line[x + 4] = (self.line[x + 4] & 0x0101) | color | mask
+ color = (pattern >> 4)
+ if ((color & 0x0202) != 0):
+ self.line[x + 5] = (self.line[x + 5] & 0x0101) | color | mask
+ color = (pattern >> 6)
+ if ((color & 0x0202) != 0):
+ self.line[x + 7] = (self.line[x + 7] & 0x0101) | color | mask
+ color = (pattern >> 5)
+ if ((color & 0x0202) != 0):
+ self.line[x + 6] = (self.line[x + 6] & 0x0101) | color | mask
+ else:
+ color = (pattern >> 6)
+ if ((color & 0x0202) != 0):
+ self.line[x + 0] = (self.line[x + 0] & 0x0101) | color | mask
+ color = (pattern >> 5)
+ if ((color & 0x0202) != 0):
+ self.line[x + 1] = (self.line[x + 1] & 0x0101) | color | mask
+ color = (pattern >> 4)
+ if ((color & 0x0202) != 0):
+ self.line[x + 2] = (self.line[x + 2] & 0x0101) | color | mask
+ color = (pattern >> 3)
+ if ((color & 0x0202) != 0):
+ self.line[x + 3] = (self.line[x + 3] & 0x0101) | color | mask
+ color = (pattern >> 2)
+ if ((color & 0x0202) != 0):
+ self.line[x + 4] = (self.line[x + 4] & 0x0101) | color | mask
+ color = (pattern >> 1)
+ if ((color & 0x0202) != 0):
+ self.line[x + 5] = (self.line[x + 5] & 0x0101) | color | mask
+ color = (pattern >> 0)
+ if ((color & 0x0202) != 0):
+ self.line[x + 6] = (self.line[x + 6] & 0x0101) | color | mask
+ color = (pattern << 1)
+ if ((color & 0x0202) != 0):
+ self.line[x + 7] = (self.line[x + 7] & 0x0101) | color | mask
+
+
+ def drawPixels(self):
+ self.updatePalette()
+ pixels = self.driver.getPixels()
+ offset = self.ly * self.driver.getWidth()
+ for x in range(8, 168, 4):
+ pattern0 = self.line[x + 0]
+ pattern1 = self.line[x + 1]
+ pattern2 = self.line[x + 2]
+ pattern3 = self.line[x + 3]
+ pixels[offset + 0] = self.palette[pattern0]
+ pixels[offset + 1] = self.palette[pattern1]
+ pixels[offset + 2] = self.palette[pattern2]
+ pixels[offset + 3] = self.palette[pattern3]
+ offset += 4
+
+
+ def clearPixels(self):
+ pixels = self.driver.getPixels()
+ length = self.driver.getWidth() * self.driver.getHeight()
+ for offset in range(0, length):
+ pixels[offset] = constants.COLOR_MAP[0]
+
+
+ def updatePalette(self):
+ if (not self.dirty):
+ return
+ # bit 4/0 = constants.BG color, bit 5/1 = constants.OBJ color, bit 2 = constants.OBJ palette, bit
+ # 3 = constants.OBJ priority
+ for pattern in range(0, 64):
+ #color
+ if ((pattern & 0x22) == 0 or ((pattern & 0x08) != 0 and (pattern & 0x11) != 0)):
+ # constants.OBJ behind constants.BG color 1-3
+ color = (self.bgp >> ((((pattern >> 3) & 0x02) + (pattern & 0x01)) << 1)) & 0x03
+ # constants.OBJ above constants.BG
+ elif ((pattern & 0x04) == 0):
+ color = (self.obp0 >> ((((pattern >> 4) & 0x02) + ((pattern >> 1) & 0x01)) << 1)) & 0x03
+ else:
+ color = (self.obp1 >> ((((pattern >> 4) & 0x02) + ((pattern >> 1) & 0x01)) << 1)) & 0x03
- self.palette[((pattern & 0x30) << 4) + (pattern & 0x0F)] = constants.COLOR_MAP[color]
- self.dirty = False
+ self.palette[((pattern & 0x30) << 4) + (pattern & 0x0F)] = constants.COLOR_MAP[color]
+ self.dirty = False
More information about the Pypy-commit
mailing list