Simplify I/O byte writes
Can easily be mapped to 16 bit writes.
This commit is contained in:
		
							parent
							
								
									2d28451f6c
								
							
						
					
					
						commit
						a53399af58
					
				
					 1 changed files with 18 additions and 399 deletions
				
			
		
							
								
								
									
										417
									
								
								gba_memory.c
									
										
									
									
									
								
							
							
						
						
									
										417
									
								
								gba_memory.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -719,402 +719,12 @@ static cpu_alert_type trigger_dma(u32 dma_number, u32 value)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define access_register8_high(address)                                        \
 | 
			
		||||
  value = (value << 8) | (address8(io_registers, address))                    \
 | 
			
		||||
 | 
			
		||||
#define access_register8_low(address)                                         \
 | 
			
		||||
  value = ((address8(io_registers, address + 1)) << 8) | value                \
 | 
			
		||||
 | 
			
		||||
#define access_register16_high(address)                                       \
 | 
			
		||||
  value = (value << 16) | (readaddress16(io_registers, address))              \
 | 
			
		||||
 | 
			
		||||
#define access_register16_low(address)                                        \
 | 
			
		||||
  value = ((readaddress16(io_registers, address + 2)) << 16) | value          \
 | 
			
		||||
 | 
			
		||||
cpu_alert_type function_cc write_io_register8(u32 address, u32 value)
 | 
			
		||||
{
 | 
			
		||||
  value &= 0xff;
 | 
			
		||||
  switch(address)
 | 
			
		||||
  {
 | 
			
		||||
    case 0x00:
 | 
			
		||||
    {
 | 
			
		||||
      u32 dispcnt = read_ioreg(REG_DISPCNT);
 | 
			
		||||
 | 
			
		||||
      if((value & 0x07) != (dispcnt & 0x07))
 | 
			
		||||
        reg[OAM_UPDATED] = 1;
 | 
			
		||||
 | 
			
		||||
      address8(io_registers, 0x00) = value;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // DISPSTAT (lower byte)
 | 
			
		||||
    case 0x04:
 | 
			
		||||
      address8(io_registers, 0x04) =
 | 
			
		||||
       (address8(io_registers, 0x04) & 0x07) | (value & ~0x07);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // VCOUNT
 | 
			
		||||
    case 0x06:
 | 
			
		||||
    case 0x07:
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // BG2 reference X
 | 
			
		||||
    case 0x28:
 | 
			
		||||
      access_register8_low(0x28);
 | 
			
		||||
      access_register16_low(0x28);
 | 
			
		||||
      affine_reference_x[0] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x28) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x29:
 | 
			
		||||
      access_register8_high(0x28);
 | 
			
		||||
      access_register16_low(0x28);
 | 
			
		||||
      affine_reference_x[0] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x28) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x2A:
 | 
			
		||||
      access_register8_low(0x2A);
 | 
			
		||||
      access_register16_high(0x28);
 | 
			
		||||
      affine_reference_x[0] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x28) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x2B:
 | 
			
		||||
      access_register8_high(0x2A);
 | 
			
		||||
      access_register16_high(0x28);
 | 
			
		||||
      affine_reference_x[0] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x28) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // BG2 reference Y
 | 
			
		||||
    case 0x2C:
 | 
			
		||||
      access_register8_low(0x2C);
 | 
			
		||||
      access_register16_low(0x2C);
 | 
			
		||||
      affine_reference_y[0] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x2C) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x2D:
 | 
			
		||||
      access_register8_high(0x2C);
 | 
			
		||||
      access_register16_low(0x2C);
 | 
			
		||||
      affine_reference_y[0] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x2C) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x2E:
 | 
			
		||||
      access_register8_low(0x2E);
 | 
			
		||||
      access_register16_high(0x2C);
 | 
			
		||||
      affine_reference_y[0] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x2C) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x2F:
 | 
			
		||||
      access_register8_high(0x2E);
 | 
			
		||||
      access_register16_high(0x2C);
 | 
			
		||||
      affine_reference_y[0] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x2C) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // BG3 reference X
 | 
			
		||||
    case 0x38:
 | 
			
		||||
      access_register8_low(0x38);
 | 
			
		||||
      access_register16_low(0x38);
 | 
			
		||||
      affine_reference_x[1] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x38) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x39:
 | 
			
		||||
      access_register8_high(0x38);
 | 
			
		||||
      access_register16_low(0x38);
 | 
			
		||||
      affine_reference_x[1] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x38) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x3A:
 | 
			
		||||
      access_register8_low(0x3A);
 | 
			
		||||
      access_register16_high(0x38);
 | 
			
		||||
      affine_reference_x[1] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x38) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x3B:
 | 
			
		||||
      access_register8_high(0x3A);
 | 
			
		||||
      access_register16_high(0x38);
 | 
			
		||||
      affine_reference_x[1] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x38) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // BG3 reference Y
 | 
			
		||||
    case 0x3C:
 | 
			
		||||
      access_register8_low(0x3C);
 | 
			
		||||
      access_register16_low(0x3C);
 | 
			
		||||
      affine_reference_y[1] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x3C) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x3D:
 | 
			
		||||
      access_register8_high(0x3C);
 | 
			
		||||
      access_register16_low(0x3C);
 | 
			
		||||
      affine_reference_y[1] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x3C) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x3E:
 | 
			
		||||
      access_register8_low(0x3E);
 | 
			
		||||
      access_register16_high(0x3C);
 | 
			
		||||
      affine_reference_y[1] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x3C) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x3F:
 | 
			
		||||
      access_register8_high(0x3E);
 | 
			
		||||
      access_register16_high(0x3C);
 | 
			
		||||
      affine_reference_y[1] = (s32)(value << 4) >> 4;
 | 
			
		||||
      address32(io_registers, 0x3C) = eswap32(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 1 control sweep
 | 
			
		||||
    case 0x60:
 | 
			
		||||
      gbc_sound_tone_control_sweep();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 1 control duty/length/envelope
 | 
			
		||||
    case 0x62:
 | 
			
		||||
      access_register8_low(0x62);
 | 
			
		||||
      gbc_sound_tone_control_low(0, REG_SOUND1CNT_H);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x63:
 | 
			
		||||
      access_register8_high(0x62);
 | 
			
		||||
      gbc_sound_tone_control_low(0, REG_SOUND1CNT_H);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 1 control frequency
 | 
			
		||||
    case 0x64:
 | 
			
		||||
      access_register8_low(0x64);
 | 
			
		||||
      gbc_sound_tone_control_high(0, REG_SOUND1CNT_X);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x65:
 | 
			
		||||
      access_register8_high(0x64);
 | 
			
		||||
      gbc_sound_tone_control_high(0, REG_SOUND1CNT_X);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 2 control duty/length/envelope
 | 
			
		||||
    case 0x68:
 | 
			
		||||
      access_register8_low(0x68);
 | 
			
		||||
      gbc_sound_tone_control_low(1, REG_SOUND2CNT_L);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x69:
 | 
			
		||||
      access_register8_high(0x68);
 | 
			
		||||
      gbc_sound_tone_control_low(1, REG_SOUND2CNT_L);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 2 control frequency
 | 
			
		||||
    case 0x6C:
 | 
			
		||||
      access_register8_low(0x6C);
 | 
			
		||||
      gbc_sound_tone_control_high(1, REG_SOUND2CNT_H);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x6D:
 | 
			
		||||
      access_register8_high(0x6C);
 | 
			
		||||
      gbc_sound_tone_control_high(1, REG_SOUND2CNT_H);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 3 control wave
 | 
			
		||||
    case 0x70:
 | 
			
		||||
      access_register8_low(0x70);
 | 
			
		||||
      gbc_sound_wave_control();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x71:
 | 
			
		||||
      access_register8_high(0x70);
 | 
			
		||||
      gbc_sound_wave_control();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 3 control length/volume
 | 
			
		||||
    case 0x72:
 | 
			
		||||
      access_register8_low(0x72);
 | 
			
		||||
      gbc_sound_tone_control_low_wave();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x73:
 | 
			
		||||
      access_register8_high(0x72);
 | 
			
		||||
      gbc_sound_tone_control_low_wave();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 3 control frequency
 | 
			
		||||
    case 0x74:
 | 
			
		||||
      access_register8_low(0x74);
 | 
			
		||||
      gbc_sound_tone_control_high_wave();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x75:
 | 
			
		||||
      access_register8_high(0x74);
 | 
			
		||||
      gbc_sound_tone_control_high_wave();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 4 control length/envelope
 | 
			
		||||
    case 0x78:
 | 
			
		||||
      access_register8_low(0x78);
 | 
			
		||||
      gbc_sound_tone_control_low(3, REG_SOUND4CNT_L);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x79:
 | 
			
		||||
      access_register8_high(0x78);
 | 
			
		||||
      gbc_sound_tone_control_low(3, REG_SOUND4CNT_L);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound 4 control frequency
 | 
			
		||||
    case 0x7C:
 | 
			
		||||
      access_register8_low(0x7C);
 | 
			
		||||
      gbc_sound_noise_control();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x7D:
 | 
			
		||||
      access_register8_high(0x7C);
 | 
			
		||||
      gbc_sound_noise_control();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound control L
 | 
			
		||||
    case 0x80:
 | 
			
		||||
      access_register8_low(0x80);
 | 
			
		||||
      gbc_trigger_sound(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x81:
 | 
			
		||||
      access_register8_high(0x80);
 | 
			
		||||
      gbc_trigger_sound(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound control H
 | 
			
		||||
    case 0x82:
 | 
			
		||||
      access_register8_low(0x82);
 | 
			
		||||
      trigger_sound();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x83:
 | 
			
		||||
      access_register8_high(0x82);
 | 
			
		||||
      trigger_sound();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound control X
 | 
			
		||||
    case 0x84:
 | 
			
		||||
      sound_control_x(value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Sound wave RAM
 | 
			
		||||
    case 0x90 ... 0x9F:
 | 
			
		||||
      gbc_sound_wave_update = 1;
 | 
			
		||||
      address8(io_registers, address) = value;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // DMA control (trigger byte)
 | 
			
		||||
    case 0xBB:
 | 
			
		||||
      access_register8_low(0xBA);
 | 
			
		||||
      return trigger_dma(0, value);
 | 
			
		||||
 | 
			
		||||
    case 0xC7:
 | 
			
		||||
      access_register8_low(0xC6);
 | 
			
		||||
      return trigger_dma(1, value);
 | 
			
		||||
 | 
			
		||||
    case 0xD3:
 | 
			
		||||
      access_register8_low(0xD2);
 | 
			
		||||
      return trigger_dma(2, value);
 | 
			
		||||
 | 
			
		||||
    case 0xDF:
 | 
			
		||||
      access_register8_low(0xDE);
 | 
			
		||||
      return trigger_dma(3, value);
 | 
			
		||||
 | 
			
		||||
    // Timer counts
 | 
			
		||||
    case 0x100:
 | 
			
		||||
      access_register8_low(0x100);
 | 
			
		||||
      count_timer(0);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x101:
 | 
			
		||||
      access_register8_high(0x100);
 | 
			
		||||
      count_timer(0);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x104:
 | 
			
		||||
      access_register8_low(0x104);
 | 
			
		||||
      count_timer(1);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x105:
 | 
			
		||||
      access_register8_high(0x104);
 | 
			
		||||
      count_timer(1);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x108:
 | 
			
		||||
      access_register8_low(0x108);
 | 
			
		||||
      count_timer(2);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x109:
 | 
			
		||||
      access_register8_high(0x108);
 | 
			
		||||
      count_timer(2);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x10C:
 | 
			
		||||
      access_register8_low(0x10C);
 | 
			
		||||
      count_timer(3);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x10D:
 | 
			
		||||
      access_register8_high(0x10C);
 | 
			
		||||
      count_timer(3);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Timer control (trigger byte)
 | 
			
		||||
    case 0x103:
 | 
			
		||||
      access_register8_low(0x102);
 | 
			
		||||
      trigger_timer(0, value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x107:
 | 
			
		||||
      access_register8_low(0x106);
 | 
			
		||||
      trigger_timer(1, value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x10B:
 | 
			
		||||
      access_register8_low(0x10A);
 | 
			
		||||
      trigger_timer(2, value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x10F:
 | 
			
		||||
      access_register8_low(0x10E);
 | 
			
		||||
      trigger_timer(3, value);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // IF
 | 
			
		||||
    case 0x202:
 | 
			
		||||
      address8(io_registers, 0x202) &= ~value;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 0x203:
 | 
			
		||||
      address8(io_registers, 0x203) &= ~value;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    // Halt
 | 
			
		||||
    case 0x301:
 | 
			
		||||
      if((value & 0x01) == 0)
 | 
			
		||||
        reg[CPU_HALT_STATE] = CPU_HALT;
 | 
			
		||||
      else
 | 
			
		||||
        reg[CPU_HALT_STATE] = CPU_STOP;
 | 
			
		||||
 | 
			
		||||
      return CPU_ALERT_HALT;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      address8(io_registers, address) = value;
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return CPU_ALERT_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cpu_alert_type function_cc write_io_register16(u32 address, u32 value)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1338,15 +948,6 @@ cpu_alert_type function_cc write_io_register16(u32 address, u32 value)
 | 
			
		|||
      write_ioreg(REG_IME, value);
 | 
			
		||||
      return check_interrupt();
 | 
			
		||||
 | 
			
		||||
    // Halt
 | 
			
		||||
    case 0x300:
 | 
			
		||||
      if(((value >> 8) & 0x01) == 0)
 | 
			
		||||
        reg[CPU_HALT_STATE] = CPU_HALT;
 | 
			
		||||
      else
 | 
			
		||||
        reg[CPU_HALT_STATE] = CPU_STOP;
 | 
			
		||||
 | 
			
		||||
      return CPU_ALERT_HALT;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      address16(io_registers, address) = eswap16(value);
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1355,6 +956,24 @@ cpu_alert_type function_cc write_io_register16(u32 address, u32 value)
 | 
			
		|||
  return CPU_ALERT_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cpu_alert_type function_cc write_io_register8(u32 address, u32 value)
 | 
			
		||||
{
 | 
			
		||||
  if (address == 0x301) {
 | 
			
		||||
    if (value & 1)
 | 
			
		||||
      reg[CPU_HALT_STATE] = CPU_STOP;
 | 
			
		||||
    else
 | 
			
		||||
      reg[CPU_HALT_STATE] = CPU_HALT;
 | 
			
		||||
    return CPU_ALERT_HALT;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Partial 16 bit write, treat like a regular merge-write
 | 
			
		||||
  if (address & 1)
 | 
			
		||||
    value = (value << 8) | (read_ioreg((address >> 1) & 0x1FF) & 0x00ff);
 | 
			
		||||
  else
 | 
			
		||||
    value = (value & 0xff) | (read_ioreg((address >> 1) & 0x1FF) & 0xff00);
 | 
			
		||||
  return write_io_register16(address & 0x3FE, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cpu_alert_type function_cc write_io_register32(u32 address, u32 value)
 | 
			
		||||
{
 | 
			
		||||
  // Handle sound FIFO data write
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue