Skip to content

Instantly share code, notes, and snippets.

@einstein95
Last active October 17, 2022 05:51
Show Gist options
  • Save einstein95/f33906cd4ee0c6e1abae0b4141e08ea9 to your computer and use it in GitHub Desktop.
Save einstein95/f33906cd4ee0c6e1abae0b4141e08ea9 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
from base64 import b64decode
from io import BytesIO
from struct import unpack
from sys import argv
ines_header = b'NES\x1A\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
CustomNesData = BytesIO(b64decode('AAAAAAAAAAAAAAB42KkCjQCASo0AgEqNAIBKjQCASo0AgK0CIBD7rQIgEPupAKIAlQCdAAGdAAKdAAOdAASdAAWdAAadAAfo0Oai/5qpAI0AII0BICA0+SBE+SBa+akAhfKp0oXzqQCF9KkChfWpAIX2qQaF9yAA+akAhfKp2IXzqQCF9KlghfWpAIX2qSCF9yAA+aIAvQDQlQC9ANGdAAHo0PKi+JqpI0goqZCNACCpDo0BIKkAjQIgqQCNAyCpAKIgoABYTMGQ/////////////////////////////////////////////////////////////////////////6IAofKB9Bil8mkBhfKl82kAhfMYpfRpAYX0pfVpAIX1OKX26QGF9qX36QCF99DTpfbQz2CpAY0VQKkAjQFAqUCNF0BgqT+iAI0GII4GIL3Q/40HIOjgIND1YKnQhRCp+4URqSCNBiCpAI0GIKAAogSpII0HIMjQ+OrqytDzoACiBLEQjQcgyND45hHK0PNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADtAAv4C/g='))
StateFile = open(argv[1], 'rb')
baseNesData = open(argv[2], 'rb')
# "parse" the VirtuaNES save state file
assert StateFile.read(0xC) == b'VirtuaNES ST'
StateFile.seek(0x20)
StateData = {}
for _ in range(6):
sname, size = unpack('<8s4xI', StateFile.read(0x10))
StateData[sname.decode('ascii')] = StateFile.read(size)
if len(StateData['RAM DATA']) != 0x2920:
print('WARNING: RAM data doesn\'t include Family BASIC WRAM, check iNES header @ 0x6')
RAMdata = BytesIO(StateData['RAM DATA'])
MMUdata = BytesIO(StateData['MMU DATA'])
baseNesData.seek(0x10)
basicRuntime = bytearray(baseNesData.read(0x5000))
baseNesData.seek(0x8010)
# basicRuntime[0x268] = 0xF7
# basicRuntime[0x269] = 0xB2
# NOP out the keyboard check
basicRuntime[0x858] = 0xEA
basicRuntime[0x859] = 0xEA
basicData = bytearray(RAMdata.read(0x800))
MMUdata.seek(0x44)
basicData += bytearray(MMUdata.read(0x2000))
basicData += bytearray(CustomNesData.read(0x3D0))
MMUdata.seek(0x2444)
basicData += bytearray(MMUdata.read(0x400))
basicData += bytearray(RAMdata.read(0x20))
basicData[0xD] = basicData[0x5];
basicData[0xE] = basicData[0x6];
basicData[0xED] = 0x4C
basicData[0xEE] = 0x71
basicData[0xEF] = 0x89
basicData[0x1F9] = 0x8F
basicData[0x1FA] = 0xA2
basicData[0x1FB] = 0x84
basicData[0x1FC] = 0x97
basicData[0x400] = 0
basicData[0x401] = 0
basicData += bytearray(CustomNesData.read(0x10))
of = open(argv[1] + '.nes', 'wb')
of.write(ines_header)
of.write(basicRuntime)
of.write(basicData)
of.write(baseNesData.read()) # write CHR
of.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment