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

📄 memory.c

📁 psp上的GBA模拟器
💻 C
📖 第 1 页 / 共 5 页
字号:
  address32(palette_ram, palette_address) = value;                            \  convert_palette(value_high);                                                \  convert_palette(value_low);                                                 \  value = (value_high << 16) | value_low;                                     \  address32(palette_ram_converted, palette_address) = value;                  \}                                                                             \void function_cc write_backup(u32 address, u32 value){  value &= 0xFF;  if(backup_type == BACKUP_NONE)    backup_type = BACKUP_SRAM;  // gamepak SRAM or Flash ROM  if((address == 0x5555) && (flash_mode != FLASH_WRITE_MODE))  {    if((flash_command_position == 0) && (value == 0xAA))    {      backup_type = BACKUP_FLASH;      flash_command_position = 1;    }    if(flash_command_position == 2)    {      switch(value)      {        case 0x90:          // Enter ID mode, this also tells the emulator that we're using          // flash, not SRAM          if(flash_mode == FLASH_BASE_MODE)            flash_mode = FLASH_ID_MODE;          break;        case 0x80:          // Enter erase mode          if(flash_mode == FLASH_BASE_MODE)            flash_mode = FLASH_ERASE_MODE;          break;        case 0xF0:          // Terminate ID mode          if(flash_mode == FLASH_ID_MODE)            flash_mode = FLASH_BASE_MODE;          break;        case 0xA0:          // Write mode          if(flash_mode == FLASH_BASE_MODE)            flash_mode = FLASH_WRITE_MODE;          break;        case 0xB0:          // Bank switch          // Here the chip is now officially 128KB.          flash_size = FLASH_SIZE_128KB;          if(flash_mode == FLASH_BASE_MODE)            flash_mode = FLASH_BANKSWITCH_MODE;          break;        case 0x10:          // Erase chip          if(flash_mode == FLASH_ERASE_MODE)          {            if(flash_size == FLASH_SIZE_64KB)              memset(gamepak_backup, 0xFF, 1024 * 64);            else              memset(gamepak_backup, 0xFF, 1024 * 128);            backup_update = write_backup_delay;            flash_mode = FLASH_BASE_MODE;          }          break;        default:          break;      }      flash_command_position = 0;    }    if(backup_type == BACKUP_SRAM)      gamepak_backup[0x5555] = value;  }  else  if((address == 0x2AAA) && (value == 0x55) &&   (flash_command_position == 1))  {    flash_command_position = 2;  }  else  {    if((flash_command_position == 2) &&     (flash_mode == FLASH_ERASE_MODE) && (value == 0x30))    {      // Erase sector      memset(flash_bank_ptr + (address & 0xF000), 0xFF, 1024 * 4);      backup_update = write_backup_delay;      flash_mode = FLASH_BASE_MODE;      flash_command_position = 0;    }    else    if((flash_command_position == 0) &&     (flash_mode == FLASH_BANKSWITCH_MODE) && (address == 0x0000))    {      flash_bank_ptr = gamepak_backup + (value & 0x01) * (1024 * 64);      flash_mode = FLASH_BASE_MODE;    }    else    if((flash_command_position == 0) && (flash_mode == FLASH_WRITE_MODE))    {      // Write value to flash ROM      backup_update = write_backup_delay;      flash_bank_ptr[address] = value;      flash_mode = FLASH_BASE_MODE;    }    else    if(backup_type == BACKUP_SRAM)    {      // Write value to SRAM      backup_update = write_backup_delay;      // Hit 64KB territory?      if(address >= 0x8000)        sram_size = SRAM_SIZE_64KB;      gamepak_backup[address] = value;    }  }}#define write_backup8()                                                       \  write_backup(address & 0xFFFF, value)                                       \#define write_backup16()                                                      \#define write_backup32()                                                      \#define write_vram8()                                                         \  address &= ~0x01;                                                           \  address16(vram, address) = ((value << 8) | value)                           \#define write_vram16()                                                        \  address16(vram, address) = value                                            \#define write_vram32()                                                        \  address32(vram, address) = value                                            \// RTC code derived from VBA's (due to lack of any real publically available// documentation...)typedef enum{  RTC_DISABLED,  RTC_IDLE,  RTC_COMMAND,  RTC_OUTPUT_DATA,  RTC_INPUT_DATA} rtc_state_type;typedef enum{  RTC_COMMAND_RESET            = 0x60,  RTC_COMMAND_WRITE_STATUS     = 0x62,  RTC_COMMAND_READ_STATUS      = 0x63,  RTC_COMMAND_OUTPUT_TIME_FULL = 0x65,  RTC_COMMAND_OUTPUT_TIME      = 0x67} rtc_command_type;typedef enum{  RTC_WRITE_TIME,  RTC_WRITE_TIME_FULL,  RTC_WRITE_STATUS} rtc_write_mode_type;rtc_state_type rtc_state = RTC_DISABLED;rtc_write_mode_type rtc_write_mode;u8 rtc_registers[3];u32 rtc_command;u32 rtc_data[12];u32 rtc_status = 0x40;u32 rtc_data_bytes;s32 rtc_bit_count;u32 encode_bcd(u8 value){  return ((value / 10) << 4) | (value % 10);}#define write_rtc_register(index, _value)                                     \  update_address = 0x80000C4 + (index * 2);                                   \  rtc_registers[index] = _value;                                              \  rtc_page_index = update_address >> 15;                                      \  map = memory_map_read[rtc_page_index];                                      \                                                                              \  if(map == NULL)                                                             \    map = load_gamepak_page(rtc_page_index & 0x3FF);                          \                                                                              \  address16(map, update_address & 0x7FFF) = _value                            \void function_cc write_rtc(u32 address, u32 value){  u32 rtc_page_index;  u32 update_address;  u8 *map;  value &= 0xFFFF;  switch(address)  {    // RTC command    // Bit 0: SCHK, perform action    // Bit 1: IO, input/output command data    // Bit 2: CS, select input/output? If high make I/O write only    case 0xC4:      if(rtc_state == RTC_DISABLED)        rtc_state = RTC_IDLE;      if(!(rtc_registers[0] & 0x04))        value = (rtc_registers[0] & 0x02) | (value & ~0x02);      if(rtc_registers[2] & 0x01)      {        // To begin writing a command 1, 5 must be written to the command        // registers.        if((rtc_state == RTC_IDLE) && (rtc_registers[0] == 0x01) &&         (value == 0x05))        {          // We're now ready to begin receiving a command.          write_rtc_register(0, value);          rtc_state = RTC_COMMAND;          rtc_command = 0;          rtc_bit_count = 7;        }        else        {          write_rtc_register(0, value);          switch(rtc_state)          {            // Accumulate RTC command by receiving the next bit, and if we            // have accumulated enough bits to form a complete command            // execute it.            case RTC_COMMAND:              if(rtc_registers[0] & 0x01)              {                rtc_command |= ((value & 0x02) >> 1) << rtc_bit_count;                rtc_bit_count--;              }              // Have we received a full RTC command? If so execute it.              if(rtc_bit_count < 0)              {                switch(rtc_command)                {                  // Resets RTC                  case RTC_COMMAND_RESET:                    rtc_state = RTC_IDLE;                    memset(rtc_registers, 0, sizeof(rtc_registers));                    break;                  // Sets status of RTC                  case RTC_COMMAND_WRITE_STATUS:                    rtc_state = RTC_INPUT_DATA;                    rtc_data_bytes = 1;                    rtc_write_mode = RTC_WRITE_STATUS;                    break;                  // Outputs current status of RTC                  case RTC_COMMAND_READ_STATUS:                    rtc_state = RTC_OUTPUT_DATA;                    rtc_data_bytes = 1;                    rtc_data[0] = rtc_status;                    break;                  // Actually outputs the time, all of it                  case RTC_COMMAND_OUTPUT_TIME_FULL:                  {                    struct tm *current_time;                    time_t current_time_flat;                    u32 day_of_week;                    time(&current_time_flat);                    current_time = localtime(&current_time_flat);                    day_of_week = current_time->tm_wday;                    if(day_of_week == 0)                      day_of_week = 6;                    else                      day_of_week--;                    rtc_state = RTC_OUTPUT_DATA;                    rtc_data_bytes = 7;                    rtc_data[0] = encode_bcd(current_time->tm_year % 100);                    rtc_data[1] = encode_bcd(current_time->tm_mon + 1);                    rtc_data[2] = encode_bcd(current_time->tm_mday);                    rtc_data[3] = encode_bcd(day_of_week);                    rtc_data[4] = encode_bcd(current_time->tm_hour);                    rtc_data[5] = encode_bcd(current_time->tm_min);                    rtc_data[6] = encode_bcd(current_time->tm_sec);                    break;                  }                  // Only outputs the current time of day.                  case RTC_COMMAND_OUTPUT_TIME:                  {                    struct tm *current_time;                    time_t current_time_flat;                    time(&current_time_flat);                    current_time = localtime(&current_time_flat);                    rtc_state = RTC_OUTPUT_DATA;                    rtc_data_bytes = 3;                    rtc_data[0] = encode_bcd(current_time->tm_hour);                    rtc_data[1] = encode_bcd(current_time->tm_min);                    rtc_data[2] = encode_bcd(current_time->tm_sec);                    break;                  }                }                rtc_bit_count = 0;              }              break;            // Receive parameters from the game as input to the RTC            // for a given command. Read one bit at a time.            case RTC_INPUT_DATA:              // Bit 1 of parameter A must be high for input              if(rtc_registers[1] & 0x02)              {                // Read next bit for input                if(!(value & 0x01))                {                  rtc_data[rtc_bit_count >> 3] |=                   ((value & 0x01) << (7 - (rtc_bit_count & 0x07)));                }                else                {                  rtc_bit_count++;                  if(rtc_bit_count == (rtc_data_bytes * 8))                  {                    rtc_state = RTC_IDLE;                    switch(rtc_write_mode)                    {                      case RTC_WRITE_STATUS:                        rtc_status = rtc_data[0];                        break;                    }                  }                }              }              break;            case RTC_OUTPUT_DATA:              // Bit 1 of parameter A must be low for output              if(!(rtc_registers[1] & 0x02))              {                // Write next bit to output, on bit 1 of parameter B                if(!(value & 0x01))                {                  u8 current_output_byte = rtc_registers[2];                  current_output_byte =                   (current_output_byte & ~0x02) |                   (((rtc_data[rtc_bit_count >> 3] >>                   (rtc_bit_count & 0x07)) & 0x01) << 1);                  write_rtc_register(0, current_output_byte);                }                else                {                  rtc_bit_count++;                  if(rtc_bit_count == (rtc_data_bytes * 8))                  {                    rtc_state = RTC_IDLE;                    memset(rtc_registers, 0, sizeof(rtc_registers));                  }                }              }              break;          }        }      }      else      {        write_rtc_register(2, value);      }      break;    // Write parameter A    case 0xC6:      write_rtc_register(1, value);      break;    // Write parameter B    case 0xC8:      write_rtc_register(2, value);      break;  }}#define write_rtc8()                                                          \#define write_rtc16()                                                         \  write_rtc(address & 0xFF, value)                                            \#define write_rtc32()                                                         \#define write_memory(type)                                                    \  switch(address >> 24)                                                       \  {                                                                           \    case 0x02:                                                                \      /* external work RAM */                                                 \      address = (address & 0x7FFF) + ((address & 0x38000) * 2) + 0x8000;      \      address##type(ewram, address) = value;                                  \      break;                                                                  \                                                                              \    case 0x03:                                                                \      /* internal work RAM */                                                 \      address##type(iwram, (address & 0x7FFF) + 0x8000) = value;              \      break;                                                                  \                                                                              \    case 0x04:                                                                \      /* I/O registers */                                                     \      return write_io_register##type(address & 0x3FF, value);                 \                                                                              \    case 0x05:                                                                \      /* palette RAM */                                                       \      write_palette##type(address & 0x3FF, value);                            \

⌨️ 快捷键说明

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