Initial commit

This commit is contained in:
Hector Martin
2016-11-23 14:35:12 +09:00
commit 5b1c4f85b6
296 changed files with 39925 additions and 0 deletions

View File

@@ -0,0 +1,340 @@
// this file was taken from libogc, see http://www.devkitpro.org/
#ifndef __ASM_H__
#define __ASM_H__
#ifdef _LANGUAGE_ASSEMBLY
/* Condition Register Bit Fields */
#define cr0 0
#define cr1 1
#define cr2 2
#define cr3 3
#define cr4 4
#define cr5 5
#define cr6 6
#define cr7 7
/* General Purpose Registers (GPRs) */
#define r0 0
#define r1 1
#define sp 1
#define r2 2
#define toc 2
#define r3 3
#define r4 4
#define r5 5
#define r6 6
#define r7 7
#define r8 8
#define r9 9
#define r10 10
#define r11 11
#define r12 12
#define r13 13
#define r14 14
#define r15 15
#define r16 16
#define r17 17
#define r18 18
#define r19 19
#define r20 20
#define r21 21
#define r22 22
#define r23 23
#define r24 24
#define r25 25
#define r26 26
#define r27 27
#define r28 28
#define r29 29
#define r30 30
#define r31 31
/* Floating Point Registers (FPRs) */
#define fr0 0
#define fr1 1
#define fr2 2
#define fr3 3
#define fr4 4
#define fr5 5
#define fr6 6
#define fr7 7
#define fr8 8
#define fr9 9
#define fr10 10
#define fr11 11
#define fr12 12
#define fr13 13
#define fr14 14
#define fr15 15
#define fr16 16
#define fr17 17
#define fr18 18
#define fr19 19
#define fr20 20
#define fr21 21
#define fr22 22
#define fr23 23
#define fr24 24
#define fr25 25
#define fr26 26
#define fr27 27
#define fr28 28
#define fr29 29
#define fr30 30
#define fr31 31
#define vr0 0
#define vr1 1
#define vr2 2
#define vr3 3
#define vr4 4
#define vr5 5
#define vr6 6
#define vr7 7
#define vr8 8
#define vr9 9
#define vr10 10
#define vr11 11
#define vr12 12
#define vr13 13
#define vr14 14
#define vr15 15
#define vr16 16
#define vr17 17
#define vr18 18
#define vr19 19
#define vr20 20
#define vr21 21
#define vr22 22
#define vr23 23
#define vr24 24
#define vr25 25
#define vr26 26
#define vr27 27
#define vr28 28
#define vr29 29
#define vr30 30
#define vr31 31
#endif //_LANGUAGE_ASSEMBLY
#define SPRG0 272
#define SPRG1 273
#define SPRG2 274
#define SPRG3 275
#define PMC1 953
#define PMC2 954
#define PMC3 957
#define PMC4 958
#define MMCR0 952
#define MMCR1 956
#define LINK_REGISTER_CALLEE_UPDATE_ROOM 4
#define EXCEPTION_NUMBER 8
#define SRR0_OFFSET 12
#define SRR1_OFFSET 16
#define GPR0_OFFSET 20
#define GPR1_OFFSET 24
#define GPR2_OFFSET 28
#define GPR3_OFFSET 32
#define GPR4_OFFSET 36
#define GPR5_OFFSET 40
#define GPR6_OFFSET 44
#define GPR7_OFFSET 48
#define GPR8_OFFSET 52
#define GPR9_OFFSET 56
#define GPR10_OFFSET 60
#define GPR11_OFFSET 64
#define GPR12_OFFSET 68
#define GPR13_OFFSET 72
#define GPR14_OFFSET 76
#define GPR15_OFFSET 80
#define GPR16_OFFSET 84
#define GPR17_OFFSET 88
#define GPR18_OFFSET 92
#define GPR19_OFFSET 96
#define GPR20_OFFSET 100
#define GPR21_OFFSET 104
#define GPR22_OFFSET 108
#define GPR23_OFFSET 112
#define GPR24_OFFSET 116
#define GPR25_OFFSET 120
#define GPR26_OFFSET 124
#define GPR27_OFFSET 128
#define GPR28_OFFSET 132
#define GPR29_OFFSET 136
#define GPR30_OFFSET 140
#define GPR31_OFFSET 144
#define GQR0_OFFSET 148
#define GQR1_OFFSET 152
#define GQR2_OFFSET 156
#define GQR3_OFFSET 160
#define GQR4_OFFSET 164
#define GQR5_OFFSET 168
#define GQR6_OFFSET 172
#define GQR7_OFFSET 176
#define CR_OFFSET 180
#define LR_OFFSET 184
#define CTR_OFFSET 188
#define XER_OFFSET 192
#define MSR_OFFSET 196
#define DAR_OFFSET 200
#define STATE_OFFSET 204
#define MODE_OFFSET 206
#define FPR0_OFFSET 208
#define FPR1_OFFSET 216
#define FPR2_OFFSET 224
#define FPR3_OFFSET 232
#define FPR4_OFFSET 240
#define FPR5_OFFSET 248
#define FPR6_OFFSET 256
#define FPR7_OFFSET 264
#define FPR8_OFFSET 272
#define FPR9_OFFSET 280
#define FPR10_OFFSET 288
#define FPR11_OFFSET 296
#define FPR12_OFFSET 304
#define FPR13_OFFSET 312
#define FPR14_OFFSET 320
#define FPR15_OFFSET 328
#define FPR16_OFFSET 336
#define FPR17_OFFSET 344
#define FPR18_OFFSET 352
#define FPR19_OFFSET 360
#define FPR20_OFFSET 368
#define FPR21_OFFSET 376
#define FPR22_OFFSET 384
#define FPR23_OFFSET 392
#define FPR24_OFFSET 400
#define FPR25_OFFSET 408
#define FPR26_OFFSET 416
#define FPR27_OFFSET 424
#define FPR28_OFFSET 432
#define FPR29_OFFSET 440
#define FPR30_OFFSET 448
#define FPR31_OFFSET 456
#define FPSCR_OFFSET 464
#define PSR0_OFFSET 472
#define PSR1_OFFSET 480
#define PSR2_OFFSET 488
#define PSR3_OFFSET 496
#define PSR4_OFFSET 504
#define PSR5_OFFSET 512
#define PSR6_OFFSET 520
#define PSR7_OFFSET 528
#define PSR8_OFFSET 536
#define PSR9_OFFSET 544
#define PSR10_OFFSET 552
#define PSR11_OFFSET 560
#define PSR12_OFFSET 568
#define PSR13_OFFSET 576
#define PSR14_OFFSET 584
#define PSR15_OFFSET 592
#define PSR16_OFFSET 600
#define PSR17_OFFSET 608
#define PSR18_OFFSET 616
#define PSR19_OFFSET 624
#define PSR20_OFFSET 632
#define PSR21_OFFSET 640
#define PSR22_OFFSET 648
#define PSR23_OFFSET 656
#define PSR24_OFFSET 664
#define PSR25_OFFSET 672
#define PSR26_OFFSET 680
#define PSR27_OFFSET 688
#define PSR28_OFFSET 696
#define PSR29_OFFSET 704
#define PSR30_OFFSET 712
#define PSR31_OFFSET 720
/*
* maintain the EABI requested 8 bytes aligment
* As SVR4 ABI requires 16, make it 16 (as some
* exception may need more registers to be processed...)
*/
#define EXCEPTION_FRAME_END 728
#define IBAT0U 528
#define IBAT0L 529
#define IBAT1U 530
#define IBAT1L 531
#define IBAT2U 532
#define IBAT2L 533
#define IBAT3U 534
#define IBAT3L 535
#define IBAT4U 560
#define IBAT4L 561
#define IBAT5U 562
#define IBAT5L 563
#define IBAT6U 564
#define IBAT6L 565
#define IBAT7U 566
#define IBAT7L 567
#define DBAT0U 536
#define DBAT0L 537
#define DBAT1U 538
#define DBAT1L 538
#define DBAT2U 540
#define DBAT2L 541
#define DBAT3U 542
#define DBAT3L 543
#define DBAT4U 568
#define DBAT4L 569
#define DBAT5U 570
#define DBAT5L 571
#define DBAT6U 572
#define DBAT6L 573
#define DBAT7U 574
#define DBAT7L 575
#define HID0 1008
#define HID1 1009
#define HID2 920
#define HID4 1011
#define GQR0 912
#define GQR1 913
#define GQR2 914
#define GQR3 915
#define GQR4 916
#define GQR5 917
#define GQR6 918
#define GQR7 919
#define L2CR 1017
#define WPAR 921
#define DMAU 922
#define DMAL 923
#define MSR_RI 0x00000002
#define MSR_DR 0x00000010
#define MSR_IR 0x00000020
#define MSR_IP 0x00000040
#define MSR_SE 0x00000400
#define MSR_ME 0x00001000
#define MSR_FP 0x00002000
#define MSR_POW 0x00004000
#define MSR_EE 0x00008000
#define PPC_ALIGNMENT 8
#define PPC_CACHE_ALIGNMENT 32
#endif //__ASM_H__

