Exemplo n.º 1
0
BOOL
GX2RCreateSurfaceUserMemory(virt_ptr<GX2Surface> surface,
                            virt_ptr<uint8_t> image,
                            virt_ptr<uint8_t> mipmap,
                            GX2RResourceFlags flags)
{
   GX2CalcSurfaceSizeAndAlignment(surface);
   surface->resourceFlags = flags;
   surface->resourceFlags &= ~GX2RResourceFlags::Locked;
   surface->resourceFlags &= ~GX2RResourceFlags::Gx2rAllocated;
   surface->image = image;
   surface->mipmaps = mipmap;

   if ((surface->resourceFlags & GX2RResourceFlags::UsageGpuWrite) ||
      (surface->resourceFlags & GX2RResourceFlags::UsageDmaWrite)) {
      DCInvalidateRange(virt_cast<virt_addr>(surface->image),
                        surface->imageSize);

      if (surface->mipmaps) {
         DCInvalidateRange(virt_cast<virt_addr>(surface->mipmaps),
                           surface->mipmapSize);
      }
   }

   return true;
}
Exemplo n.º 2
0
/**
 * ARAMFetch
 *
 * This function will move data from ARAM to MAIN memory
 */
void
ARAMFetch (char *dst, char *src, int len)
{
  DCInvalidateRange(dst, len);
  AR_StartDMA( ARAM_READ, (u32) dst, (u32) src, len);
  while (AR_GetDMAStatus());
}
Exemplo n.º 3
0
virt_ptr<void>
GX2RLockSurfaceEx(virt_ptr<GX2Surface> surface,
                  int32_t level,
                  GX2RResourceFlags flags)
{
   decaf_check(surface);
   decaf_check(surface->resourceFlags & ~GX2RResourceFlags::Locked);
   flags = surface->resourceFlags | internal::getOptionFlags(flags);

   // Set Locked flag
   surface->resourceFlags |= GX2RResourceFlags::Locked;
   surface->resourceFlags |= flags & GX2RResourceFlags::LockedReadOnly;

   // Check if we need to invalidate the surface.
   if ((flags & GX2RResourceFlags::UsageGpuWrite) ||
      (flags & GX2RResourceFlags::UsageDmaWrite)) {
      if (!(flags & GX2RResourceFlags::DisableCpuInvalidate)) {
         auto ptr = virt_ptr<void> { nullptr };
         auto size = uint32_t { 0 };
         internal::getSurfaceData(surface, level, &ptr, &size);
         DCInvalidateRange(virt_cast<virt_addr>(ptr), size);
      }
   }

   return surface->image;
}
Exemplo n.º 4
0
s32 IOS_GetRevision()
{
	u32 vercode;
	u16 rev;
	DCInvalidateRange((void*)0x80003140,8);
	vercode = *((u32*)0x80003140);
	rev = vercode & 0xFFFF;
	if(vercode == 0 || rev == 0) return IOS_EBADVERSION;
	return rev;
}
Exemplo n.º 5
0
s32 IOS_GetVersion()
{
	u32 vercode;
	u16 version;
	DCInvalidateRange((void*)0x80003140,8);
	vercode = *((u32*)0x80003140);
	version = vercode >> 16;
	if(version == 0) return IOS_EBADVERSION;
	if(version > 0xff) return IOS_EBADVERSION;
	return version;
}
Exemplo n.º 6
0
static void build_disp_list(void)
{
   DCInvalidateRange(display_list, sizeof(display_list));
   GX_BeginDispList(display_list, sizeof(display_list));
   GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
   for (unsigned i = 0; i < 4; i++)
   {
      GX_Position1x8(i);
      GX_TexCoord1x8(i);
   }
   GX_End();
   display_list_size = GX_EndDispList();
}
Exemplo n.º 7
0
int main(int argc, char **argv)
{
	// Exit after 10 seconds if there is an error
	__exception_setreload(10);
	CheckForGecko();
	DCInvalidateRange(loader_stub, 0x1800);
	memcpy(loader_stub, (void*)0x80001800, 0x1800);
	DCFlushRange(loader_stub, 0x1800);

	if( !IsWiiU() )
	{
		gprintf("Nintendont Loader\r\n");
		gprintf("Built   : %s %s\r\n", __DATE__, __TIME__ );
		gprintf("Version : %d.%d\r\n", NIN_VERSION>>16, NIN_VERSION&0xFFFF );	
	}
Exemplo n.º 8
0
/****************************************************************************
 * dvd_read
 *
 * The only DVD function we need - you gotta luv gc-linux self-boots!
 * returns: 1 - ok ; 0 - error
 ***************************************************************************/
int
dvd_read (void *dst, unsigned int len, u64 offset)
{

	unsigned char *buffer = (unsigned char *) (unsigned int) DVDreadbuffer;

	if (len > 2048)
		return 0;				/*** We only allow 2k reads **/

	DCInvalidateRange ((void *) buffer, len);

	// don't read past the end of the DVD (1.5 GB for GC DVD, 4.7 GB for DVD)
	if(offset < 0x57057C00 || (isWii && offset < 0x118244F00LL))
	{

	#ifdef HW_DOL

		dvd[0] = 0x2E;
		dvd[1] = 0;
		dvd[2] = 0xA8000000;
		dvd[3] = (u32)(offset >> 2);
		dvd[4] = len;
		dvd[5] = (u32) buffer;
		dvd[6] = len;
		dvd[7] = 3;			/*** Enable reading with DMA ***/
		while (dvd[7] & 1);
		memcpy (dst, buffer, len);

		if (dvd[0] & 0x4)		/* Ensure it has completed */
			return 0;

		return 1;

	#elif WII_DVD
		int ret = 1;
		ret = DI_ReadDVD(dst, len >> 11, (u32)(offset >> 11));
		if (ret==0)
			return 1;
		else
			return 0;
	#endif
	}
Exemplo n.º 9
0
/* 
DVD_LowRead64(void* dst, unsigned int len, uint64_t offset)
  Read Raw, needs to be on sector boundaries
  Has 8,796,093,020,160 byte limit (8 TeraBytes)
  Synchronous function.
    return -1 if offset is out of range
*/
int DVD_LowRead64(void* dst, unsigned int len, uint64_t offset)
{
  if(offset>>2 > 0xFFFFFFFF)
    return -1;
    
  if ((((int)dst) & 0xC0000000) == 0x80000000) // cached?
		dvd[0] = 0x2E;
	dvd[1] = 0;
	dvd[2] = read_cmd;
	dvd[3] = read_cmd == DVDR ? offset>>11 : offset >> 2;
	dvd[4] = read_cmd == DVDR ? len>>11 : len;
	dvd[5] = (unsigned long)dst;
	dvd[6] = len;
	dvd[7] = 3; // enable reading!
	DCInvalidateRange(dst, len);
	while (dvd[7] & 1);

	if (dvd[0] & 0x4)
		return 1;
	return 0;
}
Exemplo n.º 10
0
model_t* MODEL_setup(const u8* model_bmb) {
	binheader_t* header = (binheader_t*) model_bmb;

	const u32 posOffset = sizeof(binheader_t);
	const u32 nrmOffset = posOffset + (sizeof(f32)* header->vcount * 3);
	const u32 texOffset = nrmOffset + (sizeof(f32)* header->vcount * 3);
	const u32 indOffset = texOffset + (sizeof(f32)* header->vcount * 2);

	f32* positions = (f32*) (model_bmb + posOffset);
	f32* normals = (f32*) (model_bmb + nrmOffset);
	f32* texcoords = (f32*) (model_bmb + texOffset);
	u16* indices = (u16*) (model_bmb + indOffset);

	/* Calculate cost */
	const u32 indicesCount = header->fcount * 3;
	const u32 indicesSize = indicesCount * 3 * sizeof(u16); /* 3 indices per vertex index (p,n,t) that are u16 in size */
	const u32 callSize = 89; /* Size of setup var */
	/* Round up to nearest 32 multiplication */
	const u32 dispSize = (((indicesSize + callSize + 63) >> 5) + 1) << 5;

	/* Build display list */
	/* Allocate and clear */
	u32 i;
	void* modelList = memalign(32, dispSize);
	memset(modelList, 0, dispSize);

	/* Set buffer data */
	DCInvalidateRange(modelList, dispSize);
	GX_BeginDispList(modelList, dispSize);

	//GX_InvVtxCache();
	GX_ClearVtxDesc();
	GX_SetVtxDesc(GX_VA_POS, GX_INDEX16);
	GX_SetVtxDesc(GX_VA_NRM, GX_INDEX16);
	GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX16);

	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);

	GX_SetArray(GX_VA_POS, (void*) positions, 3 * sizeof(f32));
	GX_SetArray(GX_VA_NRM, (void*) normals, 3 * sizeof(f32));
	GX_SetArray(GX_VA_TEX0, (void*) texcoords, 2 * sizeof(f32));

	/* Fill the list with indices */
	GX_Begin(GX_TRIANGLES, GX_VTXFMT0, indicesCount);
	for (i = 0; i < indicesCount; i++) {
		GX_Position1x16(indices[i]);
		GX_Normal1x16(indices[i]);
		GX_TexCoord1x16(indices[i]);
	}
	GX_End();

	/* Close display list */
	u32 modelListSize = GX_EndDispList();
	if (modelListSize == 0) {
		printf("Error: Display list not big enough [%u]\n", dispSize);
		return NULL;
	}

	/* Return model info */
	model_t* model = malloc(sizeof(model_t));
	model->modelList = modelList;
	model->modelListSize = modelListSize;

	model->modelFaceCount = header->fcount;
	model->modelPositions = positions;
	model->modelNormals = normals;
	model->modelTexcoords = texcoords;
	model->modelIndices = indices;

	return model;
}
Exemplo n.º 11
0
s32 Swi_Handler(u32 arg0, u32 arg1, u32 arg2, u32 arg3)
{
	u8 cmd;

	/* Check alignment */
	SwiAddr -= (SwiAddr[-4] == 0xDF) ? 3 : 1;

	/* Get command */
	cmd = SwiAddr[0];

	/* Check command */
	if(SwiAddr[0] != 0xcc) {
		if (SwiTable[cmd])
			return SwiTable[cmd](arg0, arg1, arg2, arg3);
		else
			return arg0;
	}

	/* Check argument */
	switch (arg0) {
	/** Add SWI handler **/
	case 0: {
		SwiTable[arg1]= (void *)arg2;
		break;
	}
	
	/** Memcpy (cached to cached) **/
	case 2: {
		void *src = (void *)arg2;
		void *dst = (void *)arg1;
		u32   len = arg3;

		u32 perms;

		/* Apply permissions */
		perms = Perms_Read();
		Perms_Write(0xFFFFFFFF);

		/* Copy data */
		memcpy(dst, src, len);
		DCFlushRange(dst, len);

		/* Restore permissions */
		Perms_Write(perms);

		break;
	}
	
	/** Get register **/
	case 3:
		return *(vu32 *)arg1;

	/** Set register **/
	case 4:
		*(vu32 *)arg1 = arg2;
		break;

	/** Set register **/
	case 5:
		*(vu32 *)arg1 |= arg2;
		break;

	/** Clear register **/
	case 6:
		*(vu32 *)arg1 &= ~arg2;
		break;

	/** Memcpy (uncached to cached) **/
	case 9: {
		void *src = (void *)arg2;
		void *dst = (void *)arg1;
		u32   len = arg3;

		u32 perms;

		/* Apply permissions */
		perms = Perms_Read();
		Perms_Write(0xFFFFFFFF);

		/* Copy data */
		DCInvalidateRange(src, len);
		memcpy(dst, src, len);
		DCFlushRange(dst, len);

		/* Restore permissions */
		Perms_Write(perms);

		break;
	}

	/** Call function **/
	case 16: {
		s32 (*Function)(void *in, void *out);

		/* Set function */
		Function = (void *)arg1;

		/* Call function */
		return Function((void *)arg2, (void *)arg3);
	}

	/** Get syscall base */
	case 17:
		return ios.syscall;

	/** Get IOS info **/
	case 18: {
		iosInfo *buffer = (iosInfo *)arg1;

		/* Copy IOS info */
		memcpy(buffer, &ios, sizeof(ios));
		DCFlushRange(buffer, sizeof(ios));

		break;
	}

	/** Get MLOAD version **/
	case 19:
		return (MLOAD_VER << 4) | MLOAD_SUBVER;

	/** Led on **/
	case 128:
		*(vu32 *)0x0d8000c0 |= 0x20;
		break;
	
	/** Led off **/
	case 129:
		*(vu32 *)0x0d8000c0 &=~ 0x20;
		break;

	/** Led blink **/
	case 130:
		*(vu32 *)0x0d8000c0 ^= 0x20;
		break;
		
	default:
		break;
	}

	return 0;
}
Exemplo n.º 12
0
s32 LoadKernel()
{
	u32 TMDSize;
	u32 i,u;

	s32 r = ES_GetStoredTMDSize( 0x000000010000003aLL, &TMDSize );
	if( r < 0 )
	{
		gprintf("ES_GetStoredTMDSize():%d\r\n", r );
		return r;
	}

	gprintf("TMDSize:%u\r\n", TMDSize );

	TitleMetaData *TMD = (TitleMetaData*)memalign( 32, TMDSize );
	if( TMD == (TitleMetaData*)NULL )
	{
		gprintf("Failed to alloc:%u\r\n", TMDSize );
		return r;	//todo errors are < 0 r still has >= 0 from previous call
	}

	r = ES_GetStoredTMD( 0x000000010000003aLL, (signed_blob *)TMD, TMDSize );
	if( r < 0 )
	{
		gprintf("ES_GetStoredTMD():%d\r\n", r );
		free(TMD);
		return r;
	}

//Look for boot index
	for( i=0; i < TMD->ContentCount; ++i )
	{
		if( TMD->BootIndex == TMD->Contents[i].Index )
			break;
	}
	
	gprintf("BootIndex:%u\r\n", i );

	s32 cfd = IOS_Open( "/shared1/content.map", 1 );
	if( cfd < 0 )
	{
		gprintf("IOS_Open():%d\r\n", cfd );
		free(TMD);
		return cfd;
	}

	for( u=0;; u+=0x1C )
	{
		if( IOS_Read( cfd, Entry, 0x1C ) != 0x1C )
		{
			gprintf("Hash not found in content.map\r\n");
			free(TMD);
			return -2;
		}

		if( memcmp( (char*)(Entry+8), TMD->Contents[i].SHA1, 0x14 ) == 0 )
			break;
	}
	FoundVersion = ((TMD->TitleID & 0xFFFF) << 16) | (TMD->TitleVersion);
	free(TMD);

	IOS_Close( cfd );

	u32 *IOSVersion = (u32*)0x93003000;
	DCInvalidateRange(IOSVersion, 0x20);
	*IOSVersion = FoundVersion;
	gprintf("IOS Version: 0x%08X\n", FoundVersion);
	DCFlushRange(IOSVersion, 0x20);

	//char Path[32];
	char *Path = (char*)0x93003020;
	DCInvalidateRange(Path, 1024);
	memset(Path, 0, 1024);
	sprintf( Path, "/shared1/%.8s.app", Entry );
	gprintf("Kernel:\"%s\"\r\n", Path );
	DCFlushRange(Path, 1024);

	s32 kfd = IOS_Open( Path, 1 );
	if( kfd < 0 )
	{
		gprintf("IOS_Open():%d\r\n", kfd );
		return kfd;
	}

	KernelSize = IOS_Seek( kfd, 0, SEEK_END );
	IOS_Seek( kfd, 0, 0);

	gprintf("KernelSize:%u\r\n", KernelSize );

	if( IOS_Read( kfd, Kernel, KernelSize ) != KernelSize )
	{
		gprintf("IOS_Read() failed\r\n");

		IOS_Close(kfd);
		return -1;
	}
	IOS_Close(kfd);

	return 0;
}
Exemplo n.º 13
0
Arquivo: aram.c Projeto: comex/libogc
static void __ARCheckSize()
{
	u32 i,arsize,arszflag;
	static u32 test_data[8] ATTRIBUTE_ALIGN(32);
	static u32 dummy_data[8] ATTRIBUTE_ALIGN(32);
	static u32 buffer[8] ATTRIBUTE_ALIGN(32);

#ifdef _AR_DEBUG
	printf("__ARCheckSize()\n");
#endif

	while(!(_dspReg[11]&0x0001));

	__ARSize = __ARInternalSize = arsize  = 0x1000000;
	_dspReg[9] = (_dspReg[9]&~0x3f)|0x23;

	for(i=0;i<8;i++) {
		test_data[i] = 0xBAD1BAD0;
		dummy_data[i] = 0xDEADBEEF;
	}
	DCFlushRange(test_data,32);
	DCFlushRange(dummy_data,32);
	
	__ARExpansionSize = 0;
	__ARWriteDMA((u32)test_data,0x1000000,32);
	__ARWriteDMA((u32)test_data,0x1200000,32);
	__ARWriteDMA((u32)test_data,0x2000000,32);
	__ARWriteDMA((u32)test_data,0x1000200,32);
	__ARWriteDMA((u32)test_data,0x1400000,32);

	memset(buffer,0,32);
	DCFlushRange(buffer,32);

	__ARWriteDMA((u32)dummy_data,0x1000000,32);

	DCInvalidateRange(buffer,32);
	__ARReadDMA((u32)buffer,0x1000000,32);
	_nop();

	arszflag = 0x03;
	if(buffer[0]==dummy_data[0]) {
		memset(buffer,0,32);
		DCFlushRange(buffer,32);
		__ARReadDMA((u32)buffer,0x1200000,32);
		_nop();
		if(buffer[0]==dummy_data[0]) {
			__ARExpansionSize = 0x200000;
			arsize +=  0x200000;
			goto end_check;				//not nice but fast
		}
		
		memset(buffer,0,32);
		DCFlushRange(buffer,32);
		__ARReadDMA((u32)buffer,0x2000000,32);
		_nop();
		if(buffer[0]==dummy_data[0]) {
			__ARExpansionSize = 0x400000;
			arsize +=  0x400000;
			arszflag |= 0x08;
			goto end_check;				//not nice but fast
		}
		
		memset(buffer,0,32);
		DCFlushRange(buffer,32);
		__ARReadDMA((u32)buffer,0x1400000,32);
		_nop();
		if(buffer[0]==dummy_data[0]) {
			__ARExpansionSize = 0x1000000;
			arsize +=  0x1000000;
			arszflag |= 0x18;
		} else {
			__ARExpansionSize = 0x2000000;
			arsize +=  0x2000000;
			arszflag |= 0x20;
		}
end_check:
		_dspReg[9] = (_dspReg[9]&~0x3f)|arszflag;
	}

#ifdef _AR_DEBUG
	printf("__ARCheckSize(%d)\n",arsize);
#endif
	*(u32*)0x800000d0 = arsize;
	__ARSize = arsize;
}
Exemplo n.º 14
0
void _start()
{
  /* Load a good stack */
  asm(
      "lis %r1, 0x1ab5 ;"
      "ori %r1, %r1, 0xd138 ;"
  );
 
  /* Get a handle to coreinit.rpl, dmae.rpl, and nsysnet.rpl */
  unsigned int coreinit_handle, dmae_handle, nsysnet_handle;
  OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle);
  OSDynLoad_Acquire("dmae.rpl", &dmae_handle);
  OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle);

  /* Cache, DMA, and socket functions */
  void (*DCFlushRange)(void *addr, unsigned int length);
  void (*DCInvalidateRange)(void *addr, unsigned int length);
  unsigned long long (*DMAECopyMem)(void *dst, void *src, unsigned int nwords, int endian);
  int (*DMAEWaitDone)(unsigned long long ret);
  int (*socket)(int family, int type, int proto);
  int (*connect)(int fd, struct sockaddr *addr, int addrlen);
  int (*send)(int fd, const void *buffer, int len, int flags);

  /* Read the addresses of the functions */
  OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange);
  OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange);
  OSDynLoad_FindExport(dmae_handle, 0, "DMAECopyMem", &DMAECopyMem);
  OSDynLoad_FindExport(dmae_handle, 0, "DMAEWaitDone", &DMAEWaitDone);
  OSDynLoad_FindExport(nsysnet_handle, 0, "socket", &socket);
  OSDynLoad_FindExport(nsysnet_handle, 0, "connect", &connect);
  OSDynLoad_FindExport(nsysnet_handle, 0, "send", &send);

  /* Set up our socket address structure */
  struct sockaddr sin;
  sin.sin_family = AF_INET;
  sin.sin_port = 12345;
  sin.sin_addr.s_addr = PC_IP;
  int i;
  for (i = 0; i < 8; i++)
  {
    sin.sin_zero[i] = 0;
  }

  /* Connect to the PC */
  int pc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  int status = connect(pc, &sin, 0x10);
  if (status) OSFatal("Error connecting to PC server");

  /* Cache stuff */
  DCFlushRange(0x01000000, 0x20);
  DCInvalidateRange(0x1dd7b820, 0x20);

  /* Do the copy */
  int success = DMAEWaitDone(DMAECopyMem(0x1dd7b820, 0x01000000, 2, 0));
  if (success)
  {
	  send(pc, "Success", 8, 0);
  }
  else
  {
	  send(pc, "Fail", 5, 0);
  }
  while(1);
}
Exemplo n.º 15
0
//addr == addr of 4kb block of PowerPC_block ptrs to pull out from ARAM
void ARAM_ReadBlock(u32 addr, int block_num)
{
  ARQ_PostRequest(&ARQ_request_blocks, 0x2EAD, AR_ARAMTOMRAM, ARQ_PRIO_LO,
			                (int)(BLOCKS_CACHE_ADDR + addr), (int)&cached_block[block_num][0], CACHED_BLOCK_SIZE);
	DCInvalidateRange((void*)&cached_block[block_num][0], CACHED_BLOCK_SIZE);
}
Exemplo n.º 16
0
int BuildLists(GXTexObj texture) {
	// Make the new display list
	// For display lists, each command has an associated "cost" in bytes.
	// Add all these up to calculate the size of your display list before rounding up.
	// eke-eke says GX_Begin() costs 3 bytes (u8 + u16)
	// According to my research:
	// GX_Position3f32() is 12 bytes (f32*3)
	// GX_Normal3f32() is 12 bytes (f32*3)
	// GX_Color3f32() is actually 3 bytes ((f32 -> u8) * 3)
	// GX_TexCoord2f32() is 8 bytes (f32*2)
	// GX_End() seems to cost zero (there's no actual code in it)
	// Size -must- be multiple of 32, so (12*24) + (12*24) + (3*24) + (8*24) + 3 = 843
	// Rounded up to the nearest 32 is 864.
	// NOTE: Actual size may be up to 63 bytes -larger- than you calculate it to be due to padding and cache alignment.
	for (int i=0; i<5;i++) {
		boxList[i] = memalign(32,896);
		memset(boxList[i],0,896);
		DCInvalidateRange(boxList[i],896);
		GX_BeginDispList(boxList[i],896);
		GX_Begin(GX_QUADS,GX_VTXFMT0,24); // Start drawing
			// Bottom face
			GX_Position3f32(-1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right
			GX_Position3f32( 1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left
			GX_Position3f32( 1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left
			GX_Position3f32(-1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom right
			// Front face
			GX_Position3f32(-1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left
			GX_Position3f32( 1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom right
			GX_Position3f32( 1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right
			GX_Position3f32(-1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left
			// Back face
			GX_Position3f32(-1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom right
			GX_Position3f32(-1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right
			GX_Position3f32( 1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left
			GX_Position3f32( 1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left
			// Right face
			GX_Position3f32( 1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom right
			GX_Position3f32( 1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right
			GX_Position3f32( 1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left
			GX_Position3f32( 1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left
			// Left face
			GX_Position3f32(-1.0f,-1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom right
			GX_Position3f32(-1.0f,-1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Top right
			GX_Position3f32(-1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top left
			GX_Position3f32(-1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(BoxColors[i][0],BoxColors[i][1],BoxColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Bottom left
			// Top face
			GX_Position3f32(-1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(TopColors[i][0],TopColors[i][1],TopColors[i][2]); GX_TexCoord2f32(0.0f,1.0f); // Top left
			GX_Position3f32(-1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(TopColors[i][0],TopColors[i][1],TopColors[i][2]); GX_TexCoord2f32(0.0f,0.0f); // Bottom left
			GX_Position3f32( 1.0f, 1.0f, 1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(TopColors[i][0],TopColors[i][1],TopColors[i][2]); GX_TexCoord2f32(1.0f,0.0f); // Bottom rught
			GX_Position3f32( 1.0f, 1.0f,-1.0f); GX_Normal3f32((f32)0,(f32)0,(f32)1);
			GX_Color3f32(TopColors[i][0],TopColors[i][1],TopColors[i][2]); GX_TexCoord2f32(1.0f,1.0f); // Top right
		GX_End();         // Done drawing quads
		// GX_EndDispList() returns the size of the display list, so store that value and use it with GX_CallDispList().
		boxSize[i] = GX_EndDispList(); // Done building the box list
		if (boxSize[i] == 0) return 1;
	}

	// setup texture coordinate generation
	// args: texcoord slot 0-7, matrix type, source to generate texture coordinates from, matrix to use
	GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);

	// Set up TEV to paint the textures properly.
	GX_SetTevOp(GX_TEVSTAGE0,GX_MODULATE);
	GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);

	// Load up the textures (just one this time).
	GX_LoadTexObj(&texture, GX_TEXMAP0);

	return 0;
}
Exemplo n.º 17
0
/* Install an exception handler */
int _start(int argc, char **argv)
{
	/* Get a handle to coreinit.rpl and nsysnet.rpl */
	unsigned int coreinit_handle, nsysnet_handle;
	OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle);
	OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle);

	/* Memory and cache functions */
	unsigned int (*OSEffectiveToPhysical)(void *ptr);
	void (*DCFlushRange)(void *addr, unsigned int len);
	void (*DCInvalidateRange)(void *addr, unsigned int len);
	OSDynLoad_FindExport(coreinit_handle, 0, "OSEffectiveToPhysical", &OSEffectiveToPhysical);
	OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange);
	OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange);

	/* Kernel is mapped */
	if (OSEffectiveToPhysical((void*)0xA0000000) == 0xC0000000)
	{
		/* Patches installed */
		if (*((unsigned int*)(0xA0000000 + (0xFFF00B40 - 0xC0000000))) == 1)
		{
			/* Socket functions */
			int (*socket_lib_init)();
			int (*get_socket_rm_fd)();
			int (*socket)(int family, int type, int proto);
			int (*connect)(int fd, struct sockaddr *addr, int addrlen);
			OSDynLoad_FindExport(nsysnet_handle, 0, "socket_lib_init", &socket_lib_init);
			OSDynLoad_FindExport(nsysnet_handle, 0, "get_socket_rm_fd", &get_socket_rm_fd);
			OSDynLoad_FindExport(nsysnet_handle, 0, "socket", &socket);
			OSDynLoad_FindExport(nsysnet_handle, 0, "connect", &connect);

			/* Init the sockets library */
			socket_lib_init();

			/* Set up our socket address structure */
			struct sockaddr sin;
			sin.sin_family = AF_INET;
			sin.sin_port = 12345;
			sin.sin_addr.s_addr = PC_IP;
			int i;
			for (i = 0; i < 8; i++)
			{
				sin.sin_zero[i] = 0;
			}

			/* Connect to the PC */
			int pc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
			int status = connect(pc, &sin, 0x10);
			if (status) OSFatal("Error connecting to PC");

			/* Store the socket info in a place the kernel can access */
			unsigned int sock_info[4] = {1, (unsigned int)get_socket_rm_fd(), (unsigned int)pc, 0};
			memcpy((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), sock_info, 0x10);
			DCFlushRange((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), 0x20);
			DCInvalidateRange((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), 0x20);
		}
		/* Patches not yet installed, but they will be next time */
		else
		{
			/* Signify patches installed, socket data still invalid, spinlock 0 */
			*((unsigned int*)(0xA0000000 + (0xFFF00B40 - 0xC0000000))) = 1;
			*((unsigned int*)(0xA0000000 + (0xFFF00B44 - 0xC0000000))) = -1;
			*((unsigned int*)(0xA0000000 + (0xFFF00B48 - 0xC0000000))) = -1;
			*((unsigned int*)(0xA0000000 + (0xFFF00B4C - 0xC0000000))) = 0;
			DCFlushRange((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), 0x20);
			DCInvalidateRange((void*)(0xA0000000 + (0xFFF00B40 - 0xC0000000)), 0x20);
		}
	}

	/* Return to main() */
#if VER == 532
	int (*main)(int argc, char **argv) = (int (*)(int,char**)) (*((unsigned int*)0x1005D180));
#elif VER == 550
	int (*main)(int argc, char **argv) = (int (*)(int,char**)) (*((unsigned int*)0x1005E040));
#else
	int (*main)(int argc, char **argv) = (int (*)(int,char**)) (*((unsigned int*)0x0));
#endif
	return main(argc, argv);
}
Exemplo n.º 18
0
void
InitVideo ()
{
	VIDEO_Init();
	vmode = VIDEO_GetPreferredMode(NULL); // get default video mode
	
	bool pal = false;

	if (vmode == &TVPal528IntDf)
		pal = true;

	if (CONF_GetAspectRatio() == CONF_ASPECT_16_9)
	{
		vmode->fbWidth = 640;
		vmode->efbHeight = 456;
		vmode->viWidth = 686;

		if (pal)
		{
			vmode->xfbHeight = 542;
			vmode->viHeight = 542;
		}
		else
		{
			vmode->xfbHeight = 456;
			vmode->viHeight = 456;
		}
	}
	else
	{
		if (pal)
			vmode = &TVPal574IntDfScale;

		vmode->viWidth = 672;
	}

	if (pal)
	{
		vmode->viXOrigin = (VI_MAX_WIDTH_PAL - vmode->viWidth) / 2;
		vmode->viYOrigin = (VI_MAX_HEIGHT_PAL - vmode->viHeight) / 2;
	}
	else
	{
		vmode->viXOrigin = (VI_MAX_WIDTH_NTSC - vmode->viWidth) / 2;
		vmode->viYOrigin = (VI_MAX_HEIGHT_NTSC - vmode->viHeight) / 2;
	}

	VIDEO_Configure (vmode);

	// Allocate the video buffers
	xfb[0] = (u32 *) SYS_AllocateFramebuffer (vmode);
	xfb[1] = (u32 *) SYS_AllocateFramebuffer (vmode);
	DCInvalidateRange(xfb[0], VIDEO_GetFrameBufferSize(vmode));
	DCInvalidateRange(xfb[1], VIDEO_GetFrameBufferSize(vmode));
	xfb[0] = (u32 *) MEM_K0_TO_K1 (xfb[0]);
	xfb[1] = (u32 *) MEM_K0_TO_K1 (xfb[1]);

	// Clear framebuffers etc.
	VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK);
	VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK);
	VIDEO_SetNextFramebuffer (xfb[0]);

	VIDEO_SetBlack (FALSE);
	VIDEO_Flush ();
	VIDEO_WaitVSync ();
	if (vmode->viTVMode & VI_NON_INTERLACE)
		VIDEO_WaitVSync ();

	StartGX();
	ResetVideo_Menu();
	// Finally, the video is up and ready for use :)
}
Exemplo n.º 19
0
int main(int argc, char **argv)
{
	// Exit after 10 seconds if there is an error
	__exception_setreload(10);
//	u64 timeout = 0;
	CheckForGecko();
	DCInvalidateRange(loader_stub, 0x1800);
	memcpy(loader_stub, (void*)0x80001800, 0x1800);

	RAMInit();

	//Meh, doesnt do anything anymore anyways
	//STM_RegisterEventHandler(HandleSTMEvent);

	Initialise();

	// Checking for storage devices...
	ShowMessageScreen("Checking storage devices...");

	u32 u;
	//Disables MEMPROT for patches
	write16(MEM_PROT, 0);
	//Patches FS access
	for( u = 0x93A00000; u < 0x94000000; u+=2 )
	{
		if( memcmp( (void*)(u), FSAccessPattern, sizeof(FSAccessPattern) ) == 0 )
		{
		//	gprintf("FSAccessPatch:%08X\r\n", u );
			memcpy( (void*)u, FSAccessPatch, sizeof(FSAccessPatch) );
			DCFlushRange((void*)u, sizeof(FSAccessPatch));
			break;
		}
	}

	//for BT.c
	CONF_GetPadDevices((conf_pads*)0x932C0000);
	DCFlushRange((void*)0x932C0000, sizeof(conf_pads));
	*(vu32*)0x932C0490 = CONF_GetIRSensitivity();
	*(vu32*)0x932C0494 = CONF_GetSensorBarPosition();
	DCFlushRange((void*)0x932C0490, 8);

	if(LoadKernel() < 0)
	{
		ClearScreen();
		gprintf("Failed to load kernel from NAND!\r\n");
		ShowMessageScreenAndExit("Failed to load kernel from NAND!", 1);
	}
	InsertModule((char*)kernel_bin, kernel_bin_size);

	memset( (void*)0x92f00000, 0, 0x100000 );
	DCFlushRange( (void*)0x92f00000, 0x100000 );

	DCInvalidateRange( (void*)0x939F02F0, 0x20 );

	memcpy( (void*)0x939F02F0, Boot2Patch, sizeof(Boot2Patch) );

	DCFlushRange( (void*)0x939F02F0, 0x20 );

	//libogc still has that, lets close it
	__ES_Close();
	s32 fd = IOS_Open( "/dev/es", 0 );

	memset( STATUS, 0xFFFFFFFF, 0x20  );
	DCFlushRange( STATUS, 0x20 );

	memset( (void*)0x91000000, 0xFFFFFFFF, 0x20  );
	DCFlushRange( (void*)0x91000000, 0x20 );

	*(vu32*)0xD3003420 = 0; //make sure kernel doesnt reload

	raw_irq_handler_t irq_handler = BeforeIOSReload();
	IOS_IoctlvAsync( fd, 0x1F, 0, 0, &IOCTL_Buf, NULL, NULL );
	AfterIOSReload( irq_handler, FoundVersion );

	while(1)
	{
		DCInvalidateRange( STATUS, 0x20 );
		if((STATUS_LOADING > 0 || abs(STATUS_LOADING) > 1) && STATUS_LOADING < 20)
		{
			gprintf("Kernel sent signal\n");
			break;
		}
	}

	/* For slow USB HDDs */
	time_t timeout = time(NULL);
	while(time(NULL) - timeout < 10)
	{
		if(__io_custom_usbstorage.startup() && __io_custom_usbstorage.isInserted())
			break;
		usleep(50000);
	}
	fatInitDefault();

	gprintf("Nintendont at your service!\r\n%s\r\n", NIN_BUILD_STRING);
	KernelLoaded = 1;

	char* first_slash = strrchr(argv[0], '/');
	if (first_slash != NULL) strncpy(launch_dir, argv[0], first_slash-argv[0]+1);
	gprintf("launch_dir = %s\r\n", launch_dir);

	FPAD_Init();
	FPAD_Update();

	/* Read IPL Font before doing any patches */
	void *fontbuffer = memalign(32, 0x50000);
	__SYS_ReadROM((void*)fontbuffer,0x50000,0x1AFF00);
	memcpy((void*)0xD3100000, fontbuffer, 0x50000);
	DCInvalidateRange( (void*)0x93100000, 0x50000 );
	free(fontbuffer);
	//gprintf("Font: 0x1AFF00 starts with %.4s, 0x1FCF00 with %.4s\n", (char*)0x93100000, (char*)0x93100000 + 0x4D000);

	// Simple code to autoupdate the meta.xml in Nintendont's folder
	FILE *meta = fopen("meta.xml", "w");
	if(meta != NULL)
	{
		fprintf(meta, "%s\r\n<app version=\"1\">\r\n\t<name>%s</name>\r\n", META_XML, META_NAME);
		fprintf(meta, "\t<coder>%s</coder>\r\n\t<version>%d.%d</version>\r\n", META_AUTHOR, NIN_VERSION>>16, NIN_VERSION&0xFFFF);
		fprintf(meta, "\t<release_date>20150531000000</release_date>\r\n");
		fprintf(meta, "\t<short_description>%s</short_description>\r\n", META_SHORT);
		fprintf(meta, "\t<long_description>%s\r\n\r\n%s</long_description>\r\n", META_LONG1, META_LONG2);
		fprintf(meta, "\t<ahb_access/>\r\n</app>");
		fclose(meta);
	}
Exemplo n.º 20
0
void _start()
{
	/* Get a handle to coreinit.rpl */
	unsigned int coreinit_handle;
	OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle);
	//OS memory functions
	void* (*memcpy)(void *dest, void *src, uint32_t length);
	void* (*memset)(void * dest, uint32_t value, uint32_t bytes);
	void* (*OSAllocFromSystem)(uint32_t size, int align);
	void (*OSFreeToSystem)(void *ptr);
	OSDynLoad_FindExport(coreinit_handle, 0, "memcpy", &memcpy);
	OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset);
	OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem);
	OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem);
	
	void (*OSCoherencyBarrier)();
	OSDynLoad_FindExport(coreinit_handle, 0, "OSCoherencyBarrier", &OSCoherencyBarrier);
	
	void (*_Exit)();
	OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit);
	
	//DC memory functions
	void (*DCFlushRangeNoSync)(void *buffer, uint32_t length);
	void (*DCInvalidateRange)(void *buffer, uint32_t length);
  	OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRangeNoSync", &DCFlushRangeNoSync);
	OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange);
	
	//LC memory functions
	void* (*LCAlloc)( uint32_t bytes );
	void (*LCDealloc)();
	uint32_t (*LCHardwareIsAvailable)();
	uint32_t (*LCIsDMAEnabled)();
	void (*LCEnableDMA)();
	void (*LCDisableDMA)();
	void (*LCLoadDMABlocks)(void* lc_addr, void* src_addr, uint32_t blocks);
	void (*LCStoreDMABlocks)(void* dest_addr, void* lc_addr, uint32_t blocks);
	void (*LCWaitDMAQueue)( uint32_t length );
	OSDynLoad_FindExport(coreinit_handle, 0, "LCAlloc", &LCAlloc);
	OSDynLoad_FindExport(coreinit_handle, 0, "LCDealloc", &LCDealloc);
	OSDynLoad_FindExport(coreinit_handle, 0, "LCHardwareIsAvailable", &LCHardwareIsAvailable);
	OSDynLoad_FindExport(coreinit_handle, 0, "LCIsDMAEnabled", &LCIsDMAEnabled);
	OSDynLoad_FindExport(coreinit_handle, 0, "LCEnableDMA", &LCEnableDMA);
	OSDynLoad_FindExport(coreinit_handle, 0, "LCDisableDMA", &LCDisableDMA);
	OSDynLoad_FindExport(coreinit_handle, 0, "LCLoadDMABlocks", &LCLoadDMABlocks);
	OSDynLoad_FindExport(coreinit_handle, 0, "LCStoreDMABlocks", &LCStoreDMABlocks);
	OSDynLoad_FindExport(coreinit_handle, 0, "LCWaitDMAQueue", &LCWaitDMAQueue);
		
	//Used for keeping track of vairables to print to screen
	char output[1000];
	
	//Alloc 64 byte alligned space
	void* src_addr=OSAllocFromSystem(512,64);
	void* dest_addr=OSAllocFromSystem(512,64);
	
	//Store some debug values
	__os_snprintf(output, 1000, "src_addr:%02x,",(uint32_t)src_addr);
	__os_snprintf(output+strlen(output), 255, "dest_addr: %02x,", (uint32_t)dest_addr);
	
	//Number of 32bit blocks to copy. Must be multiple of 2 between [0,127]
	uint32_t blocks=2; //2 32bit blocks
	
	//Do something to the source
	memset(src_addr,1,64);
	
	//Grab values for debug
	uint32_t * src_val=src_addr;
	uint32_t * dest_val=dest_addr;
	__os_snprintf(output+strlen(output), 255, "Old src_val: %02x\n",src_val[0]);
	__os_snprintf(output+strlen(output), 255, "Old dest_val: %02x,",dest_val[0]);
	
	//Get some locked cache address space
	void *lc_addr=LCAlloc(512); //512 Minmum. Must be multiple of 512.
	
	//Calculate size from blocks to flush/invalidate range properly
	uint32_t size;
	//If blocks is set to 0, the transaction will default to 128 blocks
	if(blocks==0)
	{
		size=32*128;
	}
	else
	{
		size=32*blocks;
	}
	//Flush the range at the source to ensure cache gets written back to memory.
	DCFlushRangeNoSync(src_addr,size);
	//Invalidate the range at the destination
	DCInvalidateRange(dest_addr,size);
	//Sync
	OSCoherencyBarrier();
	
	//Check to see of DMA hardware is avaliable
	if(LCHardwareIsAvailable()!=1)
	{
		OSFatal("Hardware is not avaliable.");
	}

	//Gets the current state of DMA, so we can restore it after our copy
	uint32_t dmaState=LCIsDMAEnabled();

	//Checks to see if DMA is enabled, if not it will try to enable it.
	if(dmaState!=1)
	{
		LCEnableDMA();
		dmaState=LCIsDMAEnabled();
		if(dmaState!=1)
		{
			OSFatal("Can't enable DMA");
		}
	}
	
	//Load memory to locked cache
	LCLoadDMABlocks(lc_addr,src_addr,blocks);
	LCWaitDMAQueue(0);
	
	//Store memory from locked cache
	LCStoreDMABlocks(dest_addr,lc_addr,blocks);
	LCWaitDMAQueue(0);

	//If DMA was not previously enabled, then disable it to restore state.
	if(dmaState!=1)
	{
		LCDisableDMA();
		dmaState=LCIsDMAEnabled();
		//If DMA failed to disable, return error code
		if(dmaState!=1)
		{
			OSFatal("Couldn't Disable DMA");
		}
	}
	__os_snprintf(output+strlen(output), 255, "New src_val: %02x,",src_val[0]);
	__os_snprintf(output+strlen(output), 255, "New dest_val: %02x,",dest_val[0]);
	
	//Cleanup
	LCDealloc(lc_addr);
	OSFreeToSystem(dest_addr);
	OSFreeToSystem(src_addr);
    OSFatal(output);
}