/****************************************/ /* PocketStation Lib - by Orion_ [2013] */ /****************************************/ // Based on Miko Hoshina & Martin Korth work. // If you use it, please give credits ! // v3.6 // Optional Functions, don't define this in your main .c file do reduce size //#define USE_SPRITE //#define USE_RANDOM //#define USE_SOUND #ifndef NULL #define NULL ((void*)0) #endif #ifndef CLOCK_SPEED #define CLOCK_SPEED CLOCK_4M #endif #ifndef FPS #define FPS 64 #endif #ifndef SOUND_FREQ #define SOUND_FREQ 4000 // If 8000Hz, then use CLOCK_8M ! #endif /**/ #define PAD_BUTTON 0x1 #define PAD_RIGHT 0x2 #define PAD_LEFT 0x4 #define PAD_DOWN 0x8 #define PAD_UP 0x10 #define PAD_STATUS ((IRQ_STATUS_RAW) & 0x1F) int PadOnRelease, PadOnPress; /**/ #define LCD_ON 0x40 #define LCD_OFF 0x00 #define LCD_64HZ 0x10 #define LCD_32HZ 0x20 #define LCD_16HZ 0x30 #define LCD_CPEN 0x08 #define LCD_MODE *((volatile unsigned int *)0xD000000) #define LCD_VRAM(_line_) *((volatile unsigned int *)(0xD000100+(_line_ << 2))) #define LCD_VRAM_ADRS (volatile unsigned int *)0xD000100 /**/ #define CLOCK_62_5K 0x1 #define CLOCK_125K 0x2 #define CLOCK_250K 0x3 #define CLOCK_500K 0x4 #define CLOCK_1M 0x5 #define CLOCK_2M 0x6 #define CLOCK_4M 0x7 #define CLOCK_8M 0x8 #define TICK_PER_SEC (15625 << CLOCK_SPEED) #define TICK_PER_FRAME (TICK_PER_SEC / FPS) /**/ #define TIMER0_START() *((volatile unsigned int *)(0xA800008)) |= 0x4 #define TIMER1_START() *((volatile unsigned int *)(0xA800018)) |= 0x4 #define TIMER2_START() *((volatile unsigned int *)(0xA800028)) |= 0x4 #define TIMER0_STOP() *((volatile unsigned int *)(0xA800008)) &= ~0x4 #define TIMER1_STOP() *((volatile unsigned int *)(0xA800018)) &= ~0x4 #define TIMER2_STOP() *((volatile unsigned int *)(0xA800028)) &= ~0x4 #define TIMER0_SETCOUNT(_x_) *((volatile unsigned int *)(0xA800000)) = (_x_) #define TIMER1_SETCOUNT(_x_) *((volatile unsigned int *)(0xA800010)) = (_x_) #define TIMER2_SETCOUNT(_x_) *((volatile unsigned int *)(0xA800020)) = (_x_) /**/ #define FIQ_COMM 0x40 #define IRQ_TIMER0 0x80 #define IRQ_TIMER1 0x100 #define IRQ_RTC 0x200 #define IRQ_BATTERY 0x400 #define IRQ_PSCOMM 0x800 #define IRQ_INFRARED 0x1000 #define FIQ_TIMER2 0x2000 #define IRQ_STATUS *((volatile unsigned int *)(0xA000000)) #define IRQ_STATUS_RAW *((volatile unsigned int *)(0xA000004)) #define IRQ_ENABLE *((volatile unsigned int *)(0xA000008)) #define IRQ_DISABLE *((volatile unsigned int *)(0xA00000c)) #define IRQ_CLEAR *((volatile unsigned int *)(0xA000010)) #define IRQ_DISABLE_ALL() IRQ_DISABLE = 0x3FFF; /**/ #define IOCTL_CONFIG *((volatile unsigned int *)0xD800000) #define IOCTL_OFF *((volatile unsigned int *)0xD800004) #define IOCTL_ON *((volatile unsigned int *)0xD800008) #define IOCTL_DAC *((volatile unsigned int *)0xD800010) #define IOCTL_DASOUND *((volatile unsigned int *)0xD800014) #define IOCTL_BATTERY *((volatile unsigned int *)0xD800020) #define IOCTL_LED 0x02 #define IOCTL_SPEAKER 0x20 #define IOCTL_IRDA 0x40 /****************************************/ // From header.S // Bios Calls void *SetCallbacks(int index, void (*function)); int SetCpuSpeed(int speed); int PrepareExecute(int flag, int dir_index, int param); void DoExecute(int snapshot_flag); void SetComOnOff(int flag); int GetDirIndex(void); // IRQ/FIQ Asm void IntIRQ(void); void IntFIQ(void); void (*UserIRQ)(void); int (*UserFIQ)(void); // Return 1 to Skip Library Sound Processing, else return 0 /****************************************/ // IRQ/Timer0 Handler (for VSync) volatile int VCount; void IRQ_Handler(void) { int status; status = IRQ_STATUS; status &= IRQ_ENABLE; status &= ~(FIQ_TIMER2 | FIQ_COMM); // Clear FIQ Bits if (status & IRQ_TIMER0) VCount++; if (UserIRQ) UserIRQ(); IRQ_CLEAR = status; } /****************************************/ // FIQ/Timer2 Handler (for Sound) void FIQ_Handler(void) { IRQ_CLEAR = FIQ_TIMER2; } /****************************************/ // Sync Functions void VSync(int count) { register int cnt = VCount; register int PadState = PAD_STATUS; PadOnRelease = PadState; PadOnRelease ^= PadOnPress; PadOnRelease &= PadOnPress; PadOnPress = PadState; while (VCount < cnt + count); // Wait For IRQ Timer0 } /****************************************/ // Init, need to be called at first ! void PocketInit(void) { SetCpuSpeed(CLOCK_SPEED); IRQ_DISABLE_ALL(); UserIRQ = NULL; UserFIQ = NULL; VCount = 0; PadOnRelease = 0; PadOnPress = 0; SetCallbacks(1, IntIRQ); // VSync Interrupt SetCallbacks(2, IntFIQ); // Audio Interrupt IRQ_CLEAR = IRQ_TIMER0 | FIQ_TIMER2; IRQ_ENABLE = IRQ_TIMER0 | FIQ_TIMER2; // Start VSync Timer TIMER0_SETCOUNT(TICK_PER_FRAME); TIMER0_START(); while (PAD_STATUS & PAD_BUTTON); // Wait for Button Release (Button pressed when comming from Menu) } /****************************************/ // Exit, need to be called to exit app ! void PocketExit(void) { SetComOnOff(0); TIMER0_STOP(); TIMER2_STOP(); IRQ_DISABLE_ALL(); IRQ_ENABLE = IRQ_RTC | IRQ_PSCOMM; PrepareExecute(1, 0, GetDirIndex() | 0x30); // Return to GUI on our Program Icon DoExecute(0); } /****************************************/