diff --git a/dspapbptester/.gitignore b/dspapbptester/.gitignore new file mode 100644 index 0000000..d92a959 --- /dev/null +++ b/dspapbptester/.gitignore @@ -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 + diff --git a/dspapbptester/Makefile b/dspapbptester/Makefile new file mode 100644 index 0000000..bf7676b --- /dev/null +++ b/dspapbptester/Makefile @@ -0,0 +1,171 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITARM)/3ds_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional) +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include +#ROMFS := romfs + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft + +CFLAGS := -g -Wall -O2 -mword-relocations \ + -fomit-frame-pointer -ffunction-sections \ + $(ARCH) + +CFLAGS += $(INCLUDE) -DARM11 -D_3DS + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lctru -lm + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CTRULIB) + + +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) +SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).cxi $(TARGET).cia $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all: $(OUTPUT).3dsx $(OUTPUT).cia + +ifeq ($(strip $(NO_SMDH)),) +$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh +else +$(OUTPUT).3dsx : $(OUTPUT).elf +endif + +$(OUTPUT).cia : $(OUTPUT).cxi + @makerom -f cia -o $(OUTPUT).cia -target t -i $(OUTPUT).cxi:0:0 + @echo built ... $(OUTPUT).cia + +$(OUTPUT).cxi : $(OUTPUT).elf $(OUTPUT).smdh $(TOPDIR)/rsf.rsf $(TOPDIR)/banner.bnr + @makerom -o $(OUTPUT).cxi -rsf $(TOPDIR)/rsf.rsf -target t -elf $(OUTPUT).elf -icon $(OUTPUT).smdh -banner $(TOPDIR)/banner.bnr + @echo built ... $(OUTPUT).cxi + +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +#--------------------------------------------------------------------------------- +# rules for assembling GPU shaders +#--------------------------------------------------------------------------------- +define shader-as + $(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@))) + picasso -o $(CURBIN) $1 + bin2s $(CURBIN) | $(AS) -o $@ + echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h + echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h + echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h +endef + +%.shbin.o : %.v.pica %.g.pica + @echo $(notdir $^) + @$(call shader-as,$^) + +%.shbin.o : %.v.pica + @echo $(notdir $<) + @$(call shader-as,$<) + +%.shbin.o : %.shlist + @echo $(notdir $<) + @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file))) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/dspapbptester/banner.bnr b/dspapbptester/banner.bnr new file mode 100644 index 0000000..6b8a120 Binary files /dev/null and b/dspapbptester/banner.bnr differ diff --git a/dspapbptester/data/cdc.bin b/dspapbptester/data/cdc.bin new file mode 100644 index 0000000..01832f8 Binary files /dev/null and b/dspapbptester/data/cdc.bin differ diff --git a/dspapbptester/dspapbptester.smdh b/dspapbptester/dspapbptester.smdh new file mode 100644 index 0000000..ed94f50 Binary files /dev/null and b/dspapbptester/dspapbptester.smdh differ diff --git a/dspapbptester/firm/source b/dspapbptester/firm/source new file mode 100644 index 0000000..ee09ebf --- /dev/null +++ b/dspapbptester/firm/source @@ -0,0 +1,135 @@ +segment p 0000 +br 0x00000000 always // reset vector +data 0800 +reti always +data 0000 +reti always +data 0000 +br 0x00000000 always // int0 +data 5000 +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 0x0000 sp // set stack pointer +data 0xF000 +mov 0x0000 mod3 // enable interrupt +data 0x0180 +load 0x0082u8 page // configure ICU +mov 0x0000 r0 +data 0x4000 +mov r0 [page:0x000eu8] +mov r0 [page:0x0010u8] +mov r0 [page:0x0006u8] // enable apbp as int0 +br 0x00000000 always +data 0x1000 + +segment p 1000 // Main loop +load 0x0000u8 page + +mov 0x0000 r0 // transfer APBP register +data 0x80CC +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 0x00000000 eq // loop back if no signal +data 1000 + +mov [page:0x0001u8] b0l // get command type + +cmpv 0x0000 b0l +data 0000 +br 0x00000000 eq +data 2000 + +cmpv 0x0000 b0l +data 0001 +br 0x00000000 eq +data 3000 + +br 0x00000000 always +data 4000 + +segment p 2000 // read +mov [page:0x0002u8] r0 +mov [r0] r1 +mov r1 [page:0x0003u8] +br 0x00000000 always +data 4000 + +segment p 3000 // write +mov [page:0x0002u8] r0 +mov [page:0x0003u8] r1 +mov r1 [r0] +br 0x00000000 always +data 4000 + +segment p 4000 // end +clr b0 always +mov b0l [page:0x0000u8] // clear signal +br 0x00000000 always +data 1000 // loop back + +segment p 5000 // interrupt handler +mov 0x0000 r5 +data 0x4000 +mov 0x0000 r4 +data 0x8202 +mov r5 [r4] // ack +mov 0x0000 r4 +data 0x0004 +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 diff --git a/dspapbptester/rsf.rsf b/dspapbptester/rsf.rsf new file mode 100755 index 0000000..7531247 --- /dev/null +++ b/dspapbptester/rsf.rsf @@ -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, : + 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. + # : + 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 diff --git a/dspapbptester/send.py b/dspapbptester/send.py new file mode 100755 index 0000000..ebe7094 --- /dev/null +++ b/dspapbptester/send.py @@ -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(' +#include +#include +#include +#include <3ds.h> +#include +#include +#include +#include +#include + +#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 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 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() != 2) { + printf("Wrong length for Read\n"); + break; + } + u16 addr = command_package[1]; + printf("Read CPU [%04X] -> ", addr); + printf("%04X\n", *(vu16*)(0x1ed03000 + addr)); + break; + } + case 3: { + if (command_package.size() != 3) { + printf("Wrong length for Write\n"); + break; + } + u16 addr = command_package[1]; + u16 value = command_package[2]; + printf("Write CPU [%04X] <- %04X", addr, value); + *(vu16*)(0x1ed03000 + 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; +} diff --git a/src/apbp.cpp b/src/apbp.cpp index da30168..00e898f 100644 --- a/src/apbp.cpp +++ b/src/apbp.cpp @@ -58,7 +58,6 @@ class Apbp::Impl { std::array data_channels; u16 semaphore = 0; u16 semaphore_mask = 0; - bool semaphore_master_signal = false; mutable std::recursive_mutex semaphore_mutex; std::function semaphore_handler; @@ -67,7 +66,6 @@ class Apbp::Impl { c.Reset(); semaphore = 0; semaphore_mask = 0; - semaphore_master_signal = false; } }; @@ -108,18 +106,17 @@ void Apbp::SetDataHandler(unsigned channel, std::function handler) { void Apbp::SetSemaphore(u16 bits) { std::lock_guard lock(impl->semaphore_mutex); - impl->semaphore |= bits; - bool new_signal = (impl->semaphore & ~impl->semaphore_mask) != 0; - if (new_signal && impl->semaphore_handler) { + bool old_signal = IsSemaphoreSignaled(); + impl->semaphore = bits; + bool new_signal = IsSemaphoreSignaled(); + if (!old_signal && new_signal && impl->semaphore_handler) { impl->semaphore_handler(); } - impl->semaphore_master_signal = impl->semaphore_master_signal || new_signal; } void Apbp::ClearSemaphore(u16 bits) { std::lock_guard lock(impl->semaphore_mutex); impl->semaphore &= ~bits; - impl->semaphore_master_signal = (impl->semaphore & ~impl->semaphore_mask) != 0; } u16 Apbp::GetSemaphore() const { @@ -129,7 +126,12 @@ u16 Apbp::GetSemaphore() const { void Apbp::MaskSemaphore(u16 bits) { std::lock_guard lock(impl->semaphore_mutex); + bool old_signal = IsSemaphoreSignaled(); impl->semaphore_mask = bits; + bool new_signal = IsSemaphoreSignaled(); + if (!old_signal && new_signal && impl->semaphore_handler) { + impl->semaphore_handler(); + } } u16 Apbp::GetSemaphoreMask() const { @@ -144,6 +146,6 @@ void Apbp::SetSemaphoreHandler(std::function handler) { bool Apbp::IsSemaphoreSignaled() const { std::lock_guard lock(impl->semaphore_mutex); - return impl->semaphore_master_signal; + return (impl->semaphore & ~impl->semaphore_mask) != 0; } } // namespace Teakra