[pypy-svn] r63033 - in pypy/trunk/pypy/lang/gameboy: . test

cami at codespeak.net cami at codespeak.net
Wed Mar 18 15:07:45 CET 2009


Author: cami
Date: Wed Mar 18 15:07:43 2009
New Revision: 63033

Modified:
   pypy/trunk/pypy/lang/gameboy/cpu.py
   pypy/trunk/pypy/lang/gameboy/cpu_register.py
   pypy/trunk/pypy/lang/gameboy/gameboy.py
   pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py
   pypy/trunk/pypy/lang/gameboy/test/test_cpu.py
   pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py
Log:
optimizing registers


Modified: pypy/trunk/pypy/lang/gameboy/cpu.py
==============================================================================
--- pypy/trunk/pypy/lang/gameboy/cpu.py	(original)
+++ pypy/trunk/pypy/lang/gameboy/cpu.py	Wed Mar 18 15:07:43 2009
@@ -272,9 +272,8 @@
         self.double_register_inverse_call(CPUPopCaller(self), register)
         
     def double_register_inverse_call(self, getCaller, register):
-        b = getCaller.get() # 1 cycle
-        a = getCaller.get() # 1 cycle
-        register.set_hi_lo(a, b) # 2 cycles
+        register.set_lo(getCaller.get()) # 2 cycles
+        register.set_hi(getCaller.get()) # 2 cycles
         self.cycles += 1
         
     def call(self, address, use_cycles=True):
@@ -694,9 +693,8 @@
 
     def ret(self):
         # RET 4 cycles
-        lo = self.pop() # 1 cycle
-        hi = self.pop() # 1 cycle
-        self.pc.set_hi_lo(hi, lo) # 2 cycles
+        self.pop_double_register(self.pc)
+        self.cycles -= 1
 
     def conditional_return(self, cc):
         # RET cc 2,5 cycles

Modified: pypy/trunk/pypy/lang/gameboy/cpu_register.py
==============================================================================
--- pypy/trunk/pypy/lang/gameboy/cpu_register.py	(original)
+++ pypy/trunk/pypy/lang/gameboy/cpu_register.py	Wed Mar 18 15:07:43 2009
@@ -1,51 +1,103 @@
 # ---------------------------------------------------------------------------
 
 class AbstractRegister(object):
+    def __init__(self):
+        self.invalid = False
+        
     def get(self, use_cycles=True):
-        return 0xFF
+        self.check_sync()
+        return self._get(use_cycles)   
+         
+    def set(self, value, use_cycles=True):
+        self.check_sync()
+        self.invalidate_other()
+        self._set(value, use_cycles)
+        
+    def sub(self, value, use_cycles=True):
+        self.check_sync()
+        self.invalidate_other()
+        return self._sub(value, use_cycles)
+        
+    def add(self, value, use_cycles=True):
+        self.check_sync()
+        self.invalidate_other()
+        return self._add(value, use_cycles)
+        
+    def _get(self, use_cycles):
+        raise Exception("not implemented")
+    
+    def _set(self, value, use_cycles):
+        raise Exception("not implemented")
+        
+    def _sub(self, value, use_cycles):
+        raise Exception("not implemented")
+        
+    def _add(self, value, use_cycles):
+        raise Exception("not implemented")
+        
+    def check_sync(self):
+        if self.invalid:
+            self.sync()
+    
+    def invalidate_other(self):
+        raise Exception("not implemented")
+            
+    def sync(self):
+        raise Exception("not implemented")
+        
 
 class Register(AbstractRegister):
     
     def __init__(self, cpu, value=0x00):
+        AbstractRegister.__init__(self)
        # assert isinstance(cpu, CPU)
         self.reset_value = self.value = value
+        self.double_register = None
         self.cpu = cpu
         if value != 0:
-            self.set(value)
+            self._set(value)
         
     def reset(self):
         self.value = self.reset_value
         
-    def set(self, value, use_cycles=True):
+    def sync(self):
+        if self.double_register is not None:
+            self.double_register.sync_registers()
+    
+    def invalidate_other(self):
+        if self.double_register is not None:
+            self.double_register.invalid = True
+    
+    def _set(self, value, use_cycles=True):
         self.value = value & 0xFF
         if use_cycles:
             self.cpu.cycles -= 1
         
-    def get(self, use_cycles=True):
+    def _get(self, use_cycles=True):
         return self.value
     
-    def add(self, value, use_cycles=True):
-        self.set(self.get(use_cycles)+value, use_cycles)
+    def _add(self, value, use_cycles=True):
+        self._set(self._get(use_cycles) + value, use_cycles)
         
-    def sub(self, value, use_cycles=True):
-        self.set(self.get(use_cycles)-value, use_cycles)
+    def _sub(self, value, use_cycles=True):
+        self._set(self._get(use_cycles) - value, use_cycles)
     
 #------------------------------------------------------------------------------
 
 class AbstractDoubleRegister(AbstractRegister):
     
     def __init__(self, cpu, reset_value=0):
+        AbstractRegister.__init__(self)
+        self.invalid = True
         self.cpu = cpu
         self.reset_value = reset_value
-        
-    def set(self, value, use_cycles=True):
-        # 1 Cycle
-        raise Exception("Not Implemented")
     
-    def set_hi_lo(self, hi, lo, use_cycles=True):
-        # 2 Cycles
+    def sync_registers(self):
         raise Exception("Not Implemented")
-            
+        
+    def sync(self):
+        raise Exception("Not Implemented")
+           
     def reset(self):
         self.set(self.reset_value, use_cycles=False)
             
@@ -57,10 +109,6 @@
         # 1 Cycle
         raise Exception("Not Implemented")
         
-    def get(self, use_cycles=True):
-        # 0 Cycles TODO: Check entanglement of cycles in CPU class.
-        raise Exception("Not Implemented")
-    
     def get_hi(self, use_cycles=True):
         # 0 Cycles
         raise Exception("Not Implemented")
@@ -79,8 +127,8 @@
         if use_cycles:
             self.cpu.cycles += 1
         
-    def add(self, value, use_cycles=True):
-        self.set(self.get(use_cycles) + value, use_cycles=use_cycles)
+    def _add(self, value, use_cycles=True):
+        self._set(self._get(use_cycles) + value, use_cycles=use_cycles)
         if use_cycles:
             self.cpu.cycles -= 2
 
@@ -90,18 +138,30 @@
     def __init__(self, cpu, hi, lo, reset_value=0):
         AbstractDoubleRegister.__init__(self, cpu, reset_value)
         self.hi = hi
+        self.hi.double_register = self
         self.lo = lo
+        self.lo.double_register = self
+        self.value = 0x0000
+    
+    def sync_registers(self):
+        self.hi._set(self.value >> 8, use_cycles=False)            
+        self.hi.invalid = False
+        self.lo._set(self.value & 0xFF, use_cycles=False)          
+        self.lo.invalid = False
+        
+    def sync(self):
+        self.value = (self.hi._get(use_cycles=False)<<8) + \
+                      self.lo._get(use_cycles=False)
+        self.invalid = False
+
+    def invalidate_other(self):
+        self.hi.invalid = True
+        self.lo.invalid = True
         
-    def set(self, value, use_cycles=True):
-        value  = value & 0xFFFF
-        self.set_hi(value >> 8, use_cycles)
-        self.set_lo(value & 0xFF, use_cycles)
+    def _set(self, value, use_cycles=True):
+        self.value  = value & 0xFFFF
         if use_cycles:
-            self.cpu.cycles += 1
-    
-    def set_hi_lo(self, hi, lo, use_cycles=True):
-        self.set_hi(hi, use_cycles)
-        self.set_lo(lo, use_cycles)
+            self.cpu.cycles -= 1
             
     def set_hi(self, hi=0, use_cycles=True):
         self.hi.set(hi, use_cycles)
@@ -109,8 +169,8 @@
     def set_lo(self, lo=0, use_cycles=True):
         self.lo.set(lo, use_cycles)
         
-    def get(self, use_cycles=True):
-        return (self.hi.get(use_cycles)<<8) + self.lo.get(use_cycles)
+    def _get(self, use_cycles=True):
+        return self.value
     
     def get_hi(self, use_cycles=True):
         return self.hi.get(use_cycles)
@@ -157,14 +217,12 @@
         return (self.value & 0xFF)
 
     def inc(self, use_cycles=True):
-        self.value += 1
-        self.value &= 0xFFFF
+        self.add(1, use_cycles=False)
         if use_cycles:
             self.cpu.cycles -= 2
 
     def dec(self, use_cycles=True):
-        self.value -= 1
-        self.value &= 0xFFFF
+        self.add(-1, use_cycles=False)
         if use_cycles:
             self.cpu.cycles -= 2
 
