Пример #1
0
/* Non-blocking read from STDIN. len parameter is max number of bytes to read.
	If less than this is available, function will quit early and return actual
	number of bytes read		*/
int read (char * buf, int len)
{
	int ret = 0;
	while(ret < len && (MemoryRead(UART_STATUS) & UART_RX_DV_MASK) == UART_RX_DV_MASK)
	{
		buf[ret++] = MemoryRead(UART_RX);
	}
	return ret;
}
Пример #2
0
/*
	A blocking delay of approximate milliseconds.
*/
void Sleep(unsigned int milliseconds)
{
	int m;
	unsigned int start;
	for(m = 0; m < milliseconds; m++)
	{
		start = MemoryRead(COUNTER2);
		while((MemoryRead(COUNTER2) - start) < 10000);
	}
}
Пример #3
0
//Plasma hardware dependent
static void OS_ThreadTickToggle(void *arg)
{
   uint32 status, mask, state;

   //Toggle looking for IRQ_COUNTER18 or IRQ_COUNTER18_NOT
   state = OS_SpinLock();
   status = MemoryRead(IRQ_STATUS) & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
   mask = MemoryRead(IRQ_MASK) | IRQ_COUNTER18 | IRQ_COUNTER18_NOT;
   mask &= ~status;
   MemoryWrite(IRQ_MASK, mask);
   OS_ThreadTick(arg);
   OS_SpinUnlock(state);
}
void HF_UpdateCounterMask(void){
	uint32_t m;

	m = MemoryRead(IRQ_MASK);					// read interrupt mask
	m ^= (IRQ_COUNTER | IRQ_COUNTER_NOT);				// toggle timer interrupt mask
	MemoryWrite(IRQ_MASK, m);					// write to irq mask register
}
Пример #5
0
static inline uint16_t NocRead(void){
	uint16_t data;

	data = (uint16_t)MemoryRead(NOC_READ);
	asm ("nop\nnop\nnop");
	return data;
}
Пример #6
0
static inline uint16_t NocStatus(void){
	uint16_t status;

	status = (uint16_t)MemoryRead(NOC_STATUS);
	asm ("nop\nnop\nnop");
	return status;
}
/* basic libc abstraction stuff */
void uart_init(uint32_t baud){
	uint16_t d;

	d = (uint16_t)(CPU_SPEED / baud);
	MemoryWrite(UART_DIVISOR, d);
	MemoryRead(UART_READ);
}
Пример #8
0
void Executor::ExecMemoryRead(MethodFrame *frame, Insn *insn) {
  Value &addr_value = frame->reg_values_[insn->src_regs_[0]->id_];
  CHECK(addr_value.type_ == Value::NUM);
  Value &dst_value = frame->reg_values_[insn->dst_regs_[0]->id_];
  int addr = addr_value.num_.int_part;
  MemoryRead(addr, &dst_value.num_);
  dst_value.type_ = Value::NUM;
}
Пример #9
0
uint32_t HF_InterruptMaskClear(uint32_t mask){		// interrupt vector mask clear
	uint32_t m, state;

	state = HF_CriticalBegin();
	m = MemoryRead(IRQ_MASK) & ~mask;
	MemoryWrite(IRQ_MASK, m);
	HF_CriticalEnd(state);
	return m;
}
Пример #10
0
//Plasma hardware dependent
uint32 OS_InterruptMaskClear(uint32 mask)
{
   uint32 state;
   state = OS_CriticalBegin();
   mask = MemoryRead(IRQ_MASK) & ~mask;
   MemoryWrite(IRQ_MASK, mask);
   OS_CriticalEnd(state);
   return mask;
}
void _usleep(uint32_t usec){
	volatile uint32_t cur, last, delta, usecs;
	uint32_t cycles_per_usec;

	last = MemoryRead(COUNTER);
	delta = usecs = 0;
	cycles_per_usec = CPU_SPEED / 1000000;
	while(usec > usecs){
		cur = MemoryRead(COUNTER);
		if (cur < last)
			delta += (cur + (CPU_SPEED - last));
		else
			delta += (cur - last);
		last = cur;
		if (delta >= cycles_per_usec){
			usecs += delta / cycles_per_usec;
			delta %= cycles_per_usec;
		}
	}
}
Пример #12
0
/*
 * ReadMem - read some memory, using toolhelp or wdebug.386
 */