View File

@@ -0,0 +1,310 @@
/*-------------------------------------------------------------
cache.h -- Cache interface
Copyright (C) 2004
Michael Wiedenbauer (shagkur)
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
-------------------------------------------------------------*/
#ifndef __CACHE_H__
#define __CACHE_H__
/*! \file cache.h
\brief Cache subsystem
*/
#include <gctypes.h>
#define LC_BASEPREFIX 0xe000
#define LC_BASE (LC_BASEPREFIX<<16)
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*!
* \fn void DCEnable()
* \brief Enable L1 d-cache
*
* \return none
*/
void DCEnable();
/*!
* \fn void DCDisable()
* \brief Disable L1 d-cache
*
* \return none
*/
void DCDisable();
/*!
* \fn void DCFreeze()
* \brief Current contents of the L1 d-cache are locked down and will not be cast out.
*
* Hits are still serviced, but misses go straight to L2 or 60x bus. Most cache operations, such as DCFlushRange(), will still execute regardless of whether the cache is frozen.<br>
* <b><i>NOTE:</i></b> In PowerPC architecture jargon, this feature is referred to as "locking" the data cache. We use the word "freeze" to distinguish it from the locked cache and DMA features.
*
* \return none
*/
void DCFreeze();
/*!
* \fn void DCUnfreeze()
* \brief Undoes actions of DCFreeze().
*
* Old cache blocks will now be cast out on subsequent L1 misses.<br>
* <b><i>NOTE:</i></b> In PowerPC architecture jargon, this feature is referred to as "locking" the data cache. We use the word "freeze" to distinguish it from the locked cache and DMA features.
*
* \return none
*/
void DCUnfreeze();
/*!
* \fn void DCFlashInvalidate()
* \brief Invalidate L1 d-cache.
*
* An invalidate operation is issued that marks the state of each data cache block as invalid without writing back modified cache blocks to memory.<br>
* Cache access is blocked during this time.Bus accesses to the cache are signaled as a miss during invalidate-all operations.
*
* \return none
*/
void DCFlashInvalidate();
/*!
* \fn void DCInvalidateRange(void *startaddress,u32 len)
* \brief Invalidates a given range of the d-cache.
*
* If any part of the range hits in the d-cache, the corresponding block will be invalidated.
*
* \param[in] startaddress pointer to the startaddress of the memory range to invalidate. <b><i>NOTE:</i></b> Has to be aligned on a 32byte boundery
* \param[in] len length of the range to invalidate. <b><i>NOTE:</i></b> Should be a multiple of 32
*
* \return none
*/
void DCInvalidateRange(void *startaddress,u32 len);
/*!
* \fn void DCFlushRange(void *startaddress,u32 len)
* \brief Flushes a given range.
*
* If any part of the range hits in the d-cache the corresponding block will be flushed to main memory and invalidated.<br>
* <b><i>NOTE:</i></b> This function invokes a "sync" after flushing the range. This means the function will stall until the CPU knows that the data has been writen to main memory
*
* \param[in] startaddress pointer to the startaddress of the memory range to flush. <b><i>NOTE:</i></b> Has to be aligned on a 32byte boundery
* \param[in] len length of range to be flushed. <b><i>NOTE:</i></b> Should be a multiple of 32
*
*\return none
*/
void DCFlushRange(void *startaddress,u32 len);
/*!
* \fn void DCStoreRange(void *startaddress,u32 len)
* \brief Ensures a range of memory is updated with any modified data in the cache.
*
* <b><i>NOTE:</i></b> This function invokes a "sync" after storing the range. This means the function will stall until the CPU knows that the data has been writen to main memory
*
* \param[in] startaddress pointer to the startaddress of the memory range to store. <b><i>NOTE:</i></b> Has to be aligned on a 32byte boundery
* \param[in] len length of the range to store. <b><i>NOTE:</i></b> Should be a multiple of 32
*
* \return none
*/
void DCStoreRange(void *startaddress,u32 len);
/*!
* \fn void DCFlushRangeNoSync(void *startaddress,u32 len)
* \brief Flushes a given range.
*
* If any part of the range hits in the d-cache the corresponding block will be flushed to main memory and invalidated.<br>
* <b><i>NOTE:</i></b> This routine does not perform a "sync" to ensure that the range has been flushed to memory. That is, the cache blocks are sent to the bus interface unit for storage to main memory, but by the time this function returns, you are not guaranteed that the blocks have been written to memory.
*
* \param[in] startaddress pointer to the startaddress of the memory range to flush. <b><i>NOTE:</i></b> Has to be aligned on a 32byte boundery
* \param[in] len length of range to be flushed. <b><i>NOTE:</i></b> Should be a multiple of 32
*
* \return none
*/
void DCFlushRangeNoSync(void *startaddress,u32 len);
/*!
* \fn void DCStoreRangeNoSync(void *startaddress,u32 len)
* \brief Ensures a range of memory is updated with any modified data in the cache.
*
* <b><i>NOTE:</i></b> This routine does not perform a "sync" to ensure that the range has been flushed to memory. That is, the cache blocks are sent to the bus interface unit for storage to main memory, but by the time this function returns, you are not guaranteed that the blocks have been written to memory
*
* \param[in] startaddress pointer to the startaddress of the memory range to store. <b><i>NOTE:</i></b> Has to be aligned on a 32byte boundery
* \param[in] len length of the range to store. <b><i>NOTE:</i></b> Should be a multiple of 32
*
* \return none
*/
void DCStoreRangeNoSync(void *startaddress,u32 len);
/*!
* \fn void DCZeroRange(void *startaddress,u32 len)
* \brief Loads a range of memory into cache and zeroes all the cache lines.
*
* \param[in] startaddress pointer to the startaddress of the memory range to load/zero. <b><i>NOTE:</i></b> Has to be aligned on a 32byte boundery
* \param[in] len length of the range to load/zero. <b><i>NOTE:</i></b> Should be a multiple of 32
*
* \return none
*/
void DCZeroRange(void *startaddress,u32 len);
/*!
* \fn void DCTouchRange(void *startaddress,u32 len)
* \brief Loads a range of memory into cache.
*
* \param[in] startaddress pointer to the startaddress of the memory range to load. <b><i>NOTE:</i></b> Has to be aligned on a 32byte boundery
* \param[in] len length of the range to load. <b><i>NOTE:</i></b> Should be a multiple of 32
*
* \return none
*/
void DCTouchRange(void *startaddress,u32 len);
/*!
* \fn void ICSync()
* \brief Performs an instruction cache synchronization.
*
* This ensures that all instructions preceding this instruction have completed before this instruction completes.
*
* \return none
*/
void ICSync();
/*!
* \fn void ICFlashInvalidate()
* \brief Invalidate the L1 i-cache.
*
* An invalidate operation is issued that marks the state of each instruction cache block as invalid without writing back modified cache blocks to memory.<br>
* Cache access is blocked during this time. Bus accesses to the cache are signaled as a miss during invalidate-all operations.
*
* \return none
*/
void ICFlashInvalidate();
/*!
* \fn void ICEnable()
* \brief Enable L1 i-cache
*
* \return none
*/
void ICEnable();
/*!
* \fn void ICDisable()
* \brief Disable L1 i-cache
*
* \return none
*/
void ICDisable();
/*!
* \fn void ICFreeze()
* \brief Current contents of the L1 i-cache are locked down and will not be cast out.
*
* Hits are still serviced, but misses go straight to L2 or 60x bus.<br>
* <b><i>NOTE:</i></b> In PowerPC architecture jargon, this feature is referred to as "locking" the data cache. We use the word "freeze" to distinguish it from the locked cache and DMA features.
*
* \return none
*/
void ICFreeze();
/*!
* \fn void ICUnfreeze()
* \brief Undoes actions of ICFreeze().
*
* Old cache blocks will now be cast out on subsequent L1 misses.<br>
* <b><i>NOTE:</i></b> In PowerPC architecture jargon, this feature is referred to as "locking" the data cache. We use the word "freeze" to distinguish it from the locked cache and DMA features.
*
* \return none
*/
void ICUnfreeze();
/*!
* \fn void ICBlockInvalidate(void *startaddress)
* \brief Invalidates a block in the i-cache.
*
* If the block hits in the i-cache, the corresponding block will be invalidated.
*
* \param[in] startaddress pointer to the startaddress of the memory block to invalidate. <b><i>NOTE:</i></b> Has to be aligned on a 32byte boundery
*
*\return none
*/
void ICBlockInvalidate(void *startaddress);
/*!
* \fn void ICInvalidateRange(void *startaddress,u32 len)
* \brief Invalidate a range in the L1 i-cache.
*
* If any part of the range hits in the i-cache, the corresponding block will be invalidated.
*
* \param[in] startaddress pointer to the startaddress of the memory range to invalidate. <b><i>NOTE:</i></b> Has to be aligned on a 32byte boundery
* \param[in] len length of the range to invalidate. <b><i>NOTE:</i></b> Should be a multiple of 32
*
* \return none
*/
void ICInvalidateRange(void *startaddress,u32 len);
void LCEnable();
void LCDisable();
void LCLoadBlocks(void *,void *,u32);
void LCStoreBlocks(void *,void *,u32);
u32 LCLoadData(void *,void *,u32);
u32 LCStoreData(void *,void *,u32);
u32 LCQueueLength();
u32 LCQueueWait(u32);
void LCFlushQueue();
void LCAlloc(void *,u32);
void LCAllocNoInvalidate(void *,u32);
void LCAllocOneTag(BOOL,void *);
void LCAllocTags(BOOL,void *,u32);
#define LCGetBase() ((void*)LC_BASE)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@@ -0,0 +1,465 @@
/*-------------------------------------------------------------
cache_asm.S -- Cache interface
Copyright (C) 2004
Michael Wiedenbauer (shagkur)
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
-------------------------------------------------------------*/
#include "asm.h"
.globl DCFlashInvalidate
DCFlashInvalidate:
mfspr r3,HID0
ori r3,r3,0x0400
mtspr HID0,r3
blr
.globl DCEnable
DCEnable:
sync
mfspr r3,HID0
ori r3,r3,0x4000
mtspr HID0,r3
blr
/* .globl DCDisable
DCDisable:
sync
mfspr r3,HID0
rlwinm r3,r3,0,18,16
mtspr HID0,r3
blr
*/
/* .globl DCFreeze
DCFreeze:
sync
mfspr r3,HID0
ori r3,r3,0x1000
mtspr HID0,r3
blr
.globl DCUnfreeze
DCUnfreeze:
mfspr r3,HID0
rlwinm r3,r3,0,20,18
mtspr HID0,r3
blr
.globl DCTouchLoad
DCTouchLoad:
dcbt r0,r3
blr
.globl DCBlockZero
DCBlockZero:
dcbz r0,r3
blr
.globl DCBlockStore
DCBlockStore:
dcbst r0,r3
blr
.globl DCBlockFlush
DCBlockFlush:
dcbf r0,r3
blr
.globl DCBlockInvalidate
DCBlockInvalidate:
dcbi r0,r3
blr
*/
.globl DCInvalidateRange
DCInvalidateRange:
cmplwi r4, 0 # zero or negative size?
blelr
clrlwi. r5, r3, 27 # check for lower bits set in address
beq 1f
addi r4, r4, 0x20
1:
addi r4, r4, 0x1f
srwi r4, r4, 5
mtctr r4
2:
dcbi r0, r3
addi r3, r3, 0x20
bdnz 2b
blr
.globl DCFlushRange
DCFlushRange:
cmplwi r4, 0 # zero or negative size?
blelr
clrlwi. r5, r3, 27 # check for lower bits set in address
beq 1f
addi r4, r4, 0x20
1:
addi r4, r4, 0x1f
srwi r4, r4, 5
mtctr r4
2:
dcbf r0, r3
addi r3, r3, 0x20
bdnz 2b
sc
blr
/* .globl DCStoreRange
DCStoreRange:
cmplwi r4, 0 # zero or negative size?
blelr
clrlwi. r5, r3, 27 # check for lower bits set in address
beq 1f
addi r4, r4, 0x20
1:
addi r4, r4, 0x1f
srwi r4, r4, 5
mtctr r4
2:
dcbst r0, r3
addi r3, r3, 0x20
bdnz 2b
sc
blr
*/
.globl DCFlushRangeNoSync
DCFlushRangeNoSync:
cmplwi r4, 0 # zero or negative size?
blelr
clrlwi. r5, r3, 27 # check for lower bits set in address
beq 1f
addi r4, r4, 0x20
1:
addi r4, r4, 0x1f
srwi r4, r4, 5
mtctr r4
2:
dcbf r0, r3
addi r3, r3, 0x20
bdnz 2b
blr
/* .globl DCStoreRangeNoSync
DCStoreRangeNoSync:
cmplwi r4, 0 # zero or negative size?
blelr
clrlwi. r5, r3, 27 # check for lower bits set in address
beq 1f
addi r4, r4, 0x20
1:
addi r4, r4, 0x1f
srwi r4, r4, 5
mtctr r4
2:
dcbst r0, r3
addi r3, r3, 0x20
bdnz 2b
blr
.globl DCZeroRange
DCZeroRange:
cmplwi r4, 0 # zero or negative size?
blelr
clrlwi. r5, r3, 27 # check for lower bits set in address
beq 1f
addi r4, r4, 0x20
1:
addi r4, r4, 0x1f
srwi r4, r4, 5
mtctr r4
2:
dcbz r0, r3
addi r3, r3, 0x20
bdnz 2b
blr
.globl DCTouchRange
DCTouchRange:
cmplwi r4, 0 # zero or negative size?
blelr
clrlwi. r5, r3, 27 # check for lower bits set in address
beq 1f
addi r4, r4, 0x20
1:
addi r4, r4, 0x1f
srwi r4, r4, 5
mtctr r4
2:
dcbt r0, r3
addi r3, r3, 0x20
bdnz 2b
blr
*/
.globl ICInvalidateRange
ICInvalidateRange:
cmplwi r4, 0 # zero or negative size?
blelr
clrlwi. r5, r3, 27 # check for lower bits set in address
beq 1f
addi r4, r4, 0x20
1:
addi r4, r4, 0x1f
srwi r4, r4, 5
mtctr r4
2:
icbi r0, r3
addi r3, r3, 0x20
bdnz 2b
sync
isync
blr
.globl ICFlashInvalidate
ICFlashInvalidate:
mfspr r3,HID0
ori r3,r3,0x0800
mtspr HID0,r3
blr
.globl ICEnable
ICEnable:
isync
mfspr r3,HID0
ori r3,r3,0x8000
mtspr HID0,r3
blr
.globl ICDisable
ICDisable:
isync
mfspr r3,HID0
rlwinm r3,r3,0,17,15
mtspr HID0,r3
blr
/* .globl ICFreeze
ICFreeze:
isync
mfspr r3,HID0
ori r3,r3,0x2000
mtspr HID0,r3
blr
.globl ICUnfreeze
ICUnfreeze:
mfspr r3,HID0
rlwinm r3,r3,0,19,17
mtspr HID0,r3
blr
.globl ICBlockInvalidate
ICBlockInvalidate:
icbi r0,r3
blr
*/
.globl ICSync
ICSync:
isync
blr
.globl L2Init
L2Init:
mflr r0
stw r0,4(sp)
stwu sp,-16(sp)
stw r31,12(sp)
mfmsr r3
mr r31,r3
sync
li r3,48
mtmsr r3
sync
bl L2Disable
bl L2GlobalInvalidate
mr r3,r31
mtmsr r3
lwz r0,20(sp)
lwz r31,12(sp)
mtlr r0
blr
.globl L2Enable
L2Enable:
mfspr r3,L2CR;
oris r0,r3,0x8000
rlwinm r3,r0,0,11,9
mtspr L2CR,r3
blr
.globl L2Disable
L2Disable:
sync
mfspr r3,L2CR
clrlwi r3,r3,1
mtspr L2CR,r3
sync
blr
.globl L2GlobalInvalidate
L2GlobalInvalidate:
mflr r0
stw r0,4(sp)
stwu sp,-8(sp)
bl L2Disable
mfspr r3,L2CR
oris r3,r3,0x0020
mtspr L2CR,r3
1: mfspr r3,L2CR
clrlwi r0,r3,31
cmplwi r0,0x0000
bne 1b
mfspr r3,L2CR
rlwinm r3,r3,0,11,9
mtspr L2CR,r3
2: mfspr r3,L2CR
clrlwi r0,r3,31
cmplwi r0,0x0000
bne 2b
lwz r0,12(sp)
addi sp,sp,8
mtlr r0
blr
/* .globl __LCEnable
__LCEnable:
mfmsr r5
ori r5,r5,0x1000
mtmsr r5
lis r3,0x8000
li r4,1024
mtctr r4
1: dcbt r0,r3
dcbst r0,r3
bdnz 1b
mfspr r4,HID2
oris r4,r4,0x100f
mtspr HID2,r4
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
lis r3,0xe000
ori r3,r3,0x0002
mtspr DBAT3L,r3
ori r3,r3,0x01fe
mtspr DBAT3U,r3
isync
lis r3,0xe000
li r6,512
mtctr r6
li r6,0
2: dcbz_l r6,r3
addi r3,r3,32
bdnz 2b
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
blr
.globl LCDisable
LCDisable:
lis r3,0xe000
li r4,512
mtctr r4
1: dcbi r0,r3
addi r3,r3,32
bdnz 1b
mfspr r4,HID2
rlwinm r4,r4,0,4,2
mtspr HID2,r4
blr
.globl LCAllocOneTag
LCAllocOneTag:
cmpwi r3,0
beq 1f
dcbi r0,r4
1: dcbz_l r0,r4
blr
.globl LCAllocTags
LCAllocTags:
mflr r6
cmplwi r5,0
ble 2f
mtctr r5
cmpwi r3,0
beq 3f
1: dcbi r0,r4
dcbz_l r0,r4
addi r4,r4,32
bdnz 1b
b 2f
3: dcbz_l r0,r4
addi r4,r4,32
bdnz 3b
2: mtlr r6
blr
.globl LCLoadBlocks
LCLoadBlocks:
extrwi r6,r5,5,25
clrlwi r4,r4,4
or r6,r6,r4
mtspr DMAU,r6
clrlslwi r6,r5,30,2
or r6,r6,r3
ori r6,r6,0x0012
mtspr DMAL,r6
blr
.globl LCStoreBlocks
LCStoreBlocks:
extrwi r6,r5,5,25
clrlwi r4,r4,4
or r6,r6,r3
mtspr DMAU,r6
clrlslwi r6,r5,30,2
or r6,r6,r4
ori r6,r6,0x0002
mtspr DMAL,r6
blr
*/

