mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
- added new SPI and CODEC drivers ported from linux, thanks to xerpi
- circle pad simulates dpad keys (up, right, down, left) - raw touchscreen data is provided but currently unused - added a simple shared memory region thing - fixed the 10ms delay to be _after_ the backlights are turned on, thanks to profi again as always, other stuff I probably forgot about
This commit is contained in:
parent
bcff09a389
commit
bf45ee3900
188
arm11/source/hw/codec.c
Executable file
188
arm11/source/hw/codec.c
Executable file
@ -0,0 +1,188 @@
|
||||
// Based on xerpi's CODEC driver for Linux
|
||||
// Original comment follows:
|
||||
/*
|
||||
* nintendo3ds_codec.c
|
||||
*
|
||||
* Copyright (C) 2016 Sergi Granell (xerpi)
|
||||
* Copyright (C) 2017 Paul LaMendola (paulguy)
|
||||
* based on ad7879-spi.c
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <types.h>
|
||||
|
||||
#include <hid_map.h>
|
||||
|
||||
#include "hw/codec.h"
|
||||
#include "hw/spi.h"
|
||||
|
||||
#define CODEC_SPI_DEV (3)
|
||||
|
||||
#define MAX_12BIT (BIT(12) - 1)
|
||||
#define CPAD_THRESH (150)
|
||||
#define CPAD_FACTOR (150)
|
||||
|
||||
/* SPI stuff */
|
||||
static void CODEC_DualTX(u8 *tx0, u8 len0, u8 *tx1, u8 len1)
|
||||
{
|
||||
SPI_XferInfo xfers[2];
|
||||
|
||||
xfers[0].buf = (u32*)tx0;
|
||||
xfers[0].len = len0;
|
||||
xfers[0].read = false;
|
||||
|
||||
xfers[1].buf = (u32*)tx1;
|
||||
xfers[1].len = len1;
|
||||
xfers[1].read = false;
|
||||
|
||||
SPI_DoXfer(CODEC_SPI_DEV, xfers, 2);
|
||||
}
|
||||
|
||||
static void CODEC_WriteRead(u8 *tx_buf, u8 tx_len,
|
||||
u8 *rx_buf, u8 rx_len)
|
||||
{
|
||||
SPI_XferInfo xfers[2];
|
||||
|
||||
xfers[0].buf = (u32*)tx_buf;
|
||||
xfers[0].len = tx_len;
|
||||
xfers[0].read = false;
|
||||
|
||||
xfers[1].buf = (u32*)rx_buf;
|
||||
xfers[1].len = rx_len;
|
||||
xfers[1].read = true;
|
||||
|
||||
SPI_DoXfer(CODEC_SPI_DEV, xfers, 2);
|
||||
}
|
||||
|
||||
static void CODEC_RegSelect(u8 reg)
|
||||
{
|
||||
u8 buffer1[4];
|
||||
u8 buffer2[0x40];
|
||||
|
||||
buffer1[0] = 0;
|
||||
buffer2[0] = reg;
|
||||
|
||||
CODEC_DualTX(buffer1, 1, buffer2, 1);
|
||||
}
|
||||
|
||||
static u8 CODEC_RegRead(u8 offset)
|
||||
{
|
||||
u8 buffer_wr[8];
|
||||
u8 buffer_rd[0x40];
|
||||
|
||||
buffer_wr[0] = 1 | (offset << 1);
|
||||
|
||||
CODEC_WriteRead(buffer_wr, 1, buffer_rd, 1);
|
||||
|
||||
return buffer_rd[0];
|
||||
}
|
||||
|
||||
static void CODEC_RegWrite(u8 reg, u8 val)
|
||||
{
|
||||
u8 buffer1[8];
|
||||
u8 buffer2[0x40];
|
||||
|
||||
buffer1[0] = (reg << 1); // Write
|
||||
buffer2[0] = val;
|
||||
|
||||
CODEC_DualTX(buffer1, 1, buffer2, 1);
|
||||
}
|
||||
|
||||
static void CODEC_RegReadBuf(u8 offset, void *buffer, u8 size)
|
||||
{
|
||||
u8 buffer_wr[0x10];
|
||||
|
||||
buffer_wr[0] = 1 | (offset << 1);
|
||||
|
||||
CODEC_WriteRead(buffer_wr, 1, buffer, size);
|
||||
}
|
||||
|
||||
static void CODEC_RegMask(u8 offset, u8 mask0, u8 mask1)
|
||||
{
|
||||
u8 buffer1[4];
|
||||
u8 buffer2[0x40];
|
||||
|
||||
buffer1[0] = 1 | (offset << 1);
|
||||
|
||||
CODEC_WriteRead(buffer1, 1, buffer2, 1);
|
||||
|
||||
buffer1[0] = offset << 1;
|
||||
buffer2[0] = (buffer2[0] & ~mask1) | (mask0 & mask1);
|
||||
|
||||
CODEC_DualTX(buffer1, 1, buffer2, 1);
|
||||
}
|
||||
|
||||
void CODEC_Init(void)
|
||||
{
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x24, 0x98);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x26, 0x00);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x25, 0x43);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x24, 0x18);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x17, 0x43);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x19, 0x69);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x1B, 0x80);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x27, 0x11);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x26, 0xEC);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x24, 0x18);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegWrite(0x25, 0x53);
|
||||
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegMask(0x26, 0x80, 0x80);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegMask(0x24, 0x00, 0x80);
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegMask(0x25, 0x10, 0x3C);
|
||||
}
|
||||
|
||||
static void CODEC_GetRawData(u8 *buffer)
|
||||
{
|
||||
CODEC_RegSelect(0x67);
|
||||
CODEC_RegRead(0x26);
|
||||
CODEC_RegSelect(0xFB);
|
||||
CODEC_RegReadBuf(1, buffer, 0x34);
|
||||
}
|
||||
|
||||
void CODEC_Get(CODEC_Input *input)
|
||||
{
|
||||
u8 raw_data[0x34] = {0};
|
||||
s16 cpad_x, cpad_y;
|
||||
bool ts_pressed;
|
||||
|
||||
CODEC_GetRawData(raw_data);
|
||||
|
||||
cpad_x = ((raw_data[0x24] << 8 | raw_data[0x25]) & 0xFFF) - 2048;
|
||||
cpad_y = ((raw_data[0x14] << 8 | raw_data[0x15]) & 0xFFF) - 2048;
|
||||
|
||||
// X axis is inverted
|
||||
if (abs(cpad_x) > CPAD_THRESH)
|
||||
input->cpad_x = -cpad_x / CPAD_FACTOR;
|
||||
else
|
||||
input->cpad_x = 0;
|
||||
|
||||
if (abs(cpad_y) > CPAD_THRESH)
|
||||
input->cpad_y = cpad_y / CPAD_FACTOR;
|
||||
else
|
||||
input->cpad_y = 0;
|
||||
|
||||
ts_pressed = !(raw_data[0] & BIT(4));
|
||||
if (ts_pressed) {
|
||||
input->ts_x = (raw_data[0] << 8) | raw_data[1];
|
||||
input->ts_y = (raw_data[10] << 8) | raw_data[11];
|
||||
} else {
|
||||
input->ts_x = 0xFFFF;
|
||||
input->ts_y = 0xFFFF;
|
||||
}
|
||||
}
|
14
arm11/source/hw/codec.h
Executable file
14
arm11/source/hw/codec.h
Executable file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define CODEC_TOUCH_VALID(x) ((x) != 0xFFFFFFFF)
|
||||
|
||||
typedef struct {
|
||||
s16 cpad_x, cpad_y;
|
||||
s16 ts_x, ts_y;
|
||||
} CODEC_Input;
|
||||
|
||||
void CODEC_Init(void);
|
||||
|
||||
void CODEC_Get(CODEC_Input *input);
|
55
arm11/source/hw/hid.c
Executable file
55
arm11/source/hw/hid.c
Executable file
@ -0,0 +1,55 @@
|
||||
#include <common.h>
|
||||
#include <types.h>
|
||||
#include <hid_map.h>
|
||||
|
||||
#include "hw/codec.h"
|
||||
#include "hw/hid.h"
|
||||
#include "hw/mcu.h"
|
||||
|
||||
#define REG_HID (~(*(vu16*)(0x10146000)) & BUTTON_ANY)
|
||||
|
||||
static u32 HID_ConvertCPAD(s16 cpad_x, s16 cpad_y)
|
||||
{
|
||||
u32 ret = 0;
|
||||
|
||||
switch(int_sign(cpad_x)) {
|
||||
default:
|
||||
break;
|
||||
case 1:
|
||||
ret |= BUTTON_RIGHT;
|
||||
break;
|
||||
case -1:
|
||||
ret |= BUTTON_LEFT;
|
||||
}
|
||||
|
||||
switch(int_sign(cpad_y)) {
|
||||
default:
|
||||
break;
|
||||
case 1:
|
||||
ret |= BUTTON_UP;
|
||||
break;
|
||||
case -1:
|
||||
ret |= BUTTON_DOWN;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u64 HID_GetState(void)
|
||||
{
|
||||
CODEC_Input codec;
|
||||
u64 ret = 0;
|
||||
|
||||
CODEC_Get(&codec);
|
||||
|
||||
ret = REG_HID | MCU_GetSpecialHID();
|
||||
if (!(ret & BUTTON_ARROW))
|
||||
ret |= HID_ConvertCPAD(codec.cpad_x, codec.cpad_y);
|
||||
|
||||
if (codec.ts_x <= 0xFFF)
|
||||
ret |= BUTTON_TOUCH;
|
||||
|
||||
ret |= (((u64)codec.ts_x << 16) | (u64)codec.ts_y) << 32;
|
||||
|
||||
return ret;
|
||||
}
|
6
arm11/source/hw/hid.h
Executable file
6
arm11/source/hw/hid.h
Executable file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
#include <hid_map.h>
|
||||
|
||||
u64 HID_GetState(void);
|
129
arm11/source/hw/spi.c
Executable file
129
arm11/source/hw/spi.c
Executable file
@ -0,0 +1,129 @@
|
||||
// Somewhat based on xerpi's SPI driver for Linux
|
||||
// Original comment follows:
|
||||
/*
|
||||
* nintendo3ds_spi.c
|
||||
*
|
||||
* Copyright (C) 2016 Sergi Granell (xerpi)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <types.h>
|
||||
|
||||
#include "hw/spi.h"
|
||||
|
||||
#define CFG_SPI_CNT ((vu32*)0x101401C0)
|
||||
|
||||
// TODO: CURRENTLY HARDCODED FOR DEVICE 3 (TOUCHSCREEN)
|
||||
// IF ANY OTHER DEVICES ARE TO BE USED, ANOTHER BUS MUST
|
||||
// BE ACCESSED, CHECK 3dbrew.org/wiki/SPI_{Registers, Services}
|
||||
static const u32 SPI_Buses[] = { 0x10142800 };
|
||||
#define REG_SPI(b, n) (*(vu32*)(SPI_Buses[b] + (n)))
|
||||
|
||||
#define REG_SPI_CNT REG_SPI(0, 0x00)
|
||||
#define REG_SPI_DONE REG_SPI(0, 0x04)
|
||||
#define REG_SPI_BLKLEN REG_SPI(0, 0x08)
|
||||
#define REG_SPI_FIFO REG_SPI(0, 0x0C)
|
||||
#define REG_SPI_STATUS REG_SPI(0, 0x10)
|
||||
|
||||
#define SPI_CNT_BUSY BIT(15)
|
||||
#define SPI_CNT_START BIT(15)
|
||||
|
||||
#define SPI_CNT_READ (0)
|
||||
#define SPI_CNT_WRITE BIT(13)
|
||||
|
||||
#define SPI_CNT_RATE(n) (n)
|
||||
#define SPI_CNT_CS(n) ((n) << 6)
|
||||
|
||||
#define SPI_STAT_BUSY BIT(0)
|
||||
|
||||
#define SPI_FIFO_WIDTH (32)
|
||||
|
||||
static u8 SPI_GetDevSelect(u32 dev)
|
||||
{
|
||||
static const u8 SPI_DevSelect[] = { 0, 1, 2, 0, 1, 2 };
|
||||
if (dev < countof(SPI_DevSelect)) {
|
||||
return SPI_DevSelect[dev];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 SPI_GetDevBaudrate(u32 dev)
|
||||
{
|
||||
static const u8 SPI_BaudRates[] = { 2, 0, 0, 5 };
|
||||
if (dev < countof(SPI_BaudRates)) {
|
||||
return SPI_BaudRates[dev];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void SPI_WaitBusy(void)
|
||||
{
|
||||
while(REG_SPI_CNT & SPI_CNT_BUSY);
|
||||
}
|
||||
|
||||
static void SPI_WaitFIFO(void)
|
||||
{
|
||||
while(REG_SPI_STATUS & SPI_STAT_BUSY);
|
||||
}
|
||||
|
||||
static void SPI_Done(void)
|
||||
{
|
||||
REG_SPI_DONE = 0;
|
||||
}
|
||||
|
||||
static void SPI_SingleXfer(u32 reg, bool read, u32 *buffer, u32 len)
|
||||
{
|
||||
u32 pos = 0;
|
||||
|
||||
REG_SPI_BLKLEN = len;
|
||||
REG_SPI_CNT = reg | (read ? SPI_CNT_READ : SPI_CNT_WRITE) | SPI_CNT_START;
|
||||
|
||||
do {
|
||||
if ((pos % SPI_FIFO_WIDTH) == 0)
|
||||
SPI_WaitFIFO();
|
||||
|
||||
if (read) {
|
||||
buffer[pos / 4] = REG_SPI_FIFO;
|
||||
} else {
|
||||
REG_SPI_FIFO = buffer[pos / 4];
|
||||
}
|
||||
|
||||
pos += 4;
|
||||
} while(pos < len);
|
||||
}
|
||||
|
||||
int SPI_DoXfer(u32 dev, SPI_XferInfo *xfers, u32 xfer_cnt)
|
||||
{
|
||||
u32 dev_cfg;
|
||||
int baud, cs;
|
||||
|
||||
baud = SPI_GetDevBaudrate(dev);
|
||||
cs = SPI_GetDevSelect(dev);
|
||||
dev_cfg = SPI_CNT_RATE(baud) | SPI_CNT_CS(cs);
|
||||
|
||||
for (u32 i = 0; i < xfer_cnt; i++) {
|
||||
SPI_XferInfo *xfer = &xfers[i];
|
||||
|
||||
SPI_WaitBusy();
|
||||
SPI_SingleXfer(dev_cfg, xfer->read, xfer->buf, xfer->len);
|
||||
}
|
||||
|
||||
SPI_WaitBusy();
|
||||
SPI_Done();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SPI_Init(void)
|
||||
{
|
||||
// Hack: here all registers should be set to the "new" mode
|
||||
// but GM9 uses the old interface to access NVRAM
|
||||
// as such, only the bus used by CODEC will be set to new
|
||||
// *CFG_SPI_CNT = 7;
|
||||
*CFG_SPI_CNT = BIT(1);
|
||||
}
|
13
arm11/source/hw/spi.h
Executable file
13
arm11/source/hw/spi.h
Executable file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
u32 *buf;
|
||||
u8 len;
|
||||
bool read;
|
||||
} SPI_XferInfo;
|
||||
|
||||
int SPI_DoXfer(u32 dev, SPI_XferInfo *xfer, u32 xfer_cnt);
|
||||
|
||||
void SPI_Init(void);
|
@ -1,12 +1,12 @@
|
||||
#include <hid_map.h>
|
||||
#include <common.h>
|
||||
#include <types.h>
|
||||
#include <vram.h>
|
||||
#include <shmem.h>
|
||||
#include <arm.h>
|
||||
#include <pxi.h>
|
||||
|
||||
#include "arm/gic.h"
|
||||
|
||||
#include "hw/hid.h"
|
||||
#include "hw/gpulcd.h"
|
||||
#include "hw/i2c.h"
|
||||
#include "hw/mcu.h"
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
static bool legacy = false;
|
||||
|
||||
#define REG_HID (~(*(vu16*)(0x10146000)) & BUTTON_ANY)
|
||||
static GlobalSharedMemory SharedMemory_State;
|
||||
static const u8 brightness_lvls[] = {
|
||||
0x10, 0x17, 0x1E, 0x25,
|
||||
0x2C, 0x34, 0x3C, 0x44,
|
||||
@ -23,7 +23,6 @@ static const u8 brightness_lvls[] = {
|
||||
0x79, 0x8C, 0xA7, 0xD2
|
||||
};
|
||||
static int prev_bright_lvl = -1;
|
||||
static vu32 global_hid_state = 0;
|
||||
|
||||
void VBlank_Handler(u32 __attribute__((unused)) irqn)
|
||||
{
|
||||
@ -38,8 +37,8 @@ void VBlank_Handler(u32 __attribute__((unused)) irqn)
|
||||
// the state should probably be stored on its own
|
||||
// setion without caching enabled, since it must
|
||||
// be readable by the ARM9 at all times anyway
|
||||
global_hid_state = REG_HID | MCU_GetSpecialHID();
|
||||
ARM_WbDC_Range((void*)&global_hid_state, 4);
|
||||
SharedMemory_State.hid_state = HID_GetState();
|
||||
ARM_WbDC_Range(&SharedMemory_State, sizeof(SharedMemory_State));
|
||||
ARM_DMB();
|
||||
}
|
||||
|
||||
@ -69,8 +68,7 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
||||
|
||||
case PXI_GET_SHMEM:
|
||||
{
|
||||
ret = (u32)&global_hid_state;
|
||||
//ret = 0xFFFFFFFF;
|
||||
ret = (u32)&SharedMemory_State;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -110,13 +108,13 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
||||
|
||||
void __attribute__((noreturn)) MainLoop(void)
|
||||
{
|
||||
// enable MCU interrupts
|
||||
GIC_Enable(MCU_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO, MCU_HandleInterrupts);
|
||||
|
||||
// enable PXI RX interrupt
|
||||
GIC_Enable(PXI_RX_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO, PXI_RX_Handler);
|
||||
|
||||
GIC_Enable(VBLANK_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO + 1, VBlank_Handler);
|
||||
// enable MCU interrupts
|
||||
GIC_Enable(MCU_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO + 1, MCU_HandleInterrupts);
|
||||
|
||||
GIC_Enable(VBLANK_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO + 2, VBlank_Handler);
|
||||
|
||||
// ARM9 won't try anything funny until this point
|
||||
PXI_Barrier(ARM11_READY_BARRIER);
|
||||
|
@ -8,9 +8,11 @@
|
||||
#include "arm/scu.h"
|
||||
#include "arm/timer.h"
|
||||
|
||||
#include "hw/codec.h"
|
||||
#include "hw/gpulcd.h"
|
||||
#include "hw/i2c.h"
|
||||
#include "hw/mcu.h"
|
||||
#include "hw/spi.h"
|
||||
|
||||
#include "system/sections.h"
|
||||
|
||||
@ -85,6 +87,8 @@ void SYS_CoreZeroInit(void)
|
||||
PXI_Reset();
|
||||
I2C_init();
|
||||
MCU_Init();
|
||||
SPI_Init();
|
||||
CODEC_Init();
|
||||
|
||||
GPU_Init();
|
||||
GPU_PSCFill(VRAM_START, VRAM_END, 0);
|
||||
@ -95,8 +99,8 @@ void SYS_CoreZeroInit(void)
|
||||
GPU_SetFramebufferMode(0, PDC_RGB24);
|
||||
GPU_SetFramebufferMode(1, PDC_RGB24);
|
||||
|
||||
TIMER_WaitTicks(CLK_MS_TO_TICKS(10));
|
||||
MCU_WriteReg(0x22, 0x2A);
|
||||
TIMER_WaitTicks(CLK_MS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
void SYS_CoreInit(void)
|
||||
|
@ -4,10 +4,19 @@
|
||||
#include "screenshot.h" // for screenshots
|
||||
|
||||
#include "arm.h"
|
||||
#include "shmem.h"
|
||||
|
||||
// there's some weird thing going on when reading this
|
||||
// with an LDRD instruction so for now they'll be two
|
||||
// separate things - hopefully LTO won't get in the way
|
||||
u32 HID_ReadState(void)
|
||||
{ // this should probably be abstracted away in something like "SHMEM_GetHID"
|
||||
return *(u32*)ARM_GetTID();
|
||||
{
|
||||
return ARM_GetSHMEM()->hid_state;
|
||||
}
|
||||
|
||||
u32 HID_ReadRawTouchState(void)
|
||||
{
|
||||
return ARM_GetSHMEM()->hid_state >> 32;
|
||||
}
|
||||
|
||||
u32 InputWait(u32 timeout_sec) {
|
||||
|
@ -6,17 +6,13 @@
|
||||
|
||||
// see: http://3dbrew.org/wiki/CONFIG9_Registers
|
||||
// see: http://3dbrew.org/wiki/EMMC_Registers
|
||||
|
||||
u32 HID_ReadState(void);
|
||||
u32 HID_ReadRawTouchState(void);
|
||||
|
||||
#define CART_STATE (~(*(volatile u8*)0x10000010) & 0x1)
|
||||
#define SD_STATE ((*(volatile u16*)0x1000601C) & (0x1<<5))
|
||||
|
||||
|
||||
|
||||
// strings for button conversion
|
||||
#define BUTTON_STRINGS "A", "B", "SELECT", "START", "RIGHT", "LEFT", "UP", "DOWN", "R", "L", "X", "Y"
|
||||
|
||||
|
||||
u32 InputWait(u32 timeout_sec);
|
||||
bool CheckButton(u32 button);
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "i2c.h"
|
||||
|
||||
#include "arm.h"
|
||||
#include "shmem.h"
|
||||
|
||||
void main(int argc, char** argv, int entrypoint)
|
||||
{
|
||||
@ -19,7 +20,7 @@ void main(int argc, char** argv, int entrypoint)
|
||||
|
||||
// A pointer to the shared memory region is
|
||||
// stored in the thread ID register in the ARM9
|
||||
ARM_SetTID(PXI_DoCMD(PXI_GET_SHMEM, NULL, 0));
|
||||
ARM_InitSHMEM();
|
||||
|
||||
#ifdef SCRIPT_RUNNER
|
||||
// Run the script runner
|
||||
|
@ -25,6 +25,12 @@
|
||||
#define min(a,b) \
|
||||
(((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define abs(x) \
|
||||
(((x) >= 0) ? (x) : -(x))
|
||||
|
||||
#define int_sign(x) \
|
||||
(((x) > 0) - ((x) < 0))
|
||||
|
||||
#define getbe16(d) \
|
||||
(((d)[0]<<8) | (d)[1])
|
||||
#define getbe32(d) \
|
||||
|
@ -15,13 +15,18 @@
|
||||
#define BUTTON_ANY 0x00000FFF
|
||||
#define BUTTON_ARROW (BUTTON_RIGHT|BUTTON_LEFT|BUTTON_UP|BUTTON_DOWN)
|
||||
|
||||
// special buttons / cart / sd
|
||||
// strings for button conversion
|
||||
#define BUTTON_STRINGS "A", "B", "SELECT", "START", "RIGHT", "LEFT", "UP", "DOWN", "R", "L", "X", "Y"
|
||||
|
||||
// special buttons / touchscreen / cart / sd
|
||||
#define BUTTON_POWER ((u32)1 << 12)
|
||||
#define BUTTON_HOME ((u32)1 << 13)
|
||||
#define BUTTON_WIFI ((u32)1 << 14)
|
||||
#define CART_INSERT ((u32)1 << 15)
|
||||
#define CART_EJECT ((u32)1 << 16)
|
||||
#define SD_INSERT ((u32)1 << 17)
|
||||
#define SD_EJECT ((u32)1 << 18)
|
||||
#define BUTTON_TOUCH ((u32)1 << 15)
|
||||
|
||||
#define CART_INSERT ((u32)1 << 16)
|
||||
#define CART_EJECT ((u32)1 << 17)
|
||||
#define SD_INSERT ((u32)1 << 18)
|
||||
#define SD_EJECT ((u32)1 << 19)
|
||||
|
||||
#define TIMEOUT_HID ((u32)1 << 31)
|
||||
|
21
common/shmem.h
Executable file
21
common/shmem.h
Executable file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <arm.h>
|
||||
|
||||
typedef struct {
|
||||
u64 hid_state;
|
||||
} GlobalSharedMemory;
|
||||
|
||||
#ifdef ARM9
|
||||
#include <pxi.h>
|
||||
|
||||
static inline const GlobalSharedMemory *ARM_GetSHMEM(void)
|
||||
{
|
||||
return (const GlobalSharedMemory*)ARM_GetTID();
|
||||
}
|
||||
|
||||
static void ARM_InitSHMEM(void)
|
||||
{
|
||||
ARM_SetTID(PXI_DoCMD(PXI_GET_SHMEM, NULL, 0));
|
||||
}
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user