@@ -233,8 +291,8 @@
     (which do not affect C-flag).    
     """
     def __init__(self, cpu, reset_value):
+        Register.__init__(self, cpu)
         #assert isinstance(cpu, CPU)
-        self.cpu         = cpu
         self.reset_value = reset_value
         self.reset()
          
@@ -264,7 +322,7 @@
             self.s_flag = False
         self.lower = 0x00
             
-    def get(self, use_cycles=True):
+    def _get(self, use_cycles=True):
         value  = 0
         value += (int(self.is_carry)        << 4)
         value += (int(self.is_half_carry)   << 5)
@@ -272,7 +330,7 @@
         value += (int(self.is_zero)         << 7)
         return value + self.lower
             
-    def set(self, value, use_cycles=True):
+    def _set(self, value, use_cycles=True):
         self.is_carry       = bool(value & (1 << 4))
         self.is_half_carry  = bool(value & (1 << 5))
         self.is_subtraction = bool(value & (1 << 6))

Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py
==============================================================================
--- pypy/trunk/pypy/lang/gameboy/gameboy.py	(original)
+++ pypy/trunk/pypy/lang/gameboy/gameboy.py	Wed Mar 18 15:07:43 2009
@@ -38,8 +38,8 @@
         self.timer     = Timer(self.interrupt)
         self.joypad    = Joypad(self.joypad_driver, self.interrupt)
         self.video     = Video(self.video_driver, self.interrupt, self)
-        self.sound    = Sound(self.sound_driver)  
-        #self.sound     = BogusSound()
+        #self.sound    = Sound(self.sound_driver)  
+        self.sound     = BogusSound()
         
     def get_cartridge_manager(self):
         return self.cartridge_manager

Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py
==============================================================================
--- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py	(original)
+++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py	Wed Mar 18 15:07:43 2009
@@ -12,10 +12,10 @@
 from pypy.lang.gameboy import constants
 import time
 
-show_metadata = False # Extends the window with windows visualizing meta-data
+show_metadata = True # Extends the window with windows visualizing meta-data
 
 if constants.USE_RSDL:
-    from pypy.rlib.rsdl import RSDL, RSDL_helper, RMix
+    from pypy.rlib.rsdl import RSDL, RSDL_helper #, RMix
     from pypy.rpython.lltypesystem import lltype, rffi
     delay = RSDL.Delay
     get_ticks = RSDL.GetTicks
@@ -260,18 +260,20 @@
         SoundDriver.__init__(self)
         self.enabled       = False
         self.sampleRate    = 44100
-        self.chunksize     = 1024
+        self.buffersize    = 512
         self.channelCount  = 2
         self.bitsPerSample = 4
+        self.sampleSize    = self.bitsPerSample * self.channelCount
         self.create_sound_driver()
 
     def create_sound_driver(self):
-        if RMix.OpenAudio(self.sampleRate, RSDL.AUDIO_U8, 
-                          self.channelCount, self.chunksize) != 0:
-            error = rffi.charp2str(RSDL.GetError())
-            raise Exception(error)
-        else:
-            self.enabled = True
+        #if RMix.OpenAudio(self.sampleRate, RSDL.AUDIO_U8, 
+        #                  self.channelCount, self.chunksize) != 0:
+        #    error = rffi.charp2str(RSDL.GetError())
+        #    raise Exception(error)
+        #else:
+        #    self.enabled = True
+        pass
     
     def start(self):
         pass

Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu.py
==============================================================================
--- pypy/trunk/pypy/lang/gameboy/test/test_cpu.py	(original)
+++ pypy/trunk/pypy/lang/gameboy/test/test_cpu.py	Wed Mar 18 15:07:43 2009
@@ -431,7 +431,8 @@
 # ld_BCi_A
 def test_0x02():
     cpu = get_cpu();
-    cpu.bc.set_hi_lo(0xC2, 0x23);
+    cpu.bc.set_hi(0xC2)
+    cpu.bc.set_lo(0x23);
     cpu.a.set(0x12);
     cycle_test(cpu, 0x02, 2);
     assert cpu.read(cpu.bc.get()) == cpu.a.get()
@@ -451,7 +452,8 @@
 # ld_DEi_A
 def test_0x12():
     cpu = get_cpu();
-    cpu.de.set_hi_lo(0xC2, 0x23);
+    cpu.de.set_hi(0xC2)
+    cpu.de.set_lo(0x23);
     cpu.a.set(0x12);
     cycle_test(cpu, 0x12, 2);
     assert cpu.read(cpu.de.get()) == cpu.a.get()
@@ -470,7 +472,8 @@
 # ldi_HLi_A
 def test_0x22():
     cpu = get_cpu();
-    cpu.hl.set_hi_lo(0xCD, 0xEF);
+    cpu.hl.set_hi(0xCD)
+    cpu.hl.set_lo(0xEF);
     cpu.a.set(0x12);
     cycle_test(cpu, 0x22, 2);
     assert cpu.read(0xCDEF) == cpu.a.get()
@@ -479,7 +482,8 @@
 # ldd_HLi_A
 def test_0x32():
     cpu = get_cpu();
-    cpu.hl.set_hi_lo(0xCD, 0xEF);
+    cpu.hl.set_hi(0xCD)
+    cpu.hl.set_lo(0xEF);
     cpu.a.set(0x12);
     cycle_test(cpu, 0x32, 2);
     assert cpu.read(0xCDEF) == cpu.a.get()

Modified: pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py
==============================================================================
--- pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py	(original)
+++ pypy/trunk/pypy/lang/gameboy/test/test_cpu_register.py	Wed Mar 18 15:07:43 2009
@@ -26,9 +26,14 @@
         TEST_CPU = get_cpu(True)
     TEST_CPU.reset()
     return TEST_CPU
+    
+def get_double_register():
+    cpu = get_cpu()
+    return DoubleRegister(cpu, Register(cpu), Register(cpu))
 
 # ------------------------------------------------------------
 # TEST REGISTER
+
 def test_register_constructor():
     register = Register(get_cpu())
     assert register.get() == 0
@@ -103,7 +108,8 @@
     valueHi = 0x12
     valueLo = 0x34
     oldCycles = register.cpu.cycles
-    register.set_hi_lo(valueHi, valueLo)
+    register.set_hi(valueHi)
+    register.set_lo(valueLo)
     assert oldCycles-register.cpu.cycles == 2
     assert register.get_hi() == valueHi
     assert register.get_lo() == valueLo
@@ -207,7 +213,8 @@
     valueHi = 0x12
     valueLo = 0x34
     oldCycles = register.cpu.cycles
-    register.set_hi_lo(valueHi, valueLo)
+    register.set_hi(valueHi)
+    register.set_lo(valueLo)
     assert oldCycles-register.cpu.cycles == 2
     assert register.get_hi() == valueHi
     assert register.get_lo() == valueLo
@@ -265,4 +272,81 @@
     assert register.get() == value+1;
     register.reset()
     assert register.get() == value
+    
+# TEST REGISTER SYNCING -----------------------------------------------------
  
+def test_register_sync():
+    double_register = get_double_register()
+    assert double_register.invalid
+    assert not double_register.hi.invalid
+    assert not double_register.lo.invalid
+    return double_register
+    
+def test_register_sync_get():
+    double_register = test_register_sync()
+    
+    double_register.get()
+    
+    assert not double_register.invalid
+    assert not double_register.hi.invalid
+    assert not double_register.lo.invalid
+    
+    
+def test_register_sync_set():
+    double_register = test_register_sync()
+    
+    double_register.set(0xFFFF)
+    
+    assert not double_register.invalid
+    assert double_register.hi.invalid
+    assert double_register.lo.invalid
+    
+    return double_register
+    
+    
+def test_register_sync_set_get():
+    double_register = test_register_sync_set()
+    
+    assert double_register.get() == 0xFFFF
+    
+    assert not double_register.invalid
+    assert double_register.hi.invalid
+    assert double_register.lo.invalid
+    
+    
+def test_register_sync_set_get_hi():
+    double_register = test_register_sync_set()
+    
+    assert double_register.hi.get() == 0xFF
+    
+    assert not double_register.invalid
+    assert not double_register.hi.invalid
+    assert not double_register.lo.invalid
+ 
+  
+def test_register_sync_set_get_lo():
+    double_register = test_register_sync_set()
+    
+    assert double_register.lo.get() == 0xFF
+    
+    assert not double_register.invalid
+    assert not double_register.hi.invalid
+    assert not double_register.lo.invalid
+
+    
+def test_register_sync_set_hi():
+    double_register = test_register_sync()
+    double_register.hi.set(0x12)
+    
+    assert double_register.invalid
+    assert not double_register.hi.invalid
+    assert not double_register.lo.invalid
+         
+    
+def test_register_sync_set_lo():
+    double_register = test_register_sync()
+    double_register.lo.set(0x12)
+    
+    assert double_register.invalid
+    assert not double_register.hi.invalid
+    assert not double_register.lo.invalid
\ No newline at end of file



More information about the Pypy-commit mailing list