diff options
Diffstat (limited to 'src/mame/machine/konppc.c')
-rw-r--r-- | src/mame/machine/konppc.c | 697 |
1 files changed, 697 insertions, 0 deletions
diff --git a/src/mame/machine/konppc.c b/src/mame/machine/konppc.c new file mode 100644 index 00000000000..ba8625d632b --- /dev/null +++ b/src/mame/machine/konppc.c @@ -0,0 +1,697 @@ +/* Konami PowerPC-based 3D games common functions */ + +#include "driver.h" +#include "cpu/sharc/sharc.h" +#include "video/voodoo.h" +#include "konppc.h" + +#define MAX_CG_BOARDS 2 + +static UINT32 dsp_comm_ppc[MAX_CG_BOARDS][2]; +static UINT32 dsp_comm_sharc[MAX_CG_BOARDS][2]; +static int dsp_shared_ram_bank[MAX_CG_BOARDS]; + +static int cgboard_id; +static int cgboard_type; +static int num_cgboards; + +static UINT32 *dsp_shared_ram[MAX_CG_BOARDS]; + +#define DSP_BANK_SIZE 0x10000 +#define DSP_BANK_SIZE_WORD (DSP_BANK_SIZE / 4) + +static UINT32 dsp_state[MAX_CG_BOARDS]; +static UINT32 pci_bridge_enable[MAX_CG_BOARDS]; +static UINT32 nwk_device_sel[MAX_CG_BOARDS]; +static int texture_bank[MAX_CG_BOARDS]; + +static int nwk_fifo_half_full_r; +static int nwk_fifo_half_full_w; +static int nwk_fifo_full; +static int nwk_fifo_mask; + + +static UINT32 *nwk_fifo[MAX_CG_BOARDS]; +static int nwk_fifo_read_ptr[MAX_CG_BOARDS]; +static int nwk_fifo_write_ptr[MAX_CG_BOARDS]; + +static UINT32 *nwk_ram[MAX_CG_BOARDS]; + +/*****************************************************************************/ + +void init_konami_cgboard(int num_boards, int type) +{ + int i; + num_cgboards = num_boards; + + for (i=0; i < num_boards; i++) + { + dsp_comm_ppc[i][0] = 0x00; + dsp_shared_ram[i] = auto_malloc(DSP_BANK_SIZE * 2); + dsp_shared_ram_bank[i] = 0; + + dsp_state[i] = 0x80; + texture_bank[i] = -1; + + pci_bridge_enable[i] = 0; + nwk_device_sel[i] = 0; + nwk_fifo_read_ptr[i] = 0; + nwk_fifo_write_ptr[i] = 0; + + nwk_fifo[i] = auto_malloc(sizeof(UINT32) * 0x800); + nwk_ram[i] = auto_malloc(sizeof(UINT32) * 0x2000); + } + cgboard_type = type; + + if (type == CGBOARD_TYPE_NWKTR) + { + nwk_fifo_half_full_r = 0x100; + nwk_fifo_half_full_w = 0xff; + nwk_fifo_full = 0x1ff; + nwk_fifo_mask = 0x1ff; + } + if (type == CGBOARD_TYPE_HANGPLT) + { + nwk_fifo_half_full_r = 0x3ff; + nwk_fifo_half_full_w = 0x400; + nwk_fifo_full = 0x7ff; + nwk_fifo_mask = 0x7ff; + } +} + +void set_cgboard_id(int board_id) +{ + if (board_id > num_cgboards-1) + { + cgboard_id = MAX_CG_BOARDS; + } + else + { + cgboard_id = board_id; + } +} + +int get_cgboard_id(void) +{ + if (cgboard_id > num_cgboards-1) + { + return 0; + } + else + { + return cgboard_id; + } +} + +void set_cgboard_texture_bank(int board, int bank, UINT8 *rom) +{ + texture_bank[board] = bank; + + memory_configure_bank(bank, 0, 2, rom, 0x800000); +} + +/*****************************************************************************/ + +/* CG Board DSP interface for PowerPC */ + +READ32_HANDLER( cgboard_dsp_comm_r_ppc ) +{ + if (cgboard_id < MAX_CG_BOARDS) + { +// mame_printf_debug("dsp_cmd_r: (board %d) %08X, %08X at %08X\n", cgboard_id, offset, mem_mask, activecpu_get_pc()); + return dsp_comm_sharc[cgboard_id][offset] | (dsp_state[cgboard_id] << 16); + } + else + { + return 0; + } +} + +WRITE32_HANDLER( cgboard_dsp_comm_w_ppc ) +{ + int dsp = (cgboard_id == 0) ? 2 : 3; +// mame_printf_debug("dsp_cmd_w: (board %d) %08X, %08X, %08X at %08X\n", cgboard_id, data, offset, mem_mask, activecpu_get_pc()); + + if (cgboard_id < MAX_CG_BOARDS) + { + if (offset == 0) + { + if (!(mem_mask & 0xff000000)) + { + dsp_shared_ram_bank[cgboard_id] = (data >> 24) & 0x1; + + if (data & 0x80000000) + { + dsp_state[cgboard_id] |= 0x10; + } + + pci_bridge_enable[cgboard_id] = (data & 0x20000000) ? 1 : 0; + + if (data & 0x10000000) + { + cpunum_set_input_line(dsp, INPUT_LINE_RESET, CLEAR_LINE); + } + else + { + cpunum_set_input_line(dsp, INPUT_LINE_RESET, ASSERT_LINE); + } + + if (data & 0x02000000) + { + cpunum_set_input_line(dsp, INPUT_LINE_IRQ0, ASSERT_LINE); + } + if (data & 0x04000000) + { + cpunum_set_input_line(dsp, INPUT_LINE_IRQ1, ASSERT_LINE); + } + } + + if (!(mem_mask & 0x000000ff)) + { + dsp_comm_ppc[cgboard_id][offset] = data & 0xff; + } + } + else + { + dsp_comm_ppc[cgboard_id][offset] = data; + } + } +} + + + +READ32_HANDLER( cgboard_dsp_shared_r_ppc ) +{ + if (cgboard_id < MAX_CG_BOARDS) + { + return dsp_shared_ram[cgboard_id][offset + (dsp_shared_ram_bank[cgboard_id] * DSP_BANK_SIZE_WORD)]; + } + else + { + return 0; + } +} + +WRITE32_HANDLER( cgboard_dsp_shared_w_ppc ) +{ + if (cgboard_id < MAX_CG_BOARDS) + { + cpu_trigger(10000); // Remove the timeout (a part of the GTI Club FIFO test workaround) + COMBINE_DATA(dsp_shared_ram[cgboard_id] + (offset + (dsp_shared_ram_bank[cgboard_id] * DSP_BANK_SIZE_WORD))); + } +} + +/*****************************************************************************/ + +/* CG Board DSP interface for SHARC */ + +static UINT32 dsp_comm_sharc_r(int board, int offset) +{ + return dsp_comm_ppc[board][offset]; +} + +static void dsp_comm_sharc_w(int board, int offset, UINT32 data) +{ + if (offset >= 2) + { + fatalerror("dsp_comm_w: %08X, %08X", data, offset); + } + + switch (cgboard_type) + { + case CGBOARD_TYPE_ZR107: + case CGBOARD_TYPE_GTICLUB: + { + //cpunum_set_input_line(2, SHARC_INPUT_FLAG0, ASSERT_LINE); + cpuintrf_push_context(2); + sharc_set_flag_input(0, ASSERT_LINE); + cpuintrf_pop_context(); + + if (offset == 1) + { + if (data & 0x03) + { + cpunum_set_input_line(2, INPUT_LINE_IRQ2, ASSERT_LINE); + } + } + break; + } + + case CGBOARD_TYPE_NWKTR: + case CGBOARD_TYPE_HANGPLT: + { + if (offset == 1) + { + nwk_device_sel[board] = data; + + if (data & 0x01 || data & 0x10) + { + cpuintrf_push_context((board == 0) ? 2 : 3); + sharc_set_flag_input(1, ASSERT_LINE); + cpuintrf_pop_context(); + } + + if (texture_bank[board] != -1) + { + int offset = (data & 0x08) ? 1 : 0; + + memory_set_bank(texture_bank[board], offset); + } + } + break; + } + + case CGBOARD_TYPE_HORNET: + { + if (offset == 1) + { + if (texture_bank[board] != -1) + { + int offset = (data & 0x08) ? 1 : 0; + + memory_set_bank(texture_bank[board], offset); + } + } + break; + } + } + +// printf("cgboard_dsp_comm_w_sharc: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc()); + + dsp_comm_sharc[board][offset] = data; +} + +static UINT32 dsp_shared_ram_r_sharc(int board, int offset) +{ +// printf("dsp_shared_r: (board %d) %08X, (%08X, %08X)\n", cgboard_id, offset, (UINT32)dsp_shared_ram[(offset >> 1)], (UINT32)dsp_shared_ram[offset]); + + if (offset & 0x1) + { + return (dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] >> 0) & 0xffff; + } + else + { + return (dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] >> 16) & 0xffff; + } +} + +static void dsp_shared_ram_w_sharc(int board, int offset, UINT32 data) +{ +// printf("dsp_shared_w: (board %d) %08X, %08X\n", cgboard_id, offset, data); + if (offset & 0x1) + { + dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] &= 0xffff0000; + dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] |= (data & 0xffff); + } + else + { + dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] &= 0x0000ffff; + dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] |= ((data & 0xffff) << 16); + } +} + +READ32_HANDLER( cgboard_0_comm_sharc_r ) +{ + return dsp_comm_sharc_r(0, offset); +} + +WRITE32_HANDLER( cgboard_0_comm_sharc_w ) +{ + dsp_comm_sharc_w(0, offset, data); +} + +READ32_HANDLER( cgboard_0_shared_sharc_r ) +{ + return dsp_shared_ram_r_sharc(0, offset); +} + +WRITE32_HANDLER( cgboard_0_shared_sharc_w ) +{ + dsp_shared_ram_w_sharc(0, offset, data); +} + +READ32_HANDLER( cgboard_1_comm_sharc_r ) +{ + return dsp_comm_sharc_r(1, offset); +} + +WRITE32_HANDLER( cgboard_1_comm_sharc_w ) +{ + dsp_comm_sharc_w(1, offset, data); +} + +READ32_HANDLER( cgboard_1_shared_sharc_r ) +{ + return dsp_shared_ram_r_sharc(1, offset); +} + +WRITE32_HANDLER( cgboard_1_shared_sharc_w ) +{ + dsp_shared_ram_w_sharc(1, offset, data); +} + +/*****************************************************************************/ + +static UINT32 nwk_fifo_r(int board) +{ + int cpu = (board == 0) ? 2 : 3; + UINT32 data; + + if (nwk_fifo_read_ptr[board] < nwk_fifo_half_full_r) + { + cpuintrf_push_context(cpu); + sharc_set_flag_input(1, CLEAR_LINE); + cpuintrf_pop_context(); + } + else + { + cpuintrf_push_context(cpu); + sharc_set_flag_input(1, ASSERT_LINE); + cpuintrf_pop_context(); + } + + if (nwk_fifo_read_ptr[board] < nwk_fifo_full) + { + cpuintrf_push_context(cpu); + sharc_set_flag_input(2, ASSERT_LINE); + cpuintrf_pop_context(); + } + else + { + cpuintrf_push_context(cpu); + sharc_set_flag_input(2, CLEAR_LINE); + cpuintrf_pop_context(); + } + + data = nwk_fifo[board][nwk_fifo_read_ptr[board]]; + nwk_fifo_read_ptr[board]++; + nwk_fifo_read_ptr[board] &= nwk_fifo_mask; + + return data; +} + +static void nwk_fifo_w(int board, UINT32 data) +{ + int cpu = (board == 0) ? 2 : 3; + + if (nwk_fifo_write_ptr[board] < nwk_fifo_half_full_w) + { + cpuintrf_push_context(cpu); + sharc_set_flag_input(1, ASSERT_LINE); + cpuintrf_pop_context(); + } + else + { + cpuintrf_push_context(cpu); + sharc_set_flag_input(1, CLEAR_LINE); + cpuintrf_pop_context(); + } + + cpuintrf_push_context(cpu); + sharc_set_flag_input(2, ASSERT_LINE); + cpuintrf_pop_context(); + + nwk_fifo[board][nwk_fifo_write_ptr[board]] = data; + nwk_fifo_write_ptr[board]++; + nwk_fifo_write_ptr[board] &= nwk_fifo_mask; +} + +/*****************************************************************************/ + +/* Konami K033906 PCI bridge */ + +#define MAX_K033906_CHIPS 2 + +static UINT32 *K033906_reg[MAX_K033906_CHIPS]; +static UINT32 *K033906_ram[MAX_K033906_CHIPS]; + +void K033906_init(void) +{ + int i; + for (i=0; i < MAX_K033906_CHIPS; i++) + { + K033906_reg[i] = auto_malloc(sizeof(UINT32) * 256); + K033906_ram[i] = auto_malloc(sizeof(UINT32) * 32768); + } +} + +static UINT32 K033906_r(int chip, int reg) +{ + switch(reg) + { + case 0x00: return 0x0001121a; // PCI Vendor ID (0x121a = 3dfx), Device ID (0x0001 = Voodoo) + case 0x02: return 0x04000000; // Revision ID + case 0x04: return K033906_reg[chip][0x04]; // memBaseAddr + case 0x0f: return K033906_reg[chip][0x0f]; // interrupt_line, interrupt_pin, min_gnt, max_lat + + default: + fatalerror("K033906_r: %d, %08X at %08X", chip, reg, activecpu_get_pc()); + } + return 0; +} + +static void K033906_w(int chip, int reg, UINT32 data) +{ + switch(reg) + { + case 0x00: + break; + + case 0x01: // command register + break; + + case 0x04: // memBaseAddr + { + if (data == 0xffffffff) + { + K033906_reg[chip][0x04] = 0xff000000; + } + else + { + K033906_reg[chip][0x04] = data & 0xff000000; + } + break; + } + + case 0x0f: // interrupt_line, interrupt_pin, min_gnt, max_lat + { + K033906_reg[chip][0x0f] = data; + break; + } + + case 0x10: // initEnable + { + voodoo_set_init_enable(chip, data); + break; + } + + case 0x11: // busSnoop0 + case 0x12: // busSnoop1 + break; + + case 0x38: // ??? + break; + + default: + fatalerror("K033906_w: %d, %08X, %08X at %08X", chip, data, reg, activecpu_get_pc()); + } +} + +READ32_HANDLER(K033906_0_r) +{ + if (nwk_device_sel[0] & 0x01) + { + return nwk_fifo_r(0); + } + else + { + if (pci_bridge_enable[0]) + { + return K033906_r(0, offset); + } + else + { + return K033906_ram[0][offset]; + } + } +} + +WRITE32_HANDLER(K033906_0_w) +{ + if (pci_bridge_enable[0]) + { + K033906_w(0, offset, data); + } + else + { + K033906_ram[0][offset] = data; + } +} + +READ32_HANDLER(K033906_1_r) +{ + if (nwk_device_sel[1] & 0x01) + { + return nwk_fifo_r(1); + } + else + { + if (pci_bridge_enable[1]) + { + return K033906_r(1, offset); + } + else + { + return K033906_ram[1][offset]; + } + } +} + +WRITE32_HANDLER(K033906_1_w) +{ + if (pci_bridge_enable[1]) + { + K033906_w(1, offset, data); + } + else + { + K033906_ram[1][offset] = data; + } +} + +/*****************************************************************************/ + +WRITE32_HANDLER(nwk_fifo_0_w) +{ + if (nwk_device_sel[0] & 0x01) + { + nwk_fifo_w(0, data); + } + else if (nwk_device_sel[0] & 0x02) + { + int addr = ((offset >> 8) << 9) | (offset & 0xff); + nwk_ram[0][addr] = data; + } + else + { + voodoo_0_w(offset ^ 0x80000, data, mem_mask); + } +} + +WRITE32_HANDLER(nwk_fifo_1_w) +{ + if (nwk_device_sel[1] & 0x01) + { + nwk_fifo_w(1, data); + } + else if (nwk_device_sel[1] & 0x02) + { + int addr = ((offset >> 8) << 9) | (offset & 0xff); + nwk_ram[1][addr] = data; + } + else + { + voodoo_1_w(offset ^ 0x80000, data, mem_mask); + } +} + +READ32_HANDLER(nwk_voodoo_0_r) +{ + if ((nwk_device_sel[0] == 0x4) && offset >= 0x100000 && offset < 0x200000) + { + return nwk_ram[0][offset & 0x1fff]; + } + else + { + return voodoo_0_r(offset, mem_mask); + } +} + +READ32_HANDLER(nwk_voodoo_1_r) +{ + if ((nwk_device_sel[1] == 0x4) && offset >= 0x100000 && offset < 0x200000) + { + return nwk_ram[1][offset & 0x1fff]; + } + else + { + return voodoo_1_r(offset, mem_mask); + } +} + +WRITE32_HANDLER(nwk_voodoo_0_w) +{ + if (nwk_device_sel[0] & 0x01) + { + nwk_fifo_w(0, data); + } + else if (nwk_device_sel[0] & 0x02) + { + int addr = ((offset >> 8) << 9) | (offset & 0xff); + nwk_ram[0][addr] = data; + } + else + { + voodoo_0_w(offset, data, mem_mask); + } +} + +WRITE32_HANDLER(nwk_voodoo_1_w) +{ + if (nwk_device_sel[1] & 0x01) + { + nwk_fifo_w(1, data); + } + else if (nwk_device_sel[1] & 0x02) + { + int addr = ((offset >> 8) << 9) | (offset & 0xff); + nwk_ram[1][addr] = data; + } + else + { + voodoo_1_w(offset, data, mem_mask); + } +} + +/*****************************************************************************/ + +#define LED_ON 0xff00ff00 + +void draw_7segment_led(mame_bitmap *bitmap, int x, int y, UINT8 value) +{ + if ((value & 0x7f) == 0x7f) + { + return; + } + + plot_box(bitmap, x-1, y-1, 7, 11, 0x00000000); + + /* Top */ + if( (value & 0x40) == 0 ) { + plot_box(bitmap, x+1, y+0, 3, 1, LED_ON); + } + /* Middle */ + if( (value & 0x01) == 0 ) { + plot_box(bitmap, x+1, y+4, 3, 1, LED_ON); + } + /* Bottom */ + if( (value & 0x08) == 0 ) { + plot_box(bitmap, x+1, y+8, 3, 1, LED_ON); + } + /* Top Left */ + if( (value & 0x02) == 0 ) { + plot_box(bitmap, x+0, y+1, 1, 3, LED_ON); + } + /* Top Right */ + if( (value & 0x20) == 0 ) { + plot_box(bitmap, x+4, y+1, 1, 3, LED_ON); + } + /* Bottom Left */ + if( (value & 0x04) == 0 ) { + plot_box(bitmap, x+0, y+5, 1, 3, LED_ON); + } + /* Bottom Right */ + if( (value & 0x10) == 0 ) { + plot_box(bitmap, x+4, y+5, 1, 3, LED_ON); + } +} |