OpcodeTest: Handle program load addresses master
authorLucian Mogosanu <lucian.mogosanu@gmail.com>
Wed, 24 Dec 2014 20:08:41 +0000 (22:08 +0200)
committerLucian Mogosanu <lucian.mogosanu@gmail.com>
Wed, 24 Dec 2014 20:08:41 +0000 (22:08 +0200)
src/OpcodeTest.hs

index f892b4e..905dab1 100644 (file)
@@ -4,6 +4,7 @@ import Text.Printf
 import System.IO
 import System.Environment
 import Data.Word
+import Data.Bits (shiftL, (.|.))
 import qualified Data.ByteString as BS
 
 import Z80.CPU
@@ -12,6 +13,12 @@ import ZXS.Machine
 import ZXS.RAM
 import ZXS.Decode
 
+data Program = Program
+  { prgSpectrum :: Spectrum
+  , prgAddr     :: Word16
+  , prgLength   :: Word16
+  }
+
 whatevsRAM :: IO RAM
 whatevsRAM = newRAM (0x0000, 0xffff)
 
@@ -34,14 +41,23 @@ whatevsCPU = CPU
   , getPrefixed = Unprefixed
   }
 
-whatevsSpectrum :: BS.ByteString -> IO Spectrum
+whatevsSpectrum :: BS.ByteString -> IO Program
 whatevsSpectrum bs = do
   let header = BS.take 8 bs
-      code = BS.drop 8 bs
+      code = BS.drop 10 bs
+      addr = makeAddr . BS.unpack . BS.take 2 . BS.drop 8 $ bs
   if header /= BS.pack [ 0x5a, 0x38, 0x30, 0x41, 0x53, 0x4d, 0x1a, 0x0a ]
     then fail "Doesn't look like a Z80 file..."
-    else whatevsRAM >>= initRAM 0 bs -- code
-                    >>= \ ram -> return $ Spectrum whatevsCPU { getPC = 0 } ram
+    else whatevsRAM
+      >>= initRAM addr code
+      >>= \ ram -> return $ Program
+        { prgSpectrum = Spectrum whatevsCPU { getPC = addr } ram
+        , prgAddr     = addr
+        , prgLength   = fromIntegral $ BS.length code }
+  where
+  makeAddr ws = case ws of
+      [ wl, wh ]  -> fromIntegral wl .|. (fromIntegral wh `shiftL` 8)
+      _           -> error "whatevsSpectrum has a bug."
 
 initRAM :: Word16 -> BS.ByteString -> RAM -> IO RAM
 initRAM addr code ram
@@ -49,17 +65,16 @@ initRAM addr code ram
   | otherwise = ramSetByte ram addr (BS.head code)
              >> initRAM (addr + 1) (BS.tail code) ram
 
-parseZ80 :: Word16 -> ZXS [(Word16, [Word8], Instruction)]
+parseZ80 :: Word16 -> Word16 -> ZXS [(Word16, [Word8], Instruction)]
 parseZ80 = go []
-  where go acc n
-          | n == 0 = return $ reverse acc
+  where go acc addr addr'
+          | addr >= addr' = return $ reverse acc
           | otherwise = do
             pc <- getsCPU getPC
             i <- decode
             pc' <- getsCPU getPC
             ops <- getOpcodesBetween pc pc'
-            let d = pc' - pc
-            go ((pc, ops, i) : acc) (n - d)
+            go ((pc, ops, i) : acc) pc' addr'
         getOpcodesBetween pc pc'
           | pc == pc' = return []
           | otherwise = do
@@ -80,7 +95,6 @@ main = do
     then print "TODO: print usage"
     else do
       bs <- withFile (head args) ReadMode BS.hGetContents
-      let n = fromIntegral $ BS.length bs
-      s <- whatevsSpectrum bs
-      is <- evalZXST (parseZ80 n) s
+      Program s addr n <- whatevsSpectrum bs
+      is <- evalZXST (parseZ80 addr $ addr + n) s
       printInstrs is