Archived
1
0
Fork 0
This repository has been archived on 2024-04-26. You can view files and clone it, but cannot push or open issues or pull requests.
akari-bot/modules/nintendo_err/ctr_results.py

357 lines
12 KiB
Python
Raw Normal View History

2021-04-04 10:08:26 +00:00
from .types import Module, ResultInfo, ConsoleErrorInfo, ConsoleErrorField
"""
This file contains all currently known 2DS/3DS result and error codes (hexadecimal).
There may be inaccuracies here; we'll do our best to correct them
when we find out more about them.
A result code is a 32-bit integer returned when calling various commands in the
3DS's operating system, Horizon. Its breaks down like so:
Bits | Description
-------------------
00-09 | Description
10-17 | Module
21-26 | Summary
27-31 | Level
Description: A value indicating exactly what happened.
Module: A value indicating who raised the error or returned the result.
Summary: A value indicating a shorter description of what happened.
Level: A value indicating the severity of the issue (fatal, temporary, etc.).
The 3DS makes it simple by providing all of these values directly. Other
consoles, such as the Wii U and Switch do not provide summaries or levels, so
those fields in the ResultInfo class are re-used for other similar purposes.
To add a module so the code understands it, simply add a new module number
to the 'modules' dictionary, with a Module variable as the value. If the module
has no known error codes, simply add a dummy Module instead (see the dict for
more info). See the various module variables for a more in-depth example
on how to make one.
Once you've added a module, or you want to add a new result code to an existing
module, add a new description value (for 3DS it's the 4 digit number after the dash)
as the key, and a ResultInfo variable with a text description of the error or result.
You can also add a second string to the ResultInfo to designate a support URL if
one exists. Not all results or errors have support webpages.
Simple example of adding a module with a sample result code:
test = Module('test', {
5: ResultInfo('test', 'https://example.com')
})
modules = {
9999: test
}
Sources used to compile these results and information:
https://www.3dbrew.org/wiki/Error_codes
Kurisu's previous err.py module
TODO: Add a number of result codes that were in the previous result code Kurisu
used. They were left out for the sake of getting this initial code done faster.
"""
common = Module('common', {
0: ResultInfo('Success'),
1000: ResultInfo('无效的选择'),
1001: ResultInfo('过大'),
1002: ResultInfo('未授权'),
1003: ResultInfo('已经完成'),
1004: ResultInfo('无效大小'),
1005: ResultInfo('无效枚举值'),
1006: ResultInfo('无效组合'),
1007: ResultInfo('无数据'),
1008: ResultInfo('忙碌'),
1009: ResultInfo('位址偏移'),
1010: ResultInfo('大小偏移'),
1011: ResultInfo('内存溢出'),
1012: ResultInfo('未生效'),
1013: ResultInfo('无效地址'),
1014: ResultInfo('无效指针'),
1015: ResultInfo('无效标头'),
1016: ResultInfo('未初始化'),
1017: ResultInfo('已初始化'),
1018: ResultInfo('未找到'),
1019: ResultInfo('请求取消'),
1020: ResultInfo('已存在'),
1021: ResultInfo('数组越界'),
1022: ResultInfo('超时'),
1023: ResultInfo('无效结果')
})
kernel = Module('kernel', {
2: ResultInfo('无效的内存权限。')
})
os = Module('os', {
10: ResultInfo('内存不足。'),
26: ResultInfo('远端关闭了会话。'),
47: ResultInfo('非法的命令标头。')
})
fs = Module('fs', {
101: ResultInfo('档案未挂载或挂载点未找到。'),
120: ResultInfo('应用或对象未找到。'),
141: ResultInfo('卡带未插入。'),
230: ResultInfo('非法的开启标识或权限。'),
391: ResultInfo('NCCH hash检查失败。'),
302: ResultInfo('RSA或AES-MAC校验失败。'),
395: ResultInfo('RomFS或Savedata hash检查失败。'),
630: ResultInfo('命令未被允许或缺失权限。'),
702: ResultInfo('无效路径。'),
761: ResultInfo('不正确的ExeFS读取大小。'),
(100, 179): ResultInfo('[媒体]未找到。'),
(180, 199): ResultInfo('已存在。'),
(200, 219): ResultInfo('空间不足。'),
(220, 229): ResultInfo('无效档案。'),
(230, 339): ResultInfo('不允许或写保护。'),
(360, 389): ResultInfo('格式错误。'),
(390, 399): ResultInfo('校验失败。'),
(600, 629): ResultInfo('资源溢出。'),
(630, 660): ResultInfo('权限不足。'),
(700, 729): ResultInfo('无效参数。'),
(730, 749): ResultInfo('未初始化。'),
(750, 759): ResultInfo('已初始化。'),
(760, 779): ResultInfo('不支持。')
})
srv = Module('srv', {
5: ResultInfo('无效的文字长度服务名称需要在0-8个字符之间'),
6: ResultInfo('访问服务权限不足(有一个程序的服务没有得到对应的权限)。'),
7: ResultInfo('文字长度不匹配内容(服务名称包含意料之外的未知字符)。')
})
nwm = Module('nwm', {
2: ResultInfo('这个错误经常在无线模块(快/已)坏掉时出现。')
})
am = Module('am', {
4: ResultInfo('非法的ticket版本。'),
32: ResultInfo('空CIA。'),
37: ResultInfo('无效的NCCH。'),
39: ResultInfo('无效的程序版本,'),
43: ResultInfo('数据库不存在或打开失败。'),
44: ResultInfo('尝试卸载系统程序。'),
106: ResultInfo('无效的签名/CIA。'),
393: ResultInfo('无效的数据库。'),
})
http = Module('http', {
105: ResultInfo('请求超时。')
})
nim = Module('nim', {
1: ResultInfo('无效的IPC字符串参数非null终止于其指示的长度'),
12: ResultInfo('CFG模块在读取配置的0xB0000时返回了无效的地区代码。'),
13: ResultInfo('CFG的SecureInfoGetSerialNo返回了零字符长度的序列号或“000000000000000”'),
18: ResultInfo('读取在系统存档里的NIM的.dat文件发生了错误数据损坏或数据长度不正确。'),
22: ResultInfo('任天堂服务器返回了无效的数据或无效的数据长度。(仅适用某些操作)'),
2023-01-28 05:53:11 +00:00
25: ResultInfo(
'IntegrityVerificationSeed正在等待服务器同步主机。如果未先通过IPC请求完成同步则无法于在线服务进行处理。'),
26: ResultInfo(
'任天堂服务器存有不可用/不允许的IntegrityVerificationSeed。可能在完成系统迁移后NIM向服务器请求导入IntegrityVerificationSeed时出现。'),
2021-04-04 10:08:26 +00:00
27: ResultInfo('CFG模块在读取配置的0xA0002时返回了无效的地区代码。'),
37: ResultInfo('服务处于备用模式。eShop封禁常规服务离线这于一服务器回应账户信息时出现。此账户和NNID不相关。'),
39: ResultInfo('HTTP状态码非200。仅适用某些操作'),
40: ResultInfo('处理自动传递XML时写入/读取错误。'),
41: ResultInfo('处理自动传递XML时写入/读取错误。Stubbed virtual call被调用'),
58: ResultInfo('CFG模块在读取配置的0xF0006时返回了无效的NPNS口令。'),
67: ResultInfo('当下载游戏的seed时得到了404状态码。'),
68: ResultInfo('当下载游戏的seed时得到了503状态码。')
})
mvd = Module('mvd', {
271: ResultInfo('无效的配置。')
})
qtm = Module('qtm', {
8: ResultInfo('相机正在工作或忙碌。')
})
# This is largely a dummy module, but FBI errors often get passed through the bot
# which return incorrect error strings. Since there's not really a feasible way to figure out the
# application which is throwing the error, this is the best compromise without giving the user
# false information.
application = Module('application-specific error', {
(0, 1023): ResultInfo('程序抛出了错误。请向其他人请教源代码的问题或者向程序的作者发送报告。')
})
# We have some modules partially documented, those that aren't have dummy Modules.
modules = {
0: common,
1: kernel,
2: Module('util'),
3: Module('file server'),
4: Module('loader server'),
5: Module('tcb'),
6: os,
7: Module('dbg'),
8: Module('dmnt'),
9: Module('pdn'),
10: Module('gsp'),
11: Module('i2c'),
12: Module('gpio'),
13: Module('dd'),
14: Module('codec'),
15: Module('spi'),
16: Module('pxi'),
17: fs,
18: Module('di'),
19: Module('hid'),
20: Module('cam'),
21: Module('pi'),
22: Module('pm'),
23: Module('pm_low'),
24: Module('fsi'),
25: srv,
26: Module('ndm'),
27: nwm,
28: Module('soc'),
29: Module('ldr'),
30: Module('acc'),
31: Module('romfs'),
32: am,
33: Module('hio'),
34: Module('updater'),
35: Module('mic'),
36: Module('fnd'),
37: Module('mp'),
38: Module('mpwl'),
39: Module('ac'),
40: http,
41: Module('dsp'),
42: Module('snd'),
43: Module('dlp'),
44: Module('hio_low'),
45: Module('csnd'),
46: Module('ssl'),
47: Module('am_low'),
48: Module('nex'),
49: Module('friends'),
50: Module('rdt'),
51: Module('applet'),
52: nim,
53: Module('ptm'),
54: Module('midi'),
55: Module('mc'),
56: Module('swc'),
57: Module('fatfs'),
58: Module('ngc'),
59: Module('card'),
60: Module('cardnor'),
61: Module('sdmc'),
62: Module('boss'),
63: Module('dbm'),
64: Module('config'),
65: Module('ps'),
66: Module('cec'),
67: Module('ir'),
68: Module('uds'),
69: Module('pl'),
70: Module('cup'),
71: Module('gyroscope'),
72: Module('mcu'),
73: Module('ns'),
74: Module('news'),
75: Module('ro'),
76: Module('gd'),
77: Module('card spi'),
78: Module('ec'),
79: Module('web browser'),
80: Module('test'),
81: Module('enc'),
82: Module('pia'),
83: Module('act'),
84: Module('vctl'),
85: Module('olv'),
86: Module('neia'),
87: Module('npns'),
90: Module('avd'),
91: Module('l2b'),
92: mvd,
93: Module('nfc'),
94: Module('uart'),
95: Module('spm'),
96: qtm,
97: Module('nfp'),
254: application,
}
levels = {
0: 'Success',
1: 'Info',
25: 'Status',
26: 'Temporary',
27: 'Permanent',
28: 'Usage',
29: 'Reinitialize',
30: 'Reset',
31: 'Fatal'
}
summaries = {
0: 'Success',
1: 'Nothing happened',
2: 'Would block',
3: 'Out of resource',
4: 'Not found',
5: 'Invalid state',
6: 'Not supported',
7: 'Invalid argument',
8: 'Wrong argument',
9: 'Canceled',
10: 'Status changed',
11: 'Internal',
63: 'Invalid result value'
}
CONSOLE_NAME = 'Nintendo 2DS/3DS'
# Suggested color to use if displaying information through a Discord bot's embed
COLOR = 0xCE181E
def is_valid(error: str):
try:
err_int = int(error, 16)
except ValueError:
return False
2022-07-13 08:36:58 +00:00
return err_int >= 0 and err_int.bit_length() <= 32
2021-04-04 10:08:26 +00:00
def hexinfo(error: str):
error.strip()
err = int(error[2:], 16)
desc = err & 0x3FF
mod = (err >> 10) & 0xFF
summary = (err >> 21) & 0x3F
level = (err >> 27) & 0x1F
return mod, summary, level, desc
def construct_result(ret, mod, summary, level, desc):
module = modules.get(mod, Module(''))
ret.add_field(ConsoleErrorField('Module', message_str=module.name, supplementary_value=mod))
ret.add_field(ConsoleErrorField('Summary', message_str=summaries.get(summary, ''), supplementary_value=summary))
ret.add_field(ConsoleErrorField('Level', message_str=levels.get(level, ''), supplementary_value=level))
description = module.get_error(desc)
if description is None:
description = common.get_error(desc)
if description is None:
ret.add_field(ConsoleErrorField('Description', supplementary_value=desc))
else:
ret.add_field(
ConsoleErrorField('Description', message_str=description.description, supplementary_value=desc))
2021-04-04 10:08:26 +00:00
else:
ret.add_field(ConsoleErrorField('Description', message_str=description.description, supplementary_value=desc))
return ret
def get(error: str):
ret = ConsoleErrorInfo(error, CONSOLE_NAME, COLOR)
mod, summary, level, desc = hexinfo(error)
return construct_result(ret, mod, summary, level, desc)