DWORD ReadMem( WORD sel, DWORD off, LPVOID buff, DWORD size )
{
    DWORD       rc;

    if( WDebug386 ) {
        rc = CopyMemory( FP_SEG(buff), FP_OFF(buff), sel, off,  size );
    } else {
        if( DebugeeTask == NULL ) return( 0 );
        rc = MemoryRead( sel, off, buff, size );
    }
    return( rc );

} /* ReadMem */
Пример #13
0
/*
 * ReadMem - read some memory, using toolhelp or wdebug.386
 */
DWORD ReadMem( WORD sel, DWORD off, LPVOID buff, DWORD size )
{
    DWORD       rc;

    if( WDebug386 ) {
        return( CopyMemory386( FP_SEG( buff ), FP_OFF( buff ), sel, off, size  ) );
    } else {
        PushAll();
        rc = MemoryRead( sel, off, buff, size );
        PopAll();
        return( rc );
    }

} /* ReadMem */
Пример #14
0
int
ddr_init (void)
{
  volatile int i, j, k = 0;
  for (i = 0; i < sizeof (DdrInitData) / sizeof (int); ++i)
    {
      MemoryWrite (DDR_BASE + DdrInitData[i], 0);
      for (j = 0; j < 4; ++j)
	++k;
    }
  for (j = 0; j < 100; ++j)
    ++k;
  k += MemoryRead (DDR_BASE);	//Enable DDR
  return k;
}
Пример #15
0
static void OS_IdleSimulateIsr(void *arg)
{
   uint32 count=0, value;
   (void)arg;

   for(;;)
   {
      MemoryRead(IRQ_MASK + 4);       //calls Sleep(10)
#if WIN32
      while(OS_InterruptMaskSet(0) & IRQ_UART_WRITE_AVAILABLE)
         OS_InterruptServiceRoutine(IRQ_UART_WRITE_AVAILABLE, 0);
#endif
      value = OS_InterruptMaskSet(0) & 0xf;
      if(value)
         OS_InterruptServiceRoutine(value, 0);
      ++count;
   }
}
int32_t _getchar(void){			// polled getch()
	while(!kbhit()) ;
	return MemoryRead(UART_READ);
}
int32_t _kbhit(void){
	return MemoryRead(IRQ_CAUSE) & IRQ_UART_READ_AVAILABLE;
}
void _putchar(int32_t value){		// polled putchar()
	while((MemoryRead(IRQ_CAUSE) & IRQ_UART_WRITE_AVAILABLE) == 0);
	MemoryWrite(UART_WRITE, value);
}
Пример #19
0
/*
 *  設定コマンド
 */
