⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gbaemu.c

📁 这是模拟器源代码
💻 C
字号:
#include <windows.h>
#include <stdlib.h>
#include <stdio.h> 

#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; i<count; i++) {				
	
				write_word (DM3DAD, read_word (DM3SAD));
	
				switch (DM3CNT_H & 0x60) {
					case 0: DM3DAD += 4; break;
					case 1: DM3DAD -= 4; break;
					case 2:				 break;
					case 3: DM3DAD += 4; break;
				}

				switch (DM3CNT_H & 0x180) {
					case 0: DM3SAD += 4; break;
					case 1: DM3SAD -= 4; break;
					case 2:				 break;
					case 3:				 break;
				} 
			}
		}
		else {	

			for (i=0; i<count; i++) {
	
				write_hword (DM3DAD, read_hword (DM3SAD));

				switch (DM3CNT_H & 0x60) {
					case 0: DM3DAD += 2; break;
					case 1: DM3DAD -= 2; break;
					case 2:				 break;
					case 3: DM3DAD += 2; break;
				}
 
				switch (DM3CNT_H & 0x180) {
					case 0: DM3SAD += 2; break;
					case 1: DM3SAD -= 2; break;
					case 2:				 break;
					case 3:				 break;
				}
			} 
		}
	} 
} 

void run_breakpoint (u32 breakpoint)
{
	u32 i, n;
	
	for (;;) { 
		
		io_ram_u16[0x3] = 0;
		io_ram_u32[0x1] &= 0xFFFFFFFE;

		// Screen refresh	
		for (i=0; i<160; i++, io_ram_u16[0x3]++)
			for (n=0; n<1227;)
				if ((arm->gp_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);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -