First Commit

This commit is contained in:
2025-02-06 22:24:29 +08:00
parent ed7df4c81e
commit 7539e6a53c
18116 changed files with 6181499 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
*.3dsx
*.elf
*.cxi
*.cia
build/
hide/
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,116 @@
segment p 0000
br 0x0000$0800 always // reset vector
reti always
data 0000
reti always
data 0000
br 0x0000$5000 always // int0
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
reti always // int1
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
reti always // int2
segment p 0800 // init
mov 0x$f000 sp // set stack pointer
mov 0x$0180 mod3 // enable interrupt
load 0x0082u8 page // configure ICU
mov 0x$4000 r0
mov r0 [page:0x000eu8]
mov r0 [page:0x0010u8]
mov r0 [page:0x0006u8] // enable apbp as int0
br 0x0000$1000 always
segment p 1000 // Main loop
load 0x0000u8 page
mov 0x$80CC r0 // transfer APBP register
mov [r0++] r1
mov r1 [page:0x0005u8]
modr [r0++]
mov [r0++] r1
mov r1 [page:0x0006u8]
modr [r0++]
mov [r0++] r1
mov r1 [page:0x0007u8]
modr [r0++]
mov [r0++] r1
mov r1 [page:0x0008u8]
modr [r0++]
mov [r0++] r1
mov r1 [page:0x0009u8]
modr [r0++]
mov [r0++] r1
mov r1 [page:0x000au8]
modr [r0++]
mov [r0++] r1
mov r1 [page:0x000bu8]
modr [r0++]
mov [page:0x0000u8] b0l // get signal
br 0x0000$1000 eq // loop back if no signal
mov [page:0x0001u8] b0l // get command type
cmpv 0x$0000 b0l
br 0x0000$2000 eq
cmpv 0x$0001 b0l
br 0x0000$3000 eq
br 0x0000$4000 always
segment p 2000 // read
mov [page:0x0002u8] r0
mov [r0] r1
mov r1 [page:0x0003u8]
br 0x0000$4000 always
segment p 3000 // write
mov [page:0x0002u8] r0
mov [page:0x0003u8] r1
mov r1 [r0]
br 0x0000$4000 always
segment p 4000 // end
clr b0 always
mov b0l [page:0x0000u8] // clear signal
br 0x0000$1000 always
segment p 5000 // interrupt handler
mov 0x$4000 r5
mov 0x$8202 r4
mov r5 [r4] // ack
mov 0x$0004 r4
mov [r4] r5
modr [r5++]
mov r5 [r4]
reti always
segment d 0000 // signal area
data 0000 // 0, Start signal
data 0000 // 1, Operation type
data 0000 // 2, Address
data 0000 // 3, Data
data 0000 // 4, interrupt counter
data 0000 // 5, 80CC
data 0000 // 6, 80CE
data 0000 // 7, 80D0
data 0000 // 8, 80D2
data 0000 // 9, 80D4
data 0000 // A, 80D6
data 0000 // B, 80D8

View File

@@ -0,0 +1,228 @@
BasicInfo:
Title : SVRT
ProductCode : CTR-P-SVRT
Logo : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem
RomFs:
# Specifies the root path of the read only file system to include in the ROM.
#RootPath : romfs
TitleInfo:
Category : Application
UniqueId : 0xff557
Option:
UseOnSD : true # true if App is to be installed to SD
FreeProductCode : true # Removes limitations on ProductCode
MediaFootPadding : false # If true CCI files are created with padding
EnableCrypt : false # Enables encryption for NCCH and CIA
EnableCompress : true # Compresses where applicable (currently only exefs:/.code)
AccessControlInfo:
CoreVersion : 2
# Exheader Format Version
DescVersion : 2
# Minimum Required Kernel Version (below is for 4.5.0)
ReleaseKernelMajor : "02"
ReleaseKernelMinor : "33"
# ExtData
UseExtSaveData : false # enables ExtData
#ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId
# FS:USER Archive Access Permissions
# Uncomment as required
FileSystemAccess:
- CategorySystemApplication
- CategoryHardwareCheck
- CategoryFileSystemTool
- Debug
#- TwlCardBackup
#- TwlNandData
#- Boss
- DirectSdmc
#- Core
#- CtrNandRo
#- CtrNandRw
#- CtrNandRoWrite
#- CategorySystemSettings
#- CardBoard
#- ExportImportIvs
#- DirectSdmcWrite
#- SwitchCleanup
#- SaveDataMove
#- Shop
#- Shell
#- CategoryHomeMenu
# Process Settings
MemoryType : Application # Application/System/Base
SystemMode : 64MB # 64MB(Default)/96MB/80MB/72MB/32MB
IdealProcessor : 0
AffinityMask : 1
Priority : 16
MaxCpu : 0 # Let system decide
HandleTableSize : 0x200
DisableDebug : false
EnableForceDebug : false
CanWriteSharedPage : false
CanUsePrivilegedPriority : true
CanUseNonAlphabetAndNumber : true
PermitMainFunctionArgument : true
CanShareDeviceMemory : true
RunnableOnSleep : false
SpecialMemoryArrange : false
# New3DS Exclusive Process Settings
SystemModeExt : Legacy # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode
CpuSpeed : 268MHz # 268MHz(Default)/804MHz
EnableL2Cache : false # false(default)/true
CanAccessCore2 : false
# Virtual Address Mappings
IORegisterMapping:
- 1ed03000-1ed03fff # DSP registers
- 1ff00000-1ff7ffff # DSP memory
MemoryMapping:
- 1f000000-1f5fffff:r # VRAM
# Accessible SVCs, <Name>:<ID>
SystemCallAccess:
InvalidateProcessDataCache: 82
FlushProcessDataCache: 84
ArbitrateAddress: 34
Break: 60
CancelTimer: 28
ClearEvent: 25
ClearTimer: 29
CloseHandle: 35
ConnectToPort: 45
ControlMemory: 1
CreateAddressArbiter: 33
CreateEvent: 23
CreateMemoryBlock: 30
CreateMutex: 19
CreateSemaphore: 21
CreateThread: 8
CreateTimer: 26
DuplicateHandle: 39
ExitProcess: 3
ExitThread: 9
GetCurrentProcessorNumber: 17
GetHandleInfo: 41
GetProcessId: 53
GetProcessIdOfThread: 54
GetProcessIdealProcessor: 6
GetProcessInfo: 43
GetResourceLimit: 56
GetResourceLimitCurrentValues: 58
GetResourceLimitLimitValues: 57
GetSystemInfo: 42
GetSystemTick: 40
GetThreadContext: 59
GetThreadId: 55
GetThreadIdealProcessor: 15
GetThreadInfo: 44
GetThreadPriority: 11
MapMemoryBlock: 31
OutputDebugString: 61
QueryMemory: 2
ReleaseMutex: 20
ReleaseSemaphore: 22
SendSyncRequest1: 46
SendSyncRequest2: 47
SendSyncRequest3: 48
SendSyncRequest4: 49
SendSyncRequest: 50
SetThreadPriority: 12
SetTimer: 27
SignalEvent: 24
SleepThread: 10
UnmapMemoryBlock: 32
WaitSynchronization1: 36
WaitSynchronizationN: 37
Backdoor: 123
BindInterrupt: 80
# Service List
# Maximum 34 services (32 if firmware is prior to 9.3.0)
ServiceAccessControl:
- cfg:u
- fs:USER
- gsp::Gpu
- hid:USER
- ndm:u
- pxi:dev
- APT:U
- ac:u
- act:u
- am:net
- boss:U
- cam:u
- cecd:u
- csnd:SND
- frd:u
- http:C
- ir:USER
- ir:u
- ir:rst
- ldr:ro
- mic:u
- news:u
- nfc:u
- nim:aoc
- nwm::UDS
- ptm:u
- qtm:u
- soc:U
- ssl:C
- y2r:u
- ps:ps
SystemControlInfo:
SaveDataSize: 512K
RemasterVersion: 0
StackSize: 0x40000
# Modules that run services listed above should be included below
# Maximum 48 dependencies
# If a module is listed that isn't present on the 3DS, the title will get stuck at the logo (3ds waves)
# So act, nfc and qtm are commented for 4.x support. Uncomment if you need these.
# <module name>:<module titleid>
Dependency:
ac: 0x0004013000002402
#act: 0x0004013000003802
am: 0x0004013000001502
boss: 0x0004013000003402
camera: 0x0004013000001602
cecd: 0x0004013000002602
cfg: 0x0004013000001702
codec: 0x0004013000001802
csnd: 0x0004013000002702
dlp: 0x0004013000002802
dsp: 0x0004013000001a02
friends: 0x0004013000003202
gpio: 0x0004013000001b02
gsp: 0x0004013000001c02
hid: 0x0004013000001d02
http: 0x0004013000002902
i2c: 0x0004013000001e02
ir: 0x0004013000003302
mcu: 0x0004013000001f02
mic: 0x0004013000002002
ndm: 0x0004013000002b02
news: 0x0004013000003502
#nfc: 0x0004013000004002
nim: 0x0004013000002c02
nwm: 0x0004013000002d02
pdn: 0x0004013000002102
ps: 0x0004013000003102
ptm: 0x0004013000002202
#qtm: 0x0004013020004202
ro: 0x0004013000003702
socket: 0x0004013000002e02
spi: 0x0004013000002302
ssl: 0x0004013000002f02

View File

@@ -0,0 +1,28 @@
#!/usr/bin/env python3
import sys
import socket
import struct
for UDP_IP in ["192.168.1.158", "127.0.0.1"]:
UDP_PORT = 8888
MESSAGE = struct.pack('<H', 0xD592)
for i in range(1, len(sys.argv)):
inst = sys.argv[i]
if inst == "r":
MESSAGE += struct.pack('<H', 0)
continue
elif inst == "w":
MESSAGE += struct.pack('<H', 1)
continue
elif inst == "hr":
MESSAGE += struct.pack('<H', 2)
continue
elif inst == "hw":
MESSAGE += struct.pack('<H', 3)
continue
MESSAGE += struct.pack('<H', int(inst, 16))
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

View File

