Guest User

Frame-by-frame processing with openMSX (prototype)

a guest
Feb 28th, 2016
91
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python
  2.  
  3. from subprocess import Popen, PIPE, STDOUT
  4. import threading
  5. import time
  6. import os
  7.  
  8. class MSXClient:
  9.  
  10.     def __init__(self, rom_filename, machine='C-BIOS_MSX1'):
  11.         # open emulator as a pipe
  12.         self.pipe = Popen(['openmsx', '-control', 'stdio', '-machine', machine], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
  13.         # run stdout listener thread
  14.         self.finished = False
  15.         th = threading.Thread(target=self.stdout_listener)
  16.         th.start()
  17.         # send some init commands
  18.         self.command("cart %s" % rom_filename)
  19.         self.command("set power on")
  20.         self.command("set renderer SDL")
  21.         self.command("set scale_factor 1")
  22.         self.command("set pause on")
  23.         self.command("set throttle off")
  24.         self.command("reverse stop")
  25.         self.frame_num = 0
  26.         self.afters = {}
  27.  
  28.     def command(self, c, need_print=True):
  29.         """
  30.        Send a command to openMSX's stdin, print if needed.
  31.  
  32.        """
  33.         cmd = "<command>%s</command>\n" % c
  34.         self.pipe.stdin.write(cmd)
  35.         if need_print:
  36.             print cmd[:-1]
  37.  
  38.     def readline(self, need_print=False):
  39.         """
  40.        Read a line from openMSX's stdout, print if needed.
  41.        Also, detect if frame is complete (screen saved).
  42.  
  43.        """
  44.         out = self.pipe.stdout.readline().strip()
  45.         if out.find("Screen saved") >= 0 or out.find("frameisready") >= 0:
  46.             self.paused = True
  47.         if out.find("after#") >= 0:
  48.             after = out.split(">")[1].split("<")[0]
  49.             self.afters[after] = True
  50.         if need_print:
  51.             print out
  52.         return out
  53.        
  54.     def reset(self):
  55.         """
  56.        Shortcut to 'reset' command.
  57.        
  58.        """
  59.         self.command("reset")
  60.  
  61.     def shutdown(self):
  62.         """
  63.        Send 'exit' command to openMSX and wait until subprocess if finished.
  64.        
  65.        """
  66.         self.command("exit")
  67.         self.finished = True
  68.         self.pipe.communicate()
  69.  
  70.     def stdout_listener(self):
  71.         while not self.finished:
  72.             self.readline()
  73.  
  74.     def process_frame(self):
  75.         """
  76.        A frame is in ./screen.png now, process it here.
  77.  
  78.        """
  79.         pass
  80.    
  81.     def step(self):
  82.         """
  83.        Wait for the next frame and process it.
  84.        
  85.        """
  86.         self.paused = False
  87.         self.command("after frame \"set pause on; screenshot -raw ./screen.png\"")
  88.         #self.command("after frame \"set pause on; message frameisready\"")
  89.         self.command("set pause off")
  90.         while not self.paused:
  91.             time.sleep(0.001)
  92.         for after in self.afters.keys():
  93.             self.command("after cancel %s" % after)
  94.             del self.afters[after]
  95.         self.process_frame()
  96.    
  97. if __name__ == "__main__":
  98.     client = MSXClient("./roms/area5.rom")
  99.     for i in xrange(10000):
  100.         client.step()
  101.     client.shutdown()
RAW Paste Data