diff --git a/H264Decoder.py b/H264Decoder.py index c9f391a..7188cdf 100644 --- a/H264Decoder.py +++ b/H264Decoder.py @@ -81,7 +81,7 @@ def __init_avcodec(s): s.got_frame = s.ffi.new('int *') s.out_frame = s.ns.avcodec_alloc_frame() - def __init__(s, (in_x, in_y), (out_x, out_y), output_surface): + def __init__(s, (in_x, in_y), (out_x, out_y), output_surface=None): s.sws_context = None s.__init_ffi() s.__init_avcodec() @@ -142,7 +142,9 @@ def display_frame(s, encoded_nalu): (s.out_x, s.out_y), 'RGB') # I guess this is an extra copy...? - s.output_surface.blit(surface, (0, 0)) - # prev implementation just wrote out to the main display and did the flip: - # pygame.display.get_surface().blit(surface, (0, 0)) - # pygame.display.flip() + if s.output_surface: + s.output_surface.blit(surface, (0, 0)) + else: + # prev implementation just wrote out to the main display and did the flip: + pygame.display.get_surface().blit(surface, (0, 0)) + pygame.display.flip() diff --git a/InputData.py b/InputData.py index 5792092..eceb138 100644 --- a/InputData.py +++ b/InputData.py @@ -6,21 +6,30 @@ TODO tests """ from construct import ( - ULint8, - ULint16, - Array, - Struct, - BitStruct, - BitField, - Byte, - SLInt16, - Padding, - Rename - ) + ULInt8, + ULInt16, + SLInt16, + UBInt8, + UBInt16, + SBInt16, + Array, + Struct, + BitStruct, + BitField, + Byte, + Padding, + Rename, + Flag +) -u16 = ULint16 -s16 = SLInt16 -u8 = ULint8 +## turn on to make little-endian values +# u16 = ULInt16 +# s16 = SLInt16 +# u8 = ULInt8 + +u16 = UBInt16 +s16 = SBInt16 +u8 = UBInt8 AccelerometerData = Struct("AccelerometerData", s16("x_accel"), @@ -52,6 +61,24 @@ TouchscreenData = Struct("TouchscreenData", Array(10, Point)) +Buttons = BitStruct("Buttons", + Flag("a"), + Flag("b"), + Flag("x"), + Flag("y"), + Flag("left"), + Flag("right"), + Flag("up"), + Flag("down"), + Flag("zl"), + Flag("zr"), + Flag("l"), + Flag("r"), + Flag("plus"), + Flag("minus"), + Flag("home"), + Flag("sync"),) + # the real shebang InputData = Struct("InputData", u16("seq_id"), @@ -69,4 +96,4 @@ Array(4, Byte("unkown0")), u8("extra_buttons"), Array(46, Byte("unknown1")), - u8("fw_version_neg")) # ~fw_version + u8("fw_version_neg")) # u~fw_version diff --git a/app.py b/app.py index 0c44046..d4536c5 100644 --- a/app.py +++ b/app.py @@ -9,6 +9,8 @@ class ExitMain(StandardError): """ pass +SURFACE_OPTS = 0 # pygame.FULLSCREEN | pygame.HWSURFACE +SIZE = (854, 480) class App(object): """ @@ -18,7 +20,7 @@ class App(object): def __init__(self, title): pygame.init() pygame.display.set_caption(title) - pygame.display.set_mode((20, 20)) + pygame.display.set_mode((20, 20), SURFACE_OPTS) load_all_assets() asset_names = ASSET_DICT.keys() @@ -36,8 +38,8 @@ def __init__(self, title): if w > max_w: max_w = w screen = pygame.display.set_mode( - (BORDER_W + max_w + BORDER_W, - BORDER_H + max_h + BORDER_H) + SIZE, + SURFACE_OPTS ) log('calculated window size ({width}, {height}) from {count} assets'.format( diff --git a/controls/base.py b/controls/base.py index bd97b50..f723434 100644 --- a/controls/base.py +++ b/controls/base.py @@ -24,12 +24,36 @@ 'A': 0x8000 } -EXTRA_BOTTOMS = { - 'L3': 0x08, - 'R3': 0x04, +EXTRA_BUTTONS = { + 'R3': 0x40, + 'L3': 0x80, } +def inspect_mask(integer, bits=8, byte=8): + """ + print a value as a bits. printing in byte-sized blocks + + >>> bits(255) + '11111111' + + >>> bits(256) + '00000001 00000000' + """ + as_bin = bin(integer)[2:] + if len(as_bin) < bits: + missing_bits = bits - len(as_bin) + as_bin = '0' * missing_bits + as_bin + + return ' '.join(chunks(as_bin, byte)) + + +def chunks(l, n): + """Yield successive n-sized chunks from l.""" + for i in xrange(0, len(l), n): + yield l[i:i+n] + + def button_mask(controls): """ Given controls, a `Controls` instance, compute the bitmask of all pressed @@ -44,9 +68,11 @@ def button_mask(controls): def extra_button_mask(controls): mask = 0 - for button_name, button_mask in EXTRA_BOTTOMS.iteritems(): + for button_name, button_mask in EXTRA_BUTTONS.iteritems(): if controls.invoke(button_name.lower()): mask |= button_mask + #log('wow special button {b} clicked and invoked! new mask {m}'.format( + #b=button_name, m=mask), 'FUGGIN BUTTANS') return mask @@ -154,11 +180,21 @@ def accelerometer(self): def gyroscope(self): return (0, 0, 0) + """ + should return a tuple (x, y, force) of a touch location. + force should be a float between 0 and 1. + + return None if there is no touch. + """ + def touch(self): + return None + def handle_event(self, event): """ override if you wish to handle events with your controller - """ - pass + """ pass + + class MethodMissing(object): @@ -211,3 +247,17 @@ def scale(OldValue, OldMin, OldMax, NewMin, NewMax): def add(point_a, point_b): return (point_a[0] + point_b[0], point_a[1] + point_b[1]) + + +def wiiu_axis(orig): + """ + given a joystick axis motion, scale into Wii U space + """ + if abs(orig) < 0.0001: + # unsure why this starts as this value 0x800 + return 0x800 + return int(scale(orig, -1, 1, 900, 3200)) + +### +# TODO: move control value constructors to new file +### diff --git a/controls/keyboard.py b/controls/keyboard.py index 3a8e615..4cb9f05 100644 --- a/controls/keyboard.py +++ b/controls/keyboard.py @@ -43,7 +43,7 @@ def a(self): return self.key(K_h) or self.key(K_RETURN) def b(self): - return self.key(K_j) + return self.key(K_j) or self.key(K_BACKSPACE) def x(self): return self.key(K_k) or self.key(K_SPACE) @@ -83,14 +83,14 @@ def home(self): return False def minus(self): - return False + return self.key(K_MINUS) def plus(self): - return False + return self.key(K_EQUALS) # joystick presses def r3(self): - return False + return self.key(K_e) def l3(self): return False diff --git a/controls/mouse.py b/controls/mouse.py index 3b4e8e3..5655881 100644 --- a/controls/mouse.py +++ b/controls/mouse.py @@ -5,11 +5,14 @@ from util import log # TODO switch to absolute paths +JOYSTICK_MIN = 0.17 TOGGLE_LOCK_KEY = K_BACKQUOTE # lag high-magnitude movements another frame ENABLE_LAG = True -ENABLE_DOUBLE_LAG = True +ENABLE_DOUBLE_LAG = False MAX_MOVEMENT = 50.0 +LAG_WHEN_LESS_THAN = 0.1 +LAG_WHEN_GREATER_THAN = 0.8 def lag(final, prev): @@ -21,7 +24,10 @@ def lag(final, prev): # TO DO: switch joystick magnitude measuring to polar-coordiate vectors # and mreasure magnitude of both axes at once - if ENABLE_LAG and abs(prev) > 0.8 > abs(final): + if ENABLE_LAG and ( + abs(prev) > LAG_WHEN_GREATER_THAN + and abs(final) < LAG_WHEN_LESS_THAN): + # swap em. we'll play this frame again to smooth the falloff # and we get a bonus frame of high-magnitude movement log('lagged {prev} again instead of {final}'.format(prev=prev, final=final), 'MOUSE') @@ -55,9 +61,9 @@ def get(self): gets the joystick pairs """ dx, dy = pygame.mouse.get_rel() - if abs(dx) > 0 or abs(dy) > 0: - log("pygame mouse movement: ({dx}, {dy})".format(dx=dx, dy=dy), - 'MOUSE') + #if abs(dx) > 0 or abs(dy) > 0: + #log("pygame mouse movement: ({dx}, {dy})".format(dx=dx, dy=dy), + #'MOUSE') return (self.convert_x_axis(dx), self.convert_y_axis(dy)) @@ -92,7 +98,7 @@ def convert_axis(self, d): float(abs(d)), # value 0.0, # old min float(self.get_max()), # old max - 0.06, # new min -- escape deadzone + max(JOYSTICK_MIN, 0.0), # new min -- escape deadzone 1.0 # new max ) @@ -128,6 +134,9 @@ def handle_event(self, event): self.sensitivity += self.sensitivity_incr log('[+] set sensitivity to {s}, delta_max is {max} (lower = more sensitive)'.format(s=self.sensitivity, max=self.get_max()), 'MOUSE') + def is_locked(self): + return pygame.event.get_grab() + def lock(self): """ locks the mouse to the window, enabling accurate readings @@ -158,10 +167,13 @@ def handle_event(self, event): self.mouse.handle_event(event) def r(self): - return pygame.mouse.get_pressed()[2] + if self.mouse.is_locked(): + return pygame.mouse.get_pressed()[2] def zr(self): - return pygame.mouse.get_pressed()[0] + if self.mouse.is_locked(): + return pygame.mouse.get_pressed()[0] def r3(self): - return pygame.mouse.get_pressed()[1] + if self.mouse.is_locked(): + return pygame.mouse.get_pressed()[1] diff --git a/controls/wireless.py b/controls/wireless.py index 9fa5315..4ca8ec1 100644 --- a/controls/wireless.py +++ b/controls/wireless.py @@ -70,10 +70,11 @@ def a(self): # extra buttons - joystick presses def r3(self): - return False + return self.joy.get_button(10) def l3(self): - return False + return self.joy.get_button(9) + # the 'TV' button. Unsure of utility of implementing this. def tv(self): diff --git a/data_tester.py b/data_tester.py new file mode 100644 index 0000000..61affc8 --- /dev/null +++ b/data_tester.py @@ -0,0 +1,184 @@ +import array +from app import App +import InputData +from controls.mouse import KeyboardMouse +from controls.base import ( + Controls, button_mask, inspect_mask, BUTTONS, scale, + extra_button_mask, + wiiu_axis +) +from construct import ( + Container +) + + +def button_container(controls): + c = Container() + for button in BUTTONS.iterkeys(): + setattr(c, button.lower(), controls.invoke(button.lower())) + return c + + +def build_controls(controls): + return InputData.Buttons.build(button_container(controls)) + + +class DummyControls(Controls): + def a(self): + return True + + def zl(self): + return True + + def l(self): + return True + + +def int_of_bytes(bytestring): + return int(bytestring.encode('hex'), 16) + + +controller = DummyControls() + +reg = inspect_mask(button_mask(controller)) +newer = inspect_mask(int_of_bytes(build_controls(controller))) +print "{0} regular".format(reg) +print "{0} construct".format(newer) + + +def create_response(ctlr, seq_id=0): + report = array.array('H', '\0\0' * 0x40) + + # 16bit LE @ 0 seq_id + # seems to be ignored + report[0] = seq_id() + # 16bit @ 2 + button_bits = button_mask(ctlr) + + # save sticks around for rendering joystick fiddling + left_stick = ctlr.left_stick() + right_stick = ctlr.right_stick() + + # bada bing bada boom engineer sticks + l_horiz, l_vert = left_stick + r_horiz, r_vert = right_stick + report[3 + 0] = wiiu_axis(l_horiz) + report[3 + 1] = wiiu_axis(l_vert) + report[3 + 2] = wiiu_axis(r_horiz) + report[3 + 3] = wiiu_axis(r_vert) + + report[1] = (button_bits >> 8) | ((button_bits & 0xff) << 8) + + # 0 u16 seq_id; + # 1 u16 buttons; // see ButtonsMask + # 2 u8 power_status; // see PowerStatusMask + # u8 battery_charge; + # 3 u16 left_stick_x; + # 4 u16 left_stick_y; + # 5 u16 right_stick_x; + # 6 u16 right_stick_y; + # 7 u8 audio_volume; + # 7.5 AccelerometerData accelerometer; // FUCK (this is why looking into structs) + # GyroscopeData gyro; + # MagnetData magnet; + # TouchscreenData touchscreen; + # char unk0[4]; + # u8 extra_buttons; // see ExtraButtonsMask + # char unk1[46]; + # u8 fw_version_neg; // ~fw_version + + + # touchpanel crap @ 36 - 76 + byte_18 = 0 + byte_17 = 3 + byte_9b8 = 0 + byte_9fd = 6 + umi_fw_rev = 0x40 + byte_9fb = 0 + byte_19 = 2 + # TODO use controller for thisj + touch = ctlr.touch() + if touch is not None: + in_x, in_y = touch + x = int(scale(in_x, 0, 854, 200, 3800)) + y = int(scale(in_y, 0, 480, 200, 3800)) + z1 = 2000 + + for i in xrange(10): + report[18 + i * 2 + 0] = 0x80 | x + report[18 + i * 2 + 1] = 0x80 | y + + report[18 + 0 * 2 + 0] |= ((z1 >> 0) & 7) << 12 + report[18 + 0 * 2 + 1] |= ((z1 >> 3) & 7) << 12 + report[18 + 1 * 2 + 0] |= ((z1 >> 6) & 7) << 12 + report[18 + 1 * 2 + 1] |= ((z1 >> 9) & 7) << 12 + + report[18 + 3 * 2 + 1] |= ((byte_17 >> 0) & 7) << 12 + report[18 + 4 * 2 + 0] |= ((byte_17 >> 3) & 7) << 12 + report[18 + 4 * 2 + 1] |= ((byte_17 >> 6) & 3) << 12 + + report[18 + 5 * 2 + 0] |= ((byte_9fd >> 0) & 7) << 12 + report[18 + 5 * 2 + 1] |= ((byte_9fd >> 3) & 7) << 12 + report[18 + 6 * 2 + 0] |= ((byte_9fd >> 6) & 3) << 12 + + report[18 + 7 * 2 + 0] |= ((umi_fw_rev >> 4) & 7) << 12 + + # not my comment. spooky. + # TODO checkout what's up with | 4 + report[18 + 9 * 2 + 1] |= ((byte_19 & 2) | 4) << 12 + + # 8bit @ 80 + # i didn't want to move this up because I'm + # worried its location here is important. TODO + # think about it. + report[40] |= extra_button_mask(ctlr) + # log('report 40 = {n}'.format(n=report[40])) + + report[0x3f] = 0xe000 + return report + + +def accel_container(ctlr): + return Container( + x_accel=0, + y_accel=0, + z_accel=0) + + +def gyro_container(ctlr): + return Container( + roll=0, + yaw=0, + pitch=0, + ) + + +def touch_container(ctlr): + in_x, in_y = ctlr.touch() + x = int(scale(in_x, 0, 854, 200, 3800)) + y = int(scale(in_y, 0, 480, 200, 3800)) + raise NotImplementedError # got bored + + + +def controller_container(ctlr, seq_id): + l_x, l_y = ctlr.left_stick() + r_x, r_y, = ctlr.right_stick() + return Container( + seq_id=seq_id, + buttons=button_container(ctlr), + power_status=0, + left_stick_x=wiiu_axis(l_x), + left_stick_y=wiiu_axis(l_y), + right_stick_x=wiiu_axis(r_x), + right_stick_y=wiiu_axis(r_y), + audio_volume=0, + accelerometer=accel_container(ctlr), + gyro=gyro_container(ctlr), + magnet=None, + touchscreen=touch_container(ctlr), + unknown0=0, + extra_buttons=extra_buttons_container(ctlr), + unknown1=0, + fw_version_neg=0xe000 + ) diff --git a/drc-sim.py b/drc-sim.py index f6350f5..727b5dd 100644 --- a/drc-sim.py +++ b/drc-sim.py @@ -6,6 +6,8 @@ import pygame import time from H264Decoder import H264Decoder +from util import log +# from IPython.Shell import IPShellEmbed pygame.init() pygame.display.set_mode([854, 480], pygame.RESIZABLE) @@ -125,14 +127,14 @@ def update(s, packet): if h.packet_type == 0: seq_ok = s.update_seq_id(h.seq_id) if not seq_ok: - print 'astrm bad seq_id' + log('astrm bad seq_id') if h.fmt != 1 or h.channel != 0: raise Exception('astrm currently only handles 48kHz PCM stereo') if len(packet) != 8 + h.payload_size: raise Exception('astrm bad payload_size') if h.vibrate: - print '*vibrate*' + log('*vibrate*') s.pa_ring[s.pa_rpos] = array.array('H', packet[8:]) s.pa_rpos += 1 @@ -306,18 +308,18 @@ def cmd0_5_6(s, h, packet): s.send_response_cmd0(h, r) def cmd0(s, h, packet): - print 'CMD0:%i:%i' % (h.id_primary, h.id_secondary) + log('CMD0:%i:%i' % (h.id_primary, h.id_secondary)) if h.id_primary not in s.cmd0_handlers or h.id_secondary not in s.cmd0_handlers[h.id_primary]: - print 'unhandled', packet.encode('hex') + log('unhandled', packet.encode('hex')) return s.cmd0_handlers[h.id_primary][h.id_secondary](h, packet) def cmd1(s, h, packet): - print 'CMD1', packet[8:].encode('hex') + log('CMD1', packet[8:].encode('hex')) s.send_response(h, '\x00\x16\x00\x19\x9e\x00\x00\x00\x40\x00\x40\x00\x00\x00\x01\xff') def cmd2(s, h, packet): - print 'TIME base {:04x} seconds {:08x}'.format(h.JDN_base, h.seconds) + log('TIME base {:04x} seconds {:08x}'.format(h.JDN_base, h.seconds)) s.send_response(h) def ack(s, h): @@ -356,13 +358,13 @@ def update(s, packet): h = s.header.parse(packet) # don't track acks from the console for now if h.packet_type in (s.PT_REQ, s.PT_RESP): - #print 'CMD', packet.encode('hex') + #log('CMD', packet.encode('hex')) s.ack(h) s.cmd_handlers[h.cmd_id](h, packet) class ServiceMSG(ServiceBase): def update(s, packet): - print 'MSG', packet.encode('hex') + log('MSG', packet.encode('hex')) class ServiceNOP(ServiceBase): def update(s, packet): @@ -454,7 +456,7 @@ def scale_stick(OldValue, OldMin, OldMax, NewMin, NewMax): scaled = scale_stick(orig, -1, 1, 900, 3200) elif i in (1, 4): scaled = scale_stick(orig, 1, -1, 900, 3200) - #print '%04i %04i %f' % (i, scaled, orig) + #log('%04i %04i %f' % (i, scaled, orig)) stick_mapping = { 0 : 0, 1 : 1, 3 : 2, 4 : 3 } report[3 + stick_mapping[i]] = scaled report[1] = (button_bits >> 8) | ((button_bits & 0xff) << 8) @@ -473,7 +475,6 @@ def scale_stick(OldValue, OldMin, OldMax, NewMin, NewMax): x = scale_stick(point[0], 0, screen_x, 200, 3800) y = scale_stick(point[1], 0, screen_y, 200, 3800) z1 = 2000 - for i in xrange(10): report[18 + i * 2 + 0] = 0x80 | x report[18 + i * 2 + 1] = 0x80 | y @@ -501,12 +502,13 @@ def scale_stick(OldValue, OldMin, OldMax, NewMin, NewMax): # i didn't want to move this up because I'm # worried its location here is important. TODO # think about it. + # special extra buttons for i in xrange(9,11): if joystick.get_button(i): report[40] |= button_mapping[i] report[0x3f] = 0xe000 - #print report.tostring().encode('hex') + #log(report.tostring().encode('hex')) HID_S.sendto(report, ('192.168.1.10', PORT_HID)) hid_seq_id = hid_seq_id + 1 % 65534 # prevent overflow diff --git a/services.py b/services.py index 04af1c7..2a6e482 100644 --- a/services.py +++ b/services.py @@ -3,8 +3,16 @@ import socket import pyaudio import pygame -from util import log, GAMEPAD_DIM +from util import ( + log, + GAMEPAD_DIM, + ) +from H264Decoder import H264Decoder + +#def log(foo, name='bar'): + #pass +FALLBACK_IP = '127.0.0.1' def service_addend(ip): if int(ip.split('.')[3]) == 10: @@ -22,10 +30,10 @@ def udp_service(ip, port): log("couldn't bind {ip}:{port}".format(ip=ip, port=actual_port), "NETWORK") log("trying {ip}:{port} instead".format( - ip='0.0.0.0', + ip=FALLBACK_IP, port=actual_port), "NETWORK") - sock.bind(('0.0.0.0', actual_port)) + sock.bind((FALLBACK_IP, actual_port)) return sock PORT_MSG = 50010 @@ -53,8 +61,16 @@ def update_seq_id(s, seq_id): ret = True if s.seq_id_expect is None: s.seq_id_expect = seq_id - elif s.seq_id_expect != seq_id: + + if s.seq_id_expect != seq_id: + #log("[BAD] Got seq_id of " + str(seq_id) + ", expected " + str(s.seq_id_expect), + #s.__class__.__name__) ret = False + else: + pass + #log("[good :)] Got seq_id of " + str(seq_id) + ", expected " + str(s.seq_id_expect), + #s.__class__.__name__) + s.seq_id_expect = (seq_id + 1) & 0x3ff return ret @@ -140,7 +156,7 @@ def update(s, packet): if h.vibrate: # TODO: play a tone! :) - log('******* vibrate ********, ''ASTRM') + log('******* vibrate ********', 'ASTRM') s.pa_ring[s.pa_rpos] = array.array('H', packet[8:]) s.pa_rpos += 1 @@ -163,8 +179,9 @@ def update(s, packet): class ServiceVSTRM(ServiceBase): - def __init__(s, decoder): + def __init__(s, decoder, msg_socket=None): super(ServiceVSTRM, s).__init__() + s.MSG_S = msg_socket or MSG_S s.decoder = decoder s.header = construct.BitStruct('VSTRMHeader', construct.Nibble('magic'), @@ -249,7 +266,7 @@ def update(s, packet): s.is_streaming = True else: # request a new IDR frame - MSG_S.sendto('\1\0\0\0', ('192.168.1.10', PORT_MSG)) + s.MSG_S.sendto('\1\0\0\0', ('192.168.1.10', PORT_MSG)) return s.frame.fromstring(packet[16:]) @@ -323,12 +340,12 @@ def cmd0_5_6(s, h, packet): def cmd0(s, h, packet): log('CMD0:%i:%i' % (h.id_primary, h.id_secondary), 'CMD') if h.id_primary not in s.cmd0_handlers or h.id_secondary not in s.cmd0_handlers[h.id_primary]: - log('unhandled', packet.encode('hex'), 'CMD') + log('unhandled {packet}'.format(packet=packet.encode('hex')), 'CMD') return s.cmd0_handlers[h.id_primary][h.id_secondary](h, packet) def cmd1(s, h, packet): - log('CMD1', packet[8:].encode('hex'), 'CMD') + log('CMD1: {packet}'.format(packet=packet[8:].encode('hex')), 'CMD') s.send_response(h, '\x00\x16\x00\x19\x9e\x00\x00\x00\x40\x00\x40\x00\x00\x00\x01\xff') def cmd2(s, h, packet): diff --git a/simulator.py b/simulator.py index 03dce39..cda89b6 100644 --- a/simulator.py +++ b/simulator.py @@ -8,7 +8,7 @@ from H264Decoder import H264Decoder from app import App from controls.base import ( - button_mask, extra_button_mask, UnionController, scale + button_mask, extra_button_mask, UnionController, scale, wiiu_axis ) from controls.wireless import ProMap360 from controls.mouse import KeyboardMouse @@ -21,16 +21,6 @@ EVT_SEND_HID = pygame.USEREVENT -def wiiu_axis(orig): - """ - given a joystick axis motion, scale into Wii U space - """ - if abs(orig) < 0.0001: - # unsure why this starts as this value 0x800 - return 0x800 - return int(scale(orig, -1, 1, 900, 3200)) - - class Simulator(App): """ customized DRC simulator using drc-sim-keyboard clases and following pep8 @@ -38,6 +28,7 @@ class Simulator(App): def __init__(self): super(Simulator, self).__init__("DRC Simulator") self.vid_offset = (409, 247) + self.vid_offset = (0, 0) self.vid_frame = pygame.Surface(GAMEPAD_DIM) self.vid_rect = pygame.Rect(self.vid_offset, GAMEPAD_DIM) self.bg = ASSET_DICT['gamepad'] @@ -59,14 +50,14 @@ def __init__(self): self.decoder = H264Decoder( GAMEPAD_DIM, - GAMEPAD_DIM, + GAMEPAD_DIM) # pygame.display.get_surface().get_size(), - self.vid_frame) + #self.vid_frame) self.service_handlers = { services.MSG_S: services.ServiceMSG(), services.VID_S: services.ServiceVSTRM(self.decoder), - services.AUD_S: services.ServiceASTRM(), + # services.AUD_S: services.ServiceASTRM(), services.CMD_S: services.ServiceCMD() } @@ -107,6 +98,25 @@ def hid_snd(self): report[3 + 3] = wiiu_axis(r_vert) report[1] = (button_bits >> 8) | ((button_bits & 0xff) << 8) + +# 0 u16 seq_id; +# 1 u16 buttons; // see ButtonsMask +# 2 u8 power_status; // see PowerStatusMask +# u8 battery_charge; +# 3 u16 left_stick_x; +# 4 u16 left_stick_y; +# 5 u16 right_stick_x; +# 6 u16 right_stick_y; +# 7 u8 audio_volume; +# 7.5 AccelerometerData accelerometer; // FUCK +# GyroscopeData gyro; +# MagnetData magnet; +# TouchscreenData touchscreen; +# char unk0[4]; +# u8 extra_buttons; // see ExtraButtonsMask +# char unk1[46]; +# u8 fw_version_neg; // ~fw_version + # touchpanel crap @ 36 - 76 byte_18 = 0 @@ -120,11 +130,11 @@ def hid_snd(self): if (pygame.mouse.get_pressed()[0] and not pygame.event.get_grab() and # mouse was over the "screen" when clicked - self.vid_rect.collidepoint(self.mouse.get_pos())): + self.vid_rect.collidepoint(pygame.mouse.get_pos())): point = pygame.mouse.get_pos() in_x = point[0] - self.vid_offset[0] in_y = point[1] - self.vid_offset[1] - log('touchscreen click at {x, y}'.format(x, y), 'HID') + log('touchscreen click at ({x}, {y})'.format(x=in_x, y=in_y), 'HID') x = int(scale(point[0], self.vid_rect.left, self.vid_rect.right, 200, 3800)) y = int(scale(point[1], self.vid_rect.top, self.vid_rect.bottom, 200, 3800)) z1 = 2000 @@ -157,6 +167,7 @@ def hid_snd(self): # worried its location here is important. TODO # think about it. report[40] |= extra_button_mask(self.ctlr) + # log('report 40 = {n}'.format(n=report[40])) report[0x3f] = 0xe000 #print report.tostring().encode('hex') @@ -169,16 +180,19 @@ def handle_event(self, event): if event.type == pygame.KEYDOWN: if event.key == pygame.K_BACKSLASH: # TODO: What message is this? + # it has to do with video service and expected seq id failures + log('SENDING \1\0\0\0 ON YOUR COMMAND!') services.MSG_S.sendto('\1\0\0\0', ('192.168.1.10', services.PORT_MSG)) elif event.type == EVT_SEND_HID: self.hid_snd() def render(self): - self.screen.fill(15) - self.screen.blit(self.bg, self.offset) - self.vis.render(self.l_stick_prev, self.r_stick_prev) - self.screen.blit(self.vid_frame, self.vid_offset) + #self.screen.fill(15) + #self.screen.blit(self.bg, self.offset) + #self.vis.render(self.l_stick_prev, self.r_stick_prev) + #self.screen.blit(self.vid_frame, self.vid_offset) + #pygame.display.flip() # this stuff came from the default event loop in drc-sim.py # TODO see if I'm mis-managing it somehow such that video never works @@ -197,4 +211,6 @@ def clean_up(self): if __name__ == '__main__': app = Simulator() - app.main() + while True: + app.handle_all_events() + app.render()