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

📄 memory.c

📁 psp上的GBA模拟器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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"// This table is configured for sequential access on system defaultsu32 waitstate_cycles_sequential[16][3] ={  { 1, 1, 1 }, // BIOS  { 1, 1, 1 }, // Invalid  { 3, 3, 6 }, // EWRAM (default settings)  { 1, 1, 1 }, // IWRAM  { 1, 1, 1 }, // IO Registers  { 1, 1, 2 }, // Palette RAM  { 1, 1, 2 }, // VRAM  { 1, 1, 2 }, // OAM  { 3, 3, 6 }, // Gamepak (wait 0)  { 3, 3, 6 }, // Gamepak (wait 0)  { 5, 5, 9 }, // Gamepak (wait 1)  { 5, 5, 9 }, // Gamepak (wait 1)  { 9, 9, 17 }, // Gamepak (wait 2)  { 9, 9, 17 }, // Gamepak (wait 2)};// Different settings for gamepak ws0-2 sequential (2nd) accessu32 gamepak_waitstate_sequential[2][3][3] ={  {    { 3, 3, 6 },    { 5, 5, 9 },    { 9, 9, 17 }  },  {    { 2, 2, 3 },    { 2, 2, 3 },    { 2, 2, 3 }  }};#ifdef PSP_BUILD_VRAM_STORAGEu16 *palette_ram = (u16 *)(0x4000000 + (1024 * 32 * 15));u16 *palette_ram_converted = (u16 *)(0x4000000 + (1024 * 32 * 15) + 1024);u16 *oam_ram = (u16 *)(0x4000000 + (1024 * 32 * 15) + 1024 + 1024);u16 *io_registers = (u16 *)(0x4000000 + (1024 * 32 * 16));u8 *iwram = (u8 *)(0x4000000 + (1024 * 32 * 18));u8 *ewram = (u8 *)(0x4000000 + (1024 * 32 * 20));u8 *vram = (u8 *)(0x4000000 + (1024 * 32 * 36));#elseu16 palette_ram[512];u16 oam_ram[512];u16 palette_ram_converted[512];u16 io_registers[1024 * 16];u8 ewram[1024 * 256 * 2];u8 iwram[1024 * 32 * 2];u8 vram[1024 * 96 * 2];#endifu8 bios_rom[1024 * 32];u32 bios_read_protect;// Up to 128kb, store SRAM, flash ROM, or EEPROM here.u8 gamepak_backup[1024 * 128];// Keeps us knowing how much we have left.u8 *gamepak_rom;u32 gamepak_size;dma_transfer_type dma[4];u8 *memory_regions[16];u32 memory_limits[16];typedef struct{  u32 page_timestamp;  u32 physical_index;} gamepak_swap_entry_type;u32 gamepak_ram_buffer_size;u32 gamepak_ram_pages;// Enough to map the gamepak RAM space.gamepak_swap_entry_type *gamepak_memory_map;// This is global so that it can be kept open for large ROMs to swap// pages from, so there's no slowdown with opening and closing the file// a lot.#ifdef PSP_BUILDfile_tag_type gamepak_file_large = -1;#elsefile_tag_type gamepak_file_large = NULL;#endifu32 direct_map_vram = 0;// Writes to these respective locations should trigger an update// so the related subsystem may react to it.// If OAM is written to:u32 oam_update = 1;// If GBC audio is written to:u32 gbc_sound_update = 0;// If the GBC audio waveform is modified:u32 gbc_sound_wave_update = 0;// If the backup space is written (only update once this hits 0)u32 backup_update = 0;// Write out backup file this many cycles after the most recent// backup write.const u32 write_backup_delay = 10;typedef enum{  BACKUP_SRAM,  BACKUP_FLASH,  BACKUP_EEPROM,  BACKUP_NONE} backup_type_type;typedef enum{  SRAM_SIZE_32KB,  SRAM_SIZE_64KB} sram_size_type;// Keep it 32KB until the upper 64KB is accessed, then make it 64KB.backup_type_type backup_type = BACKUP_NONE;sram_size_type sram_size = SRAM_SIZE_32KB;typedef enum{  FLASH_BASE_MODE,  FLASH_ERASE_MODE,  FLASH_ID_MODE,  FLASH_WRITE_MODE,  FLASH_BANKSWITCH_MODE} flash_mode_type;typedef enum{  FLASH_SIZE_64KB,  FLASH_SIZE_128KB} flash_size_type;flash_mode_type flash_mode = FLASH_BASE_MODE;u32 flash_command_position = 0;u8 *flash_bank_ptr = gamepak_backup;flash_device_id_type flash_device_id = FLASH_DEVICE_MACRONIX_64KB;flash_manufacturer_id_type flash_manufacturer_id = FLASH_MANUFACTURER_MACRONIX;flash_size_type flash_size = FLASH_SIZE_64KB;u8 read_backup(u32 address){  u8 value;  if(backup_type == BACKUP_NONE)    backup_type = BACKUP_SRAM;  if(backup_type == BACKUP_SRAM)  {    value = gamepak_backup[address];  }  else  if(flash_mode == FLASH_ID_MODE)  {    /* ID manufacturer type */    if(address == 0x0000)      value = flash_manufacturer_id;    else    /* ID device type */    if(address == 0x0001)      value = flash_device_id;  }  else  {    value = flash_bank_ptr[address];  }  return value;}#define read_backup8()                                                        \  value = read_backup(address & 0xFFFF)                                       \#define read_backup16()                                                       \  value = 0                                                                   \#define read_backup32()                                                       \  value = 0                                                                   \// EEPROM is 512 bytes by default; it is autodetecte as 8KB if// 14bit address DMAs are made (this is done in the DMA handler).typedef enum{  EEPROM_512_BYTE,  EEPROM_8_KBYTE} eeprom_size_type;typedef enum{  EEPROM_BASE_MODE,  EEPROM_READ_MODE,  EEPROM_READ_HEADER_MODE,  EEPROM_ADDRESS_MODE,  EEPROM_WRITE_MODE,  EEPROM_WRITE_ADDRESS_MODE,  EEPROM_ADDRESS_FOOTER_MODE,  EEPROM_WRITE_FOOTER_MODE} eeprom_mode_type;eeprom_size_type eeprom_size = EEPROM_512_BYTE;eeprom_mode_type eeprom_mode = EEPROM_BASE_MODE;u32 eeprom_address_length;u32 eeprom_address = 0;s32 eeprom_counter = 0;u8 eeprom_buffer[8];void function_cc write_eeprom(u32 address, u32 value){  switch(eeprom_mode)  {    case EEPROM_BASE_MODE:      backup_type = BACKUP_EEPROM;      eeprom_buffer[0] |= (value & 0x01) << (1 - eeprom_counter);      eeprom_counter++;      if(eeprom_counter == 2)      {        if(eeprom_size == EEPROM_512_BYTE)          eeprom_address_length = 6;        else          eeprom_address_length = 14;        eeprom_counter = 0;        switch(eeprom_buffer[0] & 0x03)        {          case 0x02:            eeprom_mode = EEPROM_WRITE_ADDRESS_MODE;            break;          case 0x03:            eeprom_mode = EEPROM_ADDRESS_MODE;            break;        }        address16(eeprom_buffer, 0) = 0;      }      break;    case EEPROM_ADDRESS_MODE:    case EEPROM_WRITE_ADDRESS_MODE:      eeprom_buffer[eeprom_counter / 8]       |= (value & 0x01) << (7 - (eeprom_counter % 8));      eeprom_counter++;      if(eeprom_counter == eeprom_address_length)      {        if(eeprom_size == EEPROM_512_BYTE)        {          eeprom_address =           (address16(eeprom_buffer, 0) >> 2) * 8;        }        else        {          eeprom_address = (((u32)eeprom_buffer[1] >> 2) |           ((u32)eeprom_buffer[0] << 6)) * 8;        }        address16(eeprom_buffer, 0) = 0;        eeprom_counter = 0;        if(eeprom_mode == EEPROM_ADDRESS_MODE)        {          eeprom_mode = EEPROM_ADDRESS_FOOTER_MODE;        }        else        {          eeprom_mode = EEPROM_WRITE_MODE;          memset(gamepak_backup + eeprom_address, 0, 8);        }      }      break;    case EEPROM_WRITE_MODE:      gamepak_backup[eeprom_address + (eeprom_counter / 8)] |=       (value & 0x01) << (7 - (eeprom_counter % 8));      eeprom_counter++;      if(eeprom_counter == 64)      {        backup_update = write_backup_delay;        eeprom_counter = 0;        eeprom_mode = EEPROM_WRITE_FOOTER_MODE;      }      break;    case EEPROM_ADDRESS_FOOTER_MODE:    case EEPROM_WRITE_FOOTER_MODE:      eeprom_counter = 0;      if(eeprom_mode == EEPROM_ADDRESS_FOOTER_MODE)      {        eeprom_mode = EEPROM_READ_HEADER_MODE;      }      else      {        eeprom_mode = EEPROM_BASE_MODE;      }      break;  }}#define read_memory_gamepak(type)                                             \  u32 gamepak_index = address >> 15;                                          \  u8 *map = memory_map_read[gamepak_index];                                   \                                                                              \  if(map == NULL)                                                             \    map = load_gamepak_page(gamepak_index & 0x3FF);                           \                                                                              \  value = address##type(map, address & 0x7FFF)                                \#define read_open8()                                                          \  if(!(reg[REG_CPSR] & 0x20))                                                 \    value = read_memory8(reg[REG_PC] + 4 + (address & 0x03));                 \  else                                                                        \    value = read_memory8(reg[REG_PC] + 2 + (address & 0x01))                  \#define read_open16()                                                         \  if(!(reg[REG_CPSR] & 0x20))                                                 \    value = read_memory16(reg[REG_PC] + 4 + (address & 0x02));                \  else                                                                        \    value = read_memory16(reg[REG_PC] + 2)                                    \#define read_open32()                                                         \  if(!(reg[REG_CPSR] & 0x20))                                                 \  {                                                                           \    value = read_memory32(reg[REG_PC] + 4);                                   \  }                                                                           \  else                                                                        \  {                                                                           \    u32 current_instruction = read_memory16(reg[REG_PC] + 2);                 \    value = current_instruction | (current_instruction << 16);                \  }                                                                           \u32 function_cc read_eeprom(){  u32 value;  switch(eeprom_mode)  {    case EEPROM_BASE_MODE:      value = 1;      break;    case EEPROM_READ_MODE:      value = (gamepak_backup[eeprom_address + (eeprom_counter / 8)] >>       (7 - (eeprom_counter % 8))) & 0x01;      eeprom_counter++;      if(eeprom_counter == 64)      {        eeprom_counter = 0;        eeprom_mode = EEPROM_BASE_MODE;      }      break;    case EEPROM_READ_HEADER_MODE:      value = 0;      eeprom_counter++;      if(eeprom_counter == 4)      {        eeprom_mode = EEPROM_READ_MODE;        eeprom_counter = 0;      }      break;    default:      value = 0;      break;  }  return value;}#define read_memory(type)                                                     \  switch(address >> 24)                                                       \  {                                                                           \    case 0x00:                                                                \      /* BIOS */                                                              \      if(reg[REG_PC] >= 0x4000)                                               \        value = address##type(&bios_read_protect, address & 0x03);            \      else                                                                    \        value = address##type(bios_rom, address & 0x3FFF);                    \      break;                                                                  \                                                                              \    case 0x02:                                                                \      /* external work RAM */                                                 \      address = (address & 0x7FFF) + ((address & 0x38000) * 2) + 0x8000;      \

⌨️ 快捷键说明

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