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

📄 main.c

📁 psp上的GBA模拟器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* gameplaySP * * Copyright (C) 2006 Exophase <exophase@gmail.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include "common.h"#ifdef PSP_BUILD//PSP_MODULE_INFO("gpSP", 0x1000, 0, 6);//PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER);void vblank_interrupt_handler(u32 sub, u32 *parg);#endiftimer_type timer[4];//debug_state current_debug_state = COUNTDOWN_BREAKPOINT;//debug_state current_debug_state = PC_BREAKPOINT;u32 breakpoint_value = 0x7c5000;debug_state current_debug_state = RUN;//u32 breakpoint_value = 0;frameskip_type current_frameskip_type = auto_frameskip;u32 frameskip_value = 4;u32 random_skip = 0;u32 global_cycles_per_instruction = 3;u32 skip_next_frame = 0;u32 frameskip_counter = 0;u32 cpu_ticks = 0;u32 frame_ticks = 0;u32 execute_cycles = 960;s32 video_count = 960;u32 ticks;u32 arm_frame = 0;u32 thumb_frame = 0;u32 last_frame = 0;u32 cycle_memory_access = 0;u32 cycle_pc_relative_access = 0;u32 cycle_sp_relative_access = 0;u32 cycle_block_memory_access = 0;u32 cycle_block_memory_sp_access = 0;u32 cycle_block_memory_words = 0;u32 cycle_dma16_words = 0;u32 cycle_dma32_words = 0;u32 flush_ram_count = 0;u32 gbc_update_count = 0;u32 oam_update_count = 0;u32 synchronize_flag = 1;u32 update_backup_flag = 1;u32 clock_speed = 333;volatile u8 main_path[512];#define check_count(count_var)                                                \  if(count_var < execute_cycles)                                              \    execute_cycles = count_var;                                               \#define check_timer(timer_number)                                             \  if(timer[timer_number].status == TIMER_PRESCALE)                            \    check_count(timer[timer_number].count);                                   \#define update_timer(timer_number)                                            \  if(timer[timer_number].status != TIMER_INACTIVE)                            \  {                                                                           \    if(timer[timer_number].status != TIMER_CASCADE)                           \    {                                                                         \      timer[timer_number].count -= execute_cycles;                            \      io_registers[REG_TM##timer_number##D] =                                 \       -(timer[timer_number].count >> timer[timer_number].prescale);          \    }                                                                         \                                                                              \    if(timer[timer_number].count <= 0)                                        \    {                                                                         \      if(timer[timer_number].irq == TIMER_TRIGGER_IRQ)                        \        irq_raised |= IRQ_TIMER##timer_number;                                \                                                                              \      if((timer_number != 3) &&                                               \       (timer[timer_number + 1].status == TIMER_CASCADE))                     \      {                                                                       \        timer[timer_number + 1].count--;                                      \        io_registers[REG_TM0D + (timer_number + 1) * 2] =                     \         -(timer[timer_number + 1].count);                                    \      }                                                                       \                                                                              \      if(timer_number < 2)                                                    \      {                                                                       \        if(timer[timer_number].direct_sound_channels & 0x01)                  \          sound_timer(timer[timer_number].frequency_step, 0);                 \                                                                              \        if(timer[timer_number].direct_sound_channels & 0x02)                  \          sound_timer(timer[timer_number].frequency_step, 1);                 \      }                                                                       \                                                                              \      timer[timer_number].count +=                                            \       (timer[timer_number].reload << timer[timer_number].prescale);          \    }                                                                         \  }                                                                           \u8 *file_ext[] = { ".gba", ".bin", ".zip", NULL };void init_main(){  u32 i;  skip_next_frame = 0;  for(i = 0; i < 4; i++)  {    dma[i].start_type = DMA_INACTIVE;    dma[i].direct_sound_channel = DMA_NO_DIRECT_SOUND;    timer[i].status = TIMER_INACTIVE;    timer[i].reload = 0x10000;    timer[i].stop_cpu_ticks = 0;  }  timer[0].direct_sound_channels = TIMER_DS_CHANNEL_BOTH;  timer[1].direct_sound_channels = TIMER_DS_CHANNEL_NONE;  cpu_ticks = 0;  frame_ticks = 0;  execute_cycles = 960;  video_count = 960;  flush_translation_cache_rom();  flush_translation_cache_ram();  flush_translation_cache_bios();}int main(int argc, char *argv[]){  u32 i;  u32 vcount = 0;  u32 ticks;  u32 dispstat;  u8 load_filename[512];#ifdef PSP_BUILD  sceKernelRegisterSubIntrHandler(PSP_VBLANK_INT, 0,   vblank_interrupt_handler, NULL);  sceKernelEnableSubIntr(PSP_VBLANK_INT, 0);#else  freopen("CON", "wb", stdout);#endif  init_gamepak_buffer();  // Copy the directory path of the executable into main_path  getcwd(main_path, 512);  load_config_file();  gamepak_filename[0] = 0;  if(load_bios("gba_bios.bin") == -1)  {#ifdef PSP_BUILD    gui_action_type gui_action = CURSOR_NONE;    printf("Sorry, but gpSP requires a Gameboy Advance BIOS image to run\n");    printf("correctly. Make sure to get an authentic one (search the web,\n");    printf("beg other people if you want, but don't hold me accountable\n");    printf("if you get hated or banned for it), it'll be exactly 16384\n");    printf("bytes large and should have the following md5sum value:\n\n");    printf("a860e8c0b6d573d191e4ec7db1b1e4f6\n\n");    printf("Other BIOS files might work either partially completely, I\n");    printf("really don't know.\n\n");    printf("When you do get it name it gba_bios.bin and put it in the\n");    printf("same directory as this EBOOT.\n\n");    printf("Good luck. Press any button to exit.\n");    while(gui_action == CURSOR_NONE)    {      gui_action = get_gui_input();      delay_us(15000);    }    quit();#endif  }#ifdef PSP_BUILD  delay_us(2500000);#endif  init_main();  init_sound();  init_video();  init_input();  video_resolution_large();  if(argc > 1)  {    if(load_gamepak(argv[1]) == -1)    {      printf("Failed to load gamepak %s, exiting.\n", load_filename);      exit(-1);    }    set_gba_resolution(screen_scale);    video_resolution_small();    init_cpu();    init_memory();  }  else  {    if(load_file(file_ext, load_filename) == -1)    {      menu(copy_screen());    }    else    {      if(load_gamepak(load_filename) == -1)      {        printf("Failed to load gamepak %s, exiting.\n", load_filename);        delay_us(5000000);        exit(-1);      }      set_gba_resolution(screen_scale);      video_resolution_small();      init_cpu();      init_memory();    }  }  last_frame = 0;  // We'll never actually return from here.#ifdef PSP_BUILD  execute_arm_translate(execute_cycles);#else  execute_arm_translate(execute_cycles);//  execute_arm(execute_cycles);#endif  return 0;}void print_memory_stats(u32 *counter, u32 *region_stats, u8 *stats_str){  u32 other_region_counter = region_stats[0x1] + region_stats[0xE] + region_stats[0xF];  u32 rom_region_counter = region_stats[0x8] + region_stats[0x9] + region_stats[0xA] +   region_stats[0xB] + region_stats[0xC] + region_stats[0xD];  u32 _counter = *counter;  printf("memory access stats: %s (out of %d)\n", stats_str, _counter);  printf("bios: %f%%\tiwram: %f%%\tewram: %f%%\tvram: %f\n",   region_stats[0x0] * 100.0 / _counter, region_stats[0x3] * 100.0 / _counter,   region_stats[0x2] * 100.0 / _counter, region_stats[0x6] * 100.0 / _counter);  printf("oam: %f%%\tpalette: %f%%\trom: %f%%\tother: %f%%\n",   region_stats[0x7] * 100.0 / _counter, region_stats[0x5] * 100.0 / _counter,   rom_region_counter * 100.0 / _counter, other_region_counter * 100.0 / _counter);  *counter = 0;  memset(region_stats, 0, sizeof(u32) * 16);}u32 update_gba(){  irq_type irq_raised = IRQ_NONE;  cpu_ticks += execute_cycles;  if(gbc_sound_update)  {    gbc_update_count++;    update_gbc_sound(cpu_ticks);    gbc_sound_update = 0;  }  update_timer(0);  update_timer(1);  update_timer(2);  update_timer(3);  video_count -= execute_cycles;  if(video_count <= 0)  {    u32 vcount = io_registers[REG_VCOUNT];    u32 dispstat = io_registers[REG_DISPSTAT];    if((dispstat & 0x02) == 0)    {      // Transition from hrefresh to hblank      video_count += 272;      dispstat |= 0x02;      if((dispstat & 0x01) == 0)      {        u32 i;        if(oam_update)          oam_update_count++;        update_scanline();        // If in visible area also fire HDMA        for(i = 0; i < 4; i++)        {          if(dma[i].start_type == DMA_START_HBLANK)            dma_transfer(dma + i);        }      }      if(dispstat & 0x10)        irq_raised |= IRQ_HBLANK;    }    else    {      // Transition from hblank to next line      video_count += 960;      dispstat &= ~0x02;      vcount++;      if(vcount == 160)      {        // Transition from vrefresh to vblank        u32 i;        dispstat |= 0x01;        if(dispstat & 0x8)        {          irq_raised |= IRQ_VBLANK;        }

⌨️ 快捷键说明

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