First Commit
This commit is contained in:
20
externals/teakra/hwtest/dspapbptester/.gitignore
vendored
Normal file
20
externals/teakra/hwtest/dspapbptester/.gitignore
vendored
Normal 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
|
||||
|
||||
BIN
externals/teakra/hwtest/dspapbptester/banner.bnr
vendored
Normal file
BIN
externals/teakra/hwtest/dspapbptester/banner.bnr
vendored
Normal file
Binary file not shown.
BIN
externals/teakra/hwtest/dspapbptester/data/cdc.bin
vendored
Normal file
BIN
externals/teakra/hwtest/dspapbptester/data/cdc.bin
vendored
Normal file
Binary file not shown.
BIN
externals/teakra/hwtest/dspapbptester/dspapbptester.smdh
vendored
Normal file
BIN
externals/teakra/hwtest/dspapbptester/dspapbptester.smdh
vendored
Normal file
Binary file not shown.
116
externals/teakra/hwtest/dspapbptester/firm/source
vendored
Normal file
116
externals/teakra/hwtest/dspapbptester/firm/source
vendored
Normal 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
|
||||
228
externals/teakra/hwtest/dspapbptester/rsf.rsf
vendored
Normal file
228
externals/teakra/hwtest/dspapbptester/rsf.rsf
vendored
Normal 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
|
||||
28
externals/teakra/hwtest/dspapbptester/send.py
vendored
Normal file
28
externals/teakra/hwtest/dspapbptester/send.py
vendored
Normal 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))
|
||||
308
externals/teakra/hwtest/dspapbptester/source/main.cpp
vendored
Normal file
308
externals/teakra/hwtest/dspapbptester/source/main.cpp
vendored
Normal 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;
|
||||
}
|
||||
20
externals/teakra/hwtest/dspmemorytester/.gitignore
vendored
Normal file
20
externals/teakra/hwtest/dspmemorytester/.gitignore
vendored
Normal 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
|
||||
|
||||
BIN
externals/teakra/hwtest/dspmemorytester/banner.bnr
vendored
Normal file
BIN
externals/teakra/hwtest/dspmemorytester/banner.bnr
vendored
Normal file
Binary file not shown.
BIN
externals/teakra/hwtest/dspmemorytester/data/cdc.bin
vendored
Normal file
BIN
externals/teakra/hwtest/dspmemorytester/data/cdc.bin
vendored
Normal file
Binary file not shown.
BIN
externals/teakra/hwtest/dspmemorytester/dspmemorytester.smdh
vendored
Normal file
BIN
externals/teakra/hwtest/dspmemorytester/dspmemorytester.smdh
vendored
Normal file
Binary file not shown.
64
externals/teakra/hwtest/dspmemorytester/firm/source
vendored
Normal file
64
externals/teakra/hwtest/dspmemorytester/firm/source
vendored
Normal 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
|
||||
226
externals/teakra/hwtest/dspmemorytester/rsf.rsf
vendored
Normal file
226
externals/teakra/hwtest/dspmemorytester/rsf.rsf
vendored
Normal 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
|
||||
22
externals/teakra/hwtest/dspmemorytester/send.py
vendored
Normal file
22
externals/teakra/hwtest/dspmemorytester/send.py
vendored
Normal 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))
|
||||
291
externals/teakra/hwtest/dspmemorytester/source/main.cpp
vendored
Normal file
291
externals/teakra/hwtest/dspmemorytester/source/main.cpp
vendored
Normal 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;
|
||||
}
|
||||
20
externals/teakra/hwtest/dsptester/.gitignore
vendored
Normal file
20
externals/teakra/hwtest/dsptester/.gitignore
vendored
Normal 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
|
||||
|
||||
BIN
externals/teakra/hwtest/dsptester/banner.bnr
vendored
Normal file
BIN
externals/teakra/hwtest/dsptester/banner.bnr
vendored
Normal file
Binary file not shown.
BIN
externals/teakra/hwtest/dsptester/data/cdc.bin
vendored
Normal file
BIN
externals/teakra/hwtest/dsptester/data/cdc.bin
vendored
Normal file
Binary file not shown.
BIN
externals/teakra/hwtest/dsptester/dsptester.smdh
vendored
Normal file
BIN
externals/teakra/hwtest/dsptester/dsptester.smdh
vendored
Normal file
Binary file not shown.
171
externals/teakra/hwtest/dsptester/firm/source
vendored
Normal file
171
externals/teakra/hwtest/dsptester/firm/source
vendored
Normal 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
|
||||
0
externals/teakra/hwtest/dsptester/result-parse
vendored
Normal file
0
externals/teakra/hwtest/dsptester/result-parse
vendored
Normal file
226
externals/teakra/hwtest/dsptester/rsf.rsf
vendored
Normal file
226
externals/teakra/hwtest/dsptester/rsf.rsf
vendored
Normal 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
|
||||
24
externals/teakra/hwtest/dsptester/send-program.py
vendored
Normal file
24
externals/teakra/hwtest/dsptester/send-program.py
vendored
Normal 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))
|
||||
665
externals/teakra/hwtest/dsptester/source/main.cpp
vendored
Normal file
665
externals/teakra/hwtest/dsptester/source/main.cpp
vendored
Normal 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;
|
||||
}
|
||||
20
externals/teakra/hwtest/dspvictester/.gitignore
vendored
Normal file
20
externals/teakra/hwtest/dspvictester/.gitignore
vendored
Normal 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
|
||||
|
||||
BIN
externals/teakra/hwtest/dspvictester/banner.bnr
vendored
Normal file
BIN
externals/teakra/hwtest/dspvictester/banner.bnr
vendored
Normal file
Binary file not shown.
BIN
externals/teakra/hwtest/dspvictester/data/cdc.bin
vendored
Normal file
BIN
externals/teakra/hwtest/dspvictester/data/cdc.bin
vendored
Normal file
Binary file not shown.
BIN
externals/teakra/hwtest/dspvictester/dspvictester.smdh
vendored
Normal file
BIN
externals/teakra/hwtest/dspvictester/dspvictester.smdh
vendored
Normal file
Binary file not shown.
53
externals/teakra/hwtest/dspvictester/firm/source
vendored
Normal file
53
externals/teakra/hwtest/dspvictester/firm/source
vendored
Normal 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
|
||||
228
externals/teakra/hwtest/dspvictester/rsf.rsf
vendored
Normal file
228
externals/teakra/hwtest/dspvictester/rsf.rsf
vendored
Normal 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
|
||||
28
externals/teakra/hwtest/dspvictester/send.py
vendored
Normal file
28
externals/teakra/hwtest/dspvictester/send.py
vendored
Normal 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))
|
||||
291
externals/teakra/hwtest/dspvictester/source/main.cpp
vendored
Normal file
291
externals/teakra/hwtest/dspvictester/source/main.cpp
vendored
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user