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; i 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); }