Compare commits

..

3 commits

Author SHA1 Message Date
Yuuki Chan
2e9467c693 Import project. 2023-10-22 15:38:39 +09:00
Yuuki Chan
2b0ba1a362 Add requirements.txt 2023-10-22 15:38:15 +09:00
Yuuki Chan
9852f46be1 Updated README.md 2023-10-22 15:38:01 +09:00
5 changed files with 120 additions and 1 deletions

View file

@ -1,3 +1,14 @@
# ROM-Info
Display ROM info of select ROMs (e.g. NDS, GB/C/A, 3DS)
Display ROM info of select ROMs (e.g. NDS, GB/C/A, 3DS)
# Install (Windows - PowerShell)
1. python -m venv .venv
2. .\\.venv\Scripts\Activate.ps1
3. pip install -r requirements.txt
<br /><br />
Licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)

32
logger.py Normal file
View file

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
from datetime import datetime
import colorama
class Logger(object):
def __init__(self, module: str, datefmt: str = '%m/%d/%Y %I:%M:%S %p'):
colorama.init()
self.module = module
self.datefmt = datefmt
def info(self, msg: str, levelname: str = 'INFO'):
asctime = datetime.now().strftime(self.datefmt)
print(f'\033[92m[{asctime}] - {levelname} - {self.module} - {msg}\033[39m')
def debug(self, msg: str, levelname: str = 'DEBUG'):
asctime = datetime.now().strftime(self.datefmt)
print(f'\033[93m[{asctime}] - {levelname} - {self.module} - {msg}\033[39m')
def verbose(self, msg: str, levelname: str = 'VERBOSE'):
asctime = datetime.now().strftime(self.datefmt)
print(f'\033[96m[{asctime}] - {levelname} - {self.module} - {msg}\033[39m')
def error(self, msg: str, levelname: str = 'ERROR'):
asctime = datetime.now().strftime(self.datefmt)
print(f'\033[91m[{asctime}] - {levelname} - {self.module} - {msg}\033[39m')

20
main.py Normal file
View file

@ -0,0 +1,20 @@
import sys
from logger import Logger
from rominfo.nintendo_ds import *
logger = Logger('RomInfo')
if __name__ == '__main__':
if len(sys.argv) == 2:
# NDS(i) - https://dsibrew.org/wiki/DSi_cartridge_header
if sys.argv[1].endswith('.nds'):
with open(sys.argv[1], mode='rb') as nds:
logger.info('Title : {}'.format(nds_get_info('title', nds)))
logger.info('Game code : {}'.format(nds_get_info('gamecode', nds)))
logger.info('Maker code : {}'.format(nds_get_info('makercode', nds)))
logger.info('Unit code : {}'.format(nds_get_info('unitcode', nds)))
logger.info('Encryption seed : {}'.format(nds_get_info('encryptionseed', nds)))
logger.info('Device capacity : {}'.format(nds_get_info('devicecapacity', nds)))
else:
logger.error('No ROM specified. App requires one argument.')

1
requirements.txt Normal file
View file

@ -0,0 +1 @@
colorama==0.4.6

55
rominfo/nintendo_ds.py Normal file
View file

@ -0,0 +1,55 @@
from math import pow
from typing import BinaryIO
def nds_get_info(opt: str, inf: BinaryIO):
match opt.lower():
case 'title':
inf.seek(0x000)
return inf.read(12).decode()
case 'gamecode':
inf.seek(0x00C)
return inf.read(4).decode()
case 'makercode':
inf.seek(0x010)
return _maker_lookup(inf.read(2).decode())
case 'unitcode':
inf.seek(0x012)
return _unit_lookup(inf.read(1))
case 'encryptionseed':
inf.seek(0x013)
return str(int.from_bytes(inf.read(1), 'little'))
case 'devicecapacity':
inf.seek(0x014)
return _capacity_lookup(int.from_bytes(inf.read(1), 'little'))
case _:
return 'Unknown'
def _maker_lookup(code: str) -> str:
match code:
case '01':
return 'Nintendo ({})'.format(code)
case 'GD':
return 'Square-Enix ({})'.format(code)
case _:
return 'Unknown ({})'.format(code)
def _unit_lookup(code: bytes) -> str:
if code == b'\x00':
return 'NDS (00h)'
elif code == b'\x02':
return 'DSi Enhanced (02h)'
elif code == b'\x03':
return 'DSi Exclusive (03h)'
else:
return 'Unknown ({})'.format(code)
def _capacity_lookup(code: int) -> str: # 512Mbit (67108864 bytes) (09h)
match code:
case 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12:
return '{} MB ({})'.format(round(128 * pow(2, code) / 1024), '{}h'.format(str(code).zfill(2)))
case _:
return 'Unknown ({})'.format(code)