@@ -0,0 +1,308 @@
#include <atomic>
#include <string>
#include <unordered_map>
#include <vector>
#include <3ds.h>
#include <arpa/inet.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include "cdc_bin.h"
PrintConsole topScreen, bottomScreen;
void MoveCursor(unsigned row, unsigned col) {
printf("\x1b[%u;%uH", row + 1, col + 1);
}
enum Color {
Reset = 0,
Black = 30,
Red = 31,
Green = 32,
Yellow = 33,
Blue = 34,
Magnenta = 35,
Cyan = 36,
White = 37,
};
void SetColor(Color color, Color background) {
printf("\x1b[%dm\x1b[%dm", (int)color, (int)background + 10);
}
void FlushCache(volatile void* ptr, u32 size) {
svcFlushProcessDataCache(CUR_PROCESS_HANDLE, (void*)ptr, size);
}
void InvalidateCache(volatile void* ptr, u32 size) {
svcInvalidateProcessDataCache(CUR_PROCESS_HANDLE, (void*)ptr, size);
}
vu16* dspP = (vu16*)0x1FF00000;
vu16* dspD = (vu16*)0x1FF40000;
std::atomic<int> interrupt_counter;
void PrintAll() {
consoleSelect(&topScreen);
MoveCursor(0, 0);
printf("DSP registers:\n");
InvalidateCache(dspD + 4, 2 * 8);
printf("SetSem = %04X\n", dspD[5]);
printf("MskSem = %04X\n", dspD[6]);
printf("AckSem = %04X\n", dspD[7]);
printf("GetSem = %04X\n", dspD[8]);
printf("IrqMsk = %04X\n", dspD[9]);
printf("Status = %04X\n", dspD[10]);
printf("?????? = %04X\n", dspD[11]);
printf("interrupt = %d\n", dspD[4]);
printf("\nCPU registers:\n");
printf("PCFG = %04X\n", *(vu16*)0x1ed03008);
printf("PSTS = %04X\n", *(vu16*)0x1ed0300C);
printf("PSEM = %04X\n", *(vu16*)0x1ed03010);
printf("PMASK = %04X\n", *(vu16*)0x1ed03014);
printf("PCLEAR = %04X\n", *(vu16*)0x1ed03018);
printf("SEM = %04X\n", *(vu16*)0x1ed0301C);
printf("interrupt = %d\n", (int)interrupt_counter);
consoleSelect(&bottomScreen);
}
int udp_s;
int udp_s_broadcast;
void UdpInit() {
#define SOC_ALIGN 0x1000
#define SOC_BUFFERSIZE 0x100000
static u32* SOC_buffer;
// allocate buffer for SOC service
SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE);
if (SOC_buffer == NULL) {
printf("memalign: failed to allocate\n");
return;
}
Result ret;
if ((ret = socInit(SOC_buffer, SOC_BUFFERSIZE)) != 0) {
printf("socInit: 0x%08lX\n", ret);
return;
}
sockaddr_in si_me;
// create a UDP socket
if ((udp_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
printf("socket() failed\n");
return;
}
// zero out the structure
memset(&si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(8888);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
// bind socket to port
if (bind(udp_s, (sockaddr*)&si_me, sizeof(si_me)) == -1) {
printf("bind() failed\n");
return;
}
// create a UDP broadcast socket
if ((udp_s_broadcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
printf("socket()(broadcast) failed\n");
return;
}
}
constexpr unsigned BUFLEN = 512;
char buf[BUFLEN];
void Fire() {
dspD[0] = 1;
FlushCache((void*)dspD, 8);
while (true) {
InvalidateCache((void*)dspD, 8);
if (dspD[0] == 0)
break;
}
}
void CheckPackage() {
sockaddr_in si_other;
socklen_t slen = sizeof(si_other);
int recv_len;
if ((recv_len = recvfrom(udp_s, buf, BUFLEN, MSG_DONTWAIT, (sockaddr*)&si_other, &slen)) < 4)
return;
u16 magic;
memcpy(&magic, buf, 2);
if (magic == 0xD592) {
std::vector<u16> command_package((recv_len - 2) / 2);
printf("Command received\n");
memcpy(command_package.data(), buf + 2, command_package.size() * 2);
switch (command_package[0]) {
case 0: {
if (command_package.size() != 2) {
printf("Wrong length for Read\n");
break;
}
u16 addr = command_package[1];
printf("Read [%04X] -> ", addr);
dspD[1] = 0;
dspD[2] = addr;
dspD[3] = 0xCCCC;
Fire();
printf("%04X\n", dspD[3]);
break;
}
case 1: {
if (command_package.size() != 3) {
printf("Wrong length for Write\n");
break;
}
u16 addr = command_package[1];
u16 value = command_package[2];
printf("Write [%04X] <- %04X", addr, value);
dspD[1] = 1;
dspD[2] = addr;
dspD[3] = value;
Fire();
printf(" OK\n");
break;
}
case 2: {
if (command_package.size() != 3) {
printf("Wrong length for CPU Read\n");
break;
}
u32 addr = command_package[1] | ((u32)command_package[2] << 16);
printf("Read CPU [%08lX] -> ", addr);
// FlushCache((vu16*)addr, 2);
printf("%04X\n", *(vu16*)(addr));
break;
}
case 3: {
if (command_package.size() != 4) {
printf("Wrong length for CPU Write\n");
break;
}
u32 addr = command_package[1] | ((u32)command_package[2] << 16);
u16 value = command_package[3];
printf("Write CPU [%08lX] <- %04X", addr, value);
// InvalidateCache((vu16*)addr, 2);
*(vu16*)(addr) = value;
printf(" OK\n");
break;
}
}
}
}
Handle pmHandle;
Result pmInit_(void) {
Result res = srvGetServiceHandle(&pmHandle, "pm:app");
return res;
}
void pmExit_(void) {
svcCloseHandle(pmHandle);
}
Result PM_TerminateTitle(u64 tid, u64 timeout) {
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x4, 4, 0);
cmdbuf[1] = tid & 0xFFFFFFFF;
cmdbuf[2] = tid >> 32;
cmdbuf[3] = timeout & 0xffffffff;
cmdbuf[4] = (timeout >> 32) & 0xffffffff;
if (R_FAILED(ret = svcSendSyncRequest(pmHandle)))
return ret;
return (Result)cmdbuf[1];
}
Handle dsp_interrupt;
Handle threadA;
u32 threadA_stack[0x400];
void threadA_entry(void*) {
while (true) {
svcWaitSynchronization(dsp_interrupt, INT64_MAX);
++interrupt_counter;
}
}
int main() {
aptInit();
gfxInitDefault();
consoleInit(GFX_TOP, &topScreen);
consoleInit(GFX_BOTTOM, &bottomScreen);
consoleSelect(&bottomScreen);
printf("Hello!\n");
UdpInit();
printf("dspInit: %08lX\n", dspInit());
bool loaded = false;
printf("DSP_LoadComponent: %08lX\n",
DSP_LoadComponent(cdc_bin, cdc_bin_size, 0xFF, 0xFF, &loaded));
printf("loaded = %d\n", loaded);
svcSleepThread(1000000000);
char hostname[100];
gethostname(hostname, 100);
printf("IP: %s port: 8888\n", hostname);
pmInit_();
printf("PM_TerminateTitle(DSP): %08lX\n", PM_TerminateTitle(0x0004013000001a02, 0));
pmExit_();
svcCreateEvent(&dsp_interrupt, ResetType::RESET_ONESHOT);
interrupt_counter = 0;
svcCreateThread(&threadA, threadA_entry, 0x0, threadA_stack + 0x400, 4, 0xFFFFFFFE);
printf("BindInterrupt: %08lX\n", svcBindInterrupt(0x4A, dsp_interrupt, 4, 0));
// Main loop
while (aptMainLoop()) {
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break;
if (kDown & KEY_A)
printf("hello\n");
CheckPackage();
PrintAll();
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
// Wait for VBlank
gspWaitForVBlank();
}
socExit();
dspExit();
gfxExit();
aptExit();
return 0;
}

View File

@@ -0,0 +1,20 @@
*.3dsx
*.elf
*.cxi
*.cia
build/
hide/
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,64 @@
segment p 0000
br 0x0000$0800 always// reset vector
br 0x0000$3000 always
br 0x0000$3000 always
br 0x0000$3000 always // int0
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
br 0x0000$3000 always // int1
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
br 0x0000$3000 always // int2
segment p 0800 // pre-write shutdown sequence
load 0x0080u8 page
clr b0 always
mov b0l [page:0x00c8u8] // T_REPLY2
br 0x0000$1000 always // jump to epilogue first to dump the initial register value
segment p 1000 // Main loop
load 0x0000u8 page
mov [page:0x0000u8] b0l // get signal
br 0x0000$1000 eq // loop back if no signal
mov [page:0x0001u8] b0l // get command type
cmpv 0x$0000 b0l
br 0x0000$2000 eq
cmpv 0x$0001 b0l
br 0x0000$3000 eq
br 0x0000$4000 always
segment p 2000 // read
mov [page:0x0002u8] r0
mov [r0] r1
mov r1 [page:0x0003u8]
br 0x0000$4000 always
segment p 3000 // write
mov [page:0x0002u8] r0
mov [page:0x0003u8] r1
mov r1 [r0]
br 0x0000$4000 always
segment p 4000 // end
clr b0 always
mov b0l [page:0x0000u8] // clear signal
br 0x0000$1000 always // loop back
segment d 0000 // signal area
data 0000 // Start signal
data 0000 // Operation type
data 0000 // Address
data 0000 // Data

View File

@@ -0,0 +1,226 @@
BasicInfo:
Title : SVRT
ProductCode : CTR-P-SVRT
Logo : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem
RomFs:
# Specifies the root path of the read only file system to include in the ROM.
#RootPath : romfs
TitleInfo:
Category : Application
UniqueId : 0xff556
Option:
UseOnSD : true # true if App is to be installed to SD
FreeProductCode : true # Removes limitations on ProductCode
MediaFootPadding : false # If true CCI files are created with padding
EnableCrypt : false # Enables encryption for NCCH and CIA
EnableCompress : true # Compresses where applicable (currently only exefs:/.code)
AccessControlInfo:
CoreVersion : 2
# Exheader Format Version
DescVersion : 2
# Minimum Required Kernel Version (below is for 4.5.0)
ReleaseKernelMajor : "02"
ReleaseKernelMinor : "33"
# ExtData
UseExtSaveData : false # enables ExtData
#ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId
# FS:USER Archive Access Permissions
# Uncomment as required
FileSystemAccess:
- CategorySystemApplication
- CategoryHardwareCheck
- CategoryFileSystemTool
- Debug
#- TwlCardBackup
#- TwlNandData
#- Boss
- DirectSdmc
#- Core
#- CtrNandRo
#- CtrNandRw
#- CtrNandRoWrite
#- CategorySystemSettings
#- CardBoard
#- ExportImportIvs
#- DirectSdmcWrite
#- SwitchCleanup
#- SaveDataMove
#- Shop
#- Shell
#- CategoryHomeMenu
# Process Settings
MemoryType : Application # Application/System/Base
SystemMode : 64MB # 64MB(Default)/96MB/80MB/72MB/32MB
IdealProcessor : 0
AffinityMask : 1
Priority : 16
MaxCpu : 0 # Let system decide
HandleTableSize : 0x200
DisableDebug : false
EnableForceDebug : false
CanWriteSharedPage : false
CanUsePrivilegedPriority : false
CanUseNonAlphabetAndNumber : true
PermitMainFunctionArgument : true
CanShareDeviceMemory : true
RunnableOnSleep : false
SpecialMemoryArrange : false
# New3DS Exclusive Process Settings
SystemModeExt : Legacy # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode
CpuSpeed : 268MHz # 268MHz(Default)/804MHz
EnableL2Cache : false # false(default)/true
CanAccessCore2 : false
# Virtual Address Mappings
IORegisterMapping:
- 1ff00000-1ff7ffff # DSP memory
MemoryMapping:
- 1f000000-1f5fffff:r # VRAM
# Accessible SVCs, <Name>:<ID>
SystemCallAccess:
InvalidateProcessDataCache: 82
FlushProcessDataCache: 84
ArbitrateAddress: 34
Break: 60
CancelTimer: 28
ClearEvent: 25
ClearTimer: 29
CloseHandle: 35
ConnectToPort: 45
ControlMemory: 1
CreateAddressArbiter: 33
CreateEvent: 23
CreateMemoryBlock: 30
CreateMutex: 19
CreateSemaphore: 21
CreateThread: 8
CreateTimer: 26
DuplicateHandle: 39
ExitProcess: 3
ExitThread: 9
GetCurrentProcessorNumber: 17
GetHandleInfo: 41
GetProcessId: 53
GetProcessIdOfThread: 54
GetProcessIdealProcessor: 6
GetProcessInfo: 43
GetResourceLimit: 56
GetResourceLimitCurrentValues: 58
GetResourceLimitLimitValues: 57
GetSystemInfo: 42
GetSystemTick: 40
GetThreadContext: 59
GetThreadId: 55
GetThreadIdealProcessor: 15
GetThreadInfo: 44
GetThreadPriority: 11
MapMemoryBlock: 31
OutputDebugString: 61
QueryMemory: 2
ReleaseMutex: 20
ReleaseSemaphore: 22
SendSyncRequest1: 46
SendSyncRequest2: 47
SendSyncRequest3: 48
SendSyncRequest4: 49
SendSyncRequest: 50
SetThreadPriority: 12
SetTimer: 27
SignalEvent: 24
SleepThread: 10
UnmapMemoryBlock: 32
WaitSynchronization1: 36
WaitSynchronizationN: 37
Backdoor: 123
# Service List
# Maximum 34 services (32 if firmware is prior to 9.3.0)
ServiceAccessControl:
- cfg:u
- fs:USER
- gsp::Gpu
- hid:USER
- ndm:u
- pxi:dev
- APT:U
- ac:u
- act:u
- am:net
- boss:U
- cam:u
- cecd:u
- csnd:SND
- frd:u
- http:C
- ir:USER
- ir:u
- ir:rst
- ldr:ro
- mic:u
- news:u
- nfc:u
- nim:aoc
- nwm::UDS
- ptm:u
- qtm:u
- soc:U
- ssl:C
- y2r:u
- ps:ps
SystemControlInfo:
SaveDataSize: 512K
RemasterVersion: 0
StackSize: 0x40000
# Modules that run services listed above should be included below
# Maximum 48 dependencies
# If a module is listed that isn't present on the 3DS, the title will get stuck at the logo (3ds waves)
# So act, nfc and qtm are commented for 4.x support. Uncomment if you need these.
# <module name>:<module titleid>
Dependency:
ac: 0x0004013000002402
#act: 0x0004013000003802
am: 0x0004013000001502
boss: 0x0004013000003402
camera: 0x0004013000001602
cecd: 0x0004013000002602
cfg: 0x0004013000001702
codec: 0x0004013000001802
csnd: 0x0004013000002702
dlp: 0x0004013000002802
dsp: 0x0004013000001a02
friends: 0x0004013000003202
gpio: 0x0004013000001b02
gsp: 0x0004013000001c02
hid: 0x0004013000001d02
http: 0x0004013000002902
i2c: 0x0004013000001e02
ir: 0x0004013000003302
mcu: 0x0004013000001f02
mic: 0x0004013000002002
ndm: 0x0004013000002b02
news: 0x0004013000003502
#nfc: 0x0004013000004002
nim: 0x0004013000002c02
nwm: 0x0004013000002d02
pdn: 0x0004013000002102
ps: 0x0004013000003102
ptm: 0x0004013000002202
#qtm: 0x0004013020004202
ro: 0x0004013000003702
socket: 0x0004013000002e02
spi: 0x0004013000002302
ssl: 0x0004013000002f02

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env python3
import sys
import socket
import struct
for UDP_IP in ["192.168.1.158", "127.0.0.1"]:
UDP_PORT = 8888
MESSAGE = struct.pack('<H', 0xD592)
for i in range(1, len(sys.argv)):
inst = sys.argv[i]
if inst == "r":
MESSAGE += struct.pack('<H', 0)
continue
elif inst == "w":
MESSAGE += struct.pack('<H', 1)
continue
MESSAGE += struct.pack('<H', int(inst, 16))
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

View File

@@ -0,0 +1,291 @@
#include <string>
#include <unordered_map>
#include <vector>
#include <3ds.h>
#include <arpa/inet.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include "cdc_bin.h"
PrintConsole topScreen, bottomScreen;
void MoveCursor(unsigned row, unsigned col) {
printf("\x1b[%u;%uH", row + 1, col + 1);
}
enum Color {
Reset = 0,
Black = 30,
Red = 31,
Green = 32,
Yellow = 33,
Blue = 34,
Magnenta = 35,
Cyan = 36,
White = 37,
};
void SetColor(Color color, Color background) {
printf("\x1b[%dm\x1b[%dm", (int)color, (int)background + 10);
}
void FlushCache(void* ptr, u32 size) {
svcFlushProcessDataCache(CUR_PROCESS_HANDLE, ptr, size);
}
void InvalidateCache(void* ptr, u32 size) {
svcInvalidateProcessDataCache(CUR_PROCESS_HANDLE, ptr, size);
}
vu16* dspP = (vu16*)0x1FF00000;
vu16* dspD = (vu16*)0x1FF40000;
u32 playground_size = 0x80;
vu8* dsp_playground = (vu8*)(dspD + 0x1000); // note: address = 0x1000 in dsp space
vu8* fcram_playground;
void PrintAll() {
consoleSelect(&topScreen);
MoveCursor(0, 0);
printf("DSP @ 0x1000:\n");
InvalidateCache((void*)dsp_playground, playground_size);
for (u32 i = 0; i < playground_size; ++i) {
u8 v = dsp_playground[i];
if (v != i) {
SetColor(Green, Black);
}
printf("%02X", v);
SetColor(Reset, Reset);
if (i % 16 == 15) {
printf("\n");
} else {
printf(" ");
}
}
u32 addr = (u32)fcram_playground;
if (addr < 0x1C000000) {
addr = addr - 0x14000000 + 0x20000000;
} else {
addr = addr - 0x30000000 + 0x20000000;
}
printf("\nFCRAM @ 0x%08lX:\n", addr);
InvalidateCache((void*)fcram_playground, playground_size);
for (u32 i = 0; i < playground_size; ++i) {
u8 v = fcram_playground[i];
if (v != (i | 0x80)) {
SetColor(Green, Black);
}
printf("%02X", v);
SetColor(Reset, Reset);
if (i % 16 == 15) {
printf("\n");
} else {
printf(" ");
}
}
consoleSelect(&bottomScreen);
}
void ResetDspPlayground() {
InvalidateCache((void*)dsp_playground, playground_size);
for (u32 i = 0; i < playground_size; ++i) {
dsp_playground[i] = i;
}
FlushCache((void*)dsp_playground, playground_size);
}
void ResetFcramPlayground() {
InvalidateCache((void*)fcram_playground, playground_size);
for (u32 i = 0; i < playground_size; ++i) {
fcram_playground[i] = i | 0x80;
}
FlushCache((void*)fcram_playground, playground_size);
}
int udp_s;
int udp_s_broadcast;
void UdpInit() {
#define SOC_ALIGN 0x1000
#define SOC_BUFFERSIZE 0x100000
static u32* SOC_buffer;
// allocate buffer for SOC service
SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE);
if (SOC_buffer == NULL) {
printf("memalign: failed to allocate\n");
return;
}
Result ret;
if ((ret = socInit(SOC_buffer, SOC_BUFFERSIZE)) != 0) {
printf("socInit: 0x%08lX\n", ret);
return;
}
sockaddr_in si_me;
// create a UDP socket
if ((udp_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
printf("socket() failed\n");
return;
}
// zero out the structure
memset(&si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(8888);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
// bind socket to port
if (bind(udp_s, (sockaddr*)&si_me, sizeof(si_me)) == -1) {
printf("bind() failed\n");
return;
}
// create a UDP broadcast socket
if ((udp_s_broadcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
printf("socket()(broadcast) failed\n");
return;
}
}
constexpr unsigned BUFLEN = 512;
char buf[BUFLEN];
void Fire() {
dspD[0] = 1;
FlushCache((void*)dspD, 8);
while(true) {
InvalidateCache((void*)dspD, 8);
if (dspD[0] == 0)
break;
}
}
void CheckPackage() {
sockaddr_in si_other;
socklen_t slen = sizeof(si_other);
int recv_len;
if ((recv_len = recvfrom(udp_s, buf, BUFLEN, MSG_DONTWAIT, (sockaddr*)&si_other, &slen)) < 4)
return;
u16 magic;
memcpy(&magic, buf, 2);
if (magic == 0xD592) {
std::vector<u16> command_package((recv_len - 2) / 2);
printf("Command received\n");
memcpy(command_package.data(), buf + 2, command_package.size() * 2);
switch (command_package[0]) {
case 0: {
if (command_package.size() != 2) {
printf("Wrong length for Read\n");
break;
}
u16 addr = command_package[1];
printf("Read [%04X] -> ", addr);
dspD[1] = 0;
dspD[2] = addr;
dspD[3] = 0xCCCC;
Fire();
printf("%04X\n", dspD[3]);
break;
}
case 1: {
if (command_package.size() != 3) {
printf("Wrong length for Write\n");
break;
}
u16 addr = command_package[1];
u16 value = command_package[2];
printf("Write [%04X] <- %04X", addr, value);
dspD[1] = 1;
dspD[2] = addr;
dspD[3] = value;
Fire();
printf(" OK\n");
break;
}
}
}
}
int main() {
fcram_playground = (vu8*)linearAlloc(playground_size);
ResetDspPlayground();
ResetFcramPlayground();
aptInit();
gfxInitDefault();
consoleInit(GFX_TOP, &topScreen);
consoleInit(GFX_BOTTOM, &bottomScreen);
consoleSelect(&bottomScreen);
printf("Hello!\n");
UdpInit();
printf("dspInit: %08lX\n", dspInit());
bool loaded = false;
printf("DSP_LoadComponent: %08lX\n",
DSP_LoadComponent(cdc_bin, cdc_bin_size, 0xFF, 0xFF, &loaded));
printf("loaded = %d\n", loaded);
svcSleepThread(1000000000);
char hostname[100];
gethostname(hostname, 100);
printf("IP: %s port: 8888\n", hostname);
// Main loop
while (aptMainLoop()) {
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break;
if (kDown & KEY_A) {
ResetDspPlayground();
printf("Reset DSP playground\n");
}
if (kDown & KEY_B) {
ResetFcramPlayground();
printf("Reset FCRAM playground\n");
}
CheckPackage();
PrintAll();
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
// Wait for VBlank
gspWaitForVBlank();
}
socExit();
dspExit();
gfxExit();
aptExit();
return 0;
}

View File

@@ -0,0 +1,20 @@
*.3dsx
*.elf
*.cxi
*.cia
build/
hide/
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,171 @@
segment p 0000
br 0x0000$0800 always// reset vector
br 0x0000$3000 always
br 0x0000$3000 always
br 0x0000$3000 always // int0
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
br 0x0000$3000 always // int1
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
br 0x0000$3000 always // int2
segment p 0800 // pre-write shutdown sequence
load 0x0080u8 page
clr b0 always
mov b0l [page:0x00c8u8] // T_REPLY2
br 0x0000$1800 always // jump to epilogue first to dump the initial register value
segment p 1000 // signal handler & prologue
load 0x0000u8 page
mov [page:0x0002u8] b0l
brr 0x0003 eq
clr b0 always
mov b0l [page:0x0000u8]
mov b0l [page:0x0002u8]
mov [page:0x0001u8] b0l
brr 0x0003 eq
mov b0l [page:0x0000u8]
clr b0 always
mov b0l [page:0x0001u8]
mov [page:0x0000u8] b0l
br 0x0000$1000 eq
mov 0x$2000 sp
mov 0x$0003 mod0 // disable SAR and PS so a/b/p can be correctly loaded
mov 0x$0000 mod3 // clear mod3 from E000 to 0000. Game does this at the beginning so let it be the default env
pop r7
pop r6
pop r5
pop r4
pop r3
pop r2
pop r1
pop r0
pop a0l
mov a0l mixp
pop repc
pop a0h
mov a0h stepj0
pop a0h
mov a0h stepi0
pop lc
pop p1
pop y1
pop x1
pop p0
pop y0
pop x0
pop sv
popa b1
pop b1e
popa b0
pop b0e
popa a1
pop a1e
popa a0
pop a0e
pop arp3
pop arp2
pop arp1
pop arp0
pop ar1
pop ar0
pop mod2
pop mod1
pop mod0
pop stt2
pop stt1
pop stt0
pop cfgj
pop cfgi
mov 0x$1000 sp
br 0x0000$2000 always
segment p 1800 // epilogue
mov 0x$3000 sp
push cfgi
push cfgj
push stt0
push stt1
push stt2
push mod0
push mod1
push mod2
push ar0
push ar1
push arp0
push arp1
push arp2
push arp3
mov 0x$0003 mod0 // disable SAR and PS so a/b/p can be correctly loaded
push a0e
pusha a0
push a1e
pusha a1
push b0e
pusha b0
push b1e
pusha b1
push sv
push x0
push y0
push p0
push x1
push y1
push p1
push lc
mov stepi0 a0h
push a0h
mov stepj0 a0h
push a0h
push repc
mov mixp a0l
push a0l
push r0
push r1
push r2
push r3
push r4
push r5
push r6
push r7
load 0x0000u8 page
mov [page:0x0003u8] b0l
brr 0x0003 eq
clr b0 always
mov b0l [page:0x0000u8]
mov b0l [page:0x0003u8]
br 0x0000$1000 always
segment p 2000 // test area
br 0x0000$1800 always
segment p 3000 // interrupt
reti always
segment d 0000 // signal area
data 0000
data 0000
data 0000
data 0000

View File

View File

@@ -0,0 +1,226 @@
BasicInfo:
Title : SVRS
ProductCode : CTR-P-SVRS
Logo : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem
RomFs:
# Specifies the root path of the read only file system to include in the ROM.
#RootPath : romfs
TitleInfo:
Category : Application
UniqueId : 0xff555
Option:
UseOnSD : true # true if App is to be installed to SD
FreeProductCode : true # Removes limitations on ProductCode
MediaFootPadding : false # If true CCI files are created with padding
EnableCrypt : false # Enables encryption for NCCH and CIA
EnableCompress : true # Compresses where applicable (currently only exefs:/.code)
AccessControlInfo:
CoreVersion : 2
# Exheader Format Version
DescVersion : 2
# Minimum Required Kernel Version (below is for 4.5.0)
ReleaseKernelMajor : "02"
ReleaseKernelMinor : "33"
# ExtData
UseExtSaveData : false # enables ExtData
#ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId
# FS:USER Archive Access Permissions
# Uncomment as required
FileSystemAccess:
- CategorySystemApplication
- CategoryHardwareCheck
- CategoryFileSystemTool
- Debug
#- TwlCardBackup
#- TwlNandData
#- Boss
- DirectSdmc
#- Core
#- CtrNandRo
#- CtrNandRw
#- CtrNandRoWrite
#- CategorySystemSettings
#- CardBoard
#- ExportImportIvs
#- DirectSdmcWrite
#- SwitchCleanup
#- SaveDataMove
#- Shop
#- Shell
#- CategoryHomeMenu
# Process Settings
MemoryType : Application # Application/System/Base
SystemMode : 64MB # 64MB(Default)/96MB/80MB/72MB/32MB
IdealProcessor : 0
AffinityMask : 1
Priority : 16
MaxCpu : 0 # Let system decide
HandleTableSize : 0x200
DisableDebug : false
EnableForceDebug : false
CanWriteSharedPage : false
CanUsePrivilegedPriority : false
CanUseNonAlphabetAndNumber : true
PermitMainFunctionArgument : true
CanShareDeviceMemory : true
RunnableOnSleep : false
SpecialMemoryArrange : false
# New3DS Exclusive Process Settings
SystemModeExt : Legacy # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode
CpuSpeed : 268MHz # 268MHz(Default)/804MHz
EnableL2Cache : false # false(default)/true
CanAccessCore2 : false
# Virtual Address Mappings
IORegisterMapping:
- 1ff00000-1ff7ffff # DSP memory
MemoryMapping:
- 1f000000-1f5fffff:r # VRAM
# Accessible SVCs, <Name>:<ID>
SystemCallAccess:
InvalidateProcessDataCache: 82
FlushProcessDataCache: 84
ArbitrateAddress: 34
Break: 60
CancelTimer: 28
ClearEvent: 25
ClearTimer: 29
CloseHandle: 35
ConnectToPort: 45
ControlMemory: 1
CreateAddressArbiter: 33
CreateEvent: 23
CreateMemoryBlock: 30
CreateMutex: 19
CreateSemaphore: 21
CreateThread: 8
CreateTimer: 26
DuplicateHandle: 39
ExitProcess: 3
ExitThread: 9
GetCurrentProcessorNumber: 17
GetHandleInfo: 41
GetProcessId: 53
GetProcessIdOfThread: 54
GetProcessIdealProcessor: 6
GetProcessInfo: 43
GetResourceLimit: 56
GetResourceLimitCurrentValues: 58
GetResourceLimitLimitValues: 57
GetSystemInfo: 42
GetSystemTick: 40
GetThreadContext: 59
GetThreadId: 55
GetThreadIdealProcessor: 15
GetThreadInfo: 44
GetThreadPriority: 11
MapMemoryBlock: 31
OutputDebugString: 61
QueryMemory: 2
ReleaseMutex: 20
ReleaseSemaphore: 22
SendSyncRequest1: 46
SendSyncRequest2: 47
SendSyncRequest3: 48
SendSyncRequest4: 49
SendSyncRequest: 50
SetThreadPriority: 12
SetTimer: 27
SignalEvent: 24
SleepThread: 10
UnmapMemoryBlock: 32
WaitSynchronization1: 36
WaitSynchronizationN: 37
Backdoor: 123
# Service List
# Maximum 34 services (32 if firmware is prior to 9.3.0)
ServiceAccessControl:
- cfg:u
- fs:USER
- gsp::Gpu
- hid:USER
- ndm:u
- pxi:dev
- APT:U
- ac:u
- act:u
- am:net
- boss:U
- cam:u
- cecd:u
- csnd:SND
- frd:u
- http:C
- ir:USER
- ir:u
- ir:rst
- ldr:ro
- mic:u
- news:u
- nfc:u
- nim:aoc
- nwm::UDS
- ptm:u
- qtm:u
- soc:U
- ssl:C
- y2r:u
- ps:ps
SystemControlInfo:
SaveDataSize: 512K
RemasterVersion: 0
StackSize: 0x40000
# Modules that run services listed above should be included below
# Maximum 48 dependencies
# If a module is listed that isn't present on the 3DS, the title will get stuck at the logo (3ds waves)
# So act, nfc and qtm are commented for 4.x support. Uncomment if you need these.
# <module name>:<module titleid>
Dependency:
ac: 0x0004013000002402
#act: 0x0004013000003802
am: 0x0004013000001502
boss: 0x0004013000003402
camera: 0x0004013000001602
cecd: 0x0004013000002602
cfg: 0x0004013000001702
codec: 0x0004013000001802
csnd: 0x0004013000002702
dlp: 0x0004013000002802
dsp: 0x0004013000001a02
friends: 0x0004013000003202
gpio: 0x0004013000001b02
gsp: 0x0004013000001c02
hid: 0x0004013000001d02
http: 0x0004013000002902
i2c: 0x0004013000001e02
ir: 0x0004013000003302
mcu: 0x0004013000001f02
mic: 0x0004013000002002
ndm: 0x0004013000002b02
news: 0x0004013000003502
#nfc: 0x0004013000004002
nim: 0x0004013000002c02
nwm: 0x0004013000002d02
pdn: 0x0004013000002102
ps: 0x0004013000003102
ptm: 0x0004013000002202
#qtm: 0x0004013020004202
ro: 0x0004013000003702
socket: 0x0004013000002e02
spi: 0x0004013000002302
ssl: 0x0004013000002f02

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env python3
import sys
import socket
import struct
for UDP_IP in ["192.168.1.158", "127.0.0.1"]:
UDP_PORT = 8888
MESSAGE = struct.pack('<H', 0xD590)
for i in range(1, len(sys.argv)):
if sys.argv[i] == '-1':
MESSAGE = struct.pack('<H', 0xD591)
continue
inst = sys.argv[i]
splitted = inst.split('+')
code = int(splitted[0], 16)
for param in splitted[1:]:
v, p = param.split('@')
code += int(v) << int(p)
MESSAGE += struct.pack('<H', code)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

View File

@@ -0,0 +1,665 @@
#include <string>
#include <unordered_map>
#include <vector>
#include <3ds.h>
#include <arpa/inet.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include "cdc_bin.h"
#define COMMON_TYPE_3DS
#include "../../src/test.h"
PrintConsole topScreen, bottomScreen;
void MoveCursor(unsigned row, unsigned col) {
printf("\x1b[%u;%uH", row + 1, col + 1);
}
enum Color {
Reset = 0,
Black = 30,
Red = 31,
Green = 32,
Yellow = 33,
Blue = 34,
Magnenta = 35,
Cyan = 36,
White = 37,
};
void SetColor(Color color, Color background) {
printf("\x1b[%dm\x1b[%dm", (int)color, (int)background + 10);
}
class IReg {
public:
IReg(const std::string& name, const std::string& flags) : name(name), flags(flags) {}
virtual ~IReg() = default;
virtual unsigned GetLength() = 0;
virtual unsigned GetSrcDigit(unsigned pos) = 0;
virtual unsigned GetDstDigit(unsigned pos) = 0;
virtual void SetSrcDigit(unsigned pos, unsigned value) = 0;
virtual unsigned GetDigitRange() = 0;
void Print(unsigned row, unsigned col, unsigned selected) {
SetColor(Cyan, Black);
MoveCursor(row, col - name.size());
printf("%s", name.c_str());
unsigned len = GetLength();
for (unsigned i = 0; i < len; ++i) {
unsigned src = GetSrcDigit(len - i - 1);
unsigned dst = GetDstDigit(len - i - 1);
MoveCursor(row, col + i);
if (len - i - 1 == selected)
SetColor(Black, White);
else
SetColor(White, Black);
if (flags.empty())
printf("%X", src);
else
printf("%c", src ? flags[i] : '-');
MoveCursor(row + 1, col + i);
SetColor(src == dst ? Magnenta : Green, Black);
if (flags.empty())
printf("%X", dst);
else
printf("%c", dst ? flags[i] : '-');
}
}
private:
std::string name, flags;
};
class HexReg : public IReg {
public:
HexReg(const std::string& name, u16& src, u16& dst) : IReg(name, ""), src(src), dst(dst) {
src = dst;
}
unsigned GetLength() override {
return 4;
}
unsigned GetSrcDigit(unsigned pos) override {
return (src >> (pos * 4)) & 0xF;
}
unsigned GetDstDigit(unsigned pos) override {
return (dst >> (pos * 4)) & 0xF;
}
void SetSrcDigit(unsigned pos, unsigned value) override {
src &= ~(0xF << (pos * 4));
src |= value << (pos * 4);
}
unsigned GetDigitRange() override {
return 16;
}
private:
u16& src;
u16& dst;
};
class BinReg : public IReg {
public:
BinReg(const std::string& name, u16& src, u16& dst, const std::string flags)
: IReg(name, flags), src(src), dst(dst) {
src = dst;
}
unsigned GetLength() override {
return 16;
}
unsigned GetSrcDigit(unsigned pos) override {
return (src >> pos) & 1;
}
unsigned GetDstDigit(unsigned pos) override {
return (dst >> pos) & 1;
}
void SetSrcDigit(unsigned pos, unsigned value) override {
src &= ~(1 << pos);
src |= value << pos;
}
unsigned GetDigitRange() override {
return 2;
}
private:
u16& src;
u16& dst;
};
u16* dspP = (u16*)0x1FF00000;
u16* dspD = (u16*)0x1FF40000;
u16* srcBase = &dspD[0x2000];
u16* dstBase = &dspD[0x2FD0];
constexpr u32 reg_region_size = 0x60;
std::unordered_map<std::string, unsigned> reg_map;
IReg* MakeHexReg(const std::string& name, unsigned offset) {
reg_map[name] = offset;
return new HexReg(name, srcBase[offset], dstBase[offset]);
}
IReg* MakeBinReg(const std::string& name, unsigned offset, const std::string flags = "") {
reg_map[name] = offset;
return new BinReg(name, srcBase[offset], dstBase[offset], flags);
}
constexpr unsigned t_row = 15;
constexpr unsigned t_col = 4;
IReg* grid[t_row][t_col] = {};
unsigned c_row = 0, c_col = 0, c_pos = 0;
void PrintGrid(unsigned row, unsigned col) {
IReg* r = grid[row][col];
if (!r)
return;
r->Print(row * 2, 4 + col * 9, row == c_row && col == c_col ? c_pos : 0xFFFFFFFF);
}
void PrintAll() {
for (unsigned row = 0; row < t_row; ++row)
for (unsigned col = 0; col < t_col; ++col)
PrintGrid(row, col);
}
void FlushCache(void* ptr, u32 size) {
svcFlushProcessDataCache(CUR_PROCESS_HANDLE, ptr, size);
}
void InvalidateCache(void* ptr, u32 size) {
svcInvalidateProcessDataCache(CUR_PROCESS_HANDLE, ptr, size);
}
void StartDspProgram() {
dspD[1] = 1;
FlushCache(&dspD[1], 2);
while (dspD[1])
InvalidateCache(&dspD[1], 2);
}
void StopDspProgram() {
dspD[2] = 1;
FlushCache(&dspD[2], 2);
while (dspD[2])
InvalidateCache(&dspD[2], 2);
}
void SetOnshotDspProgram() {
dspD[3] = 1;
FlushCache(&dspD[3], 2);
}
void PulseDspProgram() {
SetOnshotDspProgram();
StartDspProgram();
StopDspProgram();
}
void ExecuteTestCases() {
consoleSelect(&bottomScreen);
printf("--------\nExecuting test cases...!\n");
FILE* fi = fopen("teaklite2_tests", "rb");
if (!fi)
printf("failed to open input file\n");
FILE* fo = fopen("teaklite2_tests_result", "wb");
if (!fo)
printf("failed to open output file\n");
StopDspProgram();
int i = 0;
while (true) {
TestCase test_case;
if (!fread(&test_case, sizeof(test_case), 1, fi))
break;
srcBase[reg_map.at("a0l")] = test_case.before.a[0] & 0xFFFF;
srcBase[reg_map.at("a0h")] = (test_case.before.a[0] >> 16) & 0xFFFF;
srcBase[reg_map.at("a0e")] = (test_case.before.a[0] >> 32) & 0xFFFF;
srcBase[reg_map.at("a1l")] = test_case.before.a[1] & 0xFFFF;
srcBase[reg_map.at("a1h")] = (test_case.before.a[1] >> 16) & 0xFFFF;
srcBase[reg_map.at("a1e")] = (test_case.before.a[1] >> 32) & 0xFFFF;
srcBase[reg_map.at("b0l")] = test_case.before.b[0] & 0xFFFF;
srcBase[reg_map.at("b0h")] = (test_case.before.b[0] >> 16) & 0xFFFF;
srcBase[reg_map.at("b0e")] = (test_case.before.b[0] >> 32) & 0xFFFF;
srcBase[reg_map.at("b1l")] = test_case.before.b[1] & 0xFFFF;
srcBase[reg_map.at("b1h")] = (test_case.before.b[1] >> 16) & 0xFFFF;
srcBase[reg_map.at("b1e")] = (test_case.before.b[1] >> 32) & 0xFFFF;
srcBase[reg_map.at("p0l")] = test_case.before.p[0] & 0xFFFF;
srcBase[reg_map.at("p0h")] = (test_case.before.p[0] >> 16) & 0xFFFF;
srcBase[reg_map.at("p1l")] = test_case.before.p[1] & 0xFFFF;
srcBase[reg_map.at("p1h")] = (test_case.before.p[1] >> 16) & 0xFFFF;
srcBase[reg_map.at("r0")] = test_case.before.r[0];
srcBase[reg_map.at("r1")] = test_case.before.r[1];
srcBase[reg_map.at("r2")] = test_case.before.r[2];
srcBase[reg_map.at("r3")] = test_case.before.r[3];
srcBase[reg_map.at("r4")] = test_case.before.r[4];
srcBase[reg_map.at("r5")] = test_case.before.r[5];
srcBase[reg_map.at("r6")] = test_case.before.r[6];
srcBase[reg_map.at("r7")] = test_case.before.r[7];
srcBase[reg_map.at("x0")] = test_case.before.x[0];
srcBase[reg_map.at("y0")] = test_case.before.y[0];
srcBase[reg_map.at("x1")] = test_case.before.x[1];
srcBase[reg_map.at("y1")] = test_case.before.y[1];
srcBase[reg_map.at("sti0")] = test_case.before.stepi0;
srcBase[reg_map.at("stj0")] = test_case.before.stepj0;
srcBase[reg_map.at("mixp")] = test_case.before.mixp;
srcBase[reg_map.at("sv")] = test_case.before.sv;
srcBase[reg_map.at("repc")] = test_case.before.repc;
srcBase[reg_map.at("lc")] = test_case.before.lc;
srcBase[reg_map.at("cfgi")] = test_case.before.cfgi;
srcBase[reg_map.at("cfgj")] = test_case.before.cfgj;
srcBase[reg_map.at("stt0")] = test_case.before.stt0;
srcBase[reg_map.at("stt1")] = test_case.before.stt1;
srcBase[reg_map.at("stt2")] = test_case.before.stt2;
srcBase[reg_map.at("mod0")] = test_case.before.mod0;
srcBase[reg_map.at("mod1")] = test_case.before.mod1;
srcBase[reg_map.at("mod2")] = test_case.before.mod2;
srcBase[reg_map.at("ar0")] = test_case.before.ar[0];
srcBase[reg_map.at("ar1")] = test_case.before.ar[1];
srcBase[reg_map.at("arp0")] = test_case.before.arp[0];
srcBase[reg_map.at("arp1")] = test_case.before.arp[1];
srcBase[reg_map.at("arp2")] = test_case.before.arp[2];
srcBase[reg_map.at("arp3")] = test_case.before.arp[3];
for (u16 i = 0; i < TestSpaceSize; ++i) {
dspD[TestSpaceX + i] = test_case.before.test_space_x[i];
dspD[TestSpaceY + i] = test_case.before.test_space_y[i];
}
InvalidateCache(&dspP[0x2000], 0x2000);
dspP[0x2000] = test_case.opcode;
dspP[0x2001] = test_case.expand;
dspP[0x2002] = 0x0000; // nop
dspP[0x2003] = 0x0000; // nop
dspP[0x2004] = 0x0000; // nop
dspP[0x2005] = 0x4180; // br 0x1800
dspP[0x2006] = 0x1800;
FlushCache(&dspP[0x2000], 0x2000);
FlushCache(&dspD[0], 0x20000);
InvalidateCache(&dspD[0], 0x20000);
PulseDspProgram();
FlushCache(&dspD[0], 0x20000);
InvalidateCache(&dspD[0], 0x20000);
test_case.after.a[0] = dstBase[reg_map.at("a0l")] |
((u64)dstBase[reg_map.at("a0h")] << 16) |
((u64)dstBase[reg_map.at("a0e")] << 32);
test_case.after.a[1] = dstBase[reg_map.at("a1l")] |
((u64)dstBase[reg_map.at("a1h")] << 16) |
((u64)dstBase[reg_map.at("a1e")] << 32);
test_case.after.b[0] = dstBase[reg_map.at("b0l")] |
((u64)dstBase[reg_map.at("b0h")] << 16) |
((u64)dstBase[reg_map.at("b0e")] << 32);
test_case.after.b[1] = dstBase[reg_map.at("b1l")] |
((u64)dstBase[reg_map.at("b1h")] << 16) |
((u64)dstBase[reg_map.at("b1e")] << 32);
test_case.after.p[0] = dstBase[reg_map.at("p0l")] | ((u64)dstBase[reg_map.at("p0h")] << 16);
test_case.after.p[1] = dstBase[reg_map.at("p1l")] | ((u64)dstBase[reg_map.at("p1h")] << 16);
test_case.after.r[0] = dstBase[reg_map.at("r0")];
test_case.after.r[1] = dstBase[reg_map.at("r1")];
test_case.after.r[2] = dstBase[reg_map.at("r2")];
test_case.after.r[3] = dstBase[reg_map.at("r3")];
test_case.after.r[4] = dstBase[reg_map.at("r4")];
test_case.after.r[5] = dstBase[reg_map.at("r5")];
test_case.after.r[6] = dstBase[reg_map.at("r6")];
test_case.after.r[7] = dstBase[reg_map.at("r7")];
test_case.after.x[0] = dstBase[reg_map.at("x0")];
test_case.after.y[0] = dstBase[reg_map.at("y0")];
test_case.after.x[1] = dstBase[reg_map.at("x1")];
test_case.after.y[1] = dstBase[reg_map.at("y1")];
test_case.after.stepi0 = dstBase[reg_map.at("sti0")];
test_case.after.stepj0 = dstBase[reg_map.at("stj0")];
test_case.after.mixp = dstBase[reg_map.at("mixp")];
test_case.after.sv = dstBase[reg_map.at("sv")];
test_case.after.repc = dstBase[reg_map.at("repc")];
test_case.after.lc = dstBase[reg_map.at("lc")];
test_case.after.cfgi = dstBase[reg_map.at("cfgi")];
test_case.after.cfgj = dstBase[reg_map.at("cfgj")];
test_case.after.stt0 = dstBase[reg_map.at("stt0")];
test_case.after.stt1 = dstBase[reg_map.at("stt1")];
test_case.after.stt2 = dstBase[reg_map.at("stt2")];
test_case.after.mod0 = dstBase[reg_map.at("mod0")];
test_case.after.mod1 = dstBase[reg_map.at("mod1")];
test_case.after.mod2 = dstBase[reg_map.at("mod2")];
test_case.after.ar[0] = dstBase[reg_map.at("ar0")];
test_case.after.ar[1] = dstBase[reg_map.at("ar1")];
test_case.after.arp[0] = dstBase[reg_map.at("arp0")];
test_case.after.arp[1] = dstBase[reg_map.at("arp1")];
test_case.after.arp[2] = dstBase[reg_map.at("arp2")];
test_case.after.arp[3] = dstBase[reg_map.at("arp3")];
for (u16 i = 0; i < TestSpaceSize; ++i) {
test_case.after.test_space_x[i] = dspD[TestSpaceX + i];
test_case.after.test_space_y[i] = dspD[TestSpaceY + i];
}
fwrite(&test_case, sizeof(test_case), 1, fo);
++i;
if (i % 100 == 0)
printf("case %d\n", i);
}
fclose(fi);
fclose(fo);
printf("Finished!\n");
consoleSelect(&topScreen);
}
void UploadDspProgram(const std::vector<u16>& code, bool oneshot) {
StopDspProgram();
InvalidateCache(&dspP[0x2000], 0x2000);
memcpy(&dspP[0x2000], code.data(), code.size() * 2);
unsigned end = 0x2000 + code.size();
dspP[end + 0] = 0x0000; // nop
dspP[end + 1] = 0x0000; // nop
dspP[end + 2] = 0x0000; // nop
dspP[end + 3] = 0x4180; // br 0x1800
dspP[end + 4] = 0x1800;
FlushCache(&dspP[0x2000], 0x2000);
if (oneshot) {
PulseDspProgram();
} else {
StartDspProgram();
}
}
int udp_s;
int udp_s_broadcast;
void UdpInit() {
#define SOC_ALIGN 0x1000
#define SOC_BUFFERSIZE 0x100000
static u32* SOC_buffer;
// allocate buffer for SOC service
SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE);
if (SOC_buffer == NULL) {
printf("memalign: failed to allocate\n");
return;
}
Result ret;
if ((ret = socInit(SOC_buffer, SOC_BUFFERSIZE)) != 0) {
printf("socInit: 0x%08lX\n", ret);
return;
}
sockaddr_in si_me;
// create a UDP socket
if ((udp_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
printf("socket() failed\n");
return;
}
// zero out the structure
memset(&si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(8888);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
// bind socket to port
if (bind(udp_s, (sockaddr*)&si_me, sizeof(si_me)) == -1) {
printf("bind() failed\n");
return;
}
// create a UDP broadcast socket
if ((udp_s_broadcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
printf("socket()(broadcast) failed\n");
return;
}
}
void CheckPackage() {
constexpr unsigned BUFLEN = 512;
char buf[BUFLEN];
sockaddr_in si_other;
socklen_t slen = sizeof(si_other);
int recv_len;
if ((recv_len = recvfrom(udp_s, buf, BUFLEN, MSG_DONTWAIT, (sockaddr*)&si_other, &slen)) < 4)
return;
u16 magic;
memcpy(&magic, buf, 2);
if (magic == 0xD590 || magic == 0xD591) {
std::vector<u16> program_package((recv_len - 2) / 2);
memcpy(program_package.data(), buf + 2, program_package.size() * 2);
consoleSelect(&bottomScreen);
printf("--------\nNew program received!\n");
for (u16 code : program_package) {
printf("%04X ", code);
}
UploadDspProgram(program_package, magic == 0xD591);
printf("\nUploaded!\n");
consoleSelect(&topScreen);
} else if (magic == 0x4352) {
recv_len -= 2;
if ((unsigned)recv_len > reg_region_size)
recv_len = reg_region_size;
consoleSelect(&bottomScreen);
printf("--------\nRegister sync received!\n");
memcpy(srcBase, buf + 2, recv_len);
printf("\nSynced!\n");
consoleSelect(&topScreen);
}
}
int main() {
aptInit();
gfxInitDefault();
consoleInit(GFX_TOP, &topScreen);
consoleInit(GFX_BOTTOM, &bottomScreen);
consoleSelect(&bottomScreen);
printf("Hello!\n");
UdpInit();
printf("dspInit: %08lX\n", dspInit());
bool loaded = false;
printf("DSP_LoadComponent: %08lX\n",
DSP_LoadComponent(cdc_bin, cdc_bin_size, 0xFF, 0xFF, &loaded));
printf("loaded = %d\n", loaded);
consoleSelect(&topScreen);
svcSleepThread(1000000000);
grid[7][0] = MakeHexReg("r7", 0);
grid[6][0] = MakeHexReg("r6", 1);
grid[5][0] = MakeHexReg("r5", 2);
grid[4][0] = MakeHexReg("r4", 3);
grid[3][0] = MakeHexReg("r3", 4);
grid[2][0] = MakeHexReg("r2", 5);
grid[1][0] = MakeHexReg("r1", 6);
grid[0][0] = MakeHexReg("r0", 7);
grid[6][1] = MakeHexReg("mixp", 8);
grid[7][1] = MakeHexReg("repc", 9);
grid[5][1] = MakeHexReg("stj0", 0xA);
grid[5][2] = MakeHexReg("sti0", 0xB);
grid[7][2] = MakeHexReg("lc", 0xC);
grid[3][1] = MakeHexReg("p1h", 0xD);
grid[3][2] = MakeHexReg("p1l", 0xE);
grid[2][2] = MakeHexReg("y1", 0xF);
grid[2][1] = MakeHexReg("x1", 0x10);
grid[1][1] = MakeHexReg("p0h", 0x11);
grid[1][2] = MakeHexReg("p0l", 0x12);
grid[0][2] = MakeHexReg("y0", 0x13);
grid[0][1] = MakeHexReg("x0", 0x14);
grid[6][2] = MakeHexReg("sv", 0x15);
grid[12][1] = MakeHexReg("b1h", 0x16);
grid[12][2] = MakeHexReg("b1l", 0x17);
grid[12][0] = MakeHexReg("b1e", 0x18);
grid[11][1] = MakeHexReg("b0h", 0x19);
grid[11][2] = MakeHexReg("b0l", 0x1A);
grid[11][0] = MakeHexReg("b0e", 0x1B);
grid[10][1] = MakeHexReg("a1h", 0x1C);
grid[10][2] = MakeHexReg("a1l", 0x1D);
grid[10][0] = MakeHexReg("a1e", 0x1E);
grid[9][1] = MakeHexReg("a0h", 0x1F);
grid[9][2] = MakeHexReg("a0l", 0x20);
grid[9][0] = MakeHexReg("a0e", 0x21);
grid[13][3] = MakeBinReg("arp3", 0x22, "#RR#RRiiiiijjjjj");
grid[12][3] = MakeBinReg("arp2", 0x23, "#RR#RRiiiiijjjjj");
grid[11][3] = MakeBinReg("arp1", 0x24, "#RR#RRiiiiijjjjj");
grid[10][3] = MakeBinReg("arp0", 0x25, "#RR#RRiiiiijjjjj");
grid[9][3] = MakeBinReg("ar1", 0x26, "RRRRRRoosssoosss");
grid[8][3] = MakeBinReg("ar0", 0x27, "RRRRRRoosssoosss");
grid[7][3] = MakeBinReg("mod2", 0x28, "7654321m7654321M");
grid[6][3] = MakeBinReg("mod1", 0x29, "jicB####pppppppp");
grid[5][3] = MakeBinReg("mod0", 0x2A, "#QQ#PPooSYY###SS");
grid[4][3] = MakeBinReg("stt2", 0x2B, "LBBB####mm##V21I");
grid[3][3] = MakeBinReg("stt1", 0x2C, "QP#########R####");
grid[2][3] = MakeBinReg("stt0", 0x2D, "####C###ZMNVCELL");
grid[1][3] = MakeBinReg("cfgj", 0x2E, "mmmmmmmmmsssssss");
grid[0][3] = MakeBinReg("cfgi", 0x2F, "mmmmmmmmmsssssss");
MoveCursor(28, 0);
char hostname[100];
gethostname(hostname, 100);
printf("IP: %s port: 8888\n", hostname);
printf("X: use sample program Y: Fill memory");
// Main loop
while (aptMainLoop()) {
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break;
if (kDown & KEY_SELECT)
ExecuteTestCases();
if (kDown & KEY_DOWN) {
for (int next = (int)c_row + 1; next < (int)t_row; ++next) {
if (grid[next][c_col]) {
c_row = next;
break;
}
}
}
if (kDown & KEY_UP) {
for (int next = (int)c_row - 1; next >= 0; --next) {
if (grid[next][c_col]) {
c_row = next;
break;
}
}
}
if (kDown & KEY_LEFT) {
if (c_pos == grid[c_row][c_col]->GetLength() - 1) {
for (int next = (int)c_col - 1; next >= 0; --next) {
if (grid[c_row][next]) {
c_col = next;
c_pos = 0;
break;
}
}
} else {
++c_pos;
}
}
if (kDown & KEY_RIGHT) {
if (c_pos == 0) {
for (int next = (int)c_col + 1; next < (int)t_col; ++next) {
if (grid[c_row][next]) {
c_col = next;
c_pos = grid[c_row][c_col]->GetLength() - 1;
break;
}
}
} else {
--c_pos;
}
}
if (kDown & KEY_A) {
unsigned v = grid[c_row][c_col]->GetSrcDigit(c_pos);
++v;
if (v == grid[c_row][c_col]->GetDigitRange())
v = 0;
grid[c_row][c_col]->SetSrcDigit(c_pos, v);
}
if (kDown & KEY_B) {
unsigned v = grid[c_row][c_col]->GetSrcDigit(c_pos);
if (v == 0)
v = grid[c_row][c_col]->GetDigitRange();
--v;
grid[c_row][c_col]->SetSrcDigit(c_pos, v);
}
if (kDown & KEY_X) {
UploadDspProgram({0x86A0}, false); // add r0, a0
}
if (kDown & KEY_Y) {
FlushCache(&dspD[0x3000], 0x40000 - 0x6000);
for (u32 i = 0x3000; i < 0x20000; ++i) {
dspD[i] = i; // i >> 4;
}
InvalidateCache(&dspD[0x3000], 0x40000 - 0x6000);
}
if (kDown & KEY_TOUCH) {
consoleSelect(&bottomScreen);
printf("--------\nSending register sync!\n");
u8 buf[reg_region_size + 2];
u16 magic = 0x4352;
memcpy(buf, &magic, 2);
memcpy(buf + 2, srcBase, reg_region_size);
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
addr.sin_addr.s_addr = 0xFFFFFFFF;
sendto(udp_s_broadcast, buf, reg_region_size + 2, 0, (sockaddr*)&addr, sizeof(addr));
printf("\nSynced!\n");
consoleSelect(&topScreen);
}
FlushCache(&dspD[0x2000], 0x1000);
InvalidateCache(&dspD[0x2000], 0x2000);
PrintAll();
CheckPackage();
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
// Wait for VBlank
gspWaitForVBlank();
}
socExit();
dspExit();
gfxExit();
aptExit();
return 0;
}

View File

@@ -0,0 +1,20 @@
*.3dsx
*.elf
*.cxi
*.cia
build/
hide/
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,53 @@
segment p 0000
br 0x0000$0800 always // reset vector
reti always
data 0000
reti always
data 0000
reti always // int0
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
reti always // int1
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
data 0000
reti always // int2
segment p 0800 // init
mov 0x$f000 sp // set stack pointer
mov 0x$0880 mod3 // enable interrupt
load 0x0082u8 page // configure ICU
mov 0x$1000 r0
mov r0 [page:0x0014u8] // set IRQ0 vint address low
mov 0x$8001 r0 // !mov 0x$0000 r0
mov r0 [page:0x0012u8] // set IRQ0 vint address high & context
mov 0x$0001 r0
mov r0 [page:0x000cu8] // enable IRQ0 as vint
load 0x00aau8 page
cntx s
load 0x00bbu8 page
mov 0x$0001 r0
mov 0x$8204 r1
mov r0 [r1] // trigger IRQ0
brr 0xffff always
segment p 11000 // interrup handler
mov st1 r0
load 0x0000u8 page
mov r0 [page:0x0000u8]
mov 0x$1234 r0
mov r0 [page:0x0001u8]
brr 0xffff always
segment d 0000 // signal area
data 0000
data 0000

View File

@@ -0,0 +1,228 @@
BasicInfo:
Title : SVRT
ProductCode : CTR-P-SVRT
Logo : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem
RomFs:
# Specifies the root path of the read only file system to include in the ROM.
#RootPath : romfs
TitleInfo:
Category : Application
UniqueId : 0xff557
Option:
UseOnSD : true # true if App is to be installed to SD
FreeProductCode : true # Removes limitations on ProductCode
MediaFootPadding : false # If true CCI files are created with padding
EnableCrypt : false # Enables encryption for NCCH and CIA
EnableCompress : true # Compresses where applicable (currently only exefs:/.code)
AccessControlInfo:
CoreVersion : 2
# Exheader Format Version
DescVersion : 2
# Minimum Required Kernel Version (below is for 4.5.0)
ReleaseKernelMajor : "02"
ReleaseKernelMinor : "33"
# ExtData
UseExtSaveData : false # enables ExtData
#ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId
# FS:USER Archive Access Permissions
# Uncomment as required
FileSystemAccess:
- CategorySystemApplication
- CategoryHardwareCheck
- CategoryFileSystemTool
- Debug
#- TwlCardBackup
#- TwlNandData
#- Boss
- DirectSdmc
#- Core
#- CtrNandRo
#- CtrNandRw
#- CtrNandRoWrite
#- CategorySystemSettings
#- CardBoard
#- ExportImportIvs
#- DirectSdmcWrite
#- SwitchCleanup
#- SaveDataMove
#- Shop
#- Shell
#- CategoryHomeMenu
# Process Settings
MemoryType : Application # Application/System/Base
SystemMode : 64MB # 64MB(Default)/96MB/80MB/72MB/32MB
IdealProcessor : 0
AffinityMask : 1
Priority : 16
MaxCpu : 0 # Let system decide
HandleTableSize : 0x200
DisableDebug : false
EnableForceDebug : false
CanWriteSharedPage : false
CanUsePrivilegedPriority : true
CanUseNonAlphabetAndNumber : true
PermitMainFunctionArgument : true
CanShareDeviceMemory : true
RunnableOnSleep : false
SpecialMemoryArrange : false
# New3DS Exclusive Process Settings
SystemModeExt : Legacy # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode
CpuSpeed : 268MHz # 268MHz(Default)/804MHz
EnableL2Cache : false # false(default)/true
CanAccessCore2 : false
# Virtual Address Mappings
IORegisterMapping:
- 1ed03000-1ed03fff # DSP registers
- 1ff00000-1ff7ffff # DSP memory
MemoryMapping:
- 1f000000-1f5fffff:r # VRAM
# Accessible SVCs, <Name>:<ID>
SystemCallAccess:
InvalidateProcessDataCache: 82
FlushProcessDataCache: 84
ArbitrateAddress: 34
Break: 60
CancelTimer: 28
ClearEvent: 25
ClearTimer: 29
CloseHandle: 35
ConnectToPort: 45
ControlMemory: 1
CreateAddressArbiter: 33
CreateEvent: 23
CreateMemoryBlock: 30
CreateMutex: 19
CreateSemaphore: 21
CreateThread: 8
CreateTimer: 26
DuplicateHandle: 39
ExitProcess: 3
ExitThread: 9
GetCurrentProcessorNumber: 17
GetHandleInfo: 41
GetProcessId: 53
GetProcessIdOfThread: 54
GetProcessIdealProcessor: 6
GetProcessInfo: 43
GetResourceLimit: 56
GetResourceLimitCurrentValues: 58
GetResourceLimitLimitValues: 57
GetSystemInfo: 42
GetSystemTick: 40
GetThreadContext: 59
GetThreadId: 55
GetThreadIdealProcessor: 15
GetThreadInfo: 44
GetThreadPriority: 11
MapMemoryBlock: 31
OutputDebugString: 61
QueryMemory: 2
ReleaseMutex: 20
ReleaseSemaphore: 22
SendSyncRequest1: 46
SendSyncRequest2: 47
SendSyncRequest3: 48
SendSyncRequest4: 49
SendSyncRequest: 50
SetThreadPriority: 12
SetTimer: 27
SignalEvent: 24
SleepThread: 10
UnmapMemoryBlock: 32
WaitSynchronization1: 36
WaitSynchronizationN: 37
Backdoor: 123
BindInterrupt: 80
# Service List
# Maximum 34 services (32 if firmware is prior to 9.3.0)
ServiceAccessControl:
- cfg:u
- fs:USER
- gsp::Gpu
- hid:USER
- ndm:u
- pxi:dev
- APT:U
- ac:u
- act:u
- am:net
- boss:U
- cam:u
- cecd:u
- csnd:SND
- frd:u
- http:C
- ir:USER
- ir:u
- ir:rst
- ldr:ro
- mic:u
- news:u
- nfc:u
- nim:aoc
- nwm::UDS
- ptm:u
- qtm:u
- soc:U
- ssl:C
- y2r:u
- ps:ps
SystemControlInfo:
SaveDataSize: 512K
RemasterVersion: 0
StackSize: 0x40000
# Modules that run services listed above should be included below
# Maximum 48 dependencies
# If a module is listed that isn't present on the 3DS, the title will get stuck at the logo (3ds waves)
# So act, nfc and qtm are commented for 4.x support. Uncomment if you need these.
# <module name>:<module titleid>
Dependency:
ac: 0x0004013000002402
#act: 0x0004013000003802
am: 0x0004013000001502
boss: 0x0004013000003402
camera: 0x0004013000001602
cecd: 0x0004013000002602
cfg: 0x0004013000001702
codec: 0x0004013000001802
csnd: 0x0004013000002702
dlp: 0x0004013000002802
dsp: 0x0004013000001a02
friends: 0x0004013000003202
gpio: 0x0004013000001b02
gsp: 0x0004013000001c02
hid: 0x0004013000001d02
http: 0x0004013000002902
i2c: 0x0004013000001e02
ir: 0x0004013000003302
mcu: 0x0004013000001f02
mic: 0x0004013000002002
ndm: 0x0004013000002b02
news: 0x0004013000003502
#nfc: 0x0004013000004002
nim: 0x0004013000002c02
nwm: 0x0004013000002d02
pdn: 0x0004013000002102
ps: 0x0004013000003102
ptm: 0x0004013000002202
#qtm: 0x0004013020004202
ro: 0x0004013000003702
socket: 0x0004013000002e02
spi: 0x0004013000002302
ssl: 0x0004013000002f02

View File

@@ -0,0 +1,28 @@
#!/usr/bin/env python3
import sys
import socket
import struct
for UDP_IP in ["192.168.1.158", "127.0.0.1"]:
UDP_PORT = 8888
MESSAGE = struct.pack('<H', 0xD592)
for i in range(1, len(sys.argv)):
inst = sys.argv[i]
if inst == "r":
MESSAGE += struct.pack('<H', 0)
continue
elif inst == "w":
MESSAGE += struct.pack('<H', 1)
continue
elif inst == "hr":
MESSAGE += struct.pack('<H', 2)
continue
elif inst == "hw":
MESSAGE += struct.pack('<H', 3)
continue
MESSAGE += struct.pack('<H', int(inst, 16))
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

View File

@@ -0,0 +1,291 @@
#include <atomic>
#include <string>
#include <unordered_map>
#include <vector>
#include <3ds.h>
#include <arpa/inet.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include "cdc_bin.h"
PrintConsole topScreen, bottomScreen;
void MoveCursor(unsigned row, unsigned col) {
printf("\x1b[%u;%uH", row + 1, col + 1);
}
enum Color {
Reset = 0,
Black = 30,
Red = 31,
Green = 32,
Yellow = 33,
Blue = 34,
Magnenta = 35,
Cyan = 36,
White = 37,
};
void SetColor(Color color, Color background) {
printf("\x1b[%dm\x1b[%dm", (int)color, (int)background + 10);
}
void FlushCache(volatile void* ptr, u32 size) {
svcFlushProcessDataCache(CUR_PROCESS_HANDLE, (void*)ptr, size);
}
void InvalidateCache(volatile void* ptr, u32 size) {
svcInvalidateProcessDataCache(CUR_PROCESS_HANDLE, (void*)ptr, size);
}
vu16* dspP = (vu16*)0x1FF00000;
vu16* dspD = (vu16*)0x1FF40000;
std::atomic<int> interrupt_counter;
void PrintAll() {
consoleSelect(&topScreen);
MoveCursor(0, 0);
printf("DSP registers:\n");
InvalidateCache(dspD + 0, 2 * 2);
printf("st1 = %04X\n", dspD[0]);
printf("mgc = %04X\n", dspD[1]);
consoleSelect(&bottomScreen);
}
int udp_s;
int udp_s_broadcast;
void UdpInit() {
#define SOC_ALIGN 0x1000
#define SOC_BUFFERSIZE 0x100000
static u32* SOC_buffer;
// allocate buffer for SOC service
SOC_buffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE);
if (SOC_buffer == NULL) {
printf("memalign: failed to allocate\n");
return;
}
Result ret;
if ((ret = socInit(SOC_buffer, SOC_BUFFERSIZE)) != 0) {
printf("socInit: 0x%08lX\n", ret);
return;
}
sockaddr_in si_me;
// create a UDP socket
if ((udp_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
printf("socket() failed\n");
return;
}
// zero out the structure
memset(&si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(8888);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
// bind socket to port
if (bind(udp_s, (sockaddr*)&si_me, sizeof(si_me)) == -1) {
printf("bind() failed\n");
return;
}
// create a UDP broadcast socket
if ((udp_s_broadcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
printf("socket()(broadcast) failed\n");
return;
}
}
constexpr unsigned BUFLEN = 512;
char buf[BUFLEN];
void Fire() {
dspD[0] = 1;
FlushCache((void*)dspD, 8);
while (true) {
InvalidateCache((void*)dspD, 8);
if (dspD[0] == 0)
break;
}
}
void CheckPackage() {
sockaddr_in si_other;
socklen_t slen = sizeof(si_other);
int recv_len;
if ((recv_len = recvfrom(udp_s, buf, BUFLEN, MSG_DONTWAIT, (sockaddr*)&si_other, &slen)) < 4)
return;
u16 magic;
memcpy(&magic, buf, 2);
if (magic == 0xD592) {
std::vector<u16> command_package((recv_len - 2) / 2);
printf("Command received\n");
memcpy(command_package.data(), buf + 2, command_package.size() * 2);
switch (command_package[0]) {
case 0: {
if (command_package.size() != 2) {
printf("Wrong length for Read\n");
break;
}
u16 addr = command_package[1];
printf("Read [%04X] -> ", addr);
dspD[1] = 0;
dspD[2] = addr;
dspD[3] = 0xCCCC;
Fire();
printf("%04X\n", dspD[3]);
break;
}
case 1: {
if (command_package.size() != 3) {
printf("Wrong length for Write\n");
break;
}
u16 addr = command_package[1];
u16 value = command_package[2];
printf("Write [%04X] <- %04X", addr, value);
dspD[1] = 1;
dspD[2] = addr;
dspD[3] = value;
Fire();
printf(" OK\n");
break;
}
case 2: {
if (command_package.size() != 3) {
printf("Wrong length for CPU Read\n");
break;
}
u32 addr = command_package[1] | ((u32)command_package[2] << 16);
printf("Read CPU [%08lX] -> ", addr);
// FlushCache((vu16*)addr, 2);
printf("%04X\n", *(vu16*)(addr));
break;
}
case 3: {
if (command_package.size() != 4) {
printf("Wrong length for CPU Write\n");
break;
}
u32 addr = command_package[1] | ((u32)command_package[2] << 16);
u16 value = command_package[3];
printf("Write CPU [%08lX] <- %04X", addr, value);
// InvalidateCache((vu16*)addr, 2);
*(vu16*)(addr) = value;
printf(" OK\n");
break;
}
}
}
}
Handle pmHandle;
Result pmInit_(void) {
Result res = srvGetServiceHandle(&pmHandle, "pm:app");
return res;
}
void pmExit_(void) {
svcCloseHandle(pmHandle);
}
Result PM_TerminateTitle(u64 tid, u64 timeout) {
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x4, 4, 0);
cmdbuf[1] = tid & 0xFFFFFFFF;
cmdbuf[2] = tid >> 32;
cmdbuf[3] = timeout & 0xffffffff;
cmdbuf[4] = (timeout >> 32) & 0xffffffff;
if (R_FAILED(ret = svcSendSyncRequest(pmHandle)))
return ret;
return (Result)cmdbuf[1];
}
Handle dsp_interrupt;
Handle threadA;
u32 threadA_stack[0x400];
void threadA_entry(void*) {
while (true) {
svcWaitSynchronization(dsp_interrupt, INT64_MAX);
++interrupt_counter;
}
}
int main() {
aptInit();
gfxInitDefault();
consoleInit(GFX_TOP, &topScreen);
consoleInit(GFX_BOTTOM, &bottomScreen);
consoleSelect(&bottomScreen);
printf("Hello!\n");
UdpInit();
printf("dspInit: %08lX\n", dspInit());
bool loaded = false;
printf("DSP_LoadComponent: %08lX\n",
DSP_LoadComponent(cdc_bin, cdc_bin_size, 0xFF, 0xFF, &loaded));
printf("loaded = %d\n", loaded);
svcSleepThread(1000000000);
char hostname[100];
gethostname(hostname, 100);
printf("IP: %s port: 8888\n", hostname);
pmInit_();
printf("PM_TerminateTitle(DSP): %08lX\n", PM_TerminateTitle(0x0004013000001a02, 0));
pmExit_();
svcCreateEvent(&dsp_interrupt, ResetType::RESET_ONESHOT);
interrupt_counter = 0;
svcCreateThread(&threadA, threadA_entry, 0x0, threadA_stack + 0x400, 4, 0xFFFFFFFE);
printf("BindInterrupt: %08lX\n", svcBindInterrupt(0x4A, dsp_interrupt, 4, 0));
// Main loop
while (aptMainLoop()) {
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break;
if (kDown & KEY_A)
printf("hello\n");
PrintAll();
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
// Wait for VBlank
gspWaitForVBlank();
}
socExit();
dspExit();
gfxExit();
aptExit();
return 0;
}