[pypy-svn] r52406 - pypy/branch/gameboy-emulator/pypy/lang/gameboy
cami at codespeak.net
cami at codespeak.net
Wed Mar 12 09:09:56 CET 2008
Author: cami
Date: Wed Mar 12 09:09:55 2008
New Revision: 52406
Modified:
pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.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/sound.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py
pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py
Log:
minor refactoring of timer, video, sound, cartridge and joypad
cartridge has been introduced to inheritance, needs a lot more of work to be done there
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 Wed Mar 12 09:09:55 2008
@@ -99,56 +99,72 @@
self.store = storeDriver
self.clock = clockDriver
+
def initialize(self):
pass
+
def getTitle(self):
pass
+
def getCartridgeType(self):
return self.rom[CARTRIDGE_TYPE_ADDRESS] & 0xFF
+
def getRom(self):
return self.rom
+
def getROMSize(self):
romSize = self.rom[CARTRIDGE_SIZE_ADDRESS] & 0xFF
if romSize>=0x00 and romSize<=0x07:
return 32768 << romSize
return -1
+
def getRAMSize(self):
return RAM_SIZE_MAPPING[self.rom[RAM_SIZE_ADDRESS]]
+
def getDestinationCode(self):
return self.rom[DESTINATION_CODE_ADDRESS] & 0xFF;
+
def getLicenseeCode():
return self.rom[LICENSEE_ADDRESS] & 0xFF;
+
def getROMVersion(self):
return self.rom[ROM_VERSION_ADDRESS] & 0xFF;
+
def getHeaderChecksum(self):
return self.rom[HEADER_CHECKSUM_ADDRESS] & 0xFF;
+
def getChecksum(self):
return ((rom[CHECKSUM_A_ADDRESS] & 0xFF) << 8) + (rom[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)
@@ -179,10 +195,12 @@
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)):
@@ -190,6 +208,7 @@
checksum = (checksum + (self.rom[address] & 0xFF)) & 0xFFFF
return (checksum == self.getChecksum());
+
def verifyHeader(self):
if self.rom.length < 0x0150:
return false;
@@ -198,6 +217,7 @@
checksum = (checksum - (rom[address] & 0xFF)) & 0xFF;
return (checksum == self.getHeaderChecksum())
+
# ==============================================================================
# CARTRIDGE TYPES
@@ -208,6 +228,44 @@
# RAM Bank Size (8KB)
RAM_BANK_SIZE = 0x2000
+ ramEnable = False
+
+ rom = []
+ ram = []
+
+ romSize = 0;
+ ramSize = 0;
+
+ minRomBankSize = 0
+ maxRomBankSize = 0
+
+ minRamBankSize = 0
+ maxRamBankSize = 0
+
+ romBank = ROM_BANK_SIZE
+ ramBank = 0
+
+
+ def reset(self):
+ self.romBank = ROM_BANK_SIZE;
+ self.ramBank = 0;
+ self.ramEnable = False;
+
+ def setROM(self, buffer):
+ banks = len(buffer) / ROM_BANK_SIZE;
+ if (banks < minRomBankSize or banks > maxRomBankSize):
+ raise Exception("Invalid ROM size");
+ self.rom = buffer;
+ self.romSize = ROM_BANK_SIZE*banks - 1;
+
+
+ def setRAM(buffer):
+ banks = len(buffer) / RAM_BANK_SIZE;
+ if (banks < minRamBankSize or banks > maxRamBankSize):
+ raise Exception("Invalid RAM size");
+ self.ram = buffer;
+ self.ramSize = RAM_BANK_SIZE*banks - 1;
+
"""
Mario GameBoy (TM) Emulator
@@ -220,20 +278,21 @@
"""
class MBC1(MBC):
- rom = []
- ram = []
- ramEnable = False
-
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):
- self.romBank= ROM_BANK_SIZE
- self.romBank = 0
+ super.reset()
self.memoryModel = 0
- self.ramEnable = False
+
def read(self, address):
if address <= 0x3FFF:
@@ -248,6 +307,7 @@
return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF;
return 0xFF;
+
def write(self, address, data):
if (address <= 0x1FFF):
# 0000-1FFF
@@ -275,24 +335,6 @@
if (self.ramEnable):
self.ram[self.ramBank + (address & 0x1FFF)] = data;
- def setROM(self, buffer):
- banks = len(buffer) / ROM_BANK_SIZE;
-
- if (banks < 2 or banks > 128):
- raise Exception("Invalid MBC1 ROM size");
-
- self.rom = buffer;
- self.romSize = ROM_BANK_SIZEbanks - 1;
-
- def setRAM(buffer):
- banks = len(buffer) / RAM_BANK_SIZE;
-
- if (banks < 0 or banks > 4):
- raise Exception("Invalid MBC1 RAM size");
-
- self.ram = buffer;
- self.ramSize = RAM_BANK_SIZEbanks - 1;
-
@@ -309,20 +351,19 @@
class MBC2(MBC):
RAM_BANK_SIZE = 512;
- rom = []
- ram = []
-
- romSize = 0
- romBank =0
- ramEnable = False
-
def __init__(self, rom, ram):
+ self.minRamBankSize = RAM_BANK_SIZE
+ self.maxRamBankSize = RAM_BANK_SIZE
+ self.minRomBankSize = 2
+ self.maxRomBankSize = 16
+
self.setROM(rom);
self.setRAM(ram);
+
def reset(self):
- self.romBank = ROM_BANK_SIZE;
- self.ramEnable = False;
+ super.reset()
+
def read(self, address):
if (address <= 0x3FFF):
@@ -336,6 +377,7 @@
return self.ram[address & 0x01FF] & 0x0F;
return 0xFF;
+
def write(self, address, data):
if (address <= 0x1FFF):
# 0000-1FFF
@@ -352,21 +394,6 @@
if (self.ramEnable):
self.ram[address & 0x01FF] = (byte) (data & 0x0F);
- def setROM(self, buffer):
- banks = buffer.length / ROM_BANK_SIZE;
-
- if (banks < 2 or banks > 16):
- raise Exception("Invalid MBC2 ROM size");
-
- self.rom = buffer;
- self.romSize = ROM_BANK_SIZEbanks - 1;
-
- def setRAM(self, buffer):
- if (buffer.length != RAM_BANK_SIZE):
- raise Exception("Invalid MBC2 RAM size");
-
- self.ram = buffer;
-
"""
Mario GameBoy (TM) Emulator
@@ -382,17 +409,9 @@
#ClockDriver
clock = None;
- rom = [];
- ram = [];
-
- romSize = 0;
- ramSize = 0;
-
romBank = 0;
ramBank = 0;
- ramEnable = False;
-
clockRegister = 0;
clockLatch = 0;
clockTime = 0;
@@ -408,16 +427,19 @@
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():
- self.romBank = ROM_BANK_SIZE;
- self.ramBank = 0;
- self.ramEnable = false;
+ def reset():
+ super.reset()
self.clockTime = self.clock.getTime();
@@ -426,6 +448,7 @@
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
@@ -450,6 +473,7 @@
return self.clockLControl;
return 0xFF;
+
def write(self, address, data):
if (address <= 0x1FFF):
# 0000-1FFF
@@ -493,6 +517,7 @@
if (self.clockRegister == 0x0C):
self.clockControl = (self.clockControl & 0x80) | data;
+
def latchClock(self):
self.updateClock();
@@ -502,6 +527,7 @@
self.clockLDays = self.clockDays & 0xFF;
self.clockLControl = (self.clockControl & 0xFE) | ((self.clockDays >> 8) & 0x01);
+
def updateClock():
now = self.clock.getTime();
@@ -540,24 +566,6 @@
self.clockTime = now;
- def setROM(self, buffer):
- banks = buffer.length / ROM_BANK_SIZE;
-
- if (banks < 2 or banks > 128):
- raise Exception("Invalid MCB3 ROM size");
-
- self.rom = buffer;
- self.romSize = ROM_BANK_SIZE * banks - 1;
-
- def setRAM(self, buffer):
- banks = buffer.length / RAM_BANK_SIZE;
-
- if (banks < 0 or banks > 4):
- raise Exception("Invalid MBC3 RAM size");
-
- self.ram = buffer;
- self.ramSize = RAM_BANK_SIZE * banks - 1;
-
"""
@@ -571,30 +579,23 @@
"""
class MBC5(MBC):
- rom = [];
- ram = [];
-
- romSize = 0;
- ramSize = 0;
-
romBank = 0;
- ramBank = 0;
- ramEnable = 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():
- self.romBank = ROM_BANK_SIZE;
- self.ramBank = 0;
-
- self.ramEnable = false;
+ super.reset()
def read(self, address):
@@ -634,24 +635,6 @@
self.ram[self.ramBank + (address & 0x1FFF)] = data;
- def setROM(self, buffer):
- banks = buffer.length / ROM_BANK_SIZE;
-
- if (banks < 2 or banks > 512):
- raise Exception("Invalid MBC5 ROM size");
-
- self.rom = buffer;
- self.romSize = ROM_BANK_SIZE * banks - 1;
-
-
- def setRAM(self, buffer):
- banks = buffer.length / RAM_BANK_SIZE;
-
- if (banks < 0 or banks > 16):
- raise Exception("Invalid MBC5 RAM size");
-
- self.ram = buffer;
- self.ramSize = RAM_BANK_SIZE * banks - 1;
class HuC1(MBC):
@@ -670,28 +653,29 @@
"""
class HuC3(MBC):
clock = None;
- rom = [];
- ram = [];
+
romBank = 0;
- ramBank = 0;
- romSize = 0;
- ramSize = 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():
- self.romBank = ROM_BANK_SIZE;
- self.ramBank = 0;
+ super.reset()
self.ramFlag = 0;
self.ramValue = 0;
@@ -747,7 +731,6 @@
self.clockShift += 4;
elif ((data & 0xF0) == 0x40):
self.updateClock();
-
if ((data & 0x0F) == 0x00):
self.clockShift = 0;
elif ((data & 0x0F) == 0x03):
@@ -768,19 +751,15 @@
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;
@@ -788,29 +767,8 @@
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;
-
- def setROM(self, buffer):
- banks = buffer.length / ROM_BANK_SIZE;
-
- if (banks < 2 or banks > 128):
- raise Exception("Invalid HuC3 ROM size");
-
- self.rom = buffer;
- self.romSize = ROM_BANK_SIZE*banks - 1;
-
-
- def setRAM(self, buffer):
- banks = buffer.length / RAM_BANK_SIZE;
-
- if (banks < 0 or banks > 4):
- raise Exception("Invalid HuC3 RAM size");
-
- self.ram = buffer;
- self.ramSize = RAM_BANK_SIZE * banks - 1;
-
Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py
==============================================================================
--- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original)
+++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Wed Mar 12 09:09:55 2008
@@ -36,6 +36,7 @@
def getCartridge(self):
return self.cartridge;
+
def getFrameSkip(self):
return self.video.getFrameSkip();
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 Wed Mar 12 09:09:55 2008
@@ -24,28 +24,35 @@
def __init__(self):
self.reset();
+
def reset(self):
self.enable = 0;
self.flag = VBLANK;
+
def isPending(self):
return (self.enable & self.flag) != 0;
+
def isPending(self, mask):
return (self.enable & self.flag & mask) != 0;
+
def raiseInterrupt(self, mask):
self.flag |= mask;
+
def lower(self, mask):
self.flag &= ~mask;
+
def write(self, address, data):
if address == IE:
self.setInterruptEnable(data);
elif address==IF:
self.setInterruptFlag(data);
+
def read(self, address):
if address==IE:
return self.getInterruptEnable();
@@ -53,14 +60,18 @@
return self.getInterruptFlag();
return 0xFF;
+
def getInterruptEnable(self):
return self.enable;
+
def getInterruptFlag(self):
return 0xE0 | self.flag;
+
def setInterruptEnable(self, data):
self.enable = 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 Wed Mar 12 09:09:55 2008
@@ -29,13 +29,16 @@
self.interrupt = interrupt;
self.reset();
+
def reset(self):
self.joyp = 0xFF;
self.cycles = JOYPAD_CLOCK;
+
def cycles(self):
return self.cycles;
+
def emulate(self, ticks):
self.cycles -= ticks;
if (self.cycles <= 0):
@@ -44,16 +47,19 @@
self.cycles = JOYPAD_CLOCK;
+
def write(self, address, data):
if (address == JOYP):
self.joyp = (self.joyp & 0xCF) + (data & 0x30);
self.update();
+
def read(self, address):
if (address == JOYP):
return self.joyp;
return 0xFF;
+
def update(self):
data = self.joyp & 0xF0;
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 Wed Mar 12 09:09:55 2008
@@ -235,9 +235,8 @@
elif address==NR52:
return self.getOutputEnable();
- else:
- if (address >= AUD3WAVERAM and address <= AUD3WAVERAM + 0x3F):
- return self.getAudio3WavePattern(address);
+ elif (address >= AUD3WAVERAM and address <= AUD3WAVERAM + 0x3F):
+ return self.getAudio3WavePattern(address);
return 0xFF;
@@ -290,42 +289,45 @@
elif address == NR52:
self.setOutputEnable(data);
- else:
- if (address >= AUD3WAVERAM and address <= AUD3WAVERAM + 0x3F):
- self.setAudio3WavePattern(address, data);
+ elif (address >= AUD3WAVERAM and address <= AUD3WAVERAM + 0x3F):
+ self.setAudio3WavePattern(address, data);
def updateAudio(self):
- if ((self.nr52 & 0x80) != 0):
- if ((self.nr52 & 0x01) != 0):
- self.updateAudio1();
+ if ((self.nr52 & 0x80) == 0):
+ return
+
+ if ((self.nr52 & 0x01) != 0):
+ self.updateAudio1();
- if ((self.nr52 & 0x02) != 0):
- self.updateAudio2();
+ if ((self.nr52 & 0x02) != 0):
+ self.updateAudio2();
- if ((self.nr52 & 0x04) != 0):
- self.updateAudio3();
+ if ((self.nr52 & 0x04) != 0):
+ self.updateAudio3();
- if ((self.nr52 & 0x08) != 0):
- self.updateAudio4();
+ 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):
- if ((self.nr52 & 0x01) != 0):
- self.mixAudio1(buffer, length);
+ 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 & 0x02) != 0):
+ self.mixAudio2(buffer, length);
- if ((self.nr52 & 0x04) != 0):
- self.mixAudio3(buffer, length);
+ if ((self.nr52 & 0x04) != 0):
+ self.mixAudio3(buffer, length);
- if ((self.nr52 & 0x08) != 0):
- self.mixAudio4(buffer, length);
+ if ((self.nr52 & 0x08) != 0):
+ self.mixAudio4(buffer, length);
# Audio Channel 1
@@ -361,20 +363,19 @@
def setAudio1Envelope(self, data):
self.nr12 = data;
- if ((self.nr14 & 0x40) == 0):
- 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;
+ 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)];
+ self.audio1Frequency = self.frequencyTable[self.nr13 + ((self.nr14 & 0x07) << 8)];
def setAudio1Playback(self, data):
@@ -396,11 +397,10 @@
def updateAudio1(self):
- if ((self.nr14 & 0x40) != 0):
- if (self.audio1Length > 0):
- self.audio1Length-=1;
- if (self.audio1Length <= 0):
- self.nr52 &= ~0x01;
+ 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):
@@ -512,11 +512,10 @@
def updateAudio2(self):
- if ((self.nr24 & 0x40) != 0):
- if (self.audio2Length > 0):
- self.audio2Length-=1;
- if (self.audio2Length <= 0):
- self.nr52 &= ~0x02;
+ 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;
@@ -618,11 +617,10 @@
def updateAudio3(self):
- if ((self.nr34 & 0x40) != 0):
- if (self.audio3Length > 0):
- self.audio3Length-=1;
- if (self.audio3Length <= 0):
- self.nr52 &= ~0x04;
+ if ((self.nr34 & 0x40) != 0 and self.audio3Length > 0):
+ self.audio3Length-=1;
+ if (self.audio3Length <= 0):
+ self.nr52 &= ~0x04;
def mixAudio3(self, buffer, length):
@@ -693,7 +691,6 @@
def setAudio4Playback(self, data):
self.nr44 = data;
-
if ((self.nr44 & 0x80) != 0):
self.nr52 |= 0x08;
@@ -708,11 +705,10 @@
def updateAudio4(self):
- if ((self.nr44 & 0x40) != 0):
- if (self.audio4Length > 0):
- self.audio4Length-=1;
- if (self.audio4Length <= 0):
- self.nr52 &= ~0x08;
+ 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;
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 Wed Mar 12 09:09:55 2008
@@ -119,8 +119,7 @@
def cycles(self):
- if ((self.tac & 0x04) != 0):
- if (self.timerCycles < self.dividerCycles):
+ if ((self.tac & 0x04) != 0 and self.timerCycles < self.dividerCycles):
return self.timerCycles;
return self.dividerCycles;
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 Wed Mar 12 09:09:55 2008
@@ -23,11 +23,11 @@
OAM_ADDR = 0xFE00;
# OAM Object Attribute Map
# (FE00..FE9F)
- OAM_SIZE = 0xA0;
+ OAM_SIZE = 0xA0
# Video RAM Addresses
VRAM_ADDR = 0x8000 #8KB Video RAM (8000..9FFF) */
- VRAM_SIZE = 0x2000;
+ VRAM_SIZE = 0x2000
# VRAM Tile Data/Maps Addresses
VRAM_DATA_A = 0x0000
@@ -49,7 +49,7 @@
# Gameboy Clock Speed (1048576 Hz)
- GAMEBOY_CLOCK = 1 << 20;
+ GAMEBOY_CLOCK = 1 << 20
# LCD Mode Durations
MODE_0_TICKS = 50 #H-Blank */
@@ -61,449 +61,446 @@
MODE_1_END_TICKS = 1 #V-Blank Line 153 */
# Objects per Line
- OBJECTS_PER_LINE = 10;
+ OBJECTS_PER_LINE = 10
# LCD Color Palette
- COLOR_MAP = [ 0x9CB916, 0x8CAA14, 0x306430,
- 0x103F10
+ COLOR_MAP = [ 0x9CB916, 0x8CAA14, 0x306430, 0x103F10
# 0xE0F8D0, 0x88C070, 0x386850, 0x081820
# 0xFFFFFF, 0xAAAAAA, 0x555555, 0x000000
- ];
+ ]
# OAM Registers
- oam = [] #= new byte[OAM_SIZE];
+ oam = [] #= new byte[OAM_SIZE]
# Video RAM
- vram = []#= new byte[VRAM_SIZE];
+ vram = []#= new byte[VRAM_SIZE]
# 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;
+ 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;
+ cycles = 0
- frames = 0;
- frameSkip = 0;
+ frames = 0
+ frameSkip = 0
#boolean
- transfer = False;
- display = False;
- vblank = False;
- dirty = False;
+ transfer = False
+ display = False
+ vblank = False
+ dirty = False
# Line Buffer, OAM Cache and Color Palette
- line = []#= new int[8 + 160 + 8];
- objects = []#= new int[OBJECTS_PER_LINE];
- palette = []#= new int[1024];
+ line = []#= new int[8 + 160 + 8]
+ objects = []#= new int[OBJECTS_PER_LINE]
+ palette = []#= new int[1024]
# Video Driver VideoDriver
- driver = None;
+ driver = None
# Interrupt Controller Interrupt
- interrupt = None;
+ interrupt = None
# Memory Interface Memory
- memory = None;
+ memory = None
+
def __init__(self, videDriver, interrupt, memory):
- self.driver = videoDriver;
- self.interrupt = interrupt;
- self.memory = memory;
- self.reset();
+ self.driver = videoDriver
+ self.interrupt = interrupt
+ self.memory = memory
+ self.reset()
def getFrameSkip(self):
- return self.frameSkip;
+ return self.frameSkip
def setFrameSkip(self, frameSkip):
- self.frameSkip = frameSkip;
+ self.frameSkip = frameSkip
def reset(self):
- self.cycles = MODE_2_TICKS;
+ self.cycles = 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;
+ 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, VRAM_SIZE):
- self.vram[index] = 0x00;
+ self.vram[index] = 0x00
for index in range(0, OAM_SIZE):
- self.oam[index] = 0x00;
+ self.oam[index] = 0x00
def write(self, address, data):
- # assert data >= 0x00 and data <= 0xFF;
-
+ # assert data >= 0x00 and data <= 0xFF
if address == LCDC :
- self.setControl(data);
+ self.setControl(data)
elif address == STAT:
- self.setStatus(data);
+ self.setStatus(data)
elif address == SCY:
- self.setScrollY(data);
+ self.setScrollY(data)
elif address == SCX:
- self.setScrollX(data);
+ self.setScrollX(data)
elif address == LY:
# Read Only
pass
elif address == LYC:
- self.setLYCompare(data);
+ self.setLYCompare(data)
elif address == DMA:
- self.setDMA(data);
+ self.setDMA(data)
elif address == BGP:
- self.setBackgroundPalette(data);
+ self.setBackgroundPalette(data)
elif address == OBP0:
- self.setObjectPalette0(data);
+ self.setObjectPalette0(data)
elif address == OBP1:
- self.setObjectPalette1(data);
+ self.setObjectPalette1(data)
elif address == WY:
- self.setWindowY(data);
+ self.setWindowY(data)
elif address == WX:
- self.setWindowX(data);
+ self.setWindowX(data)
else:
if (address >= OAM_ADDR and address < OAM_ADDR + OAM_SIZE):
#TODO convert to byte
- self.oam[address - OAM_ADDR] = data;
+ self.oam[address - OAM_ADDR] = data
elif (address >= VRAM_ADDR and address < VRAM_ADDR + VRAM_SIZE):
#TODO convert to byte
- self.vram[address - VRAM_ADDR] =data;
+ self.vram[address - VRAM_ADDR] =data
def read(self, address):
if address == LCDC:
- return self.getControl();
+ return self.getControl()
elif address == STAT:
- return self.getStatus();
+ return self.getStatus()
elif address == SCY:
- return self.getScrollY();
+ return self.getScrollY()
elif address == SCX:
- return self.getScrollX();
+ return self.getScrollX()
elif address == LY:
- return self.getLineY();
+ return self.getLineY()
elif address == LYC:
- return self.getLineYCompare();
+ return self.getLineYCompare()
elif address == DMA:
- return self.getDMA();
+ return self.getDMA()
elif address == BGP:
- return self.getBackgroundPalette();
+ return self.getBackgroundPalette()
elif address == OBP0:
- return self.getObjectPalette0();
+ return self.getObjectPalette0()
elif address == OBP1:
- return self.getObjectPalette1();
+ return self.getObjectPalette1()
elif address == WY:
- return self.getWindowY();
+ return self.getWindowY()
elif address == WX:
- return self.getWindowX();
+ return self.getWindowX()
else:
if (address >= OAM_ADDR and address < OAM_ADDR + OAM_SIZE):
- return self.oam[address - OAM_ADDR] & 0xFF;
+ return self.oam[address - OAM_ADDR] & 0xFF
elif (address >= VRAM_ADDR and address < VRAM_ADDR + VRAM_SIZE):
- return self.vram[address - VRAM_ADDR] & 0xFF;
- return 0xFF;
+ return self.vram[address - VRAM_ADDR] & 0xFF
+ return 0xFF
def cycles(self):
- return self.cycles;
+ return self.cycles
def emulate(self, ticks):
if ((self.lcdc & 0x80) != 0):
- self.cycles -= ticks;
+ self.cycles -= ticks
while (self.cycles <= 0):
switch = self.stat & 0x03
if switch == 0:
- self.emulateHBlank();
+ self.emulateHBlank()
elif switch == 1:
- self.emulateVBlank();
+ self.emulateVBlank()
elif switch == 2:
- self.emulateOAM();
+ self.emulateOAM()
elif switch == 3:
- self.emulateTransfer();
+ self.emulateTransfer()
def getControl(self):
- return self.lcdc;
+ return self.lcdc
def getStatus(self):
- return 0x80 | self.stat;
+ return 0x80 | self.stat
def getScrollY(self):
- return self.scy;
+ return self.scy
def getScrollX(self):
- return self.scx;
+ return self.scx
def getLineY(self):
- return self.ly;
+ return self.ly
def getLineYCompare(self):
- return self.lyc;
+ return self.lyc
def getDMA(self):
- return self.dma;
+ return self.dma
def getBackgroundPalette(self):
- return self.bgp;
+ return self.bgp
def getObjectPalette0(self):
- return self.obp0;
+ return self.obp0
def getObjectPalette1(self):
- return self.obp1;
+ return self.obp1
+
def getWindowY(self):
- return self.wy;
+ return self.wy
+
def getWindowX(self):
- return self.wx;
+ return self.wx
+
def setControl(self, data):
if ((self.lcdc & 0x80) != (data & 0x80)):
# NOTE: do not reset LY=LYC flag (bit 2) of the STAT register (Mr.
# Do!)
if ((data & 0x80) != 0):
- self.stat = (self.stat & 0xFC) | 0x02;
- self.cycles = MODE_2_TICKS;
- self.ly = 0;
-
- self.display = false;
+ self.stat = (self.stat & 0xFC) | 0x02
+ self.cycles = MODE_2_TICKS
+ self.ly = 0
+ self.display = False
else:
- self.stat = (self.stat & 0xFC) | 0x00;
- self.cycles = MODE_1_TICKS;
- self.ly = 0;
+ self.stat = (self.stat & 0xFC) | 0x00
+ self.cycles = MODE_1_TICKS
+ self.ly = 0
- self.clearFrame();
+ 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.wly = 144
- self.lcdc = data;
+ self.lcdc = data
def setStatus(self, data):
- self.stat = (self.stat & 0x87) | (data & 0x78);
-
+ 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(Interrupt.LCD);
+ self.interrupt.raiseInterrupt(Interrupt.LCD)
def setScrollY(self, data):
- self.scy = data;
+ self.scy = data
def setScrollX(self, data):
- self.scx = data;
+ self.scx = data
def setLYCompare(self, data):
- self.lyc = data;
+ self.lyc = data
if ((self.lcdc & 0x80) != 0):
if (self.ly == self.lyc):
# NOTE: raise interrupt once per line (Prehistorik Man, The
# Jetsons, Muhammad Ali)
if ((self.stat & 0x04) == 0):
# LYC=LY interrupt
- self.stat |= 0x04;
-
+ self.stat |= 0x04
if ((self.stat & 0x40) != 0):
- self.interrupt.raiseInterrupt(Interrupt.LCD);
+ self.interrupt.raiseInterrupt(Interrupt.LCD)
else:
- self.stat &= 0xFB;
+ self.stat &= 0xFB
def setDMA(self, data):
- self.dma = data;
+ self.dma = data
for index in range(0, OAM_SIZE):
#TODO convert to byte
- self.oam[index] = self.memory.read((self.dma << 8) + index);
+ self.oam[index] = self.memory.read((self.dma << 8) + index)
def setBackgroundPalette(self, data):
if (self.bgp != data):
- self.bgp = data;
- self.dirty = true;
+ self.bgp = data
+ self.dirty = True
def setObjectPalette0(self, data):
if (self.obp0 != data):
- self.obp0 = data;
- self.dirty = true;
+ self.obp0 = data
+ self.dirty = True
def setObjectPalette1(self, data):
if (self.obp1 != data):
- self.obp1 = data;
- self.dirty = true;
+ self.obp1 = data
+ self.dirty = True
def setWindowY(self, data):
- self.wy = data;
+ self.wy = data
def setWindowX(self, data):
- self.wx = data;
+ self.wx = data
def emulateOAM(self):
- self.stat = (self.stat & 0xFC) | 0x03;
- self.cycles += MODE_3_BEGIN_TICKS;
- self.transfer = true;
+ self.stat = (self.stat & 0xFC) | 0x03
+ self.cycles += 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 += MODE_3_END_TICKS;
- self.transfer = false;
+ self.drawLine()
+ self.stat = (self.stat & 0xFC) | 0x03
+ self.cycles += MODE_3_END_TICKS
+ self.transfer = False
else:
- self.stat = (self.stat & 0xFC) | 0x00;
- self.cycles += MODE_0_TICKS;
+ self.stat = (self.stat & 0xFC) | 0x00
+ self.cycles += MODE_0_TICKS
# H-Blank interrupt
if ((self.stat & 0x08) != 0 and (self.stat & 0x44) != 0x44):
- self.interrupt.raiseInterrupt(Interrupt.LCD);
+ self.interrupt.raiseInterrupt(Interrupt.LCD)
def emulateHBlank(self):
- self.ly+=1;
-
+ self.ly+=1
if (self.ly == self.lyc):
# LYC=LY interrupt
- self.stat |= 0x04;
+ self.stat |= 0x04
if ((self.stat & 0x40) != 0):
- self.interrupt.raiseInterrupt(Interrupt.LCD);
+ self.interrupt.raiseInterrupt(Interrupt.LCD)
else:
- self.stat &= 0xFB;
+ self.stat &= 0xFB
+
if (self.ly < 144):
- self.stat = (self.stat & 0xFC) | 0x02;
- self.cycles += MODE_2_TICKS;
+ self.stat = (self.stat & 0xFC) | 0x02
+ self.cycles += MODE_2_TICKS
# OAM interrupt
if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44):
- self.interrupt.raiseInterrupt(Interrupt.LCD);
+ self.interrupt.raiseInterrupt(Interrupt.LCD)
else:
if (self.display):
- self.drawFrame();
+ self.drawFrame()
self.frames += 1
if (self.frames >= self.frameSkip):
- self.display = true;
- self.frames = 0;
+ self.display = True
+ self.frames = 0
else:
- self.display = false;
+ self.display = False
- self.stat = (self.stat & 0xFC) | 0x01;
- self.cycles += MODE_1_BEGIN_TICKS;
- self.vblank = true;
+ self.stat = (self.stat & 0xFC) | 0x01
+ self.cycles += MODE_1_BEGIN_TICKS
+ self.vblank = True
def emulateVBlank(self):
if (self.vblank):
- self.vblank = false;
+ self.vblank = False
- self.stat = (self.stat & 0xFC) | 0x01;
- self.cycles += MODE_1_TICKS - MODE_1_BEGIN_TICKS;
+ self.stat = (self.stat & 0xFC) | 0x01
+ self.cycles += MODE_1_TICKS - MODE_1_BEGIN_TICKS
# V-Blank interrupt
if ((self.stat & 0x10) != 0):
- self.interrupt.raiseInterrupt(Interrupt.LCD);
+ self.interrupt.raiseInterrupt(Interrupt.LCD)
# V-Blank interrupt
- self.interrupt.raiseInterrupt(Interrupt.VBLANK);
+ self.interrupt.raiseInterrupt(Interrupt.VBLANK)
elif (self.ly == 0):
- self.stat = (self.stat & 0xFC) | 0x02;
- self.cycles += MODE_2_TICKS;
+ self.stat = (self.stat & 0xFC) | 0x02
+ self.cycles += MODE_2_TICKS
# OAM interrupt
if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44):
- self.interrupt.raiseInterrupt(Interrupt.LCD);
+ self.interrupt.raiseInterrupt(Interrupt.LCD)
else:
if (self.ly < 153):
- self.ly+=1;
- self.stat = (self.stat & 0xFC) | 0x01;
+ self.ly+=1
+ self.stat = (self.stat & 0xFC) | 0x01
if (self.ly == 153):
- self.cycles += MODE_1_END_TICKS;
+ self.cycles += MODE_1_END_TICKS
else:
- self.cycles += MODE_1_TICKS;
+ self.cycles += MODE_1_TICKS
else:
- self.ly = self.wly = 0;
- self.stat = (self.stat & 0xFC) | 0x01;
- self.cycles += MODE_1_TICKS - MODE_1_END_TICKS;
+ self.ly = self.wly = 0
+ self.stat = (self.stat & 0xFC) | 0x01
+ self.cycles += MODE_1_TICKS - MODE_1_END_TICKS
if (self.ly == self.lyc):
# LYC=LY interrupt
- self.stat |= 0x04;
+ self.stat |= 0x04
if ((self.stat & 0x40) != 0):
- self.interrupt.raiseInterrupt(Interrupt.LCD);
+ self.interrupt.raiseInterrupt(Interrupt.LCD)
else:
- self.stat &= 0xFB;
+ self.stat &= 0xFB
def drawFrame(self):
- self.driver.display();
+ self.driver.display()
def clearFrame(self):
- self.clearPixels();
- self.driver.display();
+ self.clearPixels()
+ self.driver.display()
def drawLine(self):
if ((self.lcdc & 0x01) != 0):
- self.drawBackground();
+ self.drawBackground()
else:
- self.drawCleanBackground();
-
+ self.drawCleanBackground()
if ((self.lcdc & 0x20) != 0):
- self.drawWindow();
+ self.drawWindow()
if ((self.lcdc & 0x02) != 0):
- self.drawObjects();
- self.drawPixels();
+ self.drawObjects()
+ self.drawPixels()
def drawCleanBackground(self):
for x in range(0, 8+160+8):
- self.line[x] = 0x00;
+ self.line[x] = 0x00
def drawBackground(self):
- y = (self.scy + self.ly) & 0xFF;
- x = self.scx & 0xFF;
+ y = (self.scy + self.ly) & 0xFF
+ x = self.scx & 0xFF
tileMap = VRAM_MAP_A
if (self.lcdc & 0x08) != 0:
@@ -512,9 +509,9 @@
if (self.lcdc & 0x10) != 0:
tileData = VRAM_DATA_A
- tileMap += ((y >> 3) << 5) + (x >> 3);
- tileData += (y & 7) << 1;
- self.drawTiles(8 - (x & 7), tileMap, tileData);
+ tileMap += ((y >> 3) << 5) + (x >> 3)
+ tileData += (y & 7) << 1
+ self.drawTiles(8 - (x & 7), tileMap, tileData)
def drawWindow(self):
@@ -526,266 +523,266 @@
if (self.lcdc & 0x10) != 0:
tileData = VRAM_DATA_A
- tileMap += (self.wly >> 3) << 5;
- tileData += (self.wly & 7) << 1;
+ tileMap += (self.wly >> 3) << 5
+ tileData += (self.wly & 7) << 1
- self.drawTiles(self.wx + 1, tileMap, tileData);
- self.wly+=1;
+ self.drawTiles(self.wx + 1, tileMap, tileData)
+ self.wly+=1
def drawObjects(self):
- count = self.scanObjects();
+ 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;
+ data = self.objects[index]
+ x = (data >> 24) & 0xFF
+ flags = (data >> 12) & 0xFF
+ address = data & 0xFFF
if (x + 8 <= lastx):
- self.drawObjectTile(x, address, flags);
+ self.drawObjectTile(x, address, flags)
else:
- self.drawOverlappedObjectTile(x, address, flags);
- lastx = x;
+ self.drawOverlappedObjectTile(x, address, flags)
+ lastx = x
def scanObjects(self):
- count = 0;
+ 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;
+ 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;
+ continue
+ tile = self.oam[offset + 2] & 0xFF
+ flags = self.oam[offset + 3] & 0xFF
- y = self.ly - y + 16;
+ y = self.ly - y + 16
if ((self.lcdc & 0x04) != 0):
# 8x16 tile size
if (y < 0 or y > 15):
- continue;
+ continue
# Y flip
if ((flags & 0x40) != 0):
- y = 15 - y;
- tile &= 0xFE;
+ y = 15 - y
+ tile &= 0xFE
else:
# 8x8 tile size
if (y < 0 or y > 7):
- continue;
+ continue
# Y flip
if ((flags & 0x40) != 0):
- y = 7 - y;
- self.objects[count] = (x << 24) + (count << 20) + (flags << 12) + ((tile << 4) + (y << 1));
+ y = 7 - y
+ self.objects[count] = (x << 24) + (count << 20) + (flags << 12) + ((tile << 4) + (y << 1))
if (++count >= OBJECTS_PER_LINE):
- break;
+ 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;
+ rightmost = index
for number in range(index+1, count):
if ((self.objects[number] >> 20) > (self.objects[rightmost] >> 20)):
- rightmost = number;
-
+ rightmost = number
if (rightmost != index):
- data = self.objects[index];
- self.objects[index] = self.objects[rightmost];
- self.objects[rightmost] = data;
- return count;
+ 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;
+ 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;
+ 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;
+ 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;
+ pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8)
+ mask = 0
# priority
if (flags & 0x80) != 0:
- mask |= 0x0008;
+ mask |= 0x0008
# palette
if (flags & 0x10) != 0:
- mask |= 0x0004;
+ mask |= 0x0004
# X flip
if (flags & 0x20) != 0:
color = (pattern << 1)
if ((color & 0x0202) != 0):
- self.line[x + 0] |= color | mask;
+ self.line[x + 0] |= color | mask
color = (pattern >> 0)
if ((color & 0x0202) != 0):
- self.line[x + 1] |= color | mask;
+ self.line[x + 1] |= color | mask
color = (pattern >> 1)
if ((color & 0x0202) != 0):
- self.line[x + 2] |= color | mask;
+ self.line[x + 2] |= color | mask
color = (pattern >> 2)
if ((color & 0x0202) != 0):
- self.line[x + 3] |= color | mask;
+ self.line[x + 3] |= color | mask
color = (pattern >> 3)
if ((color & 0x0202) != 0):
- self.line[x + 4] |= color | mask;
+ self.line[x + 4] |= color | mask
color = (pattern >> 4)
if ((color & 0x0202) != 0):
- self.line[x + 5] |= color | mask;
+ self.line[x + 5] |= color | mask
color = (pattern >> 5)
if ((color & 0x0202) != 0):
- self.line[x + 6] |= color | mask;
+ self.line[x + 6] |= color | mask
color = (pattern >> 6)
if ((color & 0x0202) != 0):
- self.line[x + 7] |= color | mask;
+ self.line[x + 7] |= color | mask
else:
color = (pattern >> 6)
if ((color & 0x0202) != 0):
- self.line[x + 0] |= color | mask;
+ self.line[x + 0] |= color | mask
color = (pattern >> 5)
if ((color & 0x0202) != 0):
- self.line[x + 1] |= color | mask;
+ self.line[x + 1] |= color | mask
color = (pattern >> 4)
if ((color & 0x0202) != 0):
- self.line[x + 2] |= color | mask;
+ self.line[x + 2] |= color | mask
color = (pattern >> 3)
if ((color & 0x0202) != 0):
- self.line[x + 3] |= color | mask;
+ self.line[x + 3] |= color | mask
color = (pattern >> 2)
if ((color & 0x0202) != 0):
- self.line[x + 4] |= color | mask;
+ self.line[x + 4] |= color | mask
color = (pattern >> 1)
if ((color & 0x0202) != 0):
- self.line[x + 5] |= color | mask;
+ self.line[x + 5] |= color | mask
color = (pattern >> 0)
if ((color & 0x0202) != 0):
- self.line[x + 6] |= color | mask;
+ self.line[x + 6] |= color | mask
color = (pattern << 1)
if ((color & 0x0202) != 0):
- self.line[x + 7] |= color | mask;
+ 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;
+ pattern = (self.vram[address] & 0xFF) + ((self.vram[address + 1] & 0xFF) << 8)
+ mask = 0
# priority
if ((flags & 0x80) != 0):
- mask |= 0x0008;
+ mask |= 0x0008
# palette
if ((flags & 0x10) != 0):
- mask |= 0x0004;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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();
+ 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];
+ 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;
+ offset += 4
def clearPixels(self):
- pixels = self.driver.getPixels();
- length = self.driver.getWidth() * self.driver.getHeight();
+ pixels = self.driver.getPixels()
+ length = self.driver.getWidth() * self.driver.getHeight()
for offset in range(0, length):
- pixels[offset] = COLOR_MAP[0];
+ pixels[offset] = COLOR_MAP[0]
def updatePalette(self):
- if (self.dirty):
- # bit 4/0 = BG color, bit 5/1 = OBJ color, bit 2 = OBJ palette, bit
- # 3 = OBJ priority
- for pattern in range(0, 64):
- #color;
-
- if ((pattern & 0x22) == 0 or ((pattern & 0x08) != 0 and (pattern & 0x11) != 0)):
- # OBJ behind BG color 1-3
- color = (self.bgp >> ((((pattern >> 3) & 0x02) + (pattern & 0x01)) << 1)) & 0x03;
- # OBJ above 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)] = COLOR_MAP[color];
+ if (not self.dirty):
+ return
+ # bit 4/0 = BG color, bit 5/1 = OBJ color, bit 2 = OBJ palette, bit
+ # 3 = OBJ priority
+ for pattern in range(0, 64):
+ #color
+ if ((pattern & 0x22) == 0 or ((pattern & 0x08) != 0 and (pattern & 0x11) != 0)):
+ # OBJ behind BG color 1-3
+ color = (self.bgp >> ((((pattern >> 3) & 0x02) + (pattern & 0x01)) << 1)) & 0x03
+ # OBJ above 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.dirty = false;
+ self.palette[((pattern & 0x30) << 4) + (pattern & 0x0F)] = COLOR_MAP[color]
+ self.dirty = False
More information about the Pypy-commit
mailing list