www.pudn.com > EloGbaR1.zip > gbaemu.c


#include  
#include  
#include   
 
#include "gbaemu.h"  
#include "interface.h"  
 
#include "exec.c" 
#include "opcodes.c" 
#include "topcodes.c" 
#include "io.c"  
#include "opedec.c" 
#include "tables.c" 
#include "ttables.c" 
 
int init_gbaemu (void) 
{ 
	if (wram_int_u8) free (wram_int_u8); 
	if (wram_ext_u8) free (wram_ext_u8); 
	if (pal_ram_u8)  free (pal_ram_u8);  
	if (vram_u8)     free (vram_u8); 
	if (oam_u8)      free (oam_u8); 
	if (arm)		 free (arm); 
	if (dummy_mem)	 free (dummy_mem); 
 
	wram_int_u8  = calloc (  0x800, 1); 
	wram_ext_u8  = calloc (0x40000, 1); 
	pal_ram_u8   = calloc (  0x400, 1); 
	vram_u8      = calloc (0x20000, 1);  
	oam_u8       = calloc (  0x400, 1); 
	io_ram_u8	 = calloc (  0x400, 1); 
	zero_page_u8 = calloc (   0xFF, 1); 
 
	wram_int_u16 = (u16*)wram_int_u8; 
	wram_int_u32 = (u32*)wram_int_u8; 
	wram_ext_u16 = (u16*)wram_ext_u8; 
	wram_ext_u32 = (u32*)wram_ext_u8; 
	pal_ram_u16  = (u16*)pal_ram_u8; 
	pal_ram_u32  = (u32*)pal_ram_u8; 
	vram_u16     = (u16*)vram_u8; 
	vram_u32     = (u32*)vram_u8; 
	oam_u16      = (u16*)oam_u8; 
	oam_u32      = (u32*)oam_u8; 
	io_ram_u16	 = (u16*)io_ram_u8; 
	io_ram_u32	 = (u32*)io_ram_u8; 
	zero_page_u16= (u16*)zero_page_u8; 
	zero_page_u32= (u32*)zero_page_u8; 
 
	screen = calloc(0x9600, 1); 
	virtual_screen  = calloc (0xA2C0*2, 1); 
 
	arm = calloc (sizeof(ARM7TDMI), 1); 
  
	setup_tables (); 
 
	blit_res_x = 240; 
	blit_res_y = 160; 
 
	if (!wram_int_u8 || !wram_ext_u8 || !pal_ram_u8 || !vram_u8 || !oam_u8  
	    ||!io_ram_u8 || !arm || !screen || !zero_page_u8 || !virtual_screen) 
		return 1; 
	else 
		return 0;  
} 
 
void reset_gbaemu (word pc, char *debug_destination, char *operand_destination) 
{  
	int i; 
	 
	debug_str = debug_destination; 
 
	for (i=0; i<0x400; i++) 
		pal_ram_u8 [i] = 0; 
 
	for (i=0; i<0x20000; i++) 
		vram_u8 [i] = 0; 
	 
	arm->cpsr = SUPERVISOR_MODE | FIQ_BIT | IRQ_BIT; 
	ZFLAG = 0; 
	NFLAG = 0; 
	CFLAG = 0; 
	VFLAG = 0; 
 
	arm->gp_reg [15] = pc; 
		 
	arm->state = 0; 
 
	fill_instruction_pipe(); 
 
	io_ram_u16 [0x98] = 0x3FF; 
 
	strcpy (debug_str, opcode_strings [((OPCODE&0xFF00000)>>16)|((OPCODE&0xF0)>>4)]); 
 
	exec = arm_exec; 
} 
 
