// license:LGPL-2.1+
// copyright-holders:Olivier Galibert, Angelo Salese, David Haywood, Tomasz Slanina
/***************************************************************************
Seibu Cop (Co-Processor) emulation
(new implementation, based on Raiden 2 code)
***************************************************************************/
#ifndef RAIDEN2COP_H
#define RAIDEN2COP_H
#define MCFG_RAIDEN2COP_VIDEORAM_OUT_CB(_devcb) \
devcb = &raiden2cop_device::set_m_videoramout_cb(*device, DEVCB_##_devcb);
#define MCFG_ITOA_UNUSED_DIGIT_VALUE(value) \
raiden2cop_device::set_itoa_unused_digit_value(*device, value);
#define MCFG_CPU_IS_68K(value) \
raiden2cop_device::set_cpu_is_68k(*device, value);
#define MCFG_RAIDEN2COP_ADD(_tag ) \
MCFG_DEVICE_ADD(_tag, RAIDEN2COP, 0) \
MCFG_CPU_IS_68K(0)
#define MCFG_LEGIONNACOP_ADD(_tag ) \
MCFG_DEVICE_ADD(_tag, RAIDEN2COP, 0) \
MCFG_CPU_IS_68K(1)
class raiden2cop_device : public device_t
{
public:
raiden2cop_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// Command Table
UINT16 cop_func_trigger[0x100/8]; /* function trigger */
UINT16 cop_func_value[0x100/8]; /* function value (?) */
UINT16 cop_func_mask[0x100/8]; /* function mask (?) */
UINT16 cop_program[0x100]; /* program "code" */
UINT16 cop_latch_addr, cop_latch_trigger, cop_latch_value, cop_latch_mask;
DECLARE_WRITE16_MEMBER( cop_pgm_data_w );
DECLARE_WRITE16_MEMBER( cop_pgm_addr_w );
DECLARE_WRITE16_MEMBER( cop_pgm_value_w );
DECLARE_WRITE16_MEMBER( cop_pgm_mask_w );
DECLARE_WRITE16_MEMBER( cop_pgm_trigger_w );
// these are used by legionna.c to find the command based on trigger value
// legionna/seicop implementation then looks up the command based on hardcoded sequences in the driver rather than actually using the trigger value (should be changed)
UINT16 get_func_value(int command) { return cop_func_value[command]; }
UINT16 get_func_mask(int command) { return cop_func_mask[command]; }
int find_trigger_match(UINT16 triggerval, UINT16 mask);
int check_command_matches(int command, UINT16 seq0, UINT16 seq1, UINT16 seq2, UINT16 seq3, UINT16 seq4, UINT16 seq5, UINT16 seq6, UINT16 seq7, UINT16 _funcval_, UINT16 _funcmask_);
// DMA
UINT16 cop_dma_v1, cop_dma_v2, cop_dma_mode;
UINT16 cop_dma_src[0x200], cop_dma_dst[0x200], cop_dma_size[0x200];
UINT16 cop_dma_adr_rel;
UINT16 pal_brightness_val;
UINT16 pal_brightness_mode;
DECLARE_WRITE16_MEMBER( cop_dma_v1_w );
DECLARE_WRITE16_MEMBER( cop_dma_v2_w );
DECLARE_WRITE16_MEMBER( cop_dma_adr_rel_w );
DECLARE_WRITE16_MEMBER( cop_dma_src_w );
DECLARE_WRITE16_MEMBER( cop_dma_size_w );
DECLARE_WRITE16_MEMBER( cop_dma_dst_w );
DECLARE_READ16_MEMBER( cop_dma_mode_r );
DECLARE_WRITE16_MEMBER( cop_dma_mode_w );
DECLARE_WRITE16_MEMBER( cop_pal_brightness_val_w );
DECLARE_WRITE16_MEMBER( cop_pal_brightness_mode_w );
DECLARE_WRITE16_MEMBER ( cop_dma_trigger_w );
UINT8 fade_table(int v);
template<class _Object> static devcb_base &set_m_videoramout_cb(device_t &device, _Object object) { return downcast<raiden2cop_device &>(device).m_videoramout_cb.set_callback(object); }
// Number Conversion
DECLARE_WRITE16_MEMBER( cop_itoa_low_w );
DECLARE_WRITE16_MEMBER( cop_itoa_high_w );
DECLARE_WRITE16_MEMBER( cop_itoa_digit_count_w );
DECLARE_READ16_MEMBER ( cop_itoa_digits_r );
UINT32 cop_itoa;
UINT16 cop_itoa_digit_count;
UINT8 cop_itoa_digits[10];
UINT8 m_cop_itoa_unused_digit_value;
static void set_itoa_unused_digit_value(device_t &device, int value) { downcast<raiden2cop_device &>(device).m_cop_itoa_unused_digit_value = value; }
// Main COP functionality
DECLARE_WRITE16_MEMBER( cop_scale_w );
DECLARE_WRITE16_MEMBER( cop_angle_target_w );
DECLARE_WRITE16_MEMBER( cop_angle_step_w );
DECLARE_READ16_MEMBER ( cop_reg_high_r );
DECLARE_WRITE16_MEMBER( cop_reg_high_w );
DECLARE_READ16_MEMBER ( cop_reg_low_r );
DECLARE_WRITE16_MEMBER( cop_reg_low_w );
DECLARE_WRITE16_MEMBER( cop_cmd_w );
DECLARE_READ16_MEMBER ( cop_collision_status_r );
DECLARE_READ16_MEMBER (cop_collision_status_val_r);
DECLARE_READ16_MEMBER (cop_collision_status_stat_r);
DECLARE_READ16_MEMBER ( cop_status_r );
DECLARE_READ16_MEMBER ( cop_dist_r );
DECLARE_READ16_MEMBER ( cop_angle_r );
DECLARE_WRITE16_MEMBER( cop_angle_compare_w );
DECLARE_WRITE16_MEMBER( cop_angle_mod_val_w );
DECLARE_WRITE16_MEMBER(cop_hitbox_baseadr_w);
UINT32 cop_regs[8];
UINT16 cop_status, cop_scale, cop_angle, cop_dist;
UINT16 cop_angle_target;
UINT16 cop_angle_step;
struct colinfo {
colinfo()
{
pos[0] = pos[1] = pos[2] = 0;
dx[0] = dx[1] = dx[2] = 0;
size[0] = size[1] = size[2] = 0;
allow_swap = false;
flags_swap = 0;
spradr = 0;
min[0] = min[1] = min[2] = 0;
max[0] = max[1] = max[2] = 0;
}
INT16 pos[3];
INT8 dx[3];
UINT8 size[3];
bool allow_swap;
UINT16 flags_swap;
UINT32 spradr;
INT16 min[3], max[3];
};
colinfo cop_collision_info[2];
UINT16 cop_hit_status, cop_hit_baseadr;
INT16 cop_hit_val[3];
UINT16 cop_hit_val_stat;
void cop_collision_read_pos(address_space &space, int slot, UINT32 spradr, bool allow_swap);
void execute_8100(address_space &space, int offset, UINT16 data);
void execute_8900(address_space &space, int offset, UINT16 data);
void execute_42c2(address_space &space, int offset, UINT16 data);
void execute_4aa0(address_space &space, int offset, UINT16 data);
void execute_6200(address_space &space, int offset, UINT16 data);
void execute_338e(address_space &space, int offset, UINT16 data);
void execute_2288(address_space &space, int offset, UINT16 data);
void execute_0205(address_space &space, int offset, UINT16 data);
void execute_3b30(address_space &space, int offset, UINT16 data);
void execute_130e(address_space &space, int offset, UINT16 data);
void execute_0904(address_space &space, int offset, UINT16 data);
void execute_2a05(address_space &space, int offset, UINT16 data);
void execute_7e05(address_space &space, int offset, UINT16 data);
void execute_5205(address_space &space, int offset, UINT16 data);
void execute_5a05(address_space &space, int offset, UINT16 data);
void execute_f205(address_space &space, int offset, UINT16 data);
void execute_a100(address_space &space, int offset, UINT16 data);
void execute_a900(address_space &space, int offset, UINT16 data);
void execute_b100(address_space &space, int offset, UINT16 data);
void execute_b900(address_space &space, int offset, UINT16 data);
void LEGACY_execute_130e(address_space &space, int offset, UINT16 data);
void LEGACY_execute_130e_cupsoc(address_space &space, int offset, UINT16 data);
void LEGACY_execute_3b30(address_space &space, int offset, UINT16 data);
void LEGACY_execute_42c2(address_space &space, int offset, UINT16 data);
void LEGACY_execute_e30e(address_space &space, int offset, UINT16 data);
void LEGACY_execute_6200(address_space &space, int offset, UINT16 data);
void LEGACY_execute_dde5(address_space &space, int offset, UINT16 data);
void LEGACY_execute_d104(address_space &space, int offset, UINT16 data);
void LEGACY_execute_6980(address_space &space, int offset, UINT16 data);
void LEGACY_execute_c480(address_space &space, int offset, UINT16 data);
// Sort DMA (zeroteam, cupsoc)
UINT32 cop_sort_ram_addr, cop_sort_lookup;
UINT16 cop_sort_param;
DECLARE_WRITE16_MEMBER(cop_sort_lookup_hi_w);
DECLARE_WRITE16_MEMBER(cop_sort_lookup_lo_w);
DECLARE_WRITE16_MEMBER(cop_sort_ram_addr_hi_w);
DECLARE_WRITE16_MEMBER(cop_sort_ram_addr_lo_w);
DECLARE_WRITE16_MEMBER(cop_sort_param_w);
DECLARE_WRITE16_MEMBER(cop_sort_dma_trig_w);
// RNG (cupsoc)
UINT16 m_cop_rng_max_value;
DECLARE_READ16_MEMBER(cop_prng_r);
DECLARE_WRITE16_MEMBER(cop_prng_maxvalue_w);
DECLARE_READ16_MEMBER(cop_prng_maxvalue_r);
// misc 68k (grainbow)
UINT32 m_cop_sprite_dma_param;
UINT32 m_cop_sprite_dma_src;
DECLARE_WRITE16_MEMBER(cop_sprite_dma_param_hi_w);
DECLARE_WRITE16_MEMBER(cop_sprite_dma_param_lo_w);
DECLARE_WRITE16_MEMBER(cop_sprite_dma_size_w);
DECLARE_WRITE16_MEMBER(cop_sprite_dma_src_hi_w);
DECLARE_WRITE16_MEMBER(cop_sprite_dma_src_lo_w);
DECLARE_WRITE16_MEMBER(cop_sprite_dma_inc_w);
int m_cop_sprite_dma_size;
// misc 68k
UINT16 m_cop_rom_addr_lo,m_cop_rom_addr_hi,m_cop_rom_addr_unk;
DECLARE_WRITE16_MEMBER(cop_rom_addr_unk_w);
DECLARE_WRITE16_MEMBER(cop_rom_addr_lo_w);
DECLARE_WRITE16_MEMBER(cop_rom_addr_hi_w);
int m_cop_sprite_dma_abs_x,m_cop_sprite_dma_abs_y;
DECLARE_WRITE16_MEMBER(cop_sprite_dma_abs_y_w);
DECLARE_WRITE16_MEMBER(cop_sprite_dma_abs_x_w);
// legacy code, to be removed / refactored into above
int m_LEGACY_r0, m_LEGACY_r1;
DECLARE_WRITE16_MEMBER(LEGACY_cop_cmd_w);
void cop_collision_update_hitbox(address_space &space, UINT16 data, int slot, UINT32 hitadr);
// endian stuff?
int m_cpu_is_68k;
static void set_cpu_is_68k(device_t &device, int value) { downcast<raiden2cop_device &>(device).m_cpu_is_68k = value; }
UINT16 cop_read_word(address_space &space, int address);
UINT8 cop_read_byte(address_space &space, int address);
void cop_write_word(address_space &space, int address, UINT16 data);
void cop_write_byte(address_space &space, int address, UINT8 data);
// DEBUG
void dump_table();
protected:
// device-level overrides
virtual void device_start();
private:
// internal state
devcb_write16 m_videoramout_cb;
required_device<palette_device> m_palette;
};
extern const device_type RAIDEN2COP;
#endif /* RAIDEN2COP_H */