Files
2021-11-15 12:36:34 -08:00

130 lines
3.1 KiB
Python

from math import ceil
from colorama import Fore, Style
def printi(msg, *args):
print(Fore.MAGENTA + msg + Style.RESET_ALL, *args)
def printe(msg, *args):
print(Fore.YELLOW + msg + Style.RESET_ALL, *args)
def printd(msg, *args):
print(Fore.BLUE + msg + Style.RESET_ALL, *args)
def round_down_word(val):
return (val // 4) * 4
def round_up_word(val):
return ceil(val / 4) * 4
def round_down_page(val):
return (val // 4096) * 4096
def round_up_page(val):
return ceil(val / 4096) * 4096
def seconds_to_frames(seconds):
return int(round(60 * seconds))
def fds_crc(data, checksum=0x8000):
"""
Do not include any existing checksum, not even the blank checksums 00 00 or FF FF.
The formula will automatically count 2 0x00 bytes without the programmer adding them manually.
Also, do not include the gap terminator (0x80) in the data.
If you wish to do so, change sum to 0x0000.
"""
size = len(data)
for i in range(size + 2):
if i < size:
byte = data[i]
else:
byte = 0x00
for bit_index in range(8):
bit = (byte >> bit_index) & 0x1
carry = checksum & 0x1
checksum = (checksum >> 1) | (bit << 15)
if carry:
checksum ^= 0x8408
return checksum.to_bytes(2, "little")
def fds_remove_crc_gaps(rom):
"""Remove each block's CRC padding so it can be played by FDS
https://wiki.nesdev.org/w/index.php/FDS_disk_format
"""
offset = 0x0
def get_block(size, crc_gap=2):
nonlocal offset
block = rom[offset : offset + size]
offset += size + crc_gap
return block
disk_info_block = get_block(0x38)
file_amount_block = get_block(0x2)
assert file_amount_block[0] == 0x02
n_files = file_amount_block[1]
blocks = [disk_info_block, file_amount_block]
for i in range(n_files):
file_header_block = get_block(0x10)
assert file_header_block[0] == 3
blocks.append(file_header_block)
file_size = int.from_bytes(file_header_block[13 : 13 + 2], "little")
file_data_block = get_block(file_size + 1)
blocks.append(file_data_block)
out = b"".join(blocks)
# Zero pad to be 65500 bytes long
padding = b"\x00" * (65500 - len(out))
out += padding
return out
def fds_add_crc_gaps(rom):
"""Add CRC gaps"""
offset = 0x0
def get_block(size):
nonlocal offset
block = bytes(rom[offset : offset + size])
offset += size
crc = fds_crc(block)
return block + crc
disk_info_block = get_block(0x38)
file_amount_block = get_block(0x2)
assert file_amount_block[0] == 0x02
n_files = file_amount_block[1]
blocks = [disk_info_block, file_amount_block]
for i in range(n_files):
file_header_block = get_block(0x10)
assert file_header_block[0] == 3
blocks.append(file_header_block)
file_size = int.from_bytes(file_header_block[13 : 13 + 2], "little")
file_data_block = get_block(file_size + 1)
blocks.append(file_data_block)
out = b"".join(blocks)
return out