View File

@@ -0,0 +1,207 @@
// this file was taken from libogc, see http://www.devkitpro.org/
#include "asm.h"
#define _SDA_BASE_ 32768
#define _SDA2_BASE_ 32768
.text
.section .init
# crt0.s file for the GameCube V1.1 by Costis (costis@gbaemu.com)!
#
# Updates: Added support for clearing the BSS section so that global
# variables are cleared to 0 upon start-up.
#
# This is start-up code for initializing the GameCube system and hardware
# before executing the actual user program code. It clears the GPR's,
# initializes the FPR's, initializes the Data, Code, and L2 caches, clears
# and initializes SPR's, and disables exceptions (interrupts).
#
# Have fun!!! Please e-mail any suggestions or bugs to costis@gbaemu.com.
# Entry Point
.extern __PSInit
.extern __SyscallInit
.extern __CacheInit
.extern __SystemInit
.extern __sbss_start, __bss_end
.extern __bat_config
.extern _main
.globl _start, __main
_start:
b startup
.ascii "STUB"
.ascii "HAXX"
.long 0
startup:
# Disable interrupts first thing
mfmsr r3
rlwinm r4,r3,0,17,15
rlwinm r4,r4,0,26,24
mtmsr r4
# Go into real mode
isync
lis r3,real@h
ori r3,r3,real@l
clrlwi r3,r3,2
mtsrr0 r3
mfmsr r3
li r4,0x30
andc r3,r3,r4
mtsrr1 r3
rfi
real:
# Set up the BATs the way we like them
// HID0 = 00110c64:
// bus checkstops off, sleep modes off,
// caches off, caches invalidate,
// store gathering off, enable data cache
// flush assist, enable branch target cache,
// enable branch history table
lis 3,0x0011 ; ori 3,3,0x0c64 ; mtspr 1008,3 ; isync
// MSR = 00002000 (FP on)
li 4,0x2000 ; mtmsr 4
// HID0 |= 0000c000 (caches on)
ori 3,3,0xc000 ; mtspr 1008,3 ; isync
// clear all BATs
li 0,0
mtspr 528,0 ; mtspr 530,0 ; mtspr 532,0 ; mtspr 534,0 // IBATU 0..3
mtspr 536,0 ; mtspr 538,0 ; mtspr 540,0 ; mtspr 542,0 // DBATU 0..3
mtspr 560,0 ; mtspr 562,0 ; mtspr 564,0 ; mtspr 566,0 // IBATU 4..7
mtspr 568,0 ; mtspr 570,0 ; mtspr 572,0 ; mtspr 574,0 // DBATU 4..7
isync
// clear all SRs
lis 0,0x8000
mtsr 0,0 ; mtsr 1,0 ; mtsr 2,0 ; mtsr 3,0
mtsr 4,0 ; mtsr 5,0 ; mtsr 6,0 ; mtsr 7,0
mtsr 8,0 ; mtsr 9,0 ; mtsr 10,0 ; mtsr 11,0
mtsr 12,0 ; mtsr 13,0 ; mtsr 14,0 ; mtsr 15,0
isync
// set [DI]BAT0 for 256MB@80000000,
// real 00000000, WIMG=0000, R/W
li 3,2 ; lis 4,0x8000 ; ori 4,4,0x1fff
mtspr IBAT0L,3 ; mtspr IBAT0U,4 ; mtspr DBAT0L,3 ; mtspr DBAT0U,4 ; isync
// set [DI]BAT4 for 256MB@90000000,
// real 10000000, WIMG=0000, R/W
addis 3,3,0x1000 ; addis 4,4,0x1000
mtspr IBAT4L,3 ; mtspr IBAT4U,4 ; mtspr DBAT4L,3 ; mtspr DBAT4U,4 ; isync
// set DBAT1 for 256MB@c0000000,
// real 00000000, WIMG=0101, R/W
li 3,0x2a ; lis 4,0xc000 ; ori 4,4,0x1fff
mtspr DBAT1L,3 ; mtspr DBAT1U,4 ; isync
// set DBAT5 for 256MB@d0000000,
// real 10000000, WIMG=0101, R/W
addis 3,3,0x1000 ; addis 4,4,0x1000
mtspr DBAT5L,3 ; mtspr DBAT5U,4 ; isync
// enable [DI]BAT4-7 in HID4
lis 3, 0x8200
mtspr 1011,3
// set MSR[DR:IR] = 11, jump to _start
lis 3,virtual@h ; ori 3,3, virtual@l ; mtsrr0 3
mfmsr 3 ; ori 3,3,0x30 ; mtsrr1 3
rfi
virtual:
bl InitGPRS # Initialize the General Purpose Registers
bl __CacheInit # Initialize the system caches
bl __SyscallInit # Initialize the System Call handler
bl __SystemInit # Initialize more cache aspects, clear a few SPR's, and disable interrupts.
# Clear the BSS section!
lis r3,__sbss_start@h
ori r3,r3,__sbss_start@l
li r4,0
lis r5,__bss_end@h
ori r5,r5,__bss_end@l
sub r5,r5,r3
bl _memset
bl _main # Branch to the user code!
eloop:
b eloop # If the main function returns, which should never happen then just loop endlessly.
InitGPRS:
# Clear all of the GPR's to 0
li r0,0
li r3,0
li r4,0
li r5,0
li r6,0
li r7,0
li r8,0
li r9,0
li r10,0
li r11,0
li r12,0
li r14,0
li r15,0
li r16,0
li r17,0
li r18,0
li r19,0
li r20,0
li r21,0
li r22,0
li r23,0
li r24,0
li r25,0
li r26,0
li r27,0
li r28,0
li r29,0
li r30,0
li r31,0
lis sp,__crt0stack@h # we take 0x8173FFF0 as the topmost starting point for our stack,this gives us ~128Kb Stack
ori sp,sp,__crt0stack@l
addi sp,sp,-4
stw r0,0(sp)
stwu sp,-56(sp)
lis r2,_SDA2_BASE_@h
ori r2,r2,_SDA2_BASE_@l # Set the Small Data 2 (Read Only) base register.
lis r13,_SDA_BASE_@h
ori r13,r13,_SDA_BASE_@l # Set the Small Data (Read\Write) base register.
blr
//r3 = ptr, r4 = fill, r5 = size
.globl _memset
_memset:
clrlwi. r6,r5,29
srwi r5,r5,2
subi r3,r3,4
mtctr r5
1: stwu r4,4(r3)
bdnz 1b
cmplwi r6,0
beq 3f
2: stbu r4,1(r3)
addic. r6,r6,-1
bne+ 2b
3: blr
.section .bss
.balign 8
__crt0stack_end:
.space 0x8000
__crt0stack:

View File

@@ -0,0 +1,290 @@
/*
* Copyright (C) 2008 segher, #wiidev efnet
* Copyright (C) 2008 bushing, #wiidev efnet
* Copyright (C) 2008 dhewg, #wiidev efnet
* Copyright (C) 2008 marcan, #wiidev efnet
*
* this file is part of the Homebrew Channel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "stub_debug.h"
#include "ios.h"
#include "processor.h"
#include "cache.h"
#include "system.h"
#define virt_to_phys(x) ((u32*)(((u32)(x))&0x7FFFFFFF))
#define phys_to_virt(x) ((u32*)(((u32)(x))|0x80000000))
// Timebase frequency is core frequency / 8. Ignore roundoff, this
// doesn't have to be very accurate.
#define TICKS_PER_USEC (729/8)
static u32 mftb(void)
{
u32 x;
asm volatile("mftb %0" : "=r"(x));
return x;
}
static void __delay(u32 ticks)
{
u32 start = mftb();
while (mftb() - start < ticks)
;
}
void udelay(u32 us)
{
__delay(TICKS_PER_USEC * us);
}
// Low-level IPC access.
static inline u32 read32(u32 addr)
{
u32 x;
asm volatile("lwz %0,0(%1) ; sync" : "=r"(x) : "b"(0xc0000000 | addr));
return x;
}
static inline void write32(u32 addr, u32 x)
{
asm volatile("stw %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr));
}
static u32 ipc_read(u32 reg) {
return read32(0x0d000000 + 4*reg);
}
static void ipc_write(u32 reg, u32 value) {
write32(0x0d000000 + 4*reg, value);
}
static void ipc_bell(u32 w)
{
ipc_write(1, (ipc_read(1) & 0x30) | w);
}
static void ipc_wait_ack(void)
{
while ((ipc_read(1) & 0x22) != 0x22)
;
udelay(100);
}
static void ipc_wait_reply(void)
{
while ((ipc_read(1) & 0x14) != 0x14)
;
udelay(100);
}
static void ipc_irq_ack(void)
{
ipc_write(12, 0x40000000);
}
// Mid-level IPC access.
struct ipc {
u32 cmd;
int result;
int fd;
u32 arg[5];
u32 user[8];
};
static struct ipc ipc __attribute__((aligned(64)));
static void ipc_send_request(void)
{
DCFlushRange(&ipc, 0x40);
ipc_write(0, (u32)virt_to_phys(&ipc));
ipc_bell(1);
ipc_wait_ack();
ipc_bell(2);
ipc_irq_ack();
}
void ipc_send_twoack(void)
{
DCFlushRange(&ipc, 0x40);
ipc_write(0, (u32)virt_to_phys(&ipc));
ipc_bell(1);
ipc_wait_ack();
ipc_irq_ack();
ipc_bell(2);
ipc_wait_ack();
ipc_irq_ack();
ipc_bell(2);
ipc_bell(8);
}
static void ipc_recv_reply(void)
{
for (;;) {
u32 reply;
ipc_wait_reply();
reply = ipc_read(2);
ipc_bell(4);
ipc_irq_ack();
ipc_bell(8);
if (((u32*)reply) == virt_to_phys(&ipc))
break;
debug_string("Ignoring unexpected IPC reply @");
debug_uint((u32)reply);
debug_string("\n\r");
}
DCInvalidateRange(&ipc, sizeof ipc);
}
// High-level IPC access.
int ios_open(const char *filename, u32 mode)
{
DCFlushRange((void*)filename, strlen(filename) + 1);
memset(&ipc, 0, sizeof ipc);
ipc.cmd = 1;
ipc.fd = 0;
ipc.arg[0] = (u32)virt_to_phys(filename);
ipc.arg[1] = mode;
ipc_send_request();
ipc_recv_reply();
return ipc.result;
}
int ios_close(int fd)
{
memset(&ipc, 0, sizeof ipc);
ipc.cmd = 2;
ipc.fd = fd;
ipc_send_request();
ipc_recv_reply();
return ipc.result;
}
int _ios_ioctlv(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec, int reboot)
{
u32 i;
memset(&ipc, 0, sizeof ipc);
for (i = 0; i < in_count + out_count; i++)
if (vec[i].data) {
DCFlushRange(vec[i].data, vec[i].len);
vec[i].data = (void *)virt_to_phys(vec[i].data);
}
DCFlushRange(vec, (in_count + out_count) * sizeof *vec);
ipc.cmd = 7;
ipc.fd = fd;
ipc.arg[0] = n;
ipc.arg[1] = in_count;
ipc.arg[2] = out_count;
ipc.arg[3] = (u32)virt_to_phys(vec);
if(reboot) {
ipc_send_twoack();
return 0;
} else {
ipc_send_request();
ipc_recv_reply();
for (i = in_count; i < in_count + out_count; i++)
if (vec[i].data) {
vec[i].data = phys_to_virt((u32)vec[i].data);
DCInvalidateRange(vec[i].data, vec[i].len);
}
return ipc.result;
}
}
int ios_ioctlv(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec) {
return _ios_ioctlv(fd, n, in_count, out_count, vec, 0);
}
int ios_ioctlvreboot(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec) {
return _ios_ioctlv(fd, n, in_count, out_count, vec, 1);
}
// Cleanup any old state.
static void ipc_cleanup_reply(void) {
if ((ipc_read(1) & 0x14) != 0x14)
return;
ipc_read(2);
ipc_bell(4);
ipc_irq_ack();
ipc_bell(8);
}
static void ipc_cleanup_request(void) {
if ((ipc_read(1) & 0x22) == 0x22)
ipc_bell(2);
}
void reset_ios(void) {
int i;
debug_string("Flushing IPC transactions");
for (i = 0; i < 10; i++) {
ipc_cleanup_request();
ipc_cleanup_reply();
ipc_irq_ack();
udelay(1000);
debug_string(".");
}
debug_string(" Done.\n\r");
debug_string("Closing file descriptors");
for (i = 0; i < 32; i++) {
ios_close(i);
debug_string(".");
}
debug_string(" Done.\n\r");
}

View File

@@ -0,0 +1,11 @@
struct ioctlv {
void *data;
u32 len;
};
int ios_open(const char *filename, u32 mode);
int ios_close(int fd);
int ios_ioctlv(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec);
int ios_ioctlvreboot(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec);
void reset_ios(void);

View File

@@ -0,0 +1,115 @@
// this file was taken from libogc, see http://www.devkitpro.org/
#ifndef __PROCESSOR_H__
#define __PROCESSOR_H__
#include <gctypes.h>
#define __stringify(rn) #rn
#define ATTRIBUTE_ALIGN(v) __attribute__((aligned(v)))
#define _sync() asm volatile("sync")
#define _nop() asm volatile("nop")
#define ppcsync() asm volatile("sc")
#define ppchalt() ({ \
asm volatile("sync"); \
while(1) { \
asm volatile("nop"); \
asm volatile("li 3,0"); \
asm volatile("nop"); \
} \
})
#define mfdcr(_rn) ({register u32 _rval; \
asm volatile("mfdcr %0," __stringify(_rn) \
: "=r" (_rval)); _rval;})
#define mtdcr(rn, val) asm volatile("mtdcr " __stringify(rn) ",%0" : : "r" (val))
#define mfmsr() ({register u32 _rval; \
asm volatile("mfmsr %0" : "=r" (_rval)); _rval;})
#define mtmsr(val) asm volatile("mtmsr %0" : : "r" (val))
#define mfdec() ({register u32 _rval; \
asm volatile("mfdec %0" : "=r" (_rval)); _rval;})
#define mtdec(_val) asm volatile("mtdec %0" : : "r" (_val))
#define mfspr(_rn) \
({ register u32 _rval = 0; \
asm volatile("mfspr %0," __stringify(_rn) \
: "=r" (_rval));\
_rval; \
})
#define mtspr(_rn, _val) asm volatile("mtspr " __stringify(_rn) ",%0" : : "r" (_val))
#define mfwpar() mfspr(WPAR)
#define mtwpar(_val) mtspr(WPAR,_val)
#define mfmmcr0() mfspr(MMCR0)
#define mtmmcr0(_val) mtspr(MMCR0,_val)
#define mfmmcr1() mfspr(MMCR1)
#define mtmmcr1(_val) mtspr(MMCR1,_val)
#define mfpmc1() mfspr(PMC1)
#define mtpmc1(_val) mtspr(PMC1,_val)
#define mfpmc2() mfspr(PMC2)
#define mtpmc2(_val) mtspr(PMC2,_val)
#define mfpmc3() mfspr(PMC3)
#define mtpmc3(_val) mtspr(PMC3,_val)
#define mfpmc4() mfspr(PMC4)
#define mtpmc4(_val) mtspr(PMC4,_val)
#define mfhid0() mfspr(HID0)
#define mthid0(_val) mtspr(HID0,_val)
#define mfhid1() mfspr(HID1)
#define mthid1(_val) mtspr(HID1,_val)
#define mfhid2() mfspr(HID2)
#define mthid2(_val) mtspr(HID2,_val)
#define mfhid4() mfspr(HID4)
#define mthid4(_val) mtspr(HID4,_val)
#define cntlzw(_val) ({register u32 _rval; \
asm volatile("cntlzw %0, %1" : "=r"((_rval)) : "r"((_val))); _rval;})
#define _CPU_MSR_GET( _msr_value ) \
do { \
_msr_value = 0; \
asm volatile ("mfmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); \
} while (0)
#define _CPU_MSR_SET( _msr_value ) \
{ asm volatile ("mtmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); }
#define _CPU_ISR_Enable() \
{ register u32 _val = 0; \
asm volatile ("mfmsr %0; ori %0,%0,0x8000; mtmsr %0" : \
"=&r" (_val) : "0" (_val));\
}
#define _CPU_ISR_Disable( _isr_cookie ) \
{ register u32 _disable_mask = MSR_EE; \
_isr_cookie = 0; \
asm volatile ( \
"mfmsr %0; andc %1,%0,%1; mtmsr %1" : \
"=&r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
"0" ((_isr_cookie)), "1" ((_disable_mask)) \
); \
}
#define _CPU_ISR_Restore( _isr_cookie ) \
{ \
asm volatile ( "mtmsr %0" : \
"=r" ((_isr_cookie)) : \
"0" ((_isr_cookie))); \
}
#define _CPU_ISR_Flash( _isr_cookie ) \
{ register u32 _disable_mask = MSR_EE; \
asm volatile ( \
"mtmsr %0; andc %1,%0,%1; mtmsr %1" : \
"=r" ((_isr_cookie)), "=r" ((_disable_mask)) : \
"0" ((_isr_cookie)), "1" ((_disable_mask)) \
); \
}
#endif

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2008 dhewg, #wiidev efnet
* Copyright (C) 2008 marcan, #wiidev efnet
*
* this file is part of the Homebrew Channel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "system.h"
#include "stub_debug.h"
#include "usb.h"
#include "ios.h"
#include "cache.h"
#include "../config.h"
#define IOCTL_ES_LAUNCH 0x08
#define IOCTL_ES_GETVIEWCNT 0x12
#define IOCTL_ES_GETVIEWS 0x13
struct ioctlv vecs[3] __attribute__((aligned(32)));
u64 *conf_magic = STUB_ADDR_MAGIC;
u64 *conf_titleID = STUB_ADDR_TITLE;
int es_fd;
int LaunchTitle(u64 titleID) {
static u64 xtitleID __attribute__((aligned(32)));
static u32 cntviews __attribute__((aligned(32)));
static u8 tikviews[0xd8*4] __attribute__((aligned(32)));
int ret;
debug_string("LaunchTitle: ");
debug_uint(titleID>>32);
debug_string("-");
debug_uint(titleID&0xFFFFFFFF);
xtitleID = titleID;
debug_string("\n\rGetTicketViewCount: ");
vecs[0].data = &xtitleID;
vecs[0].len = 8;
vecs[1].data = &cntviews;
vecs[1].len = 4;
ret = ios_ioctlv(es_fd, IOCTL_ES_GETVIEWCNT, 1, 1, vecs);
debug_uint(ret);
debug_string(", views: ");
debug_uint(cntviews);
debug_string("\n\r");
if(ret<0) return ret;
if(cntviews>4) return -1;
debug_string("GetTicketViews: ");
vecs[0].data = &xtitleID;
vecs[0].len = 8;
vecs[1].data = &cntviews;
vecs[1].len = 4;
vecs[2].data = tikviews;
vecs[2].len = 0xd8*cntviews;
ret = ios_ioctlv(es_fd, IOCTL_ES_GETVIEWS, 2, 1, vecs);
debug_uint(ret);
debug_string("\n\r");
if(ret<0) return ret;
debug_string("Attempting to launch...\n\r");
vecs[0].data = &xtitleID;
vecs[0].len = 8;
vecs[1].data = tikviews;
vecs[1].len = 0xd8;
ret = ios_ioctlvreboot(es_fd, IOCTL_ES_LAUNCH, 2, 0, vecs);
if(ret < 0) {
debug_string("Launch failed: ");
debug_uint(ret);
debug_string("\r\n");
}
return ret;
}
s32 IOS_GetVersion()
{
u32 vercode;
u16 version;
DCInvalidateRange((void*)0x80003140,8);
vercode = *((u32*)0x80003140);
version = vercode >> 16;
if(version == 0) return -1;
if(version > 0xff) return -1;
return version;
}
void printversion(void) {
debug_string("IOS version: ");
debug_uint(IOS_GetVersion());
debug_string("\n\r");
}
int es_init(void) {
debug_string("Opening /dev/es: ");
es_fd = ios_open("/dev/es", 0);
debug_uint(es_fd);
debug_string("\n\r");
return es_fd;
}
void _main (void) {
int iosver;
u64 titleID = MY_TITLEID;
debug_string("\n\rHomebrew Channel stub code\n\r");
if(*conf_magic == STUB_MAGIC) titleID = *conf_titleID;
reset_ios();
if(es_init() < 0) goto fail;
iosver = STUB_LOAD_IOS_VERSION;
if(iosver < 0)
iosver = 21; //bah
printversion();
debug_string("\n\rReloading IOS...\n\r");
LaunchTitle(0x0000000100000000LL | iosver);
printversion();
if(es_init() < 0) goto fail;
debug_string("\n\rLoading requested channel...\n\r");
LaunchTitle(titleID);
// if fail, try system menu
debug_string("\n\rChannel load failed, trying with system menu...\n\r");
LaunchTitle(0x0000000100000002LL);
printversion();
fail:
debug_string("FAILURE\n\r");
while(1);
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2008 dhewg, #wiidev efnet
*
* this file is part of the Homebrew Channel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "stub_debug.h"
#include "usb.h"
#ifdef DEBUG_STUB
static char int2hex[] = "0123456789abcdef";
void debug_uint (u32 i) {
int j;
usb_sendbuffersafe ("0x", 2);
for (j = 0; j < 8; ++j) {
usb_sendbuffersafe (&int2hex[(i >> 28) & 0xf], 1);
i <<= 4;
}
}
void debug_string (const char *s) {
u32 i = 0;
while (s[i])
i++;
usb_sendbuffersafe (s, i);
}
#endif

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2008 dhewg, #wiidev efnet
*
* this file is part of the Homebrew Channel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _STUB_DEBUG_H_
#define _STUB_DEBUG_H_
#include <gctypes.h>
#include "../config.h"
#ifdef DEBUG_STUB
void debug_uint (u32 i);
void debug_string (const char *s);
#else
#define debug_uint(x)
#define debug_string(x)
#endif
#endif

View File

@@ -0,0 +1,28 @@
#include "asm.h"
#include "cache.h"
#include "system.h"
#include "processor.h"
extern char systemcallhandler_start[], systemcallhandler_end[];
void __SyscallInit(void)
{
memcpy((void*)0x80000c00, systemcallhandler_start,
systemcallhandler_end - systemcallhandler_start);
DCFlushRangeNoSync((void*)0x80000c00, 0x100);
ICInvalidateRange((void*)0x80000c00, 0x100);
_sync();
}
void *memcpy(void *ptr, const void *src, int size) {
char* ptr2 = ptr;
const char* src2 = src;
while(size--) *ptr2++ = *src2++;
return ptr;
}
int strlen(const char *ptr) {
int i=0;
while(*ptr++) i++;
return i;
}

View File

@@ -0,0 +1,24 @@
// this code was taken from libogc, see http://www.devkitpro.org/
#ifndef __SYSTEM_H__
#define __SYSTEM_H__
#include <gctypes.h>
void ICInvalidateRange(void *startaddress,u32 len);
void DCInvalidateRange(void *startaddress,u32 len);
void DCFlushRange(void *startaddress,u32 len);
void DCFlushRangeNoSync(void *startaddress,u32 len);
void dol_relocstart(void *dolstart);
void* memmove(void *dst0,const void *src0,register int length);
extern void _memset(void *,int,int);
//void *memset(void *ptr, int c, int size);
#define memset _memset
void *memcpy(void *ptr, const void *src, int size);
int strlen(const char *ptr);
extern void __exception_closeall();
#endif

View File

@@ -0,0 +1,100 @@
// this code was taken from libogc, see http://www.devkitpro.org/
#include "asm.h"
.extern ICFlashInvalidate
.extern ICEnable
.extern DCEnable
.extern L2Init
.extern L2Enable
.globl __CacheInit
__CacheInit:
mflr r0
stw r0, 4(sp)
stwu sp, -16(sp)
stw r31, 12(sp)
mfspr r3,HID0 # (HID0)
rlwinm r0,r3, 0, 16, 16
cmplwi r0, 0x0000 # Check if the Instruction Cache has been enabled or not.
bne ICEnabled
bl ICEnable
ICEnabled:
mfspr r3, HID0 # bl PPCMfhid0
rlwinm r0, r3, 0, 17, 17
cmplwi r0, 0x0000 # Check if the Data Cache has been enabled or not.
bne DCEnabled
bl DCEnable
DCEnabled:
mfspr r3, L2CR # (L2CR)
clrrwi r0, r3, 31 # Clear all of the bits except 31
cmplwi r0, 0x0000
bne L2Enabled
bl L2Init
bl L2Enable
L2Enabled:
# Restore the non-volatile registers to their previous values and return.
lwz r0, 20(sp)
lwz r31, 12(sp)
addi sp, sp, 16
mtlr r0
blr
.globl __SystemInit
__SystemInit:
mflr r0
stw r0, 4(sp)
stwu sp, -24(sp)
stw r31, 20(sp)
stw r30, 16(sp)
stw r29, 12(sp)
# Clear various SPR's
li r3,0
mtspr 952, r3
mtspr 956, r3
mtspr 953, r3
mtspr 954, r3
mtspr 957, r3
mtspr 958, r3
#if 0
lis r3,0x8390 //bits set: H4A(HID4 access), SBE(2nd BAT enabled), SR0(store 0), LPE(PS LE exception), L2CFI(L2 castout prior to L2 inv. flash)
mtspr HID4,r3
#endif
# Disable Speculative Bus Accesses to non-guarded space from both caches.
mfspr r3, HID0
ori r3, r3, 0x0200
mtspr HID0, r3
mfspr r3,HID2 # (HID2)
rlwinm r3, r3, 0, 2, 0
mtspr HID2,r3 # (HID2)
# Restore the non-volatile registers to their previous values and return.
lwz r0, 28(sp)
lwz r31,20(sp)
lwz r30,16(sp)
lwz r29,12(sp)
addi sp, sp, 24
mtlr r0
blr
.global systemcallhandler_start,systemcallhandler_end
systemcallhandler_start:
mfspr r3,HID0
ori r4,r3,0x0008
mtspr HID0,r4
isync
sync
mtspr HID0,r3
rfi
systemcallhandler_end:
nop

View File

@@ -0,0 +1,221 @@
/*---------------------------------------------------------------------------------------------
* USB Gecko Development Kit - http://www.usbgecko.com
* --------------------------------------------------------------------------------------------
*
*
* usb.c - V1.2 functions for the USB Gecko adapter (www.usbgecko.com).
* Now works for Wii Mode - use WIIMODE define in usb.h to set
* Copyright (c) 2008 - Nuke - <wiinuke@gmail.com>
*
*---------------------------------------------------------------------------------------------*/
#include <gctypes.h> // If not using libogc need types
#include "usb.h"
#ifdef DEBUG_STUB
/*---------------------------------------------------------------------------------------------*
Name: usb_sendbyte
Description: Send byte to Gamecube/Wii over EXI memory card port
*----------------------------------------------------------------------------------------------*/
static int __usb_sendbyte (char sendbyte)
{
s32 i;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0xB0000000 | (sendbyte<<20);
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0;
if (i&0x04000000){
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_receivebyte
Description: Receive byte from Gamecube/Wii over EXI memory card port
*----------------------------------------------------------------------------------------------*/
static int __usb_receivebyte (char *receivebyte)
{
s32 i = 0;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0xA0000000;
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0;
if (i&0x08000000){
*receivebyte=(i>>16)&0xff;
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_checksendstatus
Description: Chesk the FIFO is ready to send
*----------------------------------------------------------------------------------------------*/
static int __usb_checksendstatus()
{
s32 i = 0;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0xC0000000;
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0x0;
if (i&0x04000000){
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_checkreceivestatus
Description: Check the FIFO is ready to receive
*----------------------------------------------------------------------------------------------*/
static int __usb_checkreceivestatus()
{
s32 i = 0;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0xD0000000;
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0x0;
if (i&0x04000000){
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_sendbuffer
Description: Simple buffer send routine
*----------------------------------------------------------------------------------------------*/
void usb_sendbuffer (const void *buffer, int size)
{
char *sendbyte = (char*) buffer;
s32 bytesleft = size;
s32 returnvalue;
while (bytesleft > 0)
{
returnvalue = __usb_sendbyte(*sendbyte);
if(returnvalue) {
sendbyte++;
bytesleft--;
}
}
}
/*---------------------------------------------------------------------------------------------*
Name: usb_receivebuffer
Description: Simple buffer receive routine
*----------------------------------------------------------------------------------------------*/
void usb_receivebuffer (void *buffer, int size)
{
char *receivebyte = (char*)buffer;
s32 bytesleft = size;
s32 returnvalue;
while (bytesleft > 0)
{
returnvalue = __usb_receivebyte(receivebyte);
if(returnvalue) {
receivebyte++;
bytesleft--;
}
}
}
/*---------------------------------------------------------------------------------------------*
Name: usb_sendbuffersafe
Description: Simple buffer send routine with fifo check (use for large transfers)
*----------------------------------------------------------------------------------------------*/
void usb_sendbuffersafe (const void *buffer, int size)
{
char *sendbyte = (char*) buffer;
s32 bytesleft = size;
s32 returnvalue;
while (bytesleft > 0)
{
if(__usb_checksendstatus()){
returnvalue = __usb_sendbyte(*sendbyte);
if(returnvalue) {
sendbyte++;
bytesleft--;
}
}
}
}
/*---------------------------------------------------------------------------------------------*
Name: usb_receivebuffersafe
Description: Simple buffer receive routine with fifo check (use for large transfers)
*----------------------------------------------------------------------------------------------*/
void usb_receivebuffersafe (void *buffer, int size)
{
char *receivebyte = (char*)buffer;
s32 bytesleft = size;
s32 returnvalue;
while (bytesleft > 0)
{
if(__usb_checkreceivestatus()){
returnvalue = __usb_receivebyte(receivebyte);
if(returnvalue) {
receivebyte++;
bytesleft--;
}
}
}
}
/*---------------------------------------------------------------------------------------------*
Name: usb_checkgecko
Description: Chesk the Gecko is connected
*----------------------------------------------------------------------------------------------*/
int usb_checkgecko()
{
s32 i = 0;
exi_chan1sr = 0x000000D0;
exi_chan1data = 0x90000000;
exi_chan1cr = 0x19;
while((exi_chan1cr)&1);
i = exi_chan1data;
exi_chan1sr = 0x0;
if (i==0x04700000){
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------------------------*
Name: usb_flush
Description: Flushes the FIFO, Use at the start of your program to avoid trash
*----------------------------------------------------------------------------------------------*/
void usb_flush()
{
char tempbyte;
while (__usb_receivebyte(&tempbyte));
}
#endif

View File

@@ -0,0 +1,65 @@
/*---------------------------------------------------------------------------------------------
* USB Gecko Development Kit - http://www.usbgecko.com
* --------------------------------------------------------------------------------------------
*
*
* usb.h - functions for the USB Gecko adapter (www.usbgecko.com).
*
* Copyright (c) 2008 - Nuke - <wiinuke@gmail.com>
*
*---------------------------------------------------------------------------------------------*/
#ifndef __USB_H__
#define __USB_H__
#include "../config.h"
#ifdef DEBUG_STUB
#define WIIMODE
// Wii Mode
#ifdef WIIMODE
#define exi_chan0sr *(volatile unsigned int*) 0xCD006800 // Channel 0 Status Register
#define exi_chan1sr *(volatile unsigned int*) 0xCD006814 // Channel 1 Status Register
#define exi_chan2sr *(volatile unsigned int*) 0xCD006828 // Channel 2 Status Register
#define exi_chan0cr *(volatile unsigned int*) 0xCD00680c // Channel 0 Control Register
#define exi_chan1cr *(volatile unsigned int*) 0xCD006820 // Channel 1 Control Register
#define exi_chan2cr *(volatile unsigned int*) 0xCD006834 // Channel 2 Control Register
#define exi_chan0data *(volatile unsigned int*) 0xCD006810 // Channel 0 Immediate Data
#define exi_chan1data *(volatile unsigned int*) 0xCD006824 // Channel 1 Immediate Data
#define exi_chan2data *(volatile unsigned int*) 0xCD006838 // Channel 2 Immediate Data
#define exi_chan0dmasta *(volatile unsigned int*) 0xCD006804 // Channel 0 DMA Start address
#define exi_chan1dmasta *(volatile unsigned int*) 0xCD006818 // Channel 1 DMA Start address
#define exi_chan2dmasta *(volatile unsigned int*) 0xCD00682c // Channel 2 DMA Start address
#define exi_chan0dmalen *(volatile unsigned int*) 0xCD006808 // Channel 0 DMA Length
#define exi_chan1dmalen *(volatile unsigned int*) 0xCD00681c // Channel 1 DMA Length
#define exi_chan2dmalen *(volatile unsigned int*) 0xCD006830 // Channel 2 DMA Length
#else
// GC Mode
#define exi_chan0sr *(volatile unsigned int*) 0xCC006800 // Channel 0 Status Register
#define exi_chan1sr *(volatile unsigned int*) 0xCC006814 // Channel 1 Status Register
#define exi_chan2sr *(volatile unsigned int*) 0xCC006828 // Channel 2 Status Register
#define exi_chan0cr *(volatile unsigned int*) 0xCC00680c // Channel 0 Control Register
#define exi_chan1cr *(volatile unsigned int*) 0xCC006820 // Channel 1 Control Register
#define exi_chan2cr *(volatile unsigned int*) 0xCC006834 // Channel 2 Control Register
#define exi_chan0data *(volatile unsigned int*) 0xCC006810 // Channel 0 Immediate Data
#define exi_chan1data *(volatile unsigned int*) 0xCC006824 // Channel 1 Immediate Data
#define exi_chan2data *(volatile unsigned int*) 0xCC006838 // Channel 2 Immediate Data
#define exi_chan0dmasta *(volatile unsigned int*) 0xCC006804 // Channel 0 DMA Start address
#define exi_chan1dmasta *(volatile unsigned int*) 0xCC006818 // Channel 1 DMA Start address
#define exi_chan2dmasta *(volatile unsigned int*) 0xCC00682c // Channel 2 DMA Start address
#define exi_chan0dmalen *(volatile unsigned int*) 0xCC006808 // Channel 0 DMA Length
#define exi_chan1dmalen *(volatile unsigned int*) 0xCC00681c // Channel 1 DMA Length
#define exi_chan2dmalen *(volatile unsigned int*) 0xCC006830 // Channel 2 DMA Length
#endif
// Function prototypes
void usb_flush();
int usb_checkgecko();
void usb_sendbuffer (const void *buffer, int size);
void usb_receivebuffer (void *buffer, int size);
void usb_sendbuffersafe (const void *buffer, int size);
void usb_receivebuffersafe (void *buffer, int size);
#endif
#endif // __USB_H__