static UW
set_command(B *command)
{
	INT  point=0;
	B    cmd=0;
	UB   b;
	UH   h;
	UW   w, value1, value2;
	int  no, count;
	BOOL cont;

	count = sizeof(mon_set) / sizeof(struct SUBCOMMAND_TABLE);
	if(command[point]){
		for(no = 0 ; no < count ; no++){
			if(compare_word(mon_set[no].subcommand, command, 0)){
				skip_word(command, &point);
				cmd = mon_set[no].type;
				break;
			}
		}
	}
	switch(cmd){
	default:						/* デフォルト */
		cmd = mon_datatype;
	case MONSET_BYTE:				/* バイト単位メモリ設定 */
	case MONSET_HALF:				/* ハーフ単位メモリ設定 */
	case MONSET_WORD:				/* ワード単位メモリ設定 */
		if(!get_value(command, &point, &value1, HEX_BASE))
			value1 = mon_address;
		value1 = MonAlignAddress(value1);
		mon_datatype = cmd;
		do{
			printf("  %08lx", (unsigned long)value1);
			switch(mon_datatype){
			case DATA_HALF:
				if(MemoryRead(value1, &h, 2) == 0)
					h = -1;
				printf(" %04x =", h);
				break;
			case DATA_WORD:
				if(MemoryRead(value1, &w, 4) == 0)
					w = -1;
				printf(" %08lx =", (unsigned long)w);
				break;
			default:
				if(MemoryRead(value1, &b, 1) == 0)
					b = -1;
				printf(" %02x =", b);
				break;
			}
			monitor_getstring(mon_command, &point);
			if(get_value(mon_command, &point, &value2, HEX_BASE)){
				switch(mon_datatype){
				case DATA_HALF:
					h = value2;
					MemoryWrite(value1, &h, 2);
					if(MemoryRead(value1, &h, 2) == 0)
						h = -1;
					printf(" %04x\n", h);
					break;
				case DATA_WORD:
					w = value2;
					MemoryWrite(value1, &w, 4);
					if(MemoryRead(value1, &w, 4) == 0)
						w = -1;
					printf(" %08lx\n", (unsigned long)w);
					break;
				default:
					b = value2;
					MemoryWrite(value1, &b, 1);
					if(MemoryRead(value1, &b, 1) == 0)
						b = -1;
					printf(" %02x\n", b);
					break;
				}
				value1 += mon_datatype;
				cont = TRUE;
			}
			else
				cont = FALSE;
		}while(cont || point == 0);
		putchar('\n');
		mon_address = value1;
		break;
	case MONSET_COMMAND:			/* コマンドモード設定 */
		if(get_value(command, &point, &value1, DEC_BASE)){
			if(value1 == 1 || value1 == 2){
				printf("  set %d command(s) mode !\n", value1);
				mon_mode = value1;
			}
		}
		printf("  set command mode=%d word(s) !\n", mon_mode);
		break;
	case MONSET_SERIAL:				/* シリアル設定 */
		if(get_value(command, &point, &value1, DEC_BASE)){
			if(value1 > 0 && mon_portid != value1){
				if(mon_portid != mon_default_portid && mon_portid != CONSOLE_PORTID)
					syscall(serial_cls_por(mon_portid));
				mon_portid = value1;
				if(mon_portid != mon_default_portid && mon_portid != CONSOLE_PORTID)
					syscall(serial_opn_por(mon_portid));
				syscall(serial_ctl_por(mon_portid, (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
				printf(banner,
					(TMONITOR_PRVER >> 12) & 0x0f,
					(TMONITOR_PRVER >> 4) & 0xff,
					TMONITOR_PRVER & 0x0f);
			}
		}
		printf("  set serial port id=%d !\n", mon_portid);
		break;
	case MONSET_TASK:				/* タスク選択 */
		if(get_value(command, &point, &value1, DEC_BASE)){
			if(value1 >= TMIN_TSKID && value1 < (TMIN_TSKID+tmax_tskid))
				current_tskid = value1;
			else
				current_tskid = MONTASK;
		}
		else
			current_tskid = MONTASK;
		break;
	case MONSET_IN:					/* 入力設定 */
		value1 = 0;
		get_value(command, &point, &value1, DEC_BASE);
		if(value1 == 1)
			mon_infile = stdout;
		else if(value1 == 2)
			mon_infile = stderr;
		else
			mon_infile = stdin;
		break;
	}
	return 0;
}
uint32_t HF_ReadCounter(void){
	return MemoryRead(COUNTER);
}
Пример #21
0
static trap_elen ReadMemory( addr48_ptr *addr, void *data, trap_elen len )
/************************************************************************/
{
    return( MemoryRead( addr->offset, addr->segment, data, len ) );
}
Пример #22
0
int main(int argc, char **argv)
{
    char cDiskName[] = "/dev/sg2";
    int fd = open(cDiskName, O_RDWR);
    if (fd < 0)
    {
        printf("Open error: %s, errno=%d (%s)\n", cDiskName, errno, strerror(errno));
        return 1;
    }

    if (!checkDevice(fd)) {
        printf("checkDevice fail\n");
        return 2;
    }
    printf("init ok\n");

    DataInfo_t datainfo;
    int last_addr = 0;
    DeviceState_t last_state = STATE_INVALIDxx;
    DI_Status_t last_status = DI_STATUS_INVALIDxx;

    unsigned scanned_imgs = 0;

    while (true) {
        // get state: scanning or idle
        DeviceState_t state = GetDeviceState(fd);
        if (state >= STATE_INVALIDxx || state < 0) {
            return 7;
        }
        if (state != last_state) {
            printf("DeviceState: %d => %s\n", (unsigned)state, state_lut[state]);
        }

        // get data info: new data ready or not?
        if (!GetDeviceDataInfo(fd, &datainfo)) {
            return 8;
        }
        if (datainfo.status < 0 || datainfo.status > 2) {
            return 9;
        }
        if (datainfo.status != last_status || datainfo.addr != last_addr) {
            dumpDataInfo(&datainfo);
        }

        if (datainfo.status != DI_STATUS_NOT_READY) {
            // there's data for us
            unsigned imgbufsize = datainfo.width * datainfo.height;
            if (datainfo.color == DI_COLOR_COLOR) {
                imgbufsize *= 3;
            }

            // image buffer
            unsigned char *imgbuf = new unsigned char[imgbufsize];

            // read data
            bool ok = MemoryRead(fd, datainfo.addr, imgbuf, imgbufsize);
            if (ok) {
                printf("read %d bytes\n", imgbufsize);

                shuffleBitmap(imgbuf, imgbufsize, datainfo.width, datainfo.height, datainfo.color);

                int ifd;
                if (!scanned_imgs) {
                    ifd = open("out.data", O_WRONLY|O_CREAT|O_TRUNC, 0644);
                } else {
                    ifd = open("out.data", O_WRONLY|O_APPEND);
                }

                if (ifd) {
                    write(ifd, imgbuf, imgbufsize);
                    close(ifd);

                    scanned_imgs++;
                }
            } else {
                printf("failed reading data\n");
            }

            delete [] imgbuf;
            imgbuf = 0;
        }

        usleep(20000);
        last_state = state;
        last_status = datainfo.status;
        last_addr = datainfo.addr;
    }

    close(fd);
    printf("all ok\n");
    return 0;
}
Пример #23
0
int main(int argc, char* argv[])
{
	mos6502 cpu(MemoryRead, MemoryWrite);
	disasm dasm;
	int SPEED = 100; // %
	int CPUFREQ = 1000000; // Hz - CPU clock frequency
	bool HALT = false;
	// Todo optimize this string buffer size?
	char str[400];

	if (argc < 2)
	{
		std::cout << "Filename required!" << std::endl;
		return 0;
	}

	if (rom.loadFromFile(argv[1]) == 0)
	{
		std::cout << "Rom invalid!" << std::endl;
	}

	std::string caption("CBS6000 Emulator - (C)2015 Koen van Vliet");
	sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), caption);
	sf::RenderWindow dbgwindow(sf::VideoMode(DBGWINDOW_WIDTH, DBGWINDOW_HEIGHT), caption);
	sf::RenderWindow zpwindow(sf::VideoMode(ZPWINDOW_WIDTH, ZPWINDOW_HEIGHT), caption);
	window.setFramerateLimit(FPS);
	dbgwindow.setFramerateLimit(FPS);
	zpwindow.setFramerateLimit(FPS);

	if (!term.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	if (!dbgterm.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	if (!dasmterm.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	if (!regterm.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	if (!zpterm.load("terminal8x16.png",8,16))
	{
		std::cout << "Failed to open bitmap font file!" << std::endl;
		return 0;
	}

	int ctile = 177;
	term.setCursorTile(ctile);
	dbgterm.setCursorTile(ctile);
	dbgterm.enableCursor(false);
	dbgterm.setTextColor(sf::Color::Green);
	dasmterm.enableCursor(false);
	dasmterm.setTextColor(sf::Color::Cyan);
	regterm.enableCursor(false);
	regterm.setTextColor(sf::Color::White);
	zpterm.enableCursor(false);
	zpterm.setTextColor(sf::Color::White);

	consoleLog("---[Debug console]---");
	consoleLog(versionInfo);
	net.init();
	consoleLog("Starting CPU emulation");

	// Reset Cpu and internal IO port for the 6510
	Direction = 0x00;
	PortOut = 0x00;
	cpu.Reset();

	bool SHOWDASM = false;

	while(window.isOpen())
	{
		if (SPEED <= 20)
		{
			SHOWDASM = true;
		}

		sf::Event event;
		while (window.pollEvent(event))
		{
			switch (event.type) {
				case sf::Event::Closed :
					window.close();
					break;
				case sf::Event::TextEntered:
					if (event.text.unicode < 128)
					{
						char c = (char)event.text.unicode;
						term.feedChar(c);
					}
					break;
				case sf::Event::KeyPressed :
					// Increase and decrease the CPU speed
					if (event.key.code == sf::Keyboard::PageUp)
					{
						if (SPEED < 500)
						{
							SPEED += 5;
						}

						sprintf(str, "%d%% speed", SPEED);
						consoleLog(str);
					}
					if (event.key.code == sf::Keyboard::PageDown)
					{
						if (SPEED)
						{
							SPEED -= 5;
							if (SPEED < 0)
							{
								SPEED = 0;
							}
							sprintf(str, "%d%% speed", SPEED);
							consoleLog(str);
						}
					}

					// Stop execution
					if (event.key.code == sf::Keyboard::Delete)
					{
						HALT = true;
						SHOWDASM = true;
						consoleLog("F8 to continue, F5 to step");
					}

					// Stop/Resume execution
					if (event.key.code == sf::Keyboard::F8)
					{
						if (HALT)
						{
							HALT = false;
							consoleLog("Resumed execution...");
						}
						else
						{
							HALT = true;
							SHOWDASM = true;
							consoleLog("F8 to continue, F5 to step");
						}
					}
					// Execute single instruction
					if (event.key.code == sf::Keyboard::F5)
					{
						if (HALT)
						{
							cpu.Run(1);
							SHOWDASM = true;
						}
					}


					if (event.key.code == sf::Keyboard::End)
					{
						// Reset Cpu and internal IO port for the 6510
						Direction = 0x00;
						PortOut = 0x00;
						cpu.Reset();
						HALT = false;
						consoleLog("Reset CPU");
					}

					break;
				default:
					break;
			}
		}

		// Run a bunch of instructions
		if(!HALT)
		{
			int IPF = (CPUFREQ * SPEED) /(FPS * AVG_INSTRUCTION_CYCLES * 100); 			// Instructions per frame
			cpu.Run(IPF);
		}

		if (SHOWDASM)
		{
			// Show live disassembly of the memory
			SHOWDASM = false;
			// Todo fix pc
			uint16_t state[6];
			uint8_t buff[3];
			uint16_t pc;
			cpu.GetState(state);
			pc = state[3];
			for(int i = 0; i< 9; i++)
			{
				uint pc_prev = pc;
				dasmterm.printString("\r\n");
				buff[0] = MemoryRead(pc);
				buff[1] = MemoryRead(pc+1);
				buff[2] = MemoryRead(pc+2);
				pc += 1 + dasm.getDisassembly((char*)str, buff, 1, pc_prev);
				if(i ==0)
					dasmterm.printString(">");
				else
					dasmterm.printString(" ");
				dasmterm.printString(str);
			}

			// Display CPU register contents
			char charA = state[0], charX = state[1], charY = state[2];

			if (charA < ' ')
			{
				charA = ' ';
			}
			if (charX < ' ')
			{
				charX = ' ';
			}
			if (charY < ' ')
			{
				charY = ' ';
			}

			sprintf(str,"\r\n"
						"A:  $%02X  %03d \'%c\'\r\n"
						"X:  $%02X  %03d \'%c\'\r\n"
						"Y:  $%02X  %03d \'%c\'\r\n"
						"PC: $%04X\r\n"
						"SP: $%02X  %03d\r\n"
						"SR: $%02X, Z: %d, C: %d",
						state[0],
						state[0],
						charA,
						state[1],
						state[1],
						charX,
						state[2],
						state[2],
						charY,
						state[3],
						state[4],
						state[4],
						state[5],
						(state[5]>>1) & 1,
						state[5] & 1);
			regterm.printString(str);

			// Show zero page contents
			zpterm.setTextColor(sf::Color::Cyan);
			zpterm.printString("\r\n----: -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F");
			zpterm.setTextColor(sf::Color::White);
			for(int i = 0; i < 16; i++)
			{
				uint8_t d;
				zpterm.printString("\r\n");
				sprintf(str, "%04X: ", (uint16_t)(i * 16));
				zpterm.printString(str);
				for(int j = 0; j < 16; j++)
				{
					d = MemoryRead(i*16 + j);
					if (j == 15)
						sprintf(str,"%02X",d);
					else
						sprintf(str,"%02X,",d);
					if(i*16 + j >= 0x5C && i*16+j < 0x5C+ 0x27)
						zpterm.setTextColor(sf::Color::Green);
					zpterm.printString(str);
					zpterm.setTextColor(sf::Color::White);
				}
				for(int j = 0; j < 16; j++)
				{
					d = MemoryRead(i*16 + j);
					if (d < ' ')
					{
						d = ' ';
					}
					if(i*16 + j >= 0x5C && i*16+j < 0x5C+ 0x27)
						zpterm.setTextColor(sf::Color::Green);
					zpterm.Write(d);
					zpterm.setTextColor(sf::Color::Blue);
					zpterm.Write(ctile);
					zpterm.setTextColor(sf::Color::White);
				}
				zpterm.setTextColor(sf::Color::Blue);
				for(int i = 0; i< 86; i++)
					zpterm.Write(177);
				zpterm.setTextColor(sf::Color::White);
			}
		}

		// Update the screen
		window.clear();
		dbgwindow.clear();
		zpwindow.clear();
		net.update();
		term.update();
		dbgterm.update();
		dasmterm.update();
		zpterm.update();
		regterm.update();
		window.draw(term);
		dbgwindow.draw(dbgterm);
		zpwindow.draw(zpterm);
		//if(HALT)
		//{
			dbgwindow.draw(dasmterm);
			dbgwindow.draw(regterm);
		//}
		window.display();
		dbgwindow.display();
		zpwindow.display();
	}
	return 0;
}
Пример #24
0
/* Blocking write to STDIN */
void writeChar(unsigned char c)
{
	while((MemoryRead(UART_STATUS) & UART_TX_FULL_MASK) > 0);
	printChar(c);
}
Пример #25
0
/* Blocking read from STDIN */
unsigned char readChar()
{
	while((MemoryRead(UART_STATUS) & UART_RX_DV_MASK) == 0);
	return (unsigned char)MemoryRead(UART_RX);
}
int32_t _getchar(void){			// polled getch()
	return MemoryRead(DEBUG_ADDR);
}
Пример #27
0
/*
interrupt management routines
*/
uint32_t HF_InterruptStatus(void){			// check interrupt status
	return MemoryRead(IRQ_STATUS);
}
Пример #28
0
uint32_t HF_InterruptMaskRead(void){			// check interrupt status
	return MemoryRead(IRQ_MASK);
}
Пример #29
0
static unsigned ReadMemory( addr48_ptr *addr, void *data, unsigned len )
/**********************************************************************/
{
    return( MemoryRead( addr->offset, addr->segment, data, len ) );
}
Пример #30
0
Lst::HashTable<Nx::CTexture>* LoadTextureFileFromMemory( void **pp_mem, Lst::HashTable<Nx::CTexture> *p_texture_table, bool okay_to_rebuild_texture_table )
{
	uint8 *p_data = (uint8*)( *pp_mem );

	// Read the texture file version and number of textures.
	int version, num_textures;
	MemoryRead( &version, sizeof( int ), 1, p_data );
	MemoryRead( &num_textures, sizeof( int ), 1, p_data );

	// If allowed, rebuild the texture table to the optimum size, using the same heap as the original table.
	if( okay_to_rebuild_texture_table )
	{
		uint32 optimal_table_size	= num_textures * 2;
		uint32 test					= 2;
		uint32 size					= 1;
		for( ;; test <<= 1, ++size )
		{
			// Check if this iteration of table size is sufficient, or if we have hit the maximum size.
			if(( optimal_table_size <= test ) || ( size >= 12 ))
			{
				Mem::Allocator::BlockHeader*	p_bheader	= Mem::Allocator::BlockHeader::sRead( p_texture_table );
				Mem::Allocator*					p_allocater	= p_bheader->mpAlloc;

				delete p_texture_table;

				Mem::Manager::sHandle().PushContext( p_allocater );
				p_texture_table = new Lst::HashTable<Nx::CTexture>( size );
				Mem::Manager::sHandle().PopContext();
				break;
			}
		}
	}

	for( int t = 0; t < num_textures; ++t )
	{
		// Create the engine level texture.
		NxXbox::sTexture *p_texture = new NxXbox::sTexture;

		uint32 base_width, base_height, levels, texel_depth, palette_depth, dxt, palette_size;
		MemoryRead( &p_texture->Checksum,	sizeof( uint32 ), 1, p_data );
		MemoryRead( &base_width,			sizeof( uint32 ), 1, p_data );
		MemoryRead( &base_height,			sizeof( uint32 ), 1, p_data );
		MemoryRead( &levels,				sizeof( uint32 ), 1, p_data );
		MemoryRead( &texel_depth,			sizeof( uint32 ), 1, p_data );
		MemoryRead( &palette_depth,			sizeof( uint32 ), 1, p_data );
		MemoryRead( &dxt,					sizeof( uint32 ), 1, p_data );
		MemoryRead( &palette_size,			sizeof( uint32 ), 1, p_data );

		p_texture->BaseWidth	= (uint16)base_width;
		p_texture->BaseHeight	= (uint16)base_height;
		p_texture->Levels		= (uint8)levels;
		p_texture->TexelDepth	= (uint8)texel_depth;
		p_texture->PaletteDepth	= (uint8)palette_depth;
		p_texture->DXT			= (uint8)dxt;
		
		D3DFORMAT	texture_format;
		if( p_texture->DXT > 0 )
		{
			if(( p_texture->DXT == 1 ) || ( p_texture->DXT == 2 ))
			{
				texture_format = D3DFMT_DXT1;
			}
			else if( p_texture->DXT == 5 )
			{
				texture_format = D3DFMT_DXT5;
			}
			else
			{
				Dbg_Assert( 0 );
			}
		}
		else if( p_texture->TexelDepth == 8 )
		{
			texture_format = D3DFMT_P8;
		}
		else if( p_texture->TexelDepth == 16 )
		{
			texture_format = D3DFMT_A1R5G5B5;	// Could also be X1R5G5B5;
		}
		else if( p_texture->TexelDepth == 32 )
		{
			texture_format = D3DFMT_A8R8G8B8;
		}
		else
		{
			Dbg_Assert( 0 );
		}
		
		if( D3D_OK != D3DDevice_CreateTexture(	p_texture->BaseWidth, p_texture->BaseHeight, p_texture->Levels,	0, texture_format, 0, &p_texture->pD3DTexture ))
		{
			Dbg_Assert( 0 );
		}

		if( palette_size > 0 )
		{
			// Create and lock the palette.
			if( D3D_OK != D3DDevice_CreatePalette(	palette_size == ( 256 * sizeof( D3DCOLOR )) ? D3DPALETTE_256 : D3DPALETTE_32, &p_texture->pD3DPalette ))
			{
				Dbg_Assert( 0 );
			}
			else
			{
				D3DCOLOR* p_colors;
				if( D3D_OK != p_texture->pD3DPalette->Lock( &p_colors, 0 ))
				{
					Dbg_Assert( 0 );
				}
				else
				{
					// Read in palette data.
					MemoryRead( p_colors, palette_size, 1, p_data );
				}
			}
		}
		else
		{
			p_texture->pD3DPalette = NULL;
		}

		for( uint32 mip_level = 0; mip_level < p_texture->Levels; ++mip_level )
		{
			uint32 texture_level_data_size;
			MemoryRead( &texture_level_data_size, sizeof( uint32 ), 1, p_data );

			D3DLOCKED_RECT locked_rect;
			if( D3D_OK != p_texture->pD3DTexture->LockRect( mip_level, &locked_rect, NULL, 0 ))
			{
				Dbg_Assert( 0 );
			}
			else
			{
				MemoryRead( locked_rect.pBits, texture_level_data_size, 1, p_data );
			}
		}

		// Add this texture to the table.
		Nx::CXboxTexture *p_xbox_texture = new Nx::CXboxTexture();
		p_xbox_texture->SetEngineTexture( p_texture );
		p_texture_table->PutItem( p_texture->Checksum, p_xbox_texture );
	}
	return p_texture_table;
}