📄 gbaemu.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 + -