import System.IO
import System.Environment
import Data.Word
+import Data.Bits (shiftL, (.|.))
import qualified Data.ByteString as BS
import Z80.CPU
import ZXS.RAM
import ZXS.Decode
+data Program = Program
+ { prgSpectrum :: Spectrum
+ , prgAddr :: Word16
+ , prgLength :: Word16
+ }
+
whatevsRAM :: IO RAM
whatevsRAM = newRAM (0x0000, 0xffff)
, 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
| 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
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