int load_bin (char *filename) 
{ 
	FILE *fp; 
	int file_size; 
	int start, end; 
 
	int n, i; 
 
	if (!(fp = fopen(filename, "rb")))  
		return 0; 
 
	fseek (fp, 0, SEEK_SET); 
	start = ftell (fp); 
	fseek (fp, 0, SEEK_END); 
	end = ftell (fp); 
	 
	file_size = (end - start)+1; 
 
	fseek (fp, 0, SEEK_SET); 
 
	dummy_mem = calloc (0x10000, 1); 
 
	n=file_size/0x10000; 
 
	for (i=0; i<0x200; i++) 
		rom_pages_u8 [i] = dummy_mem; 
 
	for (i=0; i<(n+1); i++) { 
		rom_pages_u8 [i] = calloc (0x10000, 1); 
		fread (rom_pages_u8 [i], 0x10000, 1, fp); 
	} 
 
	fread (rom_pages_u8 [n+1], file_size-(n*0x10000), 1, fp); 
 
	for (i=0; i<0x200; i++) { 
		rom_pages_u16 [i] = (u16*)rom_pages_u8 [i]; 
		rom_pages_u32 [i] = (u32*)rom_pages_u8 [i]; 
	} 
	 
	bin.rom_size_u8 = file_size; 
	bin.rom_size_u16 = bin.rom_size_u8>>1; 
	bin.rom_size_u32 = bin.rom_size_u8>>2; 
 
	fclose (fp); 
 
	return 1;  
} 
 
void setup_tables (void)  
{ 
	setup_handle_tables();  
	setup_string_tables(); 
	setup_io_handle_tables();  
	setup_debug_handles(); 
	setup_handle_tables_t(); 
	setup_string_tables_t(); 
 
	render_mode [0] = render_mode0_frame; 
	render_mode [1] = render_mode1_frame; 
	render_mode [2] = render_mode2_frame; 
	render_mode [3] = render_mode3_frame; 
	render_mode [4] = render_mode4_frame; 
	render_mode [5] = render_mode5_frame; 
	render_mode [6] = render_mode4_frame; 
	render_mode [7] = render_mode4_frame; 
 
	sprite_sizes_x [0x0] = 8; 
	sprite_sizes_x [0x1] = 16; 
	sprite_sizes_x [0x2] = 32; 
	sprite_sizes_x [0x3] = 64; 
	sprite_sizes_x [0x4] = 16; 
	sprite_sizes_x [0x5] = 32; 
	sprite_sizes_x [0x6] = 32; 
	sprite_sizes_x [0x7] = 64; 
	sprite_sizes_x [0x8] = 8; 
	sprite_sizes_x [0x9] = 8; 
	sprite_sizes_x [0xA] = 16; 
	sprite_sizes_x [0xB] = 32; 
	sprite_sizes_x [0xC] = 0; 
	sprite_sizes_x [0xD] = 0; 
	sprite_sizes_x [0xE] = 0; 
	sprite_sizes_x [0xF] = 0; 
 
	sprite_sizes_y [0x0] = 8; 
	sprite_sizes_y [0x1] = 16; 
	sprite_sizes_y [0x2] = 32; 
	sprite_sizes_y [0x3] = 64; 
	sprite_sizes_y [0x4] = 8; 
	sprite_sizes_y [0x5] = 8; 
	sprite_sizes_y [0x6] = 16; 
	sprite_sizes_y [0x7] = 32; 
	sprite_sizes_y [0x8] = 16; 
	sprite_sizes_y [0x9] = 32; 
	sprite_sizes_y [0xA] = 32; 
	sprite_sizes_y [0xB] = 64; 
	sprite_sizes_y [0xC] = 0; 
	sprite_sizes_y [0xD] = 0; 
	sprite_sizes_y [0xE] = 0; 
	sprite_sizes_y [0xF] = 0; 
} 
 
void exec_step (void) 
{  
	exec(); 
} 
 
void exec_dma3 (void) 
{	 
	u32 i; 
	u16 count = DM3CNT_L; 
 
	if (DM3CNT_H & 0x8000) { 
 
		if (DM3CNT_H & 0x400) { 
	 
			for (i=0; igp_reg[15]-8)==breakpoint) return; else n+=exec();  
   
		io_ram_u32[0x1] |= 0x1;   
 
		// vblank 
		for (i=0; i<68; i++, io_ram_u16[0x3]++) 
			for (n=0; n<1227;) 
				if ((arm->gp_reg[15]-8)==breakpoint) return; else n+=exec();  
	} 
} 
 
void run_frame (void) 
{ 
		int i, n;	 
 
		io_ram_u16[0x3] = 0; 
		io_ram_u32[0x1] &= ~0x1; 
	 
		for (i=0; i<160; i++, io_ram_u16[0x3]++) 
			for (n=0; n<1227;) 
				n+=exec(); 
   
		io_ram_u32[0x1] |= 0x1; 
 
		for (i=0; i<68; i++, io_ram_u16[0x3]++) 
			for (n=0; n<1227;) 
				n+=exec(); 
		 
		render_mode [DISPCNT&0x7](); 
} 
 
void draw_mode0_bg (u32 num) 
{ 
	u32 i, n, y; 
	u32 screen_x, screen_y; 
	u32 chr_base = ((io_ram_u16[0x4+num]>>2)&0x3 )*0x4000; 
	u32 scr_base = ((io_ram_u16[0x4+num]>>8)&0x1F)*0x800; 
	u32 hoff = io_ram_u16 [0x8+(num<<1)] & 0x1FF; 
	u32 voff = io_ram_u16 [0x9+(num<<1)] & 0x1FF; 
	u32 fine_x = hoff&0x7; 
	u32 fine_y = voff&0x7; 
	u32 map_pointer; 
	u32 tile_pointer; 
	u16 tile_data; 
	u16 chr_data; 
 
	switch ((io_ram_u16[0x4+num]>>14)&0x3) { 
		case 0: screen_x = 256; screen_y = 256; break; 
		case 1: screen_x = 512; screen_y = 256; break; 
		case 2: screen_x = 256; screen_y = 512; break; 
		case 3: screen_x = 512; screen_y = 512; break; 
	} 
 
	map_pointer = (scr_base>>1) + ((voff>>3)*(screen_x>>3)) + (hoff>>3); 
 
	for (i=0; i<20; i++) { 
 
		for (n=0; n<30; n++, map_pointer++) { 
	 
			tile_data = vram_u16 [map_pointer]; 
			tile_pointer = chr_base+((tile_data&0x3FF)*64);	 
 
			switch ((tile_data>>10)&0x3) 
			{ 
				case 0: 
					for (y=0; y<64; y++) {	 
						chr_data = vram_u8 [tile_pointer+y]; 
						if (chr_data) virtual_screen [(i*1984)+(n<<3)+((y>>3)*248)+(y&0x7)] = chr_data; 
					} break; 
				case 1: 
					for (y=0; y<64; y++) { 
						chr_data = vram_u8 [tile_pointer+(y&(~0x7))+(7-(y&0x7))]; 
						if (chr_data) virtual_screen [(i*1984)+(n<<3)+((y>>3)*248)+(y&0x7)] = chr_data;				 
					} break; 
				case 2: 
					for (y=0; y<64; y++) { 
						chr_data = vram_u8 [tile_pointer+((7-(y>>3))<<3)+(y&0x7)]; 
						if (chr_data) virtual_screen [(i*1984)+(n<<3)+((y>>3)*248)+(y&0x7)] = chr_data;						 
					} break; 
				case 3: 
					for (y=0; y<64; y++) { 
						chr_data = vram_u8[tile_pointer+((7-(y>>3))<<3)+(7-(y&0x7))]; 
						if (chr_data) virtual_screen [(i*1984)+(n<<3)+((y>>3)*248)+(y&0x7)] = chr_data;						 
					}break; 
			} 
		} 
		 
		map_pointer += (screen_x-240)>>3; 
	} 
} 
 
void render_mode0_frame (void) 
{ 
	int i, n; 
 
	for (i=0; i<0xB000; i++) { 
		virtual_screen [i] = 0; 
	} 
 
	for (i=3; i>=0; i--) { 
		 
		if (((u32)(BG0CNT&0x3)==(u32)i)&&(DISPCNT&0x100)) draw_mode0_bg (0); 
		if (((u32)(BG1CNT&0x3)==(u32)i)&&(DISPCNT&0x200)) draw_mode0_bg (1); 
		if (((u32)(BG2CNT&0x3)==(u32)i)&&(DISPCNT&0x400)) draw_mode0_bg (2); 
		if (((u32)(BG3CNT&0x3)==(u32)i)&&(DISPCNT&0x800)) draw_mode0_bg (3); 
		if (DISPCNT&0x1000) draw_sprites ((u16)i); 
	} 
	 
	for (i=0; i<160; i++) { 
		for (n=0; n<240; n++) { 
			screen [(i*240)+n] = translated_palette [virtual_screen[(i*248)+n]]; 
		} 
	} 
} 
 
void render_mode1_frame (void) 
{ 
 
} 
 
void render_mode2_frame (void) 
{ 
 
} 
 
void render_mode3_frame (void) 
{ 
	u32 i; 
	u16 temp; 
 
	for (i=0; i<0x9600; i++) { 
		temp = vram_u16 [i]; 
		screen [i] = (u32)(temp<<19)|((temp&0x3E0)<<6)|((temp&0x7C00)>>7); 
	} 
} 
 
void render_mode4_frame (void) 
{ 
	u32 i; 
	u8 *temp_pointer; 
 
	if (DISPCNT&0x10) { 
		temp_pointer = vram_u8 + 0xA000; 
		for (i=0; i<0x9600; i++) { 
			screen [i] = translated_palette [temp_pointer[i]]; 
		} 
	} 
	else { 
		for (i=0; i<0x9600; i++) { 
			screen [i] = translated_palette [vram_u8[i]]; 
		} 
	} 
} 
 
void render_mode5_frame (void) 
{ 
	u32 i, n; 
	u16 temp; 
 
	if (DISPCNT&0x10) { 
		for (i=0; i<128; i++) { 
			for (n=0; n<160; n++) { 
				temp = vram_u16[(i*160)+n+0x5000]; 
				screen [(i*240)+n] = (u32)(temp<<19)|((temp&0x3E0)<<6)|((temp&0x7C00)>>7); 
			} 
		} 
	} 
	else { 
		for (i=0; i<128; i++) { 
			for (n=0; n<160; n++) { 
				temp = vram_u16[(i*160)+n]; 
				screen [(i*240)+n] = (u32)(temp<<19)|((temp&0x3E0)<<6)|((temp&0x7C00)>>7); 
			} 
		} 
	} 
} 
 
void draw_sprites (u16 priority) 
{ 
	int i; 
 
	for (i=127; i>=0; i--) { 
		 
		if (((oam_u16[2+(i<<2)]>>10)&0x3)==priority) { 
 
			draw_sprite (oam_u16 [(i<<2)], oam_u16 [(i<<2)+1], oam_u16[(i<<2)+2]); 
		} 
	} 
 
} 
 
void draw_sprite (u16 a0, u16 a1, u16 a2) 
{ 
	u32 i, n, y; 
 
	u32 chr_base = 0x10000 + ((a2&0x3FF)*64); 
	u32 size_x = sprite_sizes_x [((a0>>12)&~0x3)|(a1>>14)]; 
	u32 size_y = sprite_sizes_y [((a0>>12)&~0x3)|(a1>>14)];  
	u16 x_off = (a1&0x1FF); 
	u16 y_off = (a0&0xFF); 
	u16 chr_data; 
 
	for (i=0; i<(size_y>>3); i++) { 
		 
		for (n=0; n<(size_x>>3); n++) { 
			 
			for (y=0; y<64; y++) {	 
 
				chr_data = vram_u8 [chr_base+(i*(size_x>>3)*64)+(n*64)+y]+256; 
				if (chr_data) virtual_screen [((y_off+(y>>3))*248)+(y&0x7)+x_off+(n<<3)] = chr_data; 
			} 
		} 
	} 
} 
 
void clean_up (void) 
{ 
	if (wram_int_u8) free (wram_int_u8); 
	if (wram_ext_u8) free (wram_ext_u8); 
	if (pal_ram_u8) free (pal_ram_u8);  
	if (vram_u8) free (vram_u8); 
	if (oam_u8) free (oam_u8); 
	if (arm) free (arm); 
	if (hBitmap) free (hBitmap); 
}