Skip to content

Instantly share code, notes, and snippets.

@Pokechu22
Last active February 2, 2020 10:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pokechu22/aa91cc1c88ea666476fee9c19208f22b to your computer and use it in GitHub Desktop.
Save Pokechu22/aa91cc1c88ea666476fee9c19208f22b to your computer and use it in GitHub Desktop.
Wii/Gamecube DTK hardware test
build_gc/
build_wii/
*.elf
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <gccore.h>
#ifdef HW_RVL
#include <wiiuse/wpad.h>
#endif
#ifdef HW_RVL
volatile u32* DI_REGS = (volatile u32*)0xCD806000;
volatile u32* AI_REGS = (volatile u32*)0xCD806C00;
#else
volatile u32* DI_REGS = (volatile u32*)0xCC006000;
volatile u32* AI_REGS = (volatile u32*)0xCC006C00;
#endif
#define DISR DI_REGS[0]
#define DICVR DI_REGS[1]
#define DICMDBUF0 DI_REGS[2]
#define DICMDBUF1 DI_REGS[3]
#define DICMDBUF2 DI_REGS[4]
#define DIMAR DI_REGS[5]
#define DILENGTH DI_REGS[6]
#define DICR DI_REGS[7]
#define DIIMMBUF DI_REGS[8]
#define DICFG DI_REGS[9]
#define AI_CONTROL AI_REGS[0]
#define AI_VOLUME AI_REGS[1]
// Change these to valid values for the inserted disc to avoid earrape
// (does not actually affect the test). Can also be specified in argv.
#define DEFAULT_STREAM_START 0x40000
#define DEFAULT_STREAM_LENGTH 0x80000
static u32 buf[8] __attribute__((aligned(32)));
static void *xfb = NULL;
static GXRModeObj *rmode = NULL;
void Initialise(void) {
VIDEO_Init();
PAD_Init();
#ifdef HW_RVL
WPAD_Init();
#endif
rmode = VIDEO_GetPreferredMode(NULL);
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
printf("\x1b[2;0H");
}
void ScanPads() {
#ifdef HW_RVL
WPAD_ScanPads();
#endif
PAD_ScanPads();
}
bool APressed(void) {
#ifdef HW_RVL
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_A) {
return true;
}
#endif
if (PAD_ButtonsDown(0) & PAD_BUTTON_A) {
return true;
}
return false;
}
bool ExitPressed(void) {
#ifdef HW_RVL
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) {
return true;
}
#endif
if (PAD_ButtonsDown(0) & PAD_BUTTON_START) {
return true;
}
return false;
}
void wait_for_transfer(void) {
while (DICR & 1) { // Transfer in progress
// Do nothing.
}
}
void check_error(void) {
if (DISR & 4) {
printf("Error occurred. DISR: %08x\n", DISR);
DICMDBUF0 = 0xE0000000;
DICR = 1; // Start immediate transfer
wait_for_transfer();
printf("Error: %08x (DISR: %08x)\n", DIIMMBUF, DISR);
}
}
void print_all_audio_statuses(void) {
DICMDBUF0 = 0xE2000000;
DICMDBUF1 = 0;
DICR = 1;
wait_for_transfer();
printf("\nStream playing: %d\n", DIIMMBUF);
check_error();
DICMDBUF0 = 0xE2010000;
DICMDBUF1 = 0;
DICR = 1;
wait_for_transfer();
printf("Playback address: %08x\n", DIIMMBUF);
check_error();
DICMDBUF0 = 0xE2020000;
DICMDBUF1 = 0;
DICR = 1;
wait_for_transfer();
printf("Playback start: %08x\n", DIIMMBUF);
check_error();
DICMDBUF0 = 0xE2030000;
DICMDBUF1 = 0;
DICR = 1;
wait_for_transfer();
printf("Playback length: %08x\n", DIIMMBUF);
check_error();
}
//---------------------------------------------------------------------------------
int main(int argc, char **argv) {
//---------------------------------------------------------------------------------
Initialise();
u32 stream_start = DEFAULT_STREAM_START;
u32 stream_length = DEFAULT_STREAM_LENGTH;
if (argc > 0) {
for (int i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, argv[i]);
}
if (argc > 1) {
stream_start = strtoul(argv[1], NULL, 16);
}
if (argc > 2) {
stream_length = strtoul(argv[2], NULL, 16);
}
}
printf("Stream start: 0x%x (can be specified in argv[1])\n", stream_start);
printf("Stream length: 0x%x (can be specified in argv[2])\n", stream_length);
#ifdef HW_RVL
printf("Resetting drive through IOS\n");
int di_fd = IOS_Open("/dev/di", 2);
printf("IOS_Open returned %d\n", di_fd);
buf[0] = 0x8A << 24; // DVDLowReset
buf[1] = 1; // with spinup
int ret = IOS_Ioctl(di_fd, 0x8A, buf, 0x20, NULL, 0);
printf("IOS_Ioctl(0x8A) returned %d\n", ret);
IOS_Close(di_fd);
printf("Reading disc ID...\n");
DICMDBUF0 = 0xA8000040;
DICMDBUF1 = 0;
DICMDBUF2 = 0x20;
DILENGTH = 0x20;
DIMAR = MEM_VIRTUAL_TO_PHYSICAL(buf);
DICR = 3; // Start DMA transfer
wait_for_transfer();
printf("Done.\n");
check_error();
printf("0-3: %08x %08x %08x %08x\n", buf[0], buf[1], buf[2], buf[3]);
printf("4-7: %08x %08x %08x %08x\n", buf[4], buf[5], buf[6], buf[7]);
#else
// Assume that the disc is already spun up
#endif
AI_CONTROL |= 1;
AI_VOLUME = 0x7F7F; // Try to avoid destroying ears
printf("Configuring audio buffer...\n");
DICMDBUF0 = 0xE401000A; // Enabled with length 10
DICMDBUF1 = 0;
DICR = 1;
wait_for_transfer();
printf("Done (%x).\n", DIIMMBUF);
check_error();
printf("Starting audio...\n");
DICMDBUF0 = 0xE1000000;
DICMDBUF1 = stream_start;
DICMDBUF2 = stream_length;
DICR = 1;
wait_for_transfer();
printf("Done.\n");
check_error();
printf("Press A to check DTK status, and HOME or start to continue\n");
do {
VIDEO_WaitVSync();
ScanPads();
if (APressed()) {
print_all_audio_statuses();
}
} while (!ExitPressed());
printf("Stopping audio...\n");
DICMDBUF0 = 0xE1010000;
// For test purposes, to show that these are ignored
DICMDBUF1 = 0xDEAD0000;
DICMDBUF2 = 0xBEEF0000;
DICR = 1;
wait_for_transfer();
printf("Done.\n");
check_error();
printf("Press A to check DTK status, and HOME or start to exit\n");
do {
VIDEO_WaitVSync();
ScanPads();
if (APressed()) {
print_all_audio_statuses();
}
} while (!ExitPressed());
return 0;
}
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
include $(DEVKITPPC)/gamecube_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
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := DTKTest_GC
BUILD := build_gc
SOURCES := .
DATA := data
INCLUDES :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O0 -Wextra -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -logc -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
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_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := -L$(LIBOGC_LIB) $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
#export LIBPATHS := -L/mnt/c/Pokechu22/Git_/libogc/lib/wii/ $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.gc
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
#---------------------------------------------------------------------------------
run:
wiiload $(TARGET).dol
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
$(OFILES_SOURCES) : $(HFILES)
#---------------------------------------------------------------------------------
# This rule links in binary data with the .jpg extension
#---------------------------------------------------------------------------------
%.jpg.o %_jpg.h : %.jpg
#---------------------------------------------------------------------------------
@echo $(notdir $<)
$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
include $(DEVKITPPC)/wii_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
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := DTKTest_Wii
BUILD := build_wii
SOURCES := .
DATA := data
INCLUDES :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O0 -Wextra -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lwiiuse -lbte -logc -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
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_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := -L$(LIBOGC_LIB) $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
#export LIBPATHS := -L/mnt/c/Pokechu22/Git_/libogc/lib/wii/ $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
#---------------------------------------------------------------------------------
run:
wiiload $(TARGET).dol
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)
$(OFILES_SOURCES) : $(HFILES)
#---------------------------------------------------------------------------------
# This rule links in binary data with the .jpg extension
#---------------------------------------------------------------------------------
%.jpg.o %_jpg.h : %.jpg
#---------------------------------------------------------------------------------
@echo $(notdir $<)
$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment