Repository navigation
Expand file tree
/
Copy pathimage.py
More file actions
59 lines (43 loc) · 1.78 KB
/
Copy pathimage.py
File metadata and controls
59 lines (43 loc) · 1.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from .errors import NotWholeBanks
BANK = 0x10000
HALF = 0x8000
WINDOW_FIRST_BANK = 0xC0
WINDOW_LOW_BASE = 0x80
WINDOW_HIGH_BASE = 0x00
def bank_count(size: int) -> int:
if size % BANK:
raise NotWholeBanks(f"{size} is not a whole number of {BANK} byte banks")
return size // BANK
def snes_to_file(bank: int, addr: int, banks: int) -> int:
if addr < HALF:
return (bank + banks) * HALF + addr
return bank * HALF + (addr - HALF)
def file_to_snes(offset: int, banks: int) -> tuple[int, int]:
block, rest = divmod(offset, HALF)
if block < banks:
return block, HALF + rest
return block - banks, rest
def window_to_file(bank: int, addr: int, banks: int) -> int:
offset = bank - WINDOW_FIRST_BANK
base = WINDOW_LOW_BASE if addr < HALF else WINDOW_HIGH_BASE
return (base + offset + banks) * HALF + (addr & (HALF - 1))
def address_to_file(bank: int, addr: int, banks: int) -> int:
if bank >= WINDOW_FIRST_BANK:
return window_to_file(bank, addr, banks)
return snes_to_file(bank, addr, banks)
def interleave(logical: bytes) -> bytes:
banks = bank_count(len(logical))
built = bytearray(len(logical))
for bank in range(banks):
base = bank * BANK
built[bank * HALF : (bank + 1) * HALF] = logical[base + HALF : base + BANK]
built[(bank + banks) * HALF : (bank + banks + 1) * HALF] = logical[base : base + HALF]
return bytes(built)
def deinterleave(built: bytes) -> bytes:
banks = bank_count(len(built))
logical = bytearray(len(built))
for bank in range(banks):
base = bank * BANK
logical[base : base + HALF] = built[(bank + banks) * HALF : (bank + banks + 1) * HALF]
logical[base + HALF : base + BANK] = built[bank * HALF : (bank + 1) * HALF]
return bytes(logical)