SHARE
TWEET

mobilegb.py

a guest Jun 14th, 2016 396 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import socket
  2. import time
  3. import random
  4. import threading
  5. import sys
  6. import os
  7. from enum import Enum
  8.  
  9. # BGBLinkCable class by TheZZAZZGlitch
  10. class BGBLinkCable():
  11.     def __init__(self,ip,port):
  12.         self.ip = ip
  13.         self.port = port
  14.         self.ticks = 0
  15.         self.frames = 0
  16.         self.received = 0
  17.         self.sent = 0
  18.         self.transfer = -1
  19.         self.lock = threading.Lock()
  20.         self.exchangeHandler = None
  21.        
  22.     def start(self):
  23.         self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  24.         self.sock.connect((self.ip, self.port))
  25.         threading.Thread(target=self.networkLoop, daemon=True).start()
  26.    
  27.     def queryStatus(self):
  28.         status = [0x6a,0,0,0,0,0,0,0]
  29.         self.ticks += 1
  30.         self.frames += 8
  31.         status[2] = self.ticks % 256
  32.         status[3] = (self.ticks // 256) % 256
  33.         status[5] = self.frames % 256
  34.         status[6] = (self.frames // 256) % 256
  35.         status[7] = (self.frames // 256 // 256) % 256
  36.         return bytes(status)
  37.        
  38.     def getStatus(self):
  39.         return (self.frames, self.ticks, self.received, self.sent)
  40.    
  41.     def networkLoop(self):
  42.         while True:
  43.             try:
  44.                 data = bytearray(self.sock.recv(8))
  45.             except KeyboardInterrupt:
  46.                 raise
  47.             if len(data) == 0:
  48.                 break
  49.             if data[0] == 0x01:
  50.                 self.sock.send(data)
  51.                 self.sock.send(b'\x6c\x03\x00\x00\x00\x00\x00\x00')
  52.                 continue
  53.             if data[0] == 0x6C:
  54.                 self.sock.send(b'\x6c\x01\x00\x00\x00\x00\x00\x00')
  55.                 self.sock.send(self.queryStatus())
  56.                 continue
  57.             if data[0] == 0x65:
  58.                 continue
  59.             if data[0] == 0x6A:
  60.                 self.sock.send(self.queryStatus())
  61.                 continue
  62.             if (data[0] == 0x69 or data[0] == 0x68):
  63.                 self.received+=1
  64.                 self.sent+=1
  65.                 data[1] = self.exchangeHandler(data[1], self)
  66.                 self.sock.send(data)
  67.                 self.sock.send(self.queryStatus())
  68.                 continue
  69.             print("Unknown command " + hex(data[0]))
  70.             print(data)
  71.            
  72.     def setExchangeHandler(self, ex):
  73.         self.exchangeHandler = ex
  74. pass
  75.  
  76.  
  77. # Mobile Adapter GB implementation by Háčky
  78. class TransferState(Enum):
  79.     Waiting     = 0  # Waiting for the first byte of the preamble (0x99).
  80.     Preamble    = 1  # Expecting the second byte of the preamble (0x66).
  81.     PacketStart = 2  # Expecting the packet start.
  82.     Packet01    = 3  # Expecting packet offset 0x01 (unused?)
  83.     Packet02    = 4  # Expecting packet offset 0x02 (unused?)
  84.     PacketLen   = 5  # Expecting the packet length.
  85.     PacketBody  = 6  # Expecting the packet body.
  86.     Checksum1   = 7  # Expecting the first byte of the checksum.
  87.     Checksum2   = 8  # Expecting the second byte of the checksum.
  88.     DeviceID    = 9  # Expecting the device ID.
  89.     StatusByte  = 10 # Expecting the status byte (0x00 for sender, 0x80 ^ packetID for receiver)
  90.  
  91. adapter_state = TransferState.Waiting
  92. is_sender = False
  93. packet_data = {'id': 0, 'size': 0, 'data': [], 'checksum': 0}
  94. line_busy = False
  95. port = 0
  96. http_ready = True
  97. pop_session_begun = False
  98.  
  99. def mobileAdapter(b, obj):
  100.     global adapter_state, is_sender, packet_data
  101.     if(is_sender):
  102.         # This does not handle errors flagged by Game Boy!
  103.         if(adapter_state == TransferState.Waiting):
  104.             adapter_state = TransferState.Preamble
  105.             return 0x99
  106.  
  107.         elif(adapter_state == TransferState.Preamble):
  108.             adapter_state = TransferState.PacketStart
  109.             return 0x66
  110.  
  111.         elif(adapter_state == TransferState.PacketStart):
  112.             adapter_state = TransferState.Packet01
  113.             return packet_data['id']
  114.  
  115.         elif(adapter_state == TransferState.Packet01):
  116.             adapter_state = TransferState.Packet02
  117.             return 0x00
  118.  
  119.         elif(adapter_state == TransferState.Packet02):
  120.             adapter_state = TransferState.PacketLen
  121.             return 0x00
  122.  
  123.         elif(adapter_state == TransferState.PacketLen):
  124.             if(packet_data['size'] > 0):
  125.                 adapter_state = TransferState.PacketBody
  126.             else:
  127.                 adapter_state = TransferState.Checksum1
  128.             return packet_data['size']
  129.  
  130.         elif(adapter_state == TransferState.PacketBody):
  131.             packet_data['size'] -= 1
  132.             if(packet_data['size'] == 0):
  133.                 adapter_state = TransferState.Checksum1
  134.             return packet_data['data'][-1 - packet_data['size']]
  135.  
  136.         elif(adapter_state == TransferState.Checksum1):
  137.             adapter_state = TransferState.Checksum2
  138.             return packet_data['checksum'] >> 8
  139.  
  140.         elif(adapter_state == TransferState.Checksum2):
  141.             adapter_state = TransferState.DeviceID
  142.             return packet_data['checksum'] & 0xFF
  143.  
  144.         elif(adapter_state == TransferState.DeviceID):
  145.             adapter_state = TransferState.StatusByte
  146.             return 0x88
  147.  
  148.         elif(adapter_state == TransferState.StatusByte):
  149.             adapter_state = TransferState.Waiting
  150.             is_sender = False
  151.             return 0x00
  152.  
  153.  
  154.     else: # adapter is receiving
  155.         if(adapter_state == TransferState.Waiting):
  156.             if(b == 0x99):
  157.                 adapter_state = TransferState.Preamble
  158.                 packet_data = {'id': 0, 'size': 0, 'data': bytearray(), 'checksum': 0} # reset
  159.  
  160.         elif(adapter_state == TransferState.Preamble):
  161.             if(b == 0x66):
  162.                 adapter_state = TransferState.PacketStart
  163.             else: # fail
  164.                 adapter_state = TransferState.Waiting
  165.                 return 0xf1
  166.  
  167.         elif(adapter_state == TransferState.PacketStart):
  168.             packet_data['id'] = b
  169.             adapter_state = TransferState.Packet01
  170.  
  171.         elif(adapter_state == TransferState.Packet01):
  172.             adapter_state = TransferState.Packet02
  173.  
  174.         elif(adapter_state == TransferState.Packet02):
  175.             adapter_state = TransferState.PacketLen
  176.  
  177.         elif(adapter_state == TransferState.PacketLen):
  178.             packet_data['size'] = b
  179.             if(packet_data['size'] > 0):
  180.                 adapter_state = TransferState.PacketBody
  181.             else:
  182.                 adapter_state = TransferState.Checksum1
  183.  
  184.         elif(adapter_state == TransferState.PacketBody):
  185.             packet_data['data'].append(b)
  186.             packet_data['size'] -= 1
  187.             if(packet_data['size'] == 0):
  188.                 adapter_state = TransferState.Checksum1
  189.  
  190.         elif(adapter_state == TransferState.Checksum1):
  191.             packet_data['checksum'] = b << 8
  192.             adapter_state = TransferState.Checksum2
  193.  
  194.         elif(adapter_state == TransferState.Checksum2):
  195.             packet_data['checksum'] += b
  196.             adapter_state = TransferState.DeviceID
  197.  
  198.         elif(adapter_state == TransferState.DeviceID):
  199.             adapter_state = TransferState.StatusByte
  200.             return 0x88
  201.  
  202.         elif(adapter_state == TransferState.StatusByte):
  203.             adapter_state = TransferState.Waiting
  204.             is_sender = True
  205.             return craftResponsePacket()
  206.  
  207.     # if nothing else, send 0x4B
  208.     return 0x4B
  209.  
  210.  
  211. def craftResponsePacket():
  212.     global packet_data, configuration_data, line_busy, port, http_ready, pop_session_begun, response_text
  213.     rval = 0x80 ^ packet_data['id']
  214.  
  215.     if(packet_data['id'] == 0x10):
  216.         print('>> 10 %s' % packet_data['data'].decode())
  217.         print('<< 10 %s' % packet_data['data'].decode())
  218.         port = 0
  219.         # Echo that packet
  220.  
  221.     elif(packet_data['id'] == 0x11):
  222.         print('>> 11 Closing session')
  223.         print('<< 11 Closing session\n\n')
  224.         port = 0
  225.         line_busy = False
  226.         # Echo that packet
  227.  
  228.     elif(packet_data['id'] == 0x12):
  229.         print('>> 12 Dial %s' % packet_data['data'][1:].decode())
  230.         print('<< 12 Dialed')
  231.         # Empty response
  232.         packet_data['data'] = bytearray()
  233.         line_busy = True
  234.  
  235.     elif(packet_data['id'] == 0x13):
  236.         print('>> 13 Hang up')
  237.         print('<< 13 Hung up')
  238.         line_busy = False
  239.         # Echo that packet
  240.  
  241.     elif(packet_data['id'] == 0x15):
  242.         if(port == 110): # POP
  243.             if(len(packet_data['data']) <= 1):
  244.                 print('>> 15 No POP traffic to send')
  245.             else:
  246.                 print('>> 15 Sending POP traffic:')
  247.                 print(packet_data['data'][1:].decode())
  248.  
  249.             packet_data['id'] = 0x95
  250.             packet_data['data'] = bytearray(b'\x00') + craftPOPResponse()
  251.             if(len(packet_data['data']) <= 1):
  252.                 print('<< 95 No POP traffic received')
  253.             else:
  254.                 print('<< 95 POP response received:')
  255.                 print(packet_data['data'][1:].decode())
  256.  
  257.         elif(port == 80): # HTTP
  258.             if(len(packet_data['data']) <= 1):
  259.                 print('>> 15 No HTTP traffic to send')
  260.             else:
  261.                 print('>> 15 Send HTTP traffic:')
  262.                 try:
  263.                     print(packet_data['data'][1:].decode())
  264.                 except UnicodeDecodeError:
  265.                     hexDump(packet_data['data'][1:])
  266.  
  267.             if(http_ready or len(response_text) > 0):
  268.                 packet_data['id'] = 0x95
  269.                 packet_data['data'] = bytearray(b'\x00') + craftHTTPResponse()
  270.                 if(len(packet_data['data']) <= 1):
  271.                     print('<< 95 No HTTP traffic received')
  272.                 else:
  273.                     print('<< 95 HTTP response received:')
  274.                     try:
  275.                         print(packet_data['data'][1:].decode())
  276.                     except UnicodeDecodeError:
  277.                         hexDump(packet_data['data'][1:])
  278.             else:
  279.                 packet_data['id'] = 0x9F
  280.                 packet_data['data'] = bytearray(b'\x00')
  281.                 print('<< 9F HTTP server closed connection')
  282.  
  283.         else:
  284.             print('>> 15 Unknown protocol')
  285.             print('<< 15 Echoing data')
  286.  
  287.     elif(packet_data['id'] == 0x17):
  288.         print('>> 17 Check telephone line')
  289.         if line_busy:
  290.             print('<< 17 Line busy')
  291.             packet_data['data'] = bytearray(b'\x05')
  292.         else:
  293.             print('<< 17 Line free')
  294.             packet_data['data'] = bytearray(b'\x00')
  295.  
  296.     elif(packet_data['id'] == 0x19):
  297.         offset = packet_data['data'][0]
  298.         length = packet_data['data'][1]
  299.         print('>> 19 Read %s bytes from offset %s of configuration data' % (length, offset))
  300.         print('<< 19 Reading configuration data:')
  301.         hexDump(configuration_data[offset : offset + length])
  302.         packet_data['data'] = bytearray([offset]) + configuration_data[offset : offset + length]
  303.  
  304.     elif(packet_data['id'] == 0x1A):
  305.         offset = packet_data['data'][0]
  306.         length = len(packet_data['data']) - 1
  307.         print('>> 1A Write %s bytes at offset %s of configuration data:' % (length, offset))
  308.         hexDump(packet_data['data'][1:])
  309.         configuration_data[offset : offset + length] = packet_data['data'][1:]
  310.         print('<< 1A Configuration data written')
  311.         # Null response
  312.         packet_data['data'] = bytearray()
  313.  
  314.     elif(packet_data['id'] == 0x21):
  315.         print('>> 21 Log in to DION')
  316.         print('<< 21 Logged in')
  317.         packet_data['data'] = bytearray(b'\x00')
  318.  
  319.     elif(packet_data['id'] == 0x22):
  320.         print('>> 22 Log out of DION')
  321.         print('<< 22 Logged out')
  322.         port = 0
  323.         # Echo that packet
  324.  
  325.     elif(packet_data['id'] == 0x23):
  326.         port = (packet_data['data'][4] << 8) + packet_data['data'][5]
  327.         print('>> 23 Connect to %s.%s.%s.%s:%s' %
  328.             (packet_data['data'][0], packet_data['data'][1], packet_data['data'][2], packet_data['data'][3], port))
  329.         print('<< A3 Connected')
  330.         packet_data['id'] = 0xA3
  331.         packet_data['data'] = bytearray(b'\xFF')
  332.         http_ready = True
  333.         pop_session_begun = False
  334.  
  335.     elif(packet_data['id'] == 0x24):
  336.         print('>> 24 Close connection to server')
  337.         print('<< 24 Connection closed')
  338.         port = 0
  339.         # Echo that packet
  340.  
  341.     elif(packet_data['id'] == 0x28):
  342.         print('>> 28 DNS query for %s' % packet_data['data'].decode())
  343.         print('<< 28 Use fake IP address 250.202.222.0')
  344.         packet_data['data'] = bytearray(b'\xFA\xCA\xDE\x00')
  345.  
  346.     else:
  347.         print('>> %02x Unknown packet' % packet_data['id'])
  348.         print('<< %02x Echoing that packet' % packet_data['id'])
  349.  
  350.     packet_data['size'] = len(packet_data['data'])
  351.  
  352.     checksum = packet_data['id'] + packet_data['size']
  353.     for byte in packet_data['data']:
  354.         checksum += byte
  355.     packet_data['checksum'] = checksum
  356.  
  357.     return rval
  358.  
  359.  
  360. # This e-mail will be read by Pokémon Crystal’s Trade Corner
  361. email = (
  362.     b'From: MISSINGNO.\r\n' # The game requires the From and Date headers to be present, even though it doesn’t read them
  363.     b'Date: Sat, 27 Jan 2001 12:34:56 +0900\r\n'
  364.     b'X-Game-code: CGB-BXTJ-00\r\n'
  365.     b'X-Game-result: 1 8abe3fd7 0210 0310 1\r\n' # Change this to match your TID/SID and the trade you’re making
  366.     b'X-GBmail-type: exclusive\r\n' # This tells Mobile Trainer not to mess with it
  367.     b'\r\n'
  368.     # Base64-encoded Pokémon data
  369.     b'meOQroYQtyEcEACKvgAGTAAAAAAAAAAAAAB2OyMOIwBHAI4SDgAAACYAJgATABEA'
  370.     b'FQARABGZ45CuhkOsQ1BQoRmBpouMkp8L4xrjyX9/f05DrEOg46bJf5KMk6CsjeML'
  371.     b'meOQroaKvhC3\r\n')
  372.  
  373. response_text = bytearray()
  374. def craftPOPResponse():
  375.     global packet_data, pop_session_begun, response_text, email
  376.     pop_text = bytearray()
  377.     if(len(response_text) == 0):
  378.         if(len(packet_data['data']) > 1):
  379.             pop_text = packet_data['data'][1:]
  380.  
  381.         if(pop_text.find(b'STAT') == 0 or pop_text.find(b'LIST 1') == 0):
  382.             response_text += ('+OK 1 %s\r\n' % len(email)).encode()
  383.         elif(pop_text.find(b'LIST ') == 0):
  384.             response_text += b'-ERR\r\n'
  385.         elif(pop_text.find(b'LIST') == 0):
  386.             response_text += ('+OK\r\n1 %s\r\n.\r\n' % len(email)).encode()
  387.         elif(pop_text.find(b'TOP 1 0') == 0):
  388.             response_text += b'+OK\r\n' + email.split(b'\r\n\r\n')[0] + b'\r\n\r\n.\r\n' # e-mail headers only
  389.         elif(pop_text.find(b'RETR 1') == 0):
  390.             response_text += b'+OK\r\n' + email + b'\r\n.\r\n'
  391.         elif(len(pop_text) > 0 or not pop_session_begun): # Reply +OK at start of session or to any other command
  392.             pop_session_begun = True
  393.             response_text += b'+OK\r\n'
  394.         else: # something went wrong?
  395.             response_text += b'-ERR\r\n'
  396.  
  397.     bytes_to_send = min(254, len(response_text)) # Can’t send more than 254 bytes at once
  398.     text_to_send = response_text[:bytes_to_send]
  399.     response_text = response_text[bytes_to_send:]
  400.     return text_to_send
  401.  
  402.  
  403. http_text = bytearray()
  404. http_responses = {
  405.     # Trade Corner
  406.     b'GET /cgb/download?name=/01/CGB-BXTJ/exchange/index.txt HTTP/1.0':
  407.         { 'response': b'HTTP/1.0 200 OK', 'headers': {},
  408.         'content': (
  409.             b'http://gameboy.datacenter.ne.jp/cgb/upload?name=/01/CGB-BXTJ/exchange/10upload.cgi\r\n'
  410.             b'http://gameboy.datacenter.ne.jp/cgb/upload?name=/01/CGB-BXTJ/exchange/cancel.cgi\r\n'
  411.         )},
  412.  
  413.     b'GET /cgb/upload?name=/01/CGB-BXTJ/exchange/10upload.cgi HTTP/1.0':
  414.         { 'response': b'HTTP/1.0 401 Unauthorized', 'headers': {'Gb-Auth-ID': b'HAIL GIOVANNI'}, 'content': b'' },
  415.  
  416.     b'POST /cgb/upload?name=/01/CGB-BXTJ/exchange/10upload.cgi HTTP/1.0':
  417.         { 'response': b'HTTP/1.0 200 OK', 'headers': {}, 'content': b'' },
  418.  
  419.     b'POST /cgb/upload?name=/01/CGB-BXTJ/exchange/cancel.cgi HTTP/1.0':
  420.         { 'response': b'HTTP/1.0 200 OK', 'headers': {}, 'content': b'' },
  421.  
  422.     # Egg Ticket event
  423.     b'GET /cgb/download?name=/01/CGB-BXTJ/tamago/index.txt HTTP/1.0':
  424.         { 'response': b'HTTP/1.0 200 OK', 'headers': {},
  425.         'content': (
  426.             b'http://gameboy.datacenter.ne.jp/cgb/download?name=/01/CGB-BXTJ/tamago/tamagoXX.pkm\r\n'
  427.             b'0ccc170a2e1447ad5eb778518ccca147b0a3bfffd1eae3d6f0a2ffff\r\n'
  428.         )}
  429. }
  430.  
  431. odd_eggs = {
  432.     0:  bytes.fromhex('AC 00 54 CC 92 00 00 08 00 00 7D 00 00 00 00 00' # Pichu
  433.                       '00 00 00 00 00 00 00 1E 14 0A 00 14 00 00 00 05'
  434.                       '00 00 00 00 00 11 00 09 00 06 00 0B 00 08 00 08'
  435.                       '8F 9D 09 50 50 50'),
  436.     1:  bytes.fromhex('AC 00 54 CC 92 00 00 01 00 00 7D 00 00 00 00 00'
  437.                       '00 00 00 00 00 2A AA 1E 14 0A 00 14 00 00 00 05'
  438.                       '00 00 00 00 00 11 00 09 00 07 00 0C 00 09 00 09'
  439.                       '8F 9D 09 50 50 50'),
  440.     2:  bytes.fromhex('AD 00 01 CC 92 00 00 10 00 00 7D 00 00 00 00 00' # Cleffa
  441.                       '00 00 00 00 00 00 00 23 14 0A 00 14 00 00 00 05'
  442.                       '00 00 00 00 00 14 00 07 00 07 00 06 00 09 00 0A'
  443.                       '8F 9D 09 50 50 50'),
  444.     3:  bytes.fromhex('AD 00 01 CC 92 00 00 03 00 00 7D 00 00 00 00 00'
  445.                       '00 00 00 00 00 2A AA 23 14 0A 00 14 00 00 00 05'
  446.                       '00 00 00 00 00 14 00 07 00 08 00 07 00 0A 00 0B'
  447.                       '8F 9D 09 50 50 50'),
  448.     4:  bytes.fromhex('AE 00 2F CC 92 00 00 10 00 00 7D 00 00 00 00 00' # Igglybuff
  449.                       '00 00 00 00 00 00 00 0F 14 0A 00 14 00 00 00 05'
  450.                       '00 00 00 00 00 18 00 08 00 06 00 06 00 09 00 07'
  451.                       '8F 9D 09 50 50 50'),
  452.     5:  bytes.fromhex('AE 00 2F CC 92 00 00 03 00 00 7D 00 00 00 00 00'
  453.                       '00 00 00 00 00 2A AA 0F 14 0A 00 14 00 00 00 05'
  454.                       '00 00 00 00 00 18 00 08 00 07 00 07 00 0A 00 08'
  455.                       '8F 9D 09 50 50 50'),
  456.     6:  bytes.fromhex('EE 00 01 7A 92 00 00 0E 00 00 7D 00 00 00 00 00' # Smoochum
  457.                       '00 00 00 00 00 00 00 23 1E 0A 00 14 00 00 00 05'
  458.                       '00 00 00 00 00 13 00 08 00 06 00 0B 00 0D 00 0B'
  459.                       '8F 9D 09 50 50 50'),
  460.     7:  bytes.fromhex('EE 00 01 7A 92 00 00 02 00 00 7D 00 00 00 00 00'
  461.                       '00 00 00 00 00 2A AA 23 1E 0A 00 14 00 00 00 05'
  462.                       '00 00 00 00 00 13 00 08 00 07 00 0C 00 0E 00 0C'
  463.                       '8F 9D 09 50 50 50'),
  464.     8:  bytes.fromhex('F0 00 34 92 00 00 00 0A 00 00 7D 00 00 00 00 00' # Magby
  465.                       '00 00 00 00 00 00 00 19 0A 00 00 14 00 00 00 05'
  466.                       '00 00 00 00 00 13 00 0C 00 08 00 0D 00 0C 00 0A'
  467.                       '8F 9D 09 50 50 50'),
  468.     9:  bytes.fromhex('F0 00 34 92 00 00 00 02 00 00 7D 00 00 00 00 00'
  469.                       '00 00 00 00 00 2A AA 19 0A 00 00 14 00 00 00 05'
  470.                       '00 00 00 00 00 13 00 0C 00 09 00 0E 00 0D 00 0B'
  471.                       '8F 9D 09 50 50 50'),
  472.     10: bytes.fromhex('EF 00 62 2B 92 00 00 0C 00 00 7D 00 00 00 00 00' # Elekid
  473.                       '00 00 00 00 00 00 00 1E 1E 0A 00 14 00 00 00 05'
  474.                       '00 00 00 00 00 13 00 0B 00 08 00 0E 00 0B 00 0A'
  475.                       '8F 9D 09 50 50 50'),
  476.     11: bytes.fromhex('EF 00 62 2B 92 00 00 02 00 00 7D 00 00 00 00 00'
  477.                       '00 00 00 00 00 2A AA 1E 1E 0A 00 14 00 00 00 05'
  478.                       '00 00 00 00 00 13 00 0B 00 09 00 0F 00 0C 00 0B'
  479.                       '8F 9D 09 50 50 50'),
  480.     12: bytes.fromhex('EC 00 21 92 00 00 00 0A 00 00 7D 00 00 00 00 00' # Tyrogue
  481.                       '00 00 00 00 00 00 00 23 0A 00 00 14 00 00 00 05'
  482.                       '00 00 00 00 00 12 00 08 00 08 00 08 00 08 00 08'
  483.                       '8F 9D 09 50 50 50'),
  484.     13: bytes.fromhex('EC 00 21 92 00 00 00 01 00 00 7D 00 00 00 00 00'
  485.                       '00 00 00 00 00 2A AA 23 0A 00 00 14 00 00 00 05'
  486.                       '00 00 00 00 00 12 00 08 00 09 00 09 00 09 00 09'
  487.                       '8F 9D 09 50 50 50')
  488. }
  489.  
  490. for i, odd_egg in odd_eggs.items():
  491.     http_responses[('GET /cgb/download?name=/01/CGB-BXTJ/tamago/tamago%02x.pkm HTTP/1.0' % i).encode()] = {
  492.         'response': b'HTTP/1.0 200 OK', 'headers': {}, 'content': odd_egg
  493.     }
  494.  
  495. def craftHTTPResponse():
  496.     global packet_data, http_text, http_responses, http_ready, response_text
  497.     if(len(response_text) == 0):
  498.         if(len(packet_data['data']) > 1):
  499.             http_text += packet_data['data'][1:]
  500.  
  501.         http_data = parseHTTPRequest(http_text)
  502.         if('request' in http_data):
  503.             # if this is a POST request, is it done?
  504.             if(http_data['request'].find(b'POST') == 0):
  505.                 if('Content-Length' in http_data['headers']):
  506.                     content_length = int(http_data['headers']['Content-Length'])
  507.                     if(len(http_data['content']) >= content_length):
  508.                         http_ready = False # request is done
  509.             else: # this is a GET request, so we’re definitely done
  510.                 http_ready = False
  511.  
  512.             if(not http_ready):
  513.                 # Clear http_text before the next request
  514.                 http_text = bytearray()
  515.  
  516.                 response = http_responses.get(bytes(http_data['request']))
  517.                 if(http_data['request'] == b'GET /cgb/upload?name=/01/CGB-BXTJ/exchange/10upload.cgi HTTP/1.0'):
  518.                     if('Gb-Auth-ID' in http_data['headers']):
  519.                         response = { 'response': b'HTTP/1.0 200 OK', 'headers': {'Gb-Auth-ID': b'HAIL GIOVANNI'}, 'content': b'\r\n' }
  520.  
  521.                 if(response is None):
  522.                     print('No response known for %s' % http_data['request'].decode())
  523.                     response_text = b'HTTP/1.0 404 Not Found\r\n\r\n'
  524.                 else:
  525.                     response_text = response['response'] + b'\r\n'
  526.                     for header, value in response['headers'].items():
  527.                         response_text += header.encode() + b': ' + value + b'\r\n'
  528.                     response_text += b'\r\n' + response['content']
  529.  
  530.     bytes_to_send = min(254, len(response_text)) # Can’t send more than 254 bytes at once
  531.     text_to_send = response_text[:bytes_to_send]
  532.     response_text = response_text[bytes_to_send:]
  533.     return text_to_send
  534.  
  535.  
  536. def parseHTTPRequest(x):
  537.     http_data = {}
  538.     if(b'\r\n\r\n' in x): # if this is a complete request
  539.         http_data['request'] = x.split(b'\r\n')[0]
  540.  
  541.         http_data['headers'] = {}
  542.         if(x.find(b'\r\n') < x.find(b'\r\n\r\n')): # if there are headers
  543.             headers = x[x.find(b'\r\n') + 2 : x.find(b'\r\n\r\n')]
  544.             headers = headers.split(b'\r\n')
  545.             for header in headers:
  546.                 header = header.split(b': ')
  547.                 http_data['headers'][header[0].decode()] = header[1]
  548.  
  549.         http_data['content'] = x[x.find(b'\r\n\r\n') + 4:]
  550.  
  551.     return http_data
  552.  
  553.  
  554. def hexDump(x):
  555.         for i in range(0, len(x), 16):
  556.             print('   ' + ''.join('%02x ' % j for j in x[i : min(len(x), i + 16)]))
  557.  
  558.  
  559.  
  560. configuration_data = bytearray()
  561. try:
  562.     with open('mobilegb.cfg', 'rb') as f:
  563.         configuration_data = bytearray(f.read())
  564.     f.closed
  565. except FileNotFoundError:
  566.     pass
  567. if(len(configuration_data) != 192):
  568.     print("Configuration data file 'mobilegb.cfg' is invalid or does not exist.")
  569.     print("Creating a blank configuration.\n")
  570.     configuration_data = bytearray([0] * 192)
  571.  
  572. try:
  573.     link = BGBLinkCable('127.0.0.1',8765)
  574.     link.setExchangeHandler(mobileAdapter)
  575.     link.start()
  576.     while True:
  577.         time.sleep(10)
  578. except KeyboardInterrupt:
  579.     print("Saving configuration to 'mobilegb.cfg'.")
  580.     with open('mobilegb.cfg', 'wb') as out:
  581.         out.write(configuration_data)
  582.     out.closed
RAW Paste Data
Top