diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 5353abbbd6c..da424f08374 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -2533,6 +2533,7 @@ files { MAME_DIR .. "src/mame/video/sega16sp.c", MAME_DIR .. "src/mame/video/segaic24.c", MAME_DIR .. "src/mame/machine/gdrom.c", + MAME_DIR .. "src/mame/machine/xbox.c", } createMAMEProjects(_target, _subtarget, "seibu") diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index bd18182c127..55374f37bd9 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -984,6 +984,7 @@ files { MAME_DIR .. "src/mame/video/vectrex.c", MAME_DIR .. "src/mame/drivers/cps1.c", MAME_DIR .. "src/mame/video/cps1.c", + MAME_DIR .. "src/mame/machine/xbox.c", } end -------------------------------------------------- diff --git a/src/mame/drivers/chihiro.c b/src/mame/drivers/chihiro.c index 881732b088d..e4e6b65e79f 100644 --- a/src/mame/drivers/chihiro.c +++ b/src/mame/drivers/chihiro.c @@ -376,7 +376,7 @@ Thanks to Alex, Mr Mudkips, and Philip Burke for this info. #include "debug/debugcmd.h" #include "debug/debugcpu.h" #include "includes/chihiro.h" - +#include "includes/xbox.h" // for now, make buggy GCC/Mingw STFU about I64FMT #if (defined(__MINGW32__) && (__GNUC__ >= 5)) @@ -386,337 +386,40 @@ Thanks to Alex, Mr Mudkips, and Philip Burke for this info. #endif #define LOG_PCI -//#define LOG_OHCI //#define LOG_BASEBOARD -//#define USB_ENABLED -struct OHCIEndpointDescriptor { - int mps; // MaximumPacketSize - int f; // Format - int k; // sKip - int s; // Speed - int d; // Direction - int en; // EndpointNumber - int fa; // FunctionAddress - UINT32 tailp; // TDQueueTailPointer - UINT32 headp; // TDQueueHeadPointer - UINT32 nexted; // NextED - int c; // toggleCarry - int h; // Halted - UINT32 word0; -}; - -struct OHCITransferDescriptor { - int cc; // ConditionCode - int ec; // ErrorCount - int t; // DataToggle - int di; // DelayInterrupt - int dp; // Direction/PID - int r; // bufferRounding - UINT32 cbp; // CurrentBufferPointer - UINT32 nexttd; // NextTD - UINT32 be; // BufferEnd - UINT32 word0; -}; - -struct OHCIIsochronousTransferDescriptor { - int cc; // ConditionCode - int fc; // FrameCount - int di; // DelayInterrupt - int sf; // StartingFrame - UINT32 bp0; // BufferPage0 - UINT32 nexttd; // NextTD - UINT32 be; // BufferEnd - UINT32 offset[8]; // Offset/PacketStatusWord -}; - -enum OHCIRegisters { - HcRevision=0, - HcControl, - HcCommandStatus, - HcInterruptStatus, - HcInterruptEnable, - HcInterruptDisable, - HcHCCA, - HcPeriodCurrentED, - HcControlHeadED, - HcControlCurrentED, - HcBulkHeadED, - HcBulkCurrentED, - HcDoneHead, - HcFmInterval, - HcFmRemaining, - HcFmNumber, - HcPeriodicStart, - HcLSThreshold, - HcRhDescriptorA, - HcRhDescriptorB, - HcRhStatus, - HcRhPortStatus1 -}; - -enum OHCIHostControllerFunctionalState { - UsbReset=0, - UsbResume, - UsbOperational, - UsbSuspend -}; - -enum OHCIInterrupt { - SchedulingOverrun=1, - WritebackDoneHead=2, - StartofFrame=4, - ResumeDetected=8, - UnrecoverableError=16, - FrameNumberOverflow=32, - RootHubStatusChange=64, - OwnershipChange=0x40000000, - MasterInterruptEnable=0x80000000 -}; - -enum OHCICompletionCode { - NoError=0, - CRC, - BitStuffing, - DataToggleMismatch, - Stall, - DeviceNotResponding, - PIDCheckFailure, - UnexpectedPID, - DataOverrun, - DataUnderrun, - BufferOverrun=12, - BufferUnderrun, - NotAccessed=14 -}; - -struct USBSetupPacket { - UINT8 bmRequestType; - UINT8 bRequest; - UINT16 wValue; - UINT16 wIndex; - UINT16 wLength; -}; - -struct USBStandardDeviceDscriptor { - UINT8 bLength; - UINT8 bDescriptorType; - UINT16 bcdUSB; - UINT8 bDeviceClass; - UINT8 bDeviceSubClass; - UINT8 bDeviceProtocol; - UINT8 bMaxPacketSize0; - UINT16 idVendor; - UINT16 idProduct; - UINT16 bcdDevice; - UINT8 iManufacturer; - UINT8 iProduct; - UINT8 iSerialNumber; - UINT8 bNumConfigurations; -}; - -struct USBStandardConfigurationDescriptor { - UINT8 bLength; - UINT8 bDescriptorType; - UINT16 wTotalLength; - UINT8 bNumInterfaces; - UINT8 bConfigurationValue; - UINT8 iConfiguration; - UINT8 bmAttributes; - UINT8 MaxPower; -}; - -struct USBStandardInterfaceDescriptor { - UINT8 bLength; - UINT8 bDescriptorType; - UINT8 bInterfaceNumber; - UINT8 bAlternateSetting; - UINT8 bNumEndpoints; - UINT8 bInterfaceClass; - UINT8 bInterfaceSubClass; - UINT8 bInterfaceProtocol; - UINT8 iInterface; -}; - -struct USBStandardEndpointDescriptor { - UINT8 bLength; - UINT8 bDescriptorType; - UINT8 bEndpointAddress; - UINT8 bmAttributes; - UINT16 wMaxPacketSize; - UINT8 bInterval; -}; - -enum USBPid { - SetupPid=0, - OutPid, - InPid -}; - -enum USBRequestCode { - GET_STATUS=0, - CLEAR_FEATURE=1, - SET_FEATURE=3, - SET_ADDRESS=5, - GET_DESCRIPTOR=6, - SET_DESCRIPTOR=7, - GET_CONFIGURATION=8, - SET_CONFIGURATION=9, - GET_INTERFACE=10, - SET_INTERFACE=11, - SYNCH_FRAME=12 -}; - -enum USBDescriptorType { - DEVICE=1, - CONFIGURATION=2, - STRING=3, - INTERFACE=4, - ENDPOINT=5 -}; - -class ohci_function_device { -public: - ohci_function_device(); - void execute_reset(); - int execute_transfer(int address, int endpoint, int pid, UINT8 *buffer, int size); -private: - int address; - int controldir; - int remain; - UINT8 *position; -}; - -class chihiro_state : public driver_device +class chihiro_state : public xbox_base_state { public: chihiro_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - nvidia_nv2a(NULL), - debug_irq_active(false), - debug_irq_number(0), - dimm_board_memory(NULL), - dimm_board_memory_size(0), + xbox_base_state(mconfig, type, tag), usbhack_index(-1), usbhack_counter(0), - m_maincpu(*this, "maincpu") { } + dimm_board_memory(NULL), + dimm_board_memory_size(0) { } - DECLARE_READ32_MEMBER(geforce_r); - DECLARE_WRITE32_MEMBER(geforce_w); - DECLARE_READ32_MEMBER(usbctrl_r); - DECLARE_WRITE32_MEMBER(usbctrl_w); - DECLARE_READ32_MEMBER(smbus_r); - DECLARE_WRITE32_MEMBER(smbus_w); DECLARE_READ32_MEMBER(mediaboard_r); DECLARE_WRITE32_MEMBER(mediaboard_w); - DECLARE_READ32_MEMBER(audio_apu_r); - DECLARE_WRITE32_MEMBER(audio_apu_w); - DECLARE_READ32_MEMBER(audio_ac93_r); - DECLARE_WRITE32_MEMBER(audio_ac93_w); - DECLARE_READ32_MEMBER(dummy_r); - DECLARE_WRITE32_MEMBER(dummy_w); - void smbus_register_device(int address, int(*handler)(chihiro_state &chs, int command, int rw, int data)); - int smbus_pic16lc(int command, int rw, int data); - int smbus_cx25871(int command, int rw, int data); - int smbus_eeprom(int command, int rw, int data); - void usb_ohci_plug(int port, ohci_function_device *function); - void usb_ohci_interrupts(); - void usb_ohci_read_endpoint_descriptor(UINT32 address); - void usb_ohci_writeback_endpoint_descriptor(UINT32 address); - void usb_ohci_read_transfer_descriptor(UINT32 address); - void usb_ohci_writeback_transfer_descriptor(UINT32 address); - void usb_ohci_read_isochronous_transfer_descriptor(UINT32 address); + virtual void machine_start(); void baseboard_ide_event(int type, UINT8 *read, UINT8 *write); UINT8 *baseboard_ide_dimmboard(UINT32 lba); void dword_write_le(UINT8 *addr, UINT32 d); void word_write_le(UINT8 *addr, UINT16 d); - void debug_generate_irq(int irq, bool active); - - void vblank_callback(screen_device &screen, bool state); - UINT32 screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - virtual void machine_start(); - DECLARE_WRITE_LINE_MEMBER(chihiro_pic8259_1_set_int_line); - DECLARE_READ8_MEMBER(get_slave_ack); - DECLARE_WRITE_LINE_MEMBER(chihiro_pit8254_out0_changed); - DECLARE_WRITE_LINE_MEMBER(chihiro_pit8254_out2_changed); - IRQ_CALLBACK_MEMBER(irq_callback); - TIMER_CALLBACK_MEMBER(audio_apu_timer); - TIMER_CALLBACK_MEMBER(usb_ohci_timer); + virtual void hack_eeprom(); + virtual void hack_usb(); struct chihiro_devices { - pic8259_device *pic8259_1; - pic8259_device *pic8259_2; bus_master_ide_controller_device *ide; naomi_gdrom_board *dimmboard; } chihiro_devs; - struct smbus_state { - int status; - int control; - int address; - int data; - int command; - int rw; - int(*devices[128])(chihiro_state &chs, int command, int rw, int data); - UINT32 words[256 / 4]; - } smbusst; - struct apu_state { - UINT32 memory[0x60000 / 4]; - UINT32 gpdsp_sgaddress; // global processor scatter-gather - UINT32 gpdsp_sgblocks; - UINT32 gpdsp_address; - UINT32 epdsp_sgaddress; // encoder processor scatter-gather - UINT32 epdsp_sgblocks; - UINT32 unknown_sgaddress; - UINT32 unknown_sgblocks; - int voice_number; - UINT32 voices_heap_blockaddr[1024]; - UINT64 voices_active[4]; //one bit for each voice: 1 playing 0 not - UINT32 voicedata_address; - int voices_frequency[256]; // sample rate - int voices_position[256]; // position in samples * 1000 - int voices_position_start[256]; // position in samples * 1000 - int voices_position_end[256]; // position in samples * 1000 - int voices_position_increment[256]; // position increment every 1ms * 1000 - emu_timer *timer; - address_space *space; - } apust; - struct ac97_state { - UINT32 mixer_regs[0x80 / 4]; - UINT32 controller_regs[0x38 / 4]; - } ac97st; - struct ohci_state { - UINT32 hc_regs[255]; - struct { - ohci_function_device *function; - int delay; - } ports[4 + 1]; - emu_timer *timer; - int state; - UINT32 framenumber; - UINT32 nextinterupted; - UINT32 nextbulked; - int interruptbulkratio; - int writebackdonehadcounter; - address_space *space; - UINT8 buffer[1024]; - OHCIEndpointDescriptor endpoint_descriptor; - OHCITransferDescriptor transfer_descriptor; - OHCIIsochronousTransferDescriptor isochronous_transfer_descriptor; - } ohcist; - UINT8 pic16lc_buffer[0xff]; - nv2a_renderer *nvidia_nv2a; - bool debug_irq_active; - int debug_irq_number; - UINT8 *dimm_board_memory; - UINT32 dimm_board_memory_size; int usbhack_index; int usbhack_counter; - required_device m_maincpu; + UINT8 *dimm_board_memory; + UINT32 dimm_board_memory_size; }; -/* jamtable instructions for Chihiro (different from console) +/* jamtable instructions for Chihiro (different from Xbox console) St. Instr. Comment 0x01 POKEPCI PCICONF[OP2] := OP1 0x02 OUTB PORT[OP2] := OP1 @@ -843,343 +546,10 @@ static void jamtable_disasm_command(running_machine &machine, int ref, int param jamtable_disasm(machine, space, (UINT32)addr, (UINT32)size); } -static void dump_string_command(running_machine &machine, int ref, int params, const char **param) -{ - chihiro_state *state = machine.driver_data(); - address_space &space = state->m_maincpu->space(); - UINT64 addr; - offs_t address; - UINT32 length, maximumlength; - offs_t buffer; - - if (params < 1) - return; - if (!debug_command_parameter_number(machine, param[0], &addr)) - return; - address = (offs_t)addr; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - { - debug_console_printf(machine, "Address is unmapped.\n"); - return; - } - length = space.read_word_unaligned(address); - maximumlength = space.read_word_unaligned(address + 2); - buffer = space.read_dword_unaligned(address + 4); - debug_console_printf(machine, "Length %d word\n", length); - debug_console_printf(machine, "MaximumLength %d word\n", maximumlength); - debug_console_printf(machine, "Buffer %08X byte* ", buffer); - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &buffer)) - { - debug_console_printf(machine, "\nBuffer is unmapped.\n"); - return; - } - if (length > 256) - length = 256; - for (int a = 0; a < length; a++) - { - UINT8 c = space.read_byte(buffer + a); - debug_console_printf(machine, "%c", c); - } - debug_console_printf(machine, "\n"); -} - -static void dump_process_command(running_machine &machine, int ref, int params, const char **param) -{ - chihiro_state *state = machine.driver_data(); - address_space &space = state->m_maincpu->space(); - UINT64 addr; - offs_t address; - - if (params < 1) - return; - if (!debug_command_parameter_number(machine, param[0], &addr)) - return; - address = (offs_t)addr; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - { - debug_console_printf(machine, "Address is unmapped.\n"); - return; - } - debug_console_printf(machine, "ReadyListHead {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address), space.read_dword_unaligned(address + 4)); - debug_console_printf(machine, "ThreadListHead {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 8), space.read_dword_unaligned(address + 12)); - debug_console_printf(machine, "StackCount %d dword\n", space.read_dword_unaligned(address + 16)); - debug_console_printf(machine, "ThreadQuantum %d dword\n", space.read_dword_unaligned(address + 20)); - debug_console_printf(machine, "BasePriority %d byte\n", space.read_byte(address + 24)); - debug_console_printf(machine, "DisableBoost %d byte\n", space.read_byte(address + 25)); - debug_console_printf(machine, "DisableQuantum %d byte\n", space.read_byte(address + 26)); - debug_console_printf(machine, "_padding %d byte\n", space.read_byte(address + 27)); -} - -static void dump_list_command(running_machine &machine, int ref, int params, const char **param) -{ - chihiro_state *state = machine.driver_data(); - address_space &space = state->m_maincpu->space(); - UINT64 addr, offs, start, old; - offs_t address, offset; - - if (params < 1) - return; - if (!debug_command_parameter_number(machine, param[0], &addr)) - return; - offs = 0; - offset = 0; - if (params >= 2) - { - if (!debug_command_parameter_number(machine, param[1], &offs)) - return; - offset = (offs_t)offs; - } - start = addr; - address = (offs_t)addr; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - { - debug_console_printf(machine, "Address is unmapped.\n"); - return; - } - if (params >= 2) - debug_console_printf(machine, "Entry Object\n"); - else - debug_console_printf(machine, "Entry\n"); - for (int num = 0; num < 32; num++) - { - if (params >= 2) - debug_console_printf(machine, "%08X %08X\n", (UINT32)addr, (offs_t)addr - offset); - else - debug_console_printf(machine, "%08X\n", (UINT32)addr); - old = addr; - addr = space.read_dword_unaligned(address); - if (addr == start) - break; - if (addr == old) - break; - address = (offs_t)addr; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - break; - } -} - -static void dump_dpc_command(running_machine &machine, int ref, int params, const char **param) -{ - chihiro_state *state = machine.driver_data(); - address_space &space = state->m_maincpu->space(); - UINT64 addr; - offs_t address; - - if (params < 1) - return; - if (!debug_command_parameter_number(machine, param[0], &addr)) - return; - address = (offs_t)addr; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - { - debug_console_printf(machine, "Address is unmapped.\n"); - return; - } - debug_console_printf(machine, "Type %d word\n", space.read_word_unaligned(address)); - debug_console_printf(machine, "Inserted %d byte\n", space.read_byte(address + 2)); - debug_console_printf(machine, "Padding %d byte\n", space.read_byte(address + 3)); - debug_console_printf(machine, "DpcListEntry {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 4), space.read_dword_unaligned(address + 8)); - debug_console_printf(machine, "DeferredRoutine %08X dword\n", space.read_dword_unaligned(address + 12)); - debug_console_printf(machine, "DeferredContext %08X dword\n", space.read_dword_unaligned(address + 16)); - debug_console_printf(machine, "SystemArgument1 %08X dword\n", space.read_dword_unaligned(address + 20)); - debug_console_printf(machine, "SystemArgument2 %08X dword\n", space.read_dword_unaligned(address + 24)); -} - -static void dump_timer_command(running_machine &machine, int ref, int params, const char **param) -{ - chihiro_state *state = machine.driver_data(); - address_space &space = state->m_maincpu->space(); - UINT64 addr; - offs_t address; - - if (params < 1) - return; - if (!debug_command_parameter_number(machine, param[0], &addr)) - return; - address = (offs_t)addr; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - { - debug_console_printf(machine, "Address is unmapped.\n"); - return; - } - debug_console_printf(machine, "Header.Type %d byte\n", space.read_byte(address)); - debug_console_printf(machine, "Header.Absolute %d byte\n", space.read_byte(address + 1)); - debug_console_printf(machine, "Header.Size %d byte\n", space.read_byte(address + 2)); - debug_console_printf(machine, "Header.Inserted %d byte\n", space.read_byte(address + 3)); - debug_console_printf(machine, "Header.SignalState %08X dword\n", space.read_dword_unaligned(address + 4)); - debug_console_printf(machine, "Header.WaitListEntry {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 8), space.read_dword_unaligned(address + 12)); - debug_console_printf(machine, "DueTime %" I64FMT "x qword\n", (INT64)space.read_qword_unaligned(address + 16)); - debug_console_printf(machine, "TimerListEntry {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 24), space.read_dword_unaligned(address + 28)); - debug_console_printf(machine, "Dpc %08X dword\n", space.read_dword_unaligned(address + 32)); - debug_console_printf(machine, "Period %d dword\n", space.read_dword_unaligned(address + 36)); -} - -static void curthread_command(running_machine &machine, int ref, int params, const char **param) -{ - chihiro_state *state = machine.driver_data(); - address_space &space = state->m_maincpu->space(); - UINT64 fsbase; - UINT32 kthrd, topstack, tlsdata; - offs_t address; - - fsbase = state->m_maincpu->state_int(44); - address = (offs_t)fsbase + 0x28; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - { - debug_console_printf(machine, "Address is unmapped.\n"); - return; - } - kthrd = space.read_dword_unaligned(address); - debug_console_printf(machine, "Current thread is %08X\n", kthrd); - address = (offs_t)kthrd + 0x1c; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - return; - topstack = space.read_dword_unaligned(address); - debug_console_printf(machine, "Current thread stack top is %08X\n", topstack); - address = (offs_t)kthrd + 0x28; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - return; - tlsdata = space.read_dword_unaligned(address); - if (tlsdata == 0) - address = (offs_t)topstack - 0x210 - 8; - else - address = (offs_t)tlsdata - 8; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) - return; - debug_console_printf(machine, "Current thread function is %08X\n", space.read_dword_unaligned(address)); -} - -static void generate_irq_command(running_machine &machine, int ref, int params, const char **param) -{ - UINT64 irq; - chihiro_state *chst = machine.driver_data(); - - if (params < 1) - return; - if (!debug_command_parameter_number(machine, param[0], &irq)) - return; - if (irq > 15) - return; - if (irq == 2) - return; - chst->debug_generate_irq((int)irq, true); -} - -static void nv2a_combiners_command(running_machine &machine, int ref, int params, const char **param) -{ - int en; - - chihiro_state *chst = machine.driver_data(); - en = chst->nvidia_nv2a->toggle_register_combiners_usage(); - if (en != 0) - debug_console_printf(machine, "Register combiners enabled\n"); - else - debug_console_printf(machine, "Register combiners disabled\n"); -} - -static void waitvblank_command(running_machine &machine, int ref, int params, const char **param) -{ - int en; - - chihiro_state *chst = machine.driver_data(); - en = chst->nvidia_nv2a->toggle_wait_vblank_support(); - if (en != 0) - debug_console_printf(machine, "Vblank method enabled\n"); - else - debug_console_printf(machine, "Vblank method disabled\n"); -} - -static void grab_texture_command(running_machine &machine, int ref, int params, const char **param) -{ - UINT64 type; - chihiro_state *chst = machine.driver_data(); - - if (params < 2) - return; - if (!debug_command_parameter_number(machine, param[0], &type)) - return; - if ((param[1][0] == 0) || (strlen(param[1]) > 127)) - return; - chst->nvidia_nv2a->debug_grab_texture((int)type, param[1]); -} - -static void grab_vprog_command(running_machine &machine, int ref, int params, const char **param) -{ - chihiro_state *chst = machine.driver_data(); - UINT32 instruction[4]; - FILE *fil; - - if (params < 1) - return; - if ((param[0][0] == 0) || (strlen(param[0]) > 127)) - return; - if ((fil = fopen(param[0], "wb")) == NULL) - return; - for (int n = 0; n < 136; n++) { - chst->nvidia_nv2a->debug_grab_vertex_program_slot(n, instruction); - fwrite(instruction, sizeof(UINT32), 4, fil); - } - fclose(fil); -} - -static void vprogdis_command(running_machine &machine, int ref, int params, const char **param) -{ - UINT64 address, length, type; - UINT32 instruction[4]; - offs_t addr; - vertex_program_disassembler vd; - char line[64]; - chihiro_state *chst = machine.driver_data(); - address_space &space = chst->m_maincpu->space(); - - if (params < 2) - return; - if (!debug_command_parameter_number(machine, param[0], &address)) - return; - if (!debug_command_parameter_number(machine, param[1], &length)) - return; - type = 0; - if (params > 2) - if (!debug_command_parameter_number(machine, param[2], &type)) - return; - while (length > 0) { - if (type == 1) { - addr = (offs_t)address; - if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &addr)) - return; - instruction[0] = space.read_dword_unaligned(address); - instruction[1] = space.read_dword_unaligned(address + 4); - instruction[2] = space.read_dword_unaligned(address + 8); - instruction[3] = space.read_dword_unaligned(address + 12); - } - else - chst->nvidia_nv2a->debug_grab_vertex_program_slot((int)address, instruction); - while (vd.disassemble(instruction, line) != 0) - debug_console_printf(machine, "%s\n", line); - if (type == 1) - address = address + 4 * 4; - else - address++; - length--; - } -} - static void help_command(running_machine &machine, int ref, int params, const char **param) { debug_console_printf(machine, "Available Chihiro commands:\n"); debug_console_printf(machine, " chihiro jamdis,, -- Disassemble bytes of JamTable instructions starting at \n"); - debug_console_printf(machine, " chihiro dump_string,
-- Dump _STRING object at
\n"); - debug_console_printf(machine, " chihiro dump_process,
-- Dump _PROCESS object at
\n"); - debug_console_printf(machine, " chihiro dump_list,
[,] -- Dump _LIST_ENTRY chain starting at
\n"); - debug_console_printf(machine, " chihiro dump_dpc,
-- Dump _KDPC object at
\n"); - debug_console_printf(machine, " chihiro dump_timer,
-- Dump _KTIMER object at
\n"); - debug_console_printf(machine, " chihiro curthread -- Print information about current thread\n"); - debug_console_printf(machine, " chihiro irq, -- Generate interrupt with irq number 0-15\n"); - debug_console_printf(machine, " chihiro nv2a_combiners -- Toggle use of register combiners\n"); - debug_console_printf(machine, " chihiro waitvblank -- Toggle support for wait vblank method\n"); - debug_console_printf(machine, " chihiro grab_texture,, -- Save to the next used texture of type \n"); - debug_console_printf(machine, " chihiro grab_vprog, -- save current vertex program instruction slots to \n"); - debug_console_printf(machine, " chihiro vprogdis,
,[,] -- disassemble vertex program instructions at
of \n"); debug_console_printf(machine, " chihiro help -- this list\n"); } @@ -1189,168 +559,19 @@ static void chihiro_debug_commands(running_machine &machine, int ref, int params return; if (strcmp("jamdis", param[0]) == 0) jamtable_disasm_command(machine, ref, params - 1, param + 1); - else if (strcmp("dump_string", param[0]) == 0) - dump_string_command(machine, ref, params - 1, param + 1); - else if (strcmp("dump_process", param[0]) == 0) - dump_process_command(machine, ref, params - 1, param + 1); - else if (strcmp("dump_list", param[0]) == 0) - dump_list_command(machine, ref, params - 1, param + 1); - else if (strcmp("dump_dpc", param[0]) == 0) - dump_dpc_command(machine, ref, params - 1, param + 1); - else if (strcmp("dump_timer", param[0]) == 0) - dump_timer_command(machine, ref, params - 1, param + 1); - else if (strcmp("curthread", param[0]) == 0) - curthread_command(machine, ref, params - 1, param + 1); - else if (strcmp("irq", param[0]) == 0) - generate_irq_command(machine, ref, params - 1, param + 1); - else if (strcmp("nv2a_combiners", param[0]) == 0) - nv2a_combiners_command(machine, ref, params - 1, param + 1); - else if (strcmp("waitvblank", param[0]) == 0) - waitvblank_command(machine, ref, params - 1, param + 1); - else if (strcmp("grab_texture", param[0]) == 0) - grab_texture_command(machine, ref, params - 1, param + 1); - else if (strcmp("grab_vprog", param[0]) == 0) - grab_vprog_command(machine, ref, params - 1, param + 1); - else if (strcmp("vprogdis", param[0]) == 0) - vprogdis_command(machine, ref, params - 1, param + 1); else help_command(machine, ref, params - 1, param + 1); } -void chihiro_state::debug_generate_irq(int irq, bool active) +void chihiro_state::hack_eeprom() { - int state; - - if (active) - { - debug_irq_active = true; - debug_irq_number = irq; - state = 1; - } - else - { - debug_irq_active = false; - state = 0; - } - switch (irq) - { - case 0: - chihiro_devs.pic8259_1->ir0_w(state); - break; - case 1: - chihiro_devs.pic8259_1->ir1_w(state); - break; - case 3: - chihiro_devs.pic8259_1->ir3_w(state); - break; - case 4: - chihiro_devs.pic8259_1->ir4_w(state); - break; - case 5: - chihiro_devs.pic8259_1->ir5_w(state); - break; - case 6: - chihiro_devs.pic8259_1->ir6_w(state); - break; - case 7: - chihiro_devs.pic8259_1->ir7_w(state); - break; - case 8: - chihiro_devs.pic8259_2->ir0_w(state); - break; - case 9: - chihiro_devs.pic8259_2->ir1_w(state); - break; - case 10: - chihiro_devs.pic8259_2->ir2_w(state); - break; - case 11: - chihiro_devs.pic8259_2->ir3_w(state); - break; - case 12: - chihiro_devs.pic8259_2->ir4_w(state); - break; - case 13: - chihiro_devs.pic8259_2->ir5_w(state); - break; - case 14: - chihiro_devs.pic8259_2->ir6_w(state); - break; - case 15: - chihiro_devs.pic8259_2->ir7_w(state); - break; - } + // 8003b744,3b744=0x90 0x90 + m_maincpu->space(0).write_byte(0x3b744, 0x90); + m_maincpu->space(0).write_byte(0x3b745, 0x90); + m_maincpu->space(0).write_byte(0x3b766, 0xc9); + m_maincpu->space(0).write_byte(0x3b767, 0xc3); } -void chihiro_state::vblank_callback(screen_device &screen, bool state) -{ - if (nvidia_nv2a->vblank_callback(screen, state)) - chihiro_devs.pic8259_1->ir3_w(1); // IRQ 3 - else - chihiro_devs.pic8259_1->ir3_w(0); // IRQ 3 -} - -UINT32 chihiro_state::screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - return nvidia_nv2a->screen_update_callback(screen, bitmap, cliprect); -} - -READ32_MEMBER(chihiro_state::geforce_r) -{ - return nvidia_nv2a->geforce_r(space, offset, mem_mask); -} - -WRITE32_MEMBER(chihiro_state::geforce_w) -{ - nvidia_nv2a->geforce_w(space, offset, data, mem_mask); -} - -static UINT32 geforce_pci_r(device_t *busdevice, device_t *device, int function, int reg, UINT32 mem_mask) -{ -#ifdef LOG_PCI - // logerror(" bus:1 device:NV_2A function:%d register:%d mask:%08X\n",function,reg,mem_mask); -#endif - return 0; -} - -static void geforce_pci_w(device_t *busdevice, device_t *device, int function, int reg, UINT32 data, UINT32 mem_mask) -{ -#ifdef LOG_PCI - // logerror(" bus:1 device:NV_2A function:%d register:%d data:%08X mask:%08X\n",function,reg,data,mem_mask); -#endif -} - -/* - * ohci usb controller (placeholder for now) - */ - -#ifdef LOG_OHCI -static const char *const usbregnames[] = { - "HcRevision", - "HcControl", - "HcCommandStatus", - "HcInterruptStatus", - "HcInterruptEnable", - "HcInterruptDisable", - "HcHCCA", - "HcPeriodCurrentED", - "HcControlHeadED", - "HcControlCurrentED", - "HcBulkHeadED", - "HcBulkCurrentED", - "HcDoneHead", - "HcFmInterval", - "HcFmRemaining", - "HcFmNumber", - "HcPeriodicStart", - "HcLSThreshold", - "HcRhDescriptorA", - "HcRhDescriptorB", - "HcRhStatus", - "HcRhPortStatus[1]" -}; -#endif - static const struct { const char *game_name; struct { @@ -1360,720 +581,24 @@ static const struct { } hacks[2] = { { "chihiro", { { 0x6a79f, 0x01 }, { 0x6a7a0, 0x00 }, { 0x6b575, 0x00 }, { 0x6b576, 0x00 }, { 0x6b5af, 0x75 }, { 0x6b78a, 0x75 }, { 0x6b7ca, 0x00 }, { 0x6b7b8, 0x00 }, { 0x8f5b2, 0x75 }, { 0x79a9e, 0x74 }, { 0x79b80, 0x74 }, { 0x79b97, 0x74 }, { 0, 0 } } }, { "outr2", { { 0x12e4cf, 0x01 }, { 0x12e4d0, 0x00 }, { 0x4793e, 0x01 }, { 0x4793f, 0x00 }, { 0x47aa3, 0x01 }, { 0x47aa4, 0x00 }, { 0x14f2b6, 0x84 }, { 0x14f2d1, 0x75 }, { 0x8732f, 0x7d }, { 0x87384, 0x7d }, { 0x87388, 0xeb }, { 0, 0 } } } }; -READ32_MEMBER(chihiro_state::usbctrl_r) +void chihiro_state::hack_usb() { - UINT32 ret; + int p; -#ifdef LOG_OHCI - if (offset >= 0x54 / 4) - logerror("usb controller 0 register HcRhPortStatus[%d] read\n", (offset - 0x54 / 4) + 1); + if (usbhack_counter == 0) + p = 0; + else if (usbhack_counter == 1) // after game loaded + p = usbhack_index; else - logerror("usb controller 0 register %s read\n", usbregnames[offset]); -#endif - ret=ohcist.hc_regs[offset]; - if (offset == 0) { /* hacks needed until usb (and jvs) is implemented */ -#ifdef USB_ENABLED -#else - int p; - - if (usbhack_counter == 0) - p = 0; - else if (usbhack_counter == 1) // after game loaded - p = usbhack_index; - else - p = -1; - if (p >= 0) { - for (int a = 0; a < 16; a++) { - if (hacks[p].modify[a].address == 0) - break; - m_maincpu->space(0).write_byte(hacks[p].modify[a].address, hacks[p].modify[a].write_byte); - } - } - usbhack_counter++; -#endif - } - return ret; -} - -WRITE32_MEMBER(chihiro_state::usbctrl_w) -{ -#ifdef USB_ENABLED - UINT32 old = ohcist.hc_regs[offset]; -#endif - -#ifdef LOG_OHCI - if (offset >= 0x54 / 4) - logerror("usb controller 0 register HcRhPortStatus[%d] write %08X\n", (offset - 0x54 / 4) + 1, data); - else - logerror("usb controller 0 register %s write %08X\n", usbregnames[offset], data); -#endif -#ifdef USB_ENABLED - if (offset == HcRhStatus) { - if (data & 0x80000000) - ohcist.hc_regs[HcRhStatus] &= ~0x8000; - if (data & 0x00020000) - ohcist.hc_regs[HcRhStatus] &= ~0x0002; - if (data & 0x00010000) - ohcist.hc_regs[HcRhStatus] &= ~0x0001; - return; - } - if (offset == HcControl) { - int hcfs; - - hcfs = (data >> 6) & 3; - if (hcfs == UsbOperational) { - ohcist.timer->enable(); - ohcist.timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1)); - ohcist.writebackdonehadcounter = 7; - } - else - ohcist.timer->enable(false); - ohcist.state = hcfs; - ohcist.interruptbulkratio = (data & 3) + 1; - } - if (offset == HcCommandStatus) { - if (data & 1) - ohcist.hc_regs[HcControl] |= 3 << 6; - ohcist.hc_regs[HcCommandStatus] |= data; - return; - } - if (offset == HcInterruptStatus) { - ohcist.hc_regs[HcInterruptStatus] &= ~data; - usb_ohci_interrupts(); - return; - } - if (offset == HcInterruptEnable) { - ohcist.hc_regs[HcInterruptEnable] |= data; - usb_ohci_interrupts(); - return; - } - if (offset == HcInterruptDisable) { - ohcist.hc_regs[HcInterruptEnable] &= ~data; - usb_ohci_interrupts(); - return; - } - if (offset >= HcRhPortStatus1) { - int port = offset - HcRhPortStatus1 + 1; // port 0 not used - // bit 0 ClearPortEnable: 1 clears PortEnableStatus - // bit 1 SetPortEnable: 1 sets PortEnableStatus - // bit 2 SetPortSuspend: 1 sets PortSuspendStatus - // bit 3 ClearSuspendStatus: 1 clears PortSuspendStatus - // bit 4 SetPortReset: 1 sets PortResetStatus - if (data & 0x10) { - ohcist.hc_regs[offset] |= 0x10; - ohcist.ports[port].function->execute_reset(); - // after 10ms set PortResetStatusChange and clear PortResetStatus and set PortEnableStatus - ohcist.ports[port].delay = 10; - } - // bit 8 SetPortPower: 1 sets PortPowerStatus - // bit 9 ClearPortPower: 1 clears PortPowerStatus - // bit 16 1 clears ConnectStatusChange - // bit 17 1 clears PortEnableStatusChange - // bit 18 1 clears PortSuspendStatusChange - // bit 19 1 clears PortOverCurrentIndicatorChange - // bit 20 1 clears PortResetStatusChange - if (ohcist.hc_regs[offset] != old) - ohcist.hc_regs[HcInterruptStatus] |= RootHubStatusChange; - usb_ohci_interrupts(); - return; - } -#endif - ohcist.hc_regs[offset] = data; -} - -TIMER_CALLBACK_MEMBER(chihiro_state::usb_ohci_timer) -{ - UINT32 hcca; - int changed = 0; - int list = 1; - bool cont = false; - int pid, remain, mps; - - hcca = ohcist.hc_regs[HcHCCA]; - if (ohcist.state == UsbOperational) { - // increment frame number - ohcist.framenumber = (ohcist.framenumber + 1) & 0xffff; - ohcist.space->write_dword(hcca + 0x80, ohcist.framenumber); - ohcist.hc_regs[HcFmNumber] = ohcist.framenumber; - } - // port reset delay - for (int p = 1; p <= 4; p++) { - if (ohcist.ports[p].delay > 0) { - ohcist.ports[p].delay--; - if (ohcist.ports[p].delay == 0) { - ohcist.hc_regs[HcRhPortStatus1 + p - 1] = (ohcist.hc_regs[HcRhPortStatus1 + p - 1] & ~(1 << 4)) | (1 << 20) | (1 << 1); // bit 1 PortEnableStatus - changed = 1; - } + p = -1; + if (p >= 0) { + for (int a = 0; a < 16; a++) { + if (hacks[p].modify[a].address == 0) + break; + m_maincpu->space(0).write_byte(hacks[p].modify[a].address, hacks[p].modify[a].write_byte); } } - if (ohcist.state == UsbOperational) { - while (list >= 0) - { - // select list, do transfer - if (list == 0) { - if (ohcist.hc_regs[HcControl] & (1 << 2)) { - // periodic - if (ohcist.hc_regs[HcControl] & (1 << 3)) { - // isochronous - } - } - list = -1; - } - if (list == 1) { - // control - if (ohcist.hc_regs[HcControl] & (1 << 4)) { - cont = true; - while (cont == true) { - // if current endpoint descriptor is not 0 use it, otherwise ... - if (ohcist.hc_regs[HcControlCurrentED] == 0) { - // ... check the filled bit ... - if (ohcist.hc_regs[HcCommandStatus] & (1 << 1)) { - // ... if 1 start processing from the head of the list - ohcist.hc_regs[HcControlCurrentED] = ohcist.hc_regs[HcControlHeadED]; - ohcist.hc_regs[HcCommandStatus] &= ~(1 << 1); - // but if the list is empty, go to the next list - if (ohcist.hc_regs[HcControlCurrentED] == 0) - cont = false; - } - else - cont = false; - } - if (cont == true) { - // service endpoint descriptor - usb_ohci_read_endpoint_descriptor(ohcist.hc_regs[HcControlCurrentED]); - // only if it is not halted and not to be skipped - if (!(ohcist.endpoint_descriptor.h | ohcist.endpoint_descriptor.k)) { - // compare the Endpoint Descriptor?s TailPointer and NextTransferDescriptor fields. - if (ohcist.endpoint_descriptor.headp != ohcist.endpoint_descriptor.tailp) { - UINT32 a, b; - // service transfer descriptor - usb_ohci_read_transfer_descriptor(ohcist.endpoint_descriptor.headp); - // get pid - if (ohcist.endpoint_descriptor.d == 1) - pid=OutPid; // out - else if (ohcist.endpoint_descriptor.d == 2) - pid=InPid; // in - else { - pid = ohcist.transfer_descriptor.dp; // 0 setup 1 out 2 in - } - // determine how much data to transfer - // setup pid must be 8 bytes - a = ohcist.transfer_descriptor.be & 0xfff; - b = ohcist.transfer_descriptor.cbp & 0xfff; - if ((ohcist.transfer_descriptor.be ^ ohcist.transfer_descriptor.cbp) & 0xfffff000) - a |= 0x1000; - remain = a - b + 1; - if (pid == InPid) { - mps = ohcist.endpoint_descriptor.mps; - if (remain < mps) - mps = remain; - } - else { - mps = ohcist.endpoint_descriptor.mps; - } - if (ohcist.transfer_descriptor.cbp == 0) - mps = 0; - b = ohcist.transfer_descriptor.cbp; - // if sending ... - if (pid != InPid) { - // ... get mps bytes - for (int c = 0; c < mps; c++) { - ohcist.buffer[c] = ohcist.space->read_byte(b); - b++; - if ((b & 0xfff) == 0) - b = ohcist.transfer_descriptor.be & 0xfffff000; - } - } - // should check for time available - // execute transaction - mps=ohcist.ports[1].function->execute_transfer(ohcist.endpoint_descriptor.fa, ohcist.endpoint_descriptor.en, pid, ohcist.buffer, mps); - // if receiving ... - if (pid == InPid) { - // ... store mps bytes - for (int c = 0; c < mps; c++) { - ohcist.space->write_byte(b,ohcist.buffer[c]); - b++; - if ((b & 0xfff) == 0) - b = ohcist.transfer_descriptor.be & 0xfffff000; - } - } - // status writeback (CompletionCode field, DataToggleControl field, CurrentBufferPointer field, ErrorCount field) - ohcist.transfer_descriptor.cc = NoError; - ohcist.transfer_descriptor.t = (ohcist.transfer_descriptor.t ^ 1) | 2; - ohcist.transfer_descriptor.cbp = b; - ohcist.transfer_descriptor.ec = 0; - if ((remain == mps) || (mps == 0)) { - // retire transfer descriptor - a = ohcist.endpoint_descriptor.headp; - ohcist.endpoint_descriptor.headp = ohcist.transfer_descriptor.nexttd; - ohcist.transfer_descriptor.nexttd = ohcist.hc_regs[HcDoneHead]; - ohcist.hc_regs[HcDoneHead] = a; - ohcist.endpoint_descriptor.c = ohcist.transfer_descriptor.t & 1; - if (ohcist.transfer_descriptor.di != 7) { - if (ohcist.transfer_descriptor.di < ohcist.writebackdonehadcounter) - ohcist.writebackdonehadcounter = ohcist.transfer_descriptor.di; - } - usb_ohci_writeback_transfer_descriptor(a); - usb_ohci_writeback_endpoint_descriptor(ohcist.hc_regs[HcControlCurrentED]); - } else { - usb_ohci_writeback_transfer_descriptor(ohcist.endpoint_descriptor.headp); - } - } else - ohcist.hc_regs[HcControlCurrentED] = ohcist.endpoint_descriptor.nexted; - } else - ohcist.hc_regs[HcControlCurrentED] = ohcist.endpoint_descriptor.nexted; - // one bulk every n control transfers - ohcist.interruptbulkratio--; - if (ohcist.interruptbulkratio <= 0) { - ohcist.interruptbulkratio = (ohcist.hc_regs[HcControl] & 3) + 1; - cont = false; - } - } - } - } - list = 2; - } - if (list == 2) { - // bulk - if (ohcist.hc_regs[HcControl] & (1 << 5)) { - ohcist.hc_regs[HcCommandStatus] &= ~(1 << 2); - if (ohcist.hc_regs[HcControlCurrentED] == 0) - list = 0; - else if (ohcist.hc_regs[HcControl] & (1 << 4)) - list = 1; - else - list = 0; - } - } - } - if (ohcist.framenumber == 0) - ohcist.hc_regs[HcInterruptStatus] |= FrameNumberOverflow; - ohcist.hc_regs[HcInterruptStatus] |= StartofFrame; - if ((ohcist.writebackdonehadcounter != 0) && (ohcist.writebackdonehadcounter != 7)) - ohcist.writebackdonehadcounter--; - if ((ohcist.writebackdonehadcounter == 0) && ((ohcist.hc_regs[HcInterruptStatus] & WritebackDoneHead) == 0)) { - UINT32 b = 0; - - if ((ohcist.hc_regs[HcInterruptStatus] & ohcist.hc_regs[HcInterruptEnable]) != WritebackDoneHead) - b = 1; - ohcist.hc_regs[HcInterruptStatus] |= WritebackDoneHead; - ohcist.space->write_dword(hcca + 0x84, ohcist.hc_regs[HcDoneHead] | b); - ohcist.hc_regs[HcDoneHead] = 0; - ohcist.writebackdonehadcounter = 7; - } - } - if (changed != 0) { - ohcist.hc_regs[HcInterruptStatus] |= RootHubStatusChange; - } - usb_ohci_interrupts(); -} - -void chihiro_state::usb_ohci_plug(int port, ohci_function_device *function) -{ - if ((port > 0) && (port <= 4)) { - ohcist.ports[port].function = function; - ohcist.hc_regs[HcRhPortStatus1+port-1] = 1; - } -} - -static USBStandardDeviceDscriptor devdesc = {18,1,0x201,0xff,0x34,0x56,64,0x100,0x101,0x301,0,0,0,1}; - -ohci_function_device::ohci_function_device() -{ - address = 0; - controldir = 0; - remain = 0; - position = NULL; -} - -void ohci_function_device::execute_reset() -{ - address = 0; -} - -int ohci_function_device::execute_transfer(int address, int endpoint, int pid, UINT8 *buffer, int size) -{ - if (endpoint == 0) { - if (pid == SetupPid) { - struct USBSetupPacket *p=(struct USBSetupPacket *)buffer; - // define direction - controldir = p->bmRequestType & 128; - // case !=0, in data stage and out status stage - // case ==0, out data stage and in status stage - position = NULL; - remain = p->wLength; - if ((p->bmRequestType & 0x60) == 0) { - switch (p->bRequest) { - case GET_DESCRIPTOR: - if ((p->wValue >> 8) == 1) { // device descriptor - //p->wValue & 255; - position = (UINT8 *)&devdesc; - remain = sizeof(devdesc); - } - break; - case SET_ADDRESS: - //p->wValue; - break; - default: - break; - } - } - } - else if (pid == InPid) { - // case !=0, give data - // case ==0, nothing - if (size > remain) - size = remain; - if (controldir != 0) { - if (position != NULL) - memcpy(buffer, position, size); - position = position + size; - remain = remain - size; - } - } - else if (pid == OutPid) { - // case !=0, nothing - // case ==0, give data - if (size > remain) - size = remain; - if (controldir == 0) { - if (position != NULL) - memcpy(position, buffer, size); - position = position + size; - remain = remain - size; - } - } - } - return size; -} - -void chihiro_state::usb_ohci_interrupts() -{ - if (((ohcist.hc_regs[HcInterruptStatus] & ohcist.hc_regs[HcInterruptEnable]) != 0) && ((ohcist.hc_regs[HcInterruptEnable] & MasterInterruptEnable) != 0)) - chihiro_devs.pic8259_1->ir1_w(1); - else - chihiro_devs.pic8259_1->ir1_w(0); -} - -void chihiro_state::usb_ohci_read_endpoint_descriptor(UINT32 address) -{ - UINT32 w; - - w = ohcist.space->read_dword(address); - ohcist.endpoint_descriptor.word0 = w; - ohcist.endpoint_descriptor.fa = w & 0x7f; - ohcist.endpoint_descriptor.en = (w >> 7) & 15; - ohcist.endpoint_descriptor.d = (w >> 11) & 3; - ohcist.endpoint_descriptor.s = (w >> 13) & 1; - ohcist.endpoint_descriptor.k = (w >> 14) & 1; - ohcist.endpoint_descriptor.f = (w >> 15) & 1; - ohcist.endpoint_descriptor.mps = (w >> 16) & 0x7ff; - ohcist.endpoint_descriptor.tailp = ohcist.space->read_dword(address + 4); - w = ohcist.space->read_dword(address + 8); - ohcist.endpoint_descriptor.headp = w & 0xfffffffc; - ohcist.endpoint_descriptor.h = w & 1; - ohcist.endpoint_descriptor.c = (w >> 1) & 1; - ohcist.endpoint_descriptor.nexted = ohcist.space->read_dword(address + 12); -} - -void chihiro_state::usb_ohci_writeback_endpoint_descriptor(UINT32 address) -{ - UINT32 w; - - w = ohcist.endpoint_descriptor.word0 & 0xf8000000; - w = w | (ohcist.endpoint_descriptor.mps << 16) | (ohcist.endpoint_descriptor.f << 15) | (ohcist.endpoint_descriptor.k << 14) | (ohcist.endpoint_descriptor.s << 13) | (ohcist.endpoint_descriptor.d << 11) | (ohcist.endpoint_descriptor.en << 7) | ohcist.endpoint_descriptor.fa; - ohcist.space->write_dword(address, w); - w = ohcist.endpoint_descriptor.headp | (ohcist.endpoint_descriptor.c << 1) | ohcist.endpoint_descriptor.h; - ohcist.space->write_dword(address + 8, w); -} - -void chihiro_state::usb_ohci_read_transfer_descriptor(UINT32 address) -{ - UINT32 w; - - w = ohcist.space->read_dword(address); - ohcist.transfer_descriptor.word0 = w; - ohcist.transfer_descriptor.cc = (w >> 28) & 15; - ohcist.transfer_descriptor.ec= (w >> 26) & 3; - ohcist.transfer_descriptor.t= (w >> 24) & 3; - ohcist.transfer_descriptor.di= (w >> 21) & 7; - ohcist.transfer_descriptor.dp= (w >> 19) & 3; - ohcist.transfer_descriptor.r = (w >> 18) & 1; - ohcist.transfer_descriptor.cbp = ohcist.space->read_dword(address + 4); - ohcist.transfer_descriptor.nexttd = ohcist.space->read_dword(address + 8); - ohcist.transfer_descriptor.be = ohcist.space->read_dword(address + 12); -} - -void chihiro_state::usb_ohci_writeback_transfer_descriptor(UINT32 address) -{ - UINT32 w; - - w = ohcist.transfer_descriptor.word0 & 0x0003ffff; - w = w | (ohcist.transfer_descriptor.cc << 28) | (ohcist.transfer_descriptor.ec << 26) | (ohcist.transfer_descriptor.t << 24) | (ohcist.transfer_descriptor.di << 21) | (ohcist.transfer_descriptor.dp << 19) | (ohcist.transfer_descriptor.r << 18); - ohcist.space->write_dword(address, w); - ohcist.space->write_dword(address + 4, ohcist.transfer_descriptor.cbp); - ohcist.space->write_dword(address + 8, ohcist.transfer_descriptor.nexttd); -} - -void chihiro_state::usb_ohci_read_isochronous_transfer_descriptor(UINT32 address) -{ - UINT32 w; - - w = ohcist.space->read_dword(address); - ohcist.isochronous_transfer_descriptor.cc = (w >> 28) & 15; - ohcist.isochronous_transfer_descriptor.fc = (w >> 24) & 7; - ohcist.isochronous_transfer_descriptor.di = (w >> 21) & 7; - ohcist.isochronous_transfer_descriptor.sf = w & 0xffff; - ohcist.isochronous_transfer_descriptor.bp0 = ohcist.space->read_dword(address + 4) & 0xfffff000; - ohcist.isochronous_transfer_descriptor.nexttd = ohcist.space->read_dword(address + 8); - ohcist.isochronous_transfer_descriptor.be = ohcist.space->read_dword(address + 12); - w = ohcist.space->read_dword(address + 16); - ohcist.isochronous_transfer_descriptor.offset[0] = w & 0xffff; - ohcist.isochronous_transfer_descriptor.offset[1] = (w >> 16) & 0xffff; - w = ohcist.space->read_dword(address + 20); - ohcist.isochronous_transfer_descriptor.offset[2] = w & 0xffff; - ohcist.isochronous_transfer_descriptor.offset[3] = (w >> 16) & 0xffff; - w = ohcist.space->read_dword(address + 24); - ohcist.isochronous_transfer_descriptor.offset[4] = w & 0xffff; - ohcist.isochronous_transfer_descriptor.offset[5] = (w >> 16) & 0xffff; - w = ohcist.space->read_dword(address + 28); - ohcist.isochronous_transfer_descriptor.offset[6] = w & 0xffff; - ohcist.isochronous_transfer_descriptor.offset[7] = (w >> 16) & 0xffff; -} - -/* - * Audio - */ - -READ32_MEMBER(chihiro_state::audio_apu_r) -{ - logerror("Audio_APU: read from %08X mask %08X\n", 0xfe800000 + offset * 4, mem_mask); - if (offset == 0x20010 / 4) // some kind of internal counter or state value - return 0x20 + 4 + 8 + 0x48 + 0x80; - return apust.memory[offset]; -} - -WRITE32_MEMBER(chihiro_state::audio_apu_w) -{ - //UINT32 old; - UINT32 v; - - logerror("Audio_APU: write at %08X mask %08X value %08X\n", 0xfe800000 + offset * 4, mem_mask, data); - //old = apust.memory[offset]; - apust.memory[offset] = data; - if (offset == 0x02040 / 4) // address of memory area with scatter-gather info (gpdsp scratch dma) - apust.gpdsp_sgaddress = data; - if (offset == 0x020d4 / 4) { // block count (gpdsp) - apust.gpdsp_sgblocks = data; - apust.gpdsp_address = apust.space->read_dword(apust.gpdsp_sgaddress); // memory address of first block - apust.timer->enable(); - apust.timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1)); - } - if (offset == 0x02048 / 4) // (epdsp scratch dma) - apust.epdsp_sgaddress = data; - if (offset == 0x020dc / 4) // (epdsp) - apust.epdsp_sgblocks = data; - if (offset == 0x0204c / 4) // address of memory area with information about blocks - apust.unknown_sgaddress = data; - if (offset == 0x020e0 / 4) // block count - 1 - apust.unknown_sgblocks = data; - if (offset == 0x0202c / 4) { // address of memory area with 0x80 bytes for each voice - apust.voicedata_address = data; - return; - } - if (offset == 0x04024 / 4) // offset in memory area indicated by 0x204c (analog output ?) - return; - if (offset == 0x04034 / 4) // size - return; - if (offset == 0x04028 / 4) // offset in memory area indicated by 0x204c (digital output ?) - return; - if (offset == 0x04038 / 4) // size - return; - if (offset == 0x20804 / 4) { // block number for scatter-gather heap that stores sampled audio to be played - if (data >= 1024) { - logerror("Audio_APU: sg block number too high, increase size of voices_heap_blockaddr\n"); - apust.memory[offset] = 1023; - } - return; - } - if (offset == 0x20808 / 4) { // block address for scatter-gather heap that stores sampled audio to be played - apust.voices_heap_blockaddr[apust.memory[0x20804 / 4]] = data; - return; - } - if (offset == 0x202f8 / 4) { // voice number for parameters ? - apust.voice_number = data; - return; - } - if (offset == 0x202fc / 4) // 1 when accessing voice parameters 0 otherwise - return; - if (offset == 0x20304 / 4) { // format - /* - bits 28-31 sample format: - 0 8-bit pcm - 5 16-bit pcm - 10 adpcm ? - 14 24-bit pcm - 15 32-bit pcm - bits 16-20 number of channels - 1: - 0 mono - 1 stereo - */ - return; - } - if (offset == 0x2037c / 4) { // value related to sample rate - INT16 v = (INT16)(data >> 16); // upper 16 bits as a signed 16 bit value - float vv = ((float)v) / 4096.0f; // divide by 4096 - float vvv = powf(2, vv); // two to the vv - int f = vvv*48000.0f; // sample rate - apust.voices_frequency[apust.voice_number] = f; - return; - } - if (offset == 0x203a0 / 4) // start offset of data in scatter-gather heap - return; - if (offset == 0x203a4 / 4) { // first sample to play - apust.voices_position_start[apust.voice_number] = data * 1000; - return; - } - if (offset == 0x203dc / 4) { // last sample to play - apust.voices_position_end[apust.voice_number] = data * 1000; - return; - } - if (offset == 0x2010c / 4) // voice processor 0 idle 1 not idle ? - return; - if (offset == 0x20124 / 4) { // voice number to activate ? - v = apust.voice_number; - apust.voices_active[v >> 6] |= ((UINT64)1 << (v & 63)); - apust.voices_position[v] = apust.voices_position_start[apust.voice_number]; - apust.voices_position_increment[apust.voice_number] = apust.voices_frequency[apust.voice_number]; - return; - } - if (offset == 0x20128 / 4) { // voice number to deactivate ? - v = apust.voice_number; - apust.voices_active[v >> 6] &= ~(1 << (v & 63)); - return; - } - if (offset == 0x20140 / 4) // voice number to ? - return; - if ((offset >= 0x20200 / 4) && (offset < 0x20280 / 4)) // headroom for each of the 32 mixbins - return; - if (offset == 0x20280 / 4) // hrtf headroom ? - return; -} - -READ32_MEMBER(chihiro_state::audio_ac93_r) -{ - UINT32 ret = 0; - - logerror("Audio_AC3: read from %08X mask %08X\n", 0xfec00000 + offset * 4, mem_mask); - if (offset < 0x80 / 4) - { - ret = ac97st.mixer_regs[offset]; - } - if ((offset >= 0x100 / 4) && (offset <= 0x138 / 4)) - { - offset = offset - 0x100 / 4; - if (offset == 0x18 / 4) - { - ac97st.controller_regs[offset] &= ~0x02000000; // REGRST: register reset - } - if (offset == 0x30 / 4) - { - ac97st.controller_regs[offset] |= 0x100; // PCRDY: primary codec ready - } - if (offset == 0x34 / 4) - { - ac97st.controller_regs[offset] &= ~1; // CAS: codec access semaphore - } - ret = ac97st.controller_regs[offset]; - } - return ret; -} - -WRITE32_MEMBER(chihiro_state::audio_ac93_w) -{ - logerror("Audio_AC3: write at %08X mask %08X value %08X\n", 0xfec00000 + offset * 4, mem_mask, data); - if (offset < 0x80 / 4) - { - COMBINE_DATA(ac97st.mixer_regs + offset); - } - if ((offset >= 0x100 / 4) && (offset <= 0x138 / 4)) - { - offset = offset - 0x100 / 4; - COMBINE_DATA(ac97st.controller_regs + offset); - } -} - -TIMER_CALLBACK_MEMBER(chihiro_state::audio_apu_timer) -{ - int cmd; - int bb, b, v; - UINT64 bv; - UINT32 phys; - - cmd = apust.space->read_dword(apust.gpdsp_address + 0x800 + 0x10); - if (cmd == 3) - apust.space->write_dword(apust.gpdsp_address + 0x800 + 0x10, 0); - /*else - logerror("Audio_APU: unexpected value at address %d\n",apust.gpdsp_address+0x800+0x10);*/ - for (b = 0; b < 4; b++) { - bv = 1; - for (bb = 0; bb < 64; bb++) { - if (apust.voices_active[b] & bv) { - v = bb + (b << 6); - apust.voices_position[v] += apust.voices_position_increment[v]; - while (apust.voices_position[v] >= apust.voices_position_end[v]) - apust.voices_position[v] = apust.voices_position_start[v] + apust.voices_position[v] - apust.voices_position_end[v] - 1000; - phys = apust.voicedata_address + 0x80 * v; - apust.space->write_dword(phys + 0x58, apust.voices_position[v] / 1000); - } - bv = bv << 1; - } - } -} - -static UINT32 hubintiasbridg_pci_r(device_t *busdevice, device_t *device, int function, int reg, UINT32 mem_mask) -{ -#ifdef LOG_PCI - // logerror(" bus:0 function:%d register:%d mask:%08X\n",function,reg,mem_mask); -#endif - if ((function == 0) && (reg == 8)) - return 0xb4; // 0:1:0 revision id must be at least 0xb4, otherwise usb will require a hub - return 0; -} - -static void hubintiasbridg_pci_w(device_t *busdevice, device_t *device, int function, int reg, UINT32 data, UINT32 mem_mask) -{ -#ifdef LOG_PCI - if (reg >= 16) logerror(" bus:0 function:%d register:%d data:%08X mask:%08X\n", function, reg, data, mem_mask); -#endif -} - -/* - * dummy for non connected devices - */ - -static UINT32 dummy_pci_r(device_t *busdevice, device_t *device, int function, int reg, UINT32 mem_mask) -{ -#ifdef LOG_PCI - // logerror(" bus:0 function:%d register:%d mask:%08X\n",function,reg,mem_mask); -#endif - return 0; -} - -static void dummy_pci_w(device_t *busdevice, device_t *device, int function, int reg, UINT32 data, UINT32 mem_mask) -{ -#ifdef LOG_PCI - if (reg >= 16) logerror(" bus:0 function:%d register:%d data:%08X mask:%08X\n", function, reg, data, mem_mask); -#endif -} - -READ32_MEMBER(chihiro_state::dummy_r) -{ - return 0; -} - -WRITE32_MEMBER(chihiro_state::dummy_w) -{ + usbhack_counter++; } // ======================> ide_baseboard_device @@ -2271,7 +796,7 @@ void chihiro_state::baseboard_ide_event(int type, UINT8 *read_buffer, UINT8 *wri // clear write_buffer[0] = write_buffer[1] = write_buffer[2] = write_buffer[3] = 0; // irq 10 active - chihiro_devs.pic8259_2->ir2_w(1); + xbox_base_devs.pic8259_2->ir2_w(1); } UINT8 *chihiro_state::baseboard_ide_dimmboard(UINT32 lba) @@ -2282,192 +807,6 @@ UINT8 *chihiro_state::baseboard_ide_dimmboard(UINT32 lba) return NULL; } -/* - * PIC & PIT - */ - -WRITE_LINE_MEMBER(chihiro_state::chihiro_pic8259_1_set_int_line) -{ - m_maincpu->set_input_line(0, state ? HOLD_LINE : CLEAR_LINE); -} - -READ8_MEMBER(chihiro_state::get_slave_ack) -{ - if (offset == 2) { // IRQ = 2 - return chihiro_devs.pic8259_2->acknowledge(); - } - return 0x00; -} - -IRQ_CALLBACK_MEMBER(chihiro_state::irq_callback) -{ - int r = 0; - r = chihiro_devs.pic8259_2->acknowledge(); - if (r == 0) - { - r = chihiro_devs.pic8259_1->acknowledge(); - } - if (debug_irq_active) - debug_generate_irq(debug_irq_number, false); - return r; -} - -WRITE_LINE_MEMBER(chihiro_state::chihiro_pit8254_out0_changed) -{ - if (chihiro_devs.pic8259_1) - { - chihiro_devs.pic8259_1->ir0_w(state); - } -} - -WRITE_LINE_MEMBER(chihiro_state::chihiro_pit8254_out2_changed) -{ - //chihiro_speaker_set_input( state ? 1 : 0 ); -} - -/* - * SMbus devices - */ - -int smbus_callback_pic16lc(chihiro_state &chs, int command, int rw, int data) -{ - return chs.smbus_pic16lc(command, rw, data); -} - -int chihiro_state::smbus_pic16lc(int command, int rw, int data) -{ - if (rw == 1) { // read - if (command == 0) { - if (pic16lc_buffer[0] == 'D') - pic16lc_buffer[0] = 'X'; - else if (pic16lc_buffer[0] == 'X') - pic16lc_buffer[0] = 'B'; - else if (pic16lc_buffer[0] == 'B') - pic16lc_buffer[0] = 'D'; - } - logerror("pic16lc: %d %d %d\n", command, rw, pic16lc_buffer[command]); - return pic16lc_buffer[command]; - } - else - if (command == 0) - pic16lc_buffer[0] = 'B'; - else - pic16lc_buffer[command] = (UINT8)data; - logerror("pic16lc: %d %d %d\n", command, rw, data); - return 0; -} - -int smbus_callback_cx25871(chihiro_state &chs, int command, int rw, int data) -{ - return chs.smbus_cx25871(command, rw, data); -} - -int chihiro_state::smbus_cx25871(int command, int rw, int data) -{ - logerror("cx25871: %d %d %d\n", command, rw, data); - return 0; -} - -// let's try to fake the missing eeprom -static int dummyeeprom[256]={0x94,0x18,0x10,0x59,0x83,0x58,0x15,0xDA,0xDF,0xCC,0x1D,0x78,0x20,0x8A,0x61,0xB8,0x08,0xB4,0xD6,0xA8, - 0x9E,0x77,0x9C,0xEB,0xEA,0xF8,0x93,0x6E,0x3E,0xD6,0x9C,0x49,0x6B,0xB5,0x6E,0xAB,0x6D,0xBC,0xB8,0x80,0x68,0x9D,0xAA,0xCD,0x0B,0x83, - 0x17,0xEC,0x2E,0xCE,0x35,0xA8,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x00,0x00, - 0x4F,0x6E,0x6C,0x69,0x6E,0x65,0x6B,0x65,0x79,0x69,0x6E,0x76,0x61,0x6C,0x69,0x64,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF, - 0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - -int smbus_callback_eeprom(chihiro_state &chs, int command, int rw, int data) -{ - return chs.smbus_eeprom(command, rw, data); -} - -int chihiro_state::smbus_eeprom(int command, int rw, int data) -{ - if (command >= 112) - return 0; - if (rw == 1) { // if reading - // 8003b744,3b744=0x90 0x90 - // hack to avoid hanging if eeprom contents are not correct - // this would need dumping the serial eeprom on the xbox board - if (command == 0) { - m_maincpu->space(0).write_byte(0x3b744, 0x90); - m_maincpu->space(0).write_byte(0x3b745, 0x90); - m_maincpu->space(0).write_byte(0x3b766, 0xc9); - m_maincpu->space(0).write_byte(0x3b767, 0xc3); - } - data = dummyeeprom[command] + dummyeeprom[command + 1] * 256; - logerror("eeprom: %d %d %d\n", command, rw, data); - return data; - } - logerror("eeprom: %d %d %d\n", command, rw, data); - dummyeeprom[command] = data; - return 0; -} - -/* - * SMbus controller - */ - -void chihiro_state::smbus_register_device(int address, int(*handler)(chihiro_state &chs, int command, int rw, int data)) -{ - if (address < 128) - smbusst.devices[address] = handler; -} - -READ32_MEMBER(chihiro_state::smbus_r) -{ - if ((offset == 0) && (mem_mask == 0xff)) // 0 smbus status - smbusst.words[offset] = (smbusst.words[offset] & ~mem_mask) | ((smbusst.status << 0) & mem_mask); - if ((offset == 1) && ((mem_mask == 0x00ff0000) || (mem_mask == 0xffff0000))) // 6 smbus data - smbusst.words[offset] = (smbusst.words[offset] & ~mem_mask) | ((smbusst.data << 16) & mem_mask); - return smbusst.words[offset]; -} - -WRITE32_MEMBER(chihiro_state::smbus_w) -{ - COMBINE_DATA(smbusst.words); - if ((offset == 0) && (mem_mask == 0xff)) // 0 smbus status - { - if (!((smbusst.status ^ data) & 0x10)) // clearing interrupt - chihiro_devs.pic8259_2->ir3_w(0); // IRQ 11 - smbusst.status &= ~data; - } - if ((offset == 0) && (mem_mask == 0xff0000)) // 2 smbus control - { - data = data >> 16; - smbusst.control = data; - int cycletype = smbusst.control & 7; - if (smbusst.control & 8) { // start - if ((cycletype & 6) == 2) - { - if (smbusst.devices[smbusst.address]) - if (smbusst.rw == 0) - smbusst.devices[smbusst.address](*this, smbusst.command, smbusst.rw, smbusst.data); - else - smbusst.data = smbusst.devices[smbusst.address](*this, smbusst.command, smbusst.rw, smbusst.data); - else - logerror("SMBUS: access to missing device at address %d\n", smbusst.address); - smbusst.status |= 0x10; - if (smbusst.control & 0x10) - { - chihiro_devs.pic8259_2->ir3_w(1); // IRQ 11 - } - } - } - } - if ((offset == 1) && (mem_mask == 0xff)) // 4 smbus address - { - smbusst.address = data >> 1; - smbusst.rw = data & 1; - } - if ((offset == 1) && ((mem_mask == 0x00ff0000) || (mem_mask == 0xffff0000))) // 6 smbus data - { - data = data >> 16; - smbusst.data = data; - } - if ((offset == 2) && (mem_mask == 0xff)) // 8 smbus command - smbusst.command = data; -} - READ32_MEMBER(chihiro_state::mediaboard_r) { UINT32 r; @@ -2494,29 +833,16 @@ WRITE32_MEMBER(chihiro_state::mediaboard_w) logerror("I/O port write %04x mask %08X value %08X\n", offset * 4 + 0x4000, mem_mask, data); // irq 10 if ((offset == 0x38) && ACCESSING_BITS_8_15) - chihiro_devs.pic8259_2->ir2_w(0); + xbox_base_devs.pic8259_2->ir2_w(0); } -static ADDRESS_MAP_START(xbox_map, AS_PROGRAM, 32, chihiro_state) - AM_RANGE(0x00000000, 0x07ffffff) AM_RAM // 128 megabytes - AM_RANGE(0xf0000000, 0xf0ffffff) AM_RAM - AM_RANGE(0xfd000000, 0xfdffffff) AM_RAM AM_READWRITE(geforce_r, geforce_w) - AM_RANGE(0xfed00000, 0xfed003ff) AM_READWRITE(usbctrl_r, usbctrl_w) - AM_RANGE(0xfe800000, 0xfe85ffff) AM_READWRITE(audio_apu_r, audio_apu_w) - AM_RANGE(0xfec00000, 0xfec001ff) AM_READWRITE(audio_ac93_r, audio_ac93_w) - AM_RANGE(0xff000000, 0xffffffff) AM_ROM AM_REGION("bios", 0) AM_MIRROR(0x00f80000) +static ADDRESS_MAP_START(chihiro_map, AS_PROGRAM, 32, chihiro_state) + AM_IMPORT_FROM(xbox_base_map) ADDRESS_MAP_END -static ADDRESS_MAP_START(xbox_map_io, AS_IO, 32, chihiro_state) - AM_RANGE(0x0020, 0x0023) AM_DEVREADWRITE8("pic8259_1", pic8259_device, read, write, 0xffffffff) - AM_RANGE(0x0040, 0x0043) AM_DEVREADWRITE8("pit8254", pit8254_device, read, write, 0xffffffff) - AM_RANGE(0x00a0, 0x00a3) AM_DEVREADWRITE8("pic8259_2", pic8259_device, read, write, 0xffffffff) - AM_RANGE(0x01f0, 0x01f7) AM_DEVREADWRITE("ide", bus_master_ide_controller_device, read_cs0, write_cs0) - AM_RANGE(0x0cf8, 0x0cff) AM_DEVREADWRITE("pcibus", pci_bus_legacy_device, read, write) +static ADDRESS_MAP_START(chihiro_map_io, AS_IO, 32, chihiro_state) + AM_IMPORT_FROM(xbox_base_map_io) AM_RANGE(0x4000, 0x40ff) AM_READWRITE(mediaboard_r, mediaboard_w) - AM_RANGE(0x8000, 0x80ff) AM_READWRITE(dummy_r, dummy_w) - AM_RANGE(0xc000, 0xc0ff) AM_READWRITE(smbus_r, smbus_w) - AM_RANGE(0xff60, 0xff67) AM_DEVREADWRITE("ide", bus_master_ide_controller_device, bmdma_r, bmdma_w) ADDRESS_MAP_END static INPUT_PORTS_START(chihiro) @@ -2524,45 +850,14 @@ INPUT_PORTS_END void chihiro_state::machine_start() { - nvidia_nv2a = auto_alloc(machine(), nv2a_renderer(machine())); - memset(pic16lc_buffer, 0, sizeof(pic16lc_buffer)); - pic16lc_buffer[0] = 'B'; - pic16lc_buffer[4] = 0; // A/V connector, 2=vga - smbus_register_device(0x10, smbus_callback_pic16lc); - smbus_register_device(0x45, smbus_callback_cx25871); - smbus_register_device(0x54, smbus_callback_eeprom); - chihiro_devs.pic8259_1 = machine().device("pic8259_1"); - chihiro_devs.pic8259_2 = machine().device("pic8259_2"); + xbox_base_state::machine_start(); chihiro_devs.ide = machine().device("ide"); chihiro_devs.dimmboard = machine().device("rom_board"); if (chihiro_devs.dimmboard != NULL) { dimm_board_memory = chihiro_devs.dimmboard->memory(dimm_board_memory_size); } - memset(apust.memory, 0, sizeof(apust.memory)); - memset(apust.voices_heap_blockaddr, 0, sizeof(apust.voices_heap_blockaddr)); - memset(apust.voices_active, 0, sizeof(apust.voices_active)); - memset(apust.voices_position, 0, sizeof(apust.voices_position)); - memset(apust.voices_position_start, 0, sizeof(apust.voices_position_start)); - memset(apust.voices_position_end, 0, sizeof(apust.voices_position_end)); - memset(apust.voices_position_increment, 0, sizeof(apust.voices_position_increment)); - apust.space = &m_maincpu->space(); - apust.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(chihiro_state::audio_apu_timer), this), (void *)"APU Timer"); - apust.timer->enable(false); if (machine().debug_flags & DEBUG_FLAG_ENABLED) debug_console_register_command(machine(), "chihiro", CMDFLAG_NONE, 0, 1, 4, chihiro_debug_commands); - memset(&ohcist, 0, sizeof(ohcist)); -#ifdef USB_ENABLED - ohcist.hc_regs[HcRevision] = 0x10; - ohcist.hc_regs[HcFmInterval] = 0x2edf; - ohcist.hc_regs[HcLSThreshold] = 0x628; - ohcist.hc_regs[HcRhDescriptorA] = 4; - ohcist.interruptbulkratio = 1; - ohcist.writebackdonehadcounter = 7; - ohcist.space = &m_maincpu->space(); - ohcist.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(chihiro_state::usb_ohci_timer), this), (void *)"USB OHCI Timer"); - ohcist.timer->enable(false); - usb_ohci_plug(1, new ohci_function_device()); // test connect -#endif usbhack_index = -1; for (int a = 1; a < 2; a++) if (strcmp(machine().basename(), hacks[a].game_name) == 0) { @@ -2571,72 +866,23 @@ void chihiro_state::machine_start() } usbhack_counter = 0; // savestates - save_item(NAME(debug_irq_active)); - save_item(NAME(debug_irq_number)); - save_item(NAME(smbusst.status)); - save_item(NAME(smbusst.control)); - save_item(NAME(smbusst.address)); - save_item(NAME(smbusst.data)); - save_item(NAME(smbusst.command)); - save_item(NAME(smbusst.rw)); - save_item(NAME(smbusst.words)); - save_item(NAME(pic16lc_buffer)); save_item(NAME(usbhack_counter)); - nvidia_nv2a->start(&m_maincpu->space()); - nvidia_nv2a->savestate_items(); } static SLOT_INTERFACE_START(ide_baseboard) SLOT_INTERFACE("bb", IDE_BASEBOARD) SLOT_INTERFACE_END -static MACHINE_CONFIG_START(chihiro_base, chihiro_state) +static MACHINE_CONFIG_DERIVED_CLASS(chihiro_base, xbox_base, chihiro_state) + MCFG_CPU_MODIFY("maincpu") + MCFG_CPU_PROGRAM_MAP(chihiro_map) + MCFG_CPU_IO_MAP(chihiro_map_io) - /* basic machine hardware */ - MCFG_CPU_ADD("maincpu", PENTIUM3, 733333333) /* Wrong! family 6 model 8 stepping 10 */ - MCFG_CPU_PROGRAM_MAP(xbox_map) - MCFG_CPU_IO_MAP(xbox_map_io) - MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(chihiro_state, irq_callback) - - MCFG_QUANTUM_TIME(attotime::from_hz(6000)) - - MCFG_PCI_BUS_LEGACY_ADD("pcibus", 0) - MCFG_PCI_BUS_LEGACY_DEVICE(0, "PCI Bridge Device - Host Bridge", dummy_pci_r, dummy_pci_w) - MCFG_PCI_BUS_LEGACY_DEVICE(1, "HUB Interface - ISA Bridge", hubintiasbridg_pci_r, hubintiasbridg_pci_w) - MCFG_PCI_BUS_LEGACY_DEVICE(2, "OHCI USB Controller 1", dummy_pci_r, dummy_pci_w) - MCFG_PCI_BUS_LEGACY_DEVICE(3, "OHCI USB Controller 2", dummy_pci_r, dummy_pci_w) - MCFG_PCI_BUS_LEGACY_DEVICE(4, "MCP Networking Adapter", dummy_pci_r, dummy_pci_w) - MCFG_PCI_BUS_LEGACY_DEVICE(5, "MCP APU", dummy_pci_r, dummy_pci_w) - MCFG_PCI_BUS_LEGACY_DEVICE(6, "AC`97 Audio Codec Interface", dummy_pci_r, dummy_pci_w) - MCFG_PCI_BUS_LEGACY_DEVICE(9, "IDE Controller", dummy_pci_r, dummy_pci_w) - MCFG_PCI_BUS_LEGACY_DEVICE(30, "AGP Host to PCI Bridge", dummy_pci_r, dummy_pci_w) - MCFG_PCI_BUS_LEGACY_ADD("agpbus", 1) - MCFG_PCI_BUS_LEGACY_SIBLING("pcibus") - MCFG_PCI_BUS_LEGACY_DEVICE(0, "NV2A GeForce 3MX Integrated GPU/Northbridge", geforce_pci_r, geforce_pci_w) - MCFG_PIC8259_ADD("pic8259_1", WRITELINE(chihiro_state, chihiro_pic8259_1_set_int_line), VCC, READ8(chihiro_state, get_slave_ack)) - MCFG_PIC8259_ADD("pic8259_2", DEVWRITELINE("pic8259_1", pic8259_device, ir2_w), GND, NULL) - - MCFG_DEVICE_ADD("pit8254", PIT8254, 0) - MCFG_PIT8253_CLK0(1125000) /* heartbeat IRQ */ - MCFG_PIT8253_OUT0_HANDLER(WRITELINE(chihiro_state, chihiro_pit8254_out0_changed)) - MCFG_PIT8253_CLK1(1125000) /* (unused) dram refresh */ - MCFG_PIT8253_CLK2(1125000) /* (unused) pio port c pin 4, and speaker polling enough */ - MCFG_PIT8253_OUT2_HANDLER(WRITELINE(chihiro_state, chihiro_pit8254_out2_changed)) - - MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide", ide_baseboard, NULL, "bb", true) - MCFG_ATA_INTERFACE_IRQ_HANDLER(DEVWRITELINE("pic8259_2", pic8259_device, ir6_w)) - MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE("maincpu", AS_PROGRAM) - - /* video hardware */ - MCFG_SCREEN_ADD("screen", RASTER) - MCFG_SCREEN_REFRESH_RATE(60) - MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ - MCFG_SCREEN_SIZE(640, 480) - MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 479) - MCFG_SCREEN_UPDATE_DRIVER(chihiro_state, screen_update_callback) - MCFG_SCREEN_VBLANK_DRIVER(chihiro_state, vblank_callback) - - MCFG_PALETTE_ADD("palette", 65536) + //MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide", ide_baseboard, NULL, "bb", true) + MCFG_DEVICE_MODIFY("ide:0") + MCFG_DEVICE_SLOT_INTERFACE(ide_baseboard, NULL, true) + MCFG_DEVICE_MODIFY("ide:1") + MCFG_DEVICE_SLOT_INTERFACE(ide_baseboard, "bb", true) MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED(chihirogd, chihiro_base) @@ -2650,7 +896,7 @@ MACHINE_CONFIG_END ROMX_LOAD(name, offset, length, hash, ROM_BIOS(bios+1)) /* Note '+1' */ #define CHIHIRO_BIOS \ - ROM_REGION( 0x1000000, "bios", 0) \ + ROM_REGION( 0x80000, "bios", 0) \ ROM_SYSTEM_BIOS( 0, "bios0", "Chihiro Bios" ) \ ROM_LOAD_BIOS( 0, "chihiro_xbox_bios.bin", 0x000000, 0x80000, CRC(66232714) SHA1(b700b0041af8f84835e45d1d1250247bf7077188) ) \ ROM_REGION( 0x404080, "others", 0) \ diff --git a/src/mame/includes/xbox.h b/src/mame/includes/xbox.h new file mode 100644 index 00000000000..e51067a37ef --- /dev/null +++ b/src/mame/includes/xbox.h @@ -0,0 +1,321 @@ +// license:BSD-3-Clause +// copyright-holders:Samuele Zannoli + +struct OHCIEndpointDescriptor { + int mps; // MaximumPacketSize + int f; // Format + int k; // sKip + int s; // Speed + int d; // Direction + int en; // EndpointNumber + int fa; // FunctionAddress + UINT32 tailp; // TDQueueTailPointer + UINT32 headp; // TDQueueHeadPointer + UINT32 nexted; // NextED + int c; // toggleCarry + int h; // Halted + UINT32 word0; +}; + +struct OHCITransferDescriptor { + int cc; // ConditionCode + int ec; // ErrorCount + int t; // DataToggle + int di; // DelayInterrupt + int dp; // Direction/PID + int r; // bufferRounding + UINT32 cbp; // CurrentBufferPointer + UINT32 nexttd; // NextTD + UINT32 be; // BufferEnd + UINT32 word0; +}; + +struct OHCIIsochronousTransferDescriptor { + int cc; // ConditionCode + int fc; // FrameCount + int di; // DelayInterrupt + int sf; // StartingFrame + UINT32 bp0; // BufferPage0 + UINT32 nexttd; // NextTD + UINT32 be; // BufferEnd + UINT32 offset[8]; // Offset/PacketStatusWord +}; + +enum OHCIRegisters { + HcRevision=0, + HcControl, + HcCommandStatus, + HcInterruptStatus, + HcInterruptEnable, + HcInterruptDisable, + HcHCCA, + HcPeriodCurrentED, + HcControlHeadED, + HcControlCurrentED, + HcBulkHeadED, + HcBulkCurrentED, + HcDoneHead, + HcFmInterval, + HcFmRemaining, + HcFmNumber, + HcPeriodicStart, + HcLSThreshold, + HcRhDescriptorA, + HcRhDescriptorB, + HcRhStatus, + HcRhPortStatus1 +}; + +enum OHCIHostControllerFunctionalState { + UsbReset=0, + UsbResume, + UsbOperational, + UsbSuspend +}; + +enum OHCIInterrupt { + SchedulingOverrun=1, + WritebackDoneHead=2, + StartofFrame=4, + ResumeDetected=8, + UnrecoverableError=16, + FrameNumberOverflow=32, + RootHubStatusChange=64, + OwnershipChange=0x40000000, + MasterInterruptEnable=0x80000000 +}; + +enum OHCICompletionCode { + NoError=0, + CRC, + BitStuffing, + DataToggleMismatch, + Stall, + DeviceNotResponding, + PIDCheckFailure, + UnexpectedPID, + DataOverrun, + DataUnderrun, + BufferOverrun=12, + BufferUnderrun, + NotAccessed=14 +}; + +struct USBSetupPacket { + UINT8 bmRequestType; + UINT8 bRequest; + UINT16 wValue; + UINT16 wIndex; + UINT16 wLength; +}; + +struct USBStandardDeviceDscriptor { + UINT8 bLength; + UINT8 bDescriptorType; + UINT16 bcdUSB; + UINT8 bDeviceClass; + UINT8 bDeviceSubClass; + UINT8 bDeviceProtocol; + UINT8 bMaxPacketSize0; + UINT16 idVendor; + UINT16 idProduct; + UINT16 bcdDevice; + UINT8 iManufacturer; + UINT8 iProduct; + UINT8 iSerialNumber; + UINT8 bNumConfigurations; +}; + +struct USBStandardConfigurationDescriptor { + UINT8 bLength; + UINT8 bDescriptorType; + UINT16 wTotalLength; + UINT8 bNumInterfaces; + UINT8 bConfigurationValue; + UINT8 iConfiguration; + UINT8 bmAttributes; + UINT8 MaxPower; +}; + +struct USBStandardInterfaceDescriptor { + UINT8 bLength; + UINT8 bDescriptorType; + UINT8 bInterfaceNumber; + UINT8 bAlternateSetting; + UINT8 bNumEndpoints; + UINT8 bInterfaceClass; + UINT8 bInterfaceSubClass; + UINT8 bInterfaceProtocol; + UINT8 iInterface; +}; + +struct USBStandardEndpointDescriptor { + UINT8 bLength; + UINT8 bDescriptorType; + UINT8 bEndpointAddress; + UINT8 bmAttributes; + UINT16 wMaxPacketSize; + UINT8 bInterval; +}; + +enum USBPid { + SetupPid=0, + OutPid, + InPid +}; + +enum USBRequestCode { + GET_STATUS=0, + CLEAR_FEATURE=1, + SET_FEATURE=3, + SET_ADDRESS=5, + GET_DESCRIPTOR=6, + SET_DESCRIPTOR=7, + GET_CONFIGURATION=8, + SET_CONFIGURATION=9, + GET_INTERFACE=10, + SET_INTERFACE=11, + SYNCH_FRAME=12 +}; + +enum USBDescriptorType { + DEVICE=1, + CONFIGURATION=2, + STRING=3, + INTERFACE=4, + ENDPOINT=5 +}; + +class ohci_function_device { +public: + ohci_function_device(); + void execute_reset(); + int execute_transfer(int address, int endpoint, int pid, UINT8 *buffer, int size); +private: + int address; + int controldir; + int remain; + UINT8 *position; +}; + +class xbox_base_state : public driver_device +{ +public: + xbox_base_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + nvidia_nv2a(NULL), + debug_irq_active(false), + debug_irq_number(0), + m_maincpu(*this, "maincpu") { } + + DECLARE_READ32_MEMBER(geforce_r); + DECLARE_WRITE32_MEMBER(geforce_w); + DECLARE_READ32_MEMBER(usbctrl_r); + DECLARE_WRITE32_MEMBER(usbctrl_w); + DECLARE_READ32_MEMBER(smbus_r); + DECLARE_WRITE32_MEMBER(smbus_w); + DECLARE_READ32_MEMBER(audio_apu_r); + DECLARE_WRITE32_MEMBER(audio_apu_w); + DECLARE_READ32_MEMBER(audio_ac93_r); + DECLARE_WRITE32_MEMBER(audio_ac93_w); + DECLARE_READ32_MEMBER(dummy_r); + DECLARE_WRITE32_MEMBER(dummy_w); + + void smbus_register_device(int address, int(*handler)(xbox_base_state &chs, int command, int rw, int data)); + int smbus_pic16lc(int command, int rw, int data); + int smbus_cx25871(int command, int rw, int data); + int smbus_eeprom(int command, int rw, int data); + void usb_ohci_plug(int port, ohci_function_device *function); + void usb_ohci_interrupts(); + void usb_ohci_read_endpoint_descriptor(UINT32 address); + void usb_ohci_writeback_endpoint_descriptor(UINT32 address); + void usb_ohci_read_transfer_descriptor(UINT32 address); + void usb_ohci_writeback_transfer_descriptor(UINT32 address); + void usb_ohci_read_isochronous_transfer_descriptor(UINT32 address); + void dword_write_le(UINT8 *addr, UINT32 d); + void word_write_le(UINT8 *addr, UINT16 d); + void debug_generate_irq(int irq, bool active); + virtual void hack_eeprom() {}; + virtual void hack_usb() {}; + + void vblank_callback(screen_device &screen, bool state); + UINT32 screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + + virtual void machine_start(); + DECLARE_WRITE_LINE_MEMBER(xbox_pic8259_1_set_int_line); + DECLARE_READ8_MEMBER(get_slave_ack); + DECLARE_WRITE_LINE_MEMBER(xbox_pit8254_out0_changed); + DECLARE_WRITE_LINE_MEMBER(xbox_pit8254_out2_changed); + IRQ_CALLBACK_MEMBER(irq_callback); + TIMER_CALLBACK_MEMBER(audio_apu_timer); + TIMER_CALLBACK_MEMBER(usb_ohci_timer); + + struct xbox_devices { + pic8259_device *pic8259_1; + pic8259_device *pic8259_2; + bus_master_ide_controller_device *ide; + } xbox_base_devs; + struct smbus_state { + int status; + int control; + int address; + int data; + int command; + int rw; + int(*devices[128])(xbox_base_state &chs, int command, int rw, int data); + UINT32 words[256 / 4]; + } smbusst; + struct apu_state { + UINT32 memory[0x60000 / 4]; + UINT32 gpdsp_sgaddress; // global processor scatter-gather + UINT32 gpdsp_sgblocks; + UINT32 gpdsp_address; + UINT32 epdsp_sgaddress; // encoder processor scatter-gather + UINT32 epdsp_sgblocks; + UINT32 unknown_sgaddress; + UINT32 unknown_sgblocks; + int voice_number; + UINT32 voices_heap_blockaddr[1024]; + UINT64 voices_active[4]; //one bit for each voice: 1 playing 0 not + UINT32 voicedata_address; + int voices_frequency[256]; // sample rate + int voices_position[256]; // position in samples * 1000 + int voices_position_start[256]; // position in samples * 1000 + int voices_position_end[256]; // position in samples * 1000 + int voices_position_increment[256]; // position increment every 1ms * 1000 + emu_timer *timer; + address_space *space; + } apust; + struct ac97_state { + UINT32 mixer_regs[0x80 / 4]; + UINT32 controller_regs[0x38 / 4]; + } ac97st; + struct ohci_state { + UINT32 hc_regs[255]; + struct { + ohci_function_device *function; + int delay; + } ports[4 + 1]; + emu_timer *timer; + int state; + UINT32 framenumber; + UINT32 nextinterupted; + UINT32 nextbulked; + int interruptbulkratio; + int writebackdonehadcounter; + address_space *space; + UINT8 buffer[1024]; + OHCIEndpointDescriptor endpoint_descriptor; + OHCITransferDescriptor transfer_descriptor; + OHCIIsochronousTransferDescriptor isochronous_transfer_descriptor; + } ohcist; + UINT8 pic16lc_buffer[0xff]; + nv2a_renderer *nvidia_nv2a; + bool debug_irq_active; + int debug_irq_number; + required_device m_maincpu; +}; + +ADDRESS_MAP_EXTERN(xbox_base_map, 32); +ADDRESS_MAP_EXTERN(xbox_base_map_io, 32); +MACHINE_CONFIG_EXTERN(xbox_base); \ No newline at end of file diff --git a/src/mame/machine/xbox.c b/src/mame/machine/xbox.c new file mode 100644 index 00000000000..047dc2ad9a5 --- /dev/null +++ b/src/mame/machine/xbox.c @@ -0,0 +1,1548 @@ +// license:BSD-3-Clause +// copyright-holders:Samuele Zannoli + +#include "emu.h" +#include "cpu/i386/i386.h" +#include "machine/lpci.h" +#include "machine/pic8259.h" +#include "machine/pit8253.h" +#include "machine/idectrl.h" +#include "machine/idehd.h" +#include "video/poly.h" +#include "bitmap.h" +#include "debug/debugcon.h" +#include "debug/debugcmd.h" +#include "debug/debugcpu.h" +#include "includes/chihiro.h" +#include "includes/xbox.h" + +// for now, make buggy GCC/Mingw STFU about I64FMT +#if (defined(__MINGW32__) && (__GNUC__ >= 5)) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wformat-extra-args" +#endif + +#define LOG_PCI +//#define LOG_OHCI +//#define USB_ENABLED + +static void dump_string_command(running_machine &machine, int ref, int params, const char **param) +{ + xbox_base_state *state = machine.driver_data(); + address_space &space = state->m_maincpu->space(); + UINT64 addr; + offs_t address; + UINT32 length, maximumlength; + offs_t buffer; + + if (params < 1) + return; + if (!debug_command_parameter_number(machine, param[0], &addr)) + return; + address = (offs_t)addr; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + { + debug_console_printf(machine, "Address is unmapped.\n"); + return; + } + length = space.read_word_unaligned(address); + maximumlength = space.read_word_unaligned(address + 2); + buffer = space.read_dword_unaligned(address + 4); + debug_console_printf(machine, "Length %d word\n", length); + debug_console_printf(machine, "MaximumLength %d word\n", maximumlength); + debug_console_printf(machine, "Buffer %08X byte* ", buffer); + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &buffer)) + { + debug_console_printf(machine, "\nBuffer is unmapped.\n"); + return; + } + if (length > 256) + length = 256; + for (int a = 0; a < length; a++) + { + UINT8 c = space.read_byte(buffer + a); + debug_console_printf(machine, "%c", c); + } + debug_console_printf(machine, "\n"); +} + +static void dump_process_command(running_machine &machine, int ref, int params, const char **param) +{ + xbox_base_state *state = machine.driver_data(); + address_space &space = state->m_maincpu->space(); + UINT64 addr; + offs_t address; + + if (params < 1) + return; + if (!debug_command_parameter_number(machine, param[0], &addr)) + return; + address = (offs_t)addr; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + { + debug_console_printf(machine, "Address is unmapped.\n"); + return; + } + debug_console_printf(machine, "ReadyListHead {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address), space.read_dword_unaligned(address + 4)); + debug_console_printf(machine, "ThreadListHead {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 8), space.read_dword_unaligned(address + 12)); + debug_console_printf(machine, "StackCount %d dword\n", space.read_dword_unaligned(address + 16)); + debug_console_printf(machine, "ThreadQuantum %d dword\n", space.read_dword_unaligned(address + 20)); + debug_console_printf(machine, "BasePriority %d byte\n", space.read_byte(address + 24)); + debug_console_printf(machine, "DisableBoost %d byte\n", space.read_byte(address + 25)); + debug_console_printf(machine, "DisableQuantum %d byte\n", space.read_byte(address + 26)); + debug_console_printf(machine, "_padding %d byte\n", space.read_byte(address + 27)); +} + +static void dump_list_command(running_machine &machine, int ref, int params, const char **param) +{ + xbox_base_state *state = machine.driver_data(); + address_space &space = state->m_maincpu->space(); + UINT64 addr, offs, start, old; + offs_t address, offset; + + if (params < 1) + return; + if (!debug_command_parameter_number(machine, param[0], &addr)) + return; + offs = 0; + offset = 0; + if (params >= 2) + { + if (!debug_command_parameter_number(machine, param[1], &offs)) + return; + offset = (offs_t)offs; + } + start = addr; + address = (offs_t)addr; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + { + debug_console_printf(machine, "Address is unmapped.\n"); + return; + } + if (params >= 2) + debug_console_printf(machine, "Entry Object\n"); + else + debug_console_printf(machine, "Entry\n"); + for (int num = 0; num < 32; num++) + { + if (params >= 2) + debug_console_printf(machine, "%08X %08X\n", (UINT32)addr, (offs_t)addr - offset); + else + debug_console_printf(machine, "%08X\n", (UINT32)addr); + old = addr; + addr = space.read_dword_unaligned(address); + if (addr == start) + break; + if (addr == old) + break; + address = (offs_t)addr; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + break; + } +} + +static void dump_dpc_command(running_machine &machine, int ref, int params, const char **param) +{ + xbox_base_state *state = machine.driver_data(); + address_space &space = state->m_maincpu->space(); + UINT64 addr; + offs_t address; + + if (params < 1) + return; + if (!debug_command_parameter_number(machine, param[0], &addr)) + return; + address = (offs_t)addr; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + { + debug_console_printf(machine, "Address is unmapped.\n"); + return; + } + debug_console_printf(machine, "Type %d word\n", space.read_word_unaligned(address)); + debug_console_printf(machine, "Inserted %d byte\n", space.read_byte(address + 2)); + debug_console_printf(machine, "Padding %d byte\n", space.read_byte(address + 3)); + debug_console_printf(machine, "DpcListEntry {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 4), space.read_dword_unaligned(address + 8)); + debug_console_printf(machine, "DeferredRoutine %08X dword\n", space.read_dword_unaligned(address + 12)); + debug_console_printf(machine, "DeferredContext %08X dword\n", space.read_dword_unaligned(address + 16)); + debug_console_printf(machine, "SystemArgument1 %08X dword\n", space.read_dword_unaligned(address + 20)); + debug_console_printf(machine, "SystemArgument2 %08X dword\n", space.read_dword_unaligned(address + 24)); +} + +static void dump_timer_command(running_machine &machine, int ref, int params, const char **param) +{ + xbox_base_state *state = machine.driver_data(); + address_space &space = state->m_maincpu->space(); + UINT64 addr; + offs_t address; + + if (params < 1) + return; + if (!debug_command_parameter_number(machine, param[0], &addr)) + return; + address = (offs_t)addr; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + { + debug_console_printf(machine, "Address is unmapped.\n"); + return; + } + debug_console_printf(machine, "Header.Type %d byte\n", space.read_byte(address)); + debug_console_printf(machine, "Header.Absolute %d byte\n", space.read_byte(address + 1)); + debug_console_printf(machine, "Header.Size %d byte\n", space.read_byte(address + 2)); + debug_console_printf(machine, "Header.Inserted %d byte\n", space.read_byte(address + 3)); + debug_console_printf(machine, "Header.SignalState %08X dword\n", space.read_dword_unaligned(address + 4)); + debug_console_printf(machine, "Header.WaitListEntry {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 8), space.read_dword_unaligned(address + 12)); + debug_console_printf(machine, "DueTime %" I64FMT "x qword\n", (INT64)space.read_qword_unaligned(address + 16)); + debug_console_printf(machine, "TimerListEntry {%08X,%08X} _LIST_ENTRY\n", space.read_dword_unaligned(address + 24), space.read_dword_unaligned(address + 28)); + debug_console_printf(machine, "Dpc %08X dword\n", space.read_dword_unaligned(address + 32)); + debug_console_printf(machine, "Period %d dword\n", space.read_dword_unaligned(address + 36)); +} + +static void curthread_command(running_machine &machine, int ref, int params, const char **param) +{ + xbox_base_state *state = machine.driver_data(); + address_space &space = state->m_maincpu->space(); + UINT64 fsbase; + UINT32 kthrd, topstack, tlsdata; + offs_t address; + + fsbase = state->m_maincpu->state_int(44); + address = (offs_t)fsbase + 0x28; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + { + debug_console_printf(machine, "Address is unmapped.\n"); + return; + } + kthrd = space.read_dword_unaligned(address); + debug_console_printf(machine, "Current thread is %08X\n", kthrd); + address = (offs_t)kthrd + 0x1c; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + return; + topstack = space.read_dword_unaligned(address); + debug_console_printf(machine, "Current thread stack top is %08X\n", topstack); + address = (offs_t)kthrd + 0x28; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + return; + tlsdata = space.read_dword_unaligned(address); + if (tlsdata == 0) + address = (offs_t)topstack - 0x210 - 8; + else + address = (offs_t)tlsdata - 8; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) + return; + debug_console_printf(machine, "Current thread function is %08X\n", space.read_dword_unaligned(address)); +} + +static void generate_irq_command(running_machine &machine, int ref, int params, const char **param) +{ + UINT64 irq; + xbox_base_state *chst = machine.driver_data(); + + if (params < 1) + return; + if (!debug_command_parameter_number(machine, param[0], &irq)) + return; + if (irq > 15) + return; + if (irq == 2) + return; + chst->debug_generate_irq((int)irq, true); +} + +static void nv2a_combiners_command(running_machine &machine, int ref, int params, const char **param) +{ + int en; + + xbox_base_state *chst = machine.driver_data(); + en = chst->nvidia_nv2a->toggle_register_combiners_usage(); + if (en != 0) + debug_console_printf(machine, "Register combiners enabled\n"); + else + debug_console_printf(machine, "Register combiners disabled\n"); +} + +static void waitvblank_command(running_machine &machine, int ref, int params, const char **param) +{ + int en; + + xbox_base_state *chst = machine.driver_data(); + en = chst->nvidia_nv2a->toggle_wait_vblank_support(); + if (en != 0) + debug_console_printf(machine, "Vblank method enabled\n"); + else + debug_console_printf(machine, "Vblank method disabled\n"); +} + +static void grab_texture_command(running_machine &machine, int ref, int params, const char **param) +{ + UINT64 type; + xbox_base_state *chst = machine.driver_data(); + + if (params < 2) + return; + if (!debug_command_parameter_number(machine, param[0], &type)) + return; + if ((param[1][0] == 0) || (strlen(param[1]) > 127)) + return; + chst->nvidia_nv2a->debug_grab_texture((int)type, param[1]); +} + +static void grab_vprog_command(running_machine &machine, int ref, int params, const char **param) +{ + xbox_base_state *chst = machine.driver_data(); + UINT32 instruction[4]; + FILE *fil; + + if (params < 1) + return; + if ((param[0][0] == 0) || (strlen(param[0]) > 127)) + return; + if ((fil = fopen(param[0], "wb")) == NULL) + return; + for (int n = 0; n < 136; n++) { + chst->nvidia_nv2a->debug_grab_vertex_program_slot(n, instruction); + fwrite(instruction, sizeof(UINT32), 4, fil); + } + fclose(fil); +} + +static void vprogdis_command(running_machine &machine, int ref, int params, const char **param) +{ + UINT64 address, length, type; + UINT32 instruction[4]; + offs_t addr; + vertex_program_disassembler vd; + char line[64]; + xbox_base_state *chst = machine.driver_data(); + address_space &space = chst->m_maincpu->space(); + + if (params < 2) + return; + if (!debug_command_parameter_number(machine, param[0], &address)) + return; + if (!debug_command_parameter_number(machine, param[1], &length)) + return; + type = 0; + if (params > 2) + if (!debug_command_parameter_number(machine, param[2], &type)) + return; + while (length > 0) { + if (type == 1) { + addr = (offs_t)address; + if (!debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &addr)) + return; + instruction[0] = space.read_dword_unaligned(address); + instruction[1] = space.read_dword_unaligned(address + 4); + instruction[2] = space.read_dword_unaligned(address + 8); + instruction[3] = space.read_dword_unaligned(address + 12); + } + else + chst->nvidia_nv2a->debug_grab_vertex_program_slot((int)address, instruction); + while (vd.disassemble(instruction, line) != 0) + debug_console_printf(machine, "%s\n", line); + if (type == 1) + address = address + 4 * 4; + else + address++; + length--; + } +} + +static void help_command(running_machine &machine, int ref, int params, const char **param) +{ + debug_console_printf(machine, "Available Xbox commands:\n"); + debug_console_printf(machine, " xbox dump_string,
-- Dump _STRING object at
\n"); + debug_console_printf(machine, " xbox dump_process,
-- Dump _PROCESS object at
\n"); + debug_console_printf(machine, " xbox dump_list,
[,] -- Dump _LIST_ENTRY chain starting at
\n"); + debug_console_printf(machine, " xbox dump_dpc,
-- Dump _KDPC object at
\n"); + debug_console_printf(machine, " xbox dump_timer,
-- Dump _KTIMER object at
\n"); + debug_console_printf(machine, " xbox curthread -- Print information about current thread\n"); + debug_console_printf(machine, " xbox irq, -- Generate interrupt with irq number 0-15\n"); + debug_console_printf(machine, " xbox nv2a_combiners -- Toggle use of register combiners\n"); + debug_console_printf(machine, " xbox waitvblank -- Toggle support for wait vblank method\n"); + debug_console_printf(machine, " xbox grab_texture,, -- Save to the next used texture of type \n"); + debug_console_printf(machine, " xbox grab_vprog, -- save current vertex program instruction slots to \n"); + debug_console_printf(machine, " xbox vprogdis,
,[,] -- disassemble vertex program instructions at
of \n"); + debug_console_printf(machine, " xbox help -- this list\n"); +} + +static void xbox_debug_commands(running_machine &machine, int ref, int params, const char **param) +{ + if (params < 1) + return; + if (strcmp("dump_string", param[0]) == 0) + dump_string_command(machine, ref, params - 1, param + 1); + else if (strcmp("dump_process", param[0]) == 0) + dump_process_command(machine, ref, params - 1, param + 1); + else if (strcmp("dump_list", param[0]) == 0) + dump_list_command(machine, ref, params - 1, param + 1); + else if (strcmp("dump_dpc", param[0]) == 0) + dump_dpc_command(machine, ref, params - 1, param + 1); + else if (strcmp("dump_timer", param[0]) == 0) + dump_timer_command(machine, ref, params - 1, param + 1); + else if (strcmp("curthread", param[0]) == 0) + curthread_command(machine, ref, params - 1, param + 1); + else if (strcmp("irq", param[0]) == 0) + generate_irq_command(machine, ref, params - 1, param + 1); + else if (strcmp("nv2a_combiners", param[0]) == 0) + nv2a_combiners_command(machine, ref, params - 1, param + 1); + else if (strcmp("waitvblank", param[0]) == 0) + waitvblank_command(machine, ref, params - 1, param + 1); + else if (strcmp("grab_texture", param[0]) == 0) + grab_texture_command(machine, ref, params - 1, param + 1); + else if (strcmp("grab_vprog", param[0]) == 0) + grab_vprog_command(machine, ref, params - 1, param + 1); + else if (strcmp("vprogdis", param[0]) == 0) + vprogdis_command(machine, ref, params - 1, param + 1); + else + help_command(machine, ref, params - 1, param + 1); +} + +void xbox_base_state::debug_generate_irq(int irq, bool active) +{ + int state; + + if (active) + { + debug_irq_active = true; + debug_irq_number = irq; + state = 1; + } + else + { + debug_irq_active = false; + state = 0; + } + switch (irq) + { + case 0: + xbox_base_devs.pic8259_1->ir0_w(state); + break; + case 1: + xbox_base_devs.pic8259_1->ir1_w(state); + break; + case 3: + xbox_base_devs.pic8259_1->ir3_w(state); + break; + case 4: + xbox_base_devs.pic8259_1->ir4_w(state); + break; + case 5: + xbox_base_devs.pic8259_1->ir5_w(state); + break; + case 6: + xbox_base_devs.pic8259_1->ir6_w(state); + break; + case 7: + xbox_base_devs.pic8259_1->ir7_w(state); + break; + case 8: + xbox_base_devs.pic8259_2->ir0_w(state); + break; + case 9: + xbox_base_devs.pic8259_2->ir1_w(state); + break; + case 10: + xbox_base_devs.pic8259_2->ir2_w(state); + break; + case 11: + xbox_base_devs.pic8259_2->ir3_w(state); + break; + case 12: + xbox_base_devs.pic8259_2->ir4_w(state); + break; + case 13: + xbox_base_devs.pic8259_2->ir5_w(state); + break; + case 14: + xbox_base_devs.pic8259_2->ir6_w(state); + break; + case 15: + xbox_base_devs.pic8259_2->ir7_w(state); + break; + } +} + +void xbox_base_state::vblank_callback(screen_device &screen, bool state) +{ + if (nvidia_nv2a->vblank_callback(screen, state)) + xbox_base_devs.pic8259_1->ir3_w(1); // IRQ 3 + else + xbox_base_devs.pic8259_1->ir3_w(0); // IRQ 3 +} + +UINT32 xbox_base_state::screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + return nvidia_nv2a->screen_update_callback(screen, bitmap, cliprect); +} + +READ32_MEMBER(xbox_base_state::geforce_r) +{ + return nvidia_nv2a->geforce_r(space, offset, mem_mask); +} + +WRITE32_MEMBER(xbox_base_state::geforce_w) +{ + nvidia_nv2a->geforce_w(space, offset, data, mem_mask); +} + +static UINT32 geforce_pci_r(device_t *busdevice, device_t *device, int function, int reg, UINT32 mem_mask) +{ +#ifdef LOG_PCI + // logerror(" bus:1 device:NV_2A function:%d register:%d mask:%08X\n",function,reg,mem_mask); +#endif + return 0; +} + +static void geforce_pci_w(device_t *busdevice, device_t *device, int function, int reg, UINT32 data, UINT32 mem_mask) +{ +#ifdef LOG_PCI + // logerror(" bus:1 device:NV_2A function:%d register:%d data:%08X mask:%08X\n",function,reg,data,mem_mask); +#endif +} + +/* + * ohci usb controller (placeholder for now) + */ + +#ifdef LOG_OHCI +static const char *const usbregnames[] = { + "HcRevision", + "HcControl", + "HcCommandStatus", + "HcInterruptStatus", + "HcInterruptEnable", + "HcInterruptDisable", + "HcHCCA", + "HcPeriodCurrentED", + "HcControlHeadED", + "HcControlCurrentED", + "HcBulkHeadED", + "HcBulkCurrentED", + "HcDoneHead", + "HcFmInterval", + "HcFmRemaining", + "HcFmNumber", + "HcPeriodicStart", + "HcLSThreshold", + "HcRhDescriptorA", + "HcRhDescriptorB", + "HcRhStatus", + "HcRhPortStatus[1]" +}; +#endif + +static const struct { + const char *game_name; + struct { + UINT32 address; + UINT8 write_byte; + } modify[16]; +} hacks[2] = { { "chihiro", { { 0x6a79f, 0x01 }, { 0x6a7a0, 0x00 }, { 0x6b575, 0x00 }, { 0x6b576, 0x00 }, { 0x6b5af, 0x75 }, { 0x6b78a, 0x75 }, { 0x6b7ca, 0x00 }, { 0x6b7b8, 0x00 }, { 0x8f5b2, 0x75 }, { 0x79a9e, 0x74 }, { 0x79b80, 0x74 }, { 0x79b97, 0x74 }, { 0, 0 } } }, + { "outr2", { { 0x12e4cf, 0x01 }, { 0x12e4d0, 0x00 }, { 0x4793e, 0x01 }, { 0x4793f, 0x00 }, { 0x47aa3, 0x01 }, { 0x47aa4, 0x00 }, { 0x14f2b6, 0x84 }, { 0x14f2d1, 0x75 }, { 0x8732f, 0x7d }, { 0x87384, 0x7d }, { 0x87388, 0xeb }, { 0, 0 } } } }; + +READ32_MEMBER(xbox_base_state::usbctrl_r) +{ + UINT32 ret; + +#ifdef LOG_OHCI + if (offset >= 0x54 / 4) + logerror("usb controller 0 register HcRhPortStatus[%d] read\n", (offset - 0x54 / 4) + 1); + else + logerror("usb controller 0 register %s read\n", usbregnames[offset]); +#endif + ret=ohcist.hc_regs[offset]; + if (offset == 0) { /* hacks needed until usb (and jvs) is implemented */ +#ifndef USB_ENABLED + hack_usb(); +#endif + } + return ret; +} + +WRITE32_MEMBER(xbox_base_state::usbctrl_w) +{ +#ifdef USB_ENABLED + UINT32 old = ohcist.hc_regs[offset]; +#endif + +#ifdef LOG_OHCI + if (offset >= 0x54 / 4) + logerror("usb controller 0 register HcRhPortStatus[%d] write %08X\n", (offset - 0x54 / 4) + 1, data); + else + logerror("usb controller 0 register %s write %08X\n", usbregnames[offset], data); +#endif +#ifdef USB_ENABLED + if (offset == HcRhStatus) { + if (data & 0x80000000) + ohcist.hc_regs[HcRhStatus] &= ~0x8000; + if (data & 0x00020000) + ohcist.hc_regs[HcRhStatus] &= ~0x0002; + if (data & 0x00010000) + ohcist.hc_regs[HcRhStatus] &= ~0x0001; + return; + } + if (offset == HcControl) { + int hcfs; + + hcfs = (data >> 6) & 3; + if (hcfs == UsbOperational) { + ohcist.timer->enable(); + ohcist.timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1)); + ohcist.writebackdonehadcounter = 7; + } + else + ohcist.timer->enable(false); + ohcist.state = hcfs; + ohcist.interruptbulkratio = (data & 3) + 1; + } + if (offset == HcCommandStatus) { + if (data & 1) + ohcist.hc_regs[HcControl] |= 3 << 6; + ohcist.hc_regs[HcCommandStatus] |= data; + return; + } + if (offset == HcInterruptStatus) { + ohcist.hc_regs[HcInterruptStatus] &= ~data; + usb_ohci_interrupts(); + return; + } + if (offset == HcInterruptEnable) { + ohcist.hc_regs[HcInterruptEnable] |= data; + usb_ohci_interrupts(); + return; + } + if (offset == HcInterruptDisable) { + ohcist.hc_regs[HcInterruptEnable] &= ~data; + usb_ohci_interrupts(); + return; + } + if (offset >= HcRhPortStatus1) { + int port = offset - HcRhPortStatus1 + 1; // port 0 not used + // bit 0 ClearPortEnable: 1 clears PortEnableStatus + // bit 1 SetPortEnable: 1 sets PortEnableStatus + // bit 2 SetPortSuspend: 1 sets PortSuspendStatus + // bit 3 ClearSuspendStatus: 1 clears PortSuspendStatus + // bit 4 SetPortReset: 1 sets PortResetStatus + if (data & 0x10) { + ohcist.hc_regs[offset] |= 0x10; + ohcist.ports[port].function->execute_reset(); + // after 10ms set PortResetStatusChange and clear PortResetStatus and set PortEnableStatus + ohcist.ports[port].delay = 10; + } + // bit 8 SetPortPower: 1 sets PortPowerStatus + // bit 9 ClearPortPower: 1 clears PortPowerStatus + // bit 16 1 clears ConnectStatusChange + // bit 17 1 clears PortEnableStatusChange + // bit 18 1 clears PortSuspendStatusChange + // bit 19 1 clears PortOverCurrentIndicatorChange + // bit 20 1 clears PortResetStatusChange + if (ohcist.hc_regs[offset] != old) + ohcist.hc_regs[HcInterruptStatus] |= RootHubStatusChange; + usb_ohci_interrupts(); + return; + } +#endif + ohcist.hc_regs[offset] = data; +} + +TIMER_CALLBACK_MEMBER(xbox_base_state::usb_ohci_timer) +{ + UINT32 hcca; + int changed = 0; + int list = 1; + bool cont = false; + int pid, remain, mps; + + hcca = ohcist.hc_regs[HcHCCA]; + if (ohcist.state == UsbOperational) { + // increment frame number + ohcist.framenumber = (ohcist.framenumber + 1) & 0xffff; + ohcist.space->write_dword(hcca + 0x80, ohcist.framenumber); + ohcist.hc_regs[HcFmNumber] = ohcist.framenumber; + } + // port reset delay + for (int p = 1; p <= 4; p++) { + if (ohcist.ports[p].delay > 0) { + ohcist.ports[p].delay--; + if (ohcist.ports[p].delay == 0) { + ohcist.hc_regs[HcRhPortStatus1 + p - 1] = (ohcist.hc_regs[HcRhPortStatus1 + p - 1] & ~(1 << 4)) | (1 << 20) | (1 << 1); // bit 1 PortEnableStatus + changed = 1; + } + } + } + if (ohcist.state == UsbOperational) { + while (list >= 0) + { + // select list, do transfer + if (list == 0) { + if (ohcist.hc_regs[HcControl] & (1 << 2)) { + // periodic + if (ohcist.hc_regs[HcControl] & (1 << 3)) { + // isochronous + } + } + list = -1; + } + if (list == 1) { + // control + if (ohcist.hc_regs[HcControl] & (1 << 4)) { + cont = true; + while (cont == true) { + // if current endpoint descriptor is not 0 use it, otherwise ... + if (ohcist.hc_regs[HcControlCurrentED] == 0) { + // ... check the filled bit ... + if (ohcist.hc_regs[HcCommandStatus] & (1 << 1)) { + // ... if 1 start processing from the head of the list + ohcist.hc_regs[HcControlCurrentED] = ohcist.hc_regs[HcControlHeadED]; + ohcist.hc_regs[HcCommandStatus] &= ~(1 << 1); + // but if the list is empty, go to the next list + if (ohcist.hc_regs[HcControlCurrentED] == 0) + cont = false; + } + else + cont = false; + } + if (cont == true) { + // service endpoint descriptor + usb_ohci_read_endpoint_descriptor(ohcist.hc_regs[HcControlCurrentED]); + // only if it is not halted and not to be skipped + if (!(ohcist.endpoint_descriptor.h | ohcist.endpoint_descriptor.k)) { + // compare the Endpoint Descriptor?s TailPointer and NextTransferDescriptor fields. + if (ohcist.endpoint_descriptor.headp != ohcist.endpoint_descriptor.tailp) { + UINT32 a, b; + // service transfer descriptor + usb_ohci_read_transfer_descriptor(ohcist.endpoint_descriptor.headp); + // get pid + if (ohcist.endpoint_descriptor.d == 1) + pid=OutPid; // out + else if (ohcist.endpoint_descriptor.d == 2) + pid=InPid; // in + else { + pid = ohcist.transfer_descriptor.dp; // 0 setup 1 out 2 in + } + // determine how much data to transfer + // setup pid must be 8 bytes + a = ohcist.transfer_descriptor.be & 0xfff; + b = ohcist.transfer_descriptor.cbp & 0xfff; + if ((ohcist.transfer_descriptor.be ^ ohcist.transfer_descriptor.cbp) & 0xfffff000) + a |= 0x1000; + remain = a - b + 1; + if (pid == InPid) { + mps = ohcist.endpoint_descriptor.mps; + if (remain < mps) + mps = remain; + } + else { + mps = ohcist.endpoint_descriptor.mps; + } + if (ohcist.transfer_descriptor.cbp == 0) + mps = 0; + b = ohcist.transfer_descriptor.cbp; + // if sending ... + if (pid != InPid) { + // ... get mps bytes + for (int c = 0; c < mps; c++) { + ohcist.buffer[c] = ohcist.space->read_byte(b); + b++; + if ((b & 0xfff) == 0) + b = ohcist.transfer_descriptor.be & 0xfffff000; + } + } + // should check for time available + // execute transaction + mps=ohcist.ports[1].function->execute_transfer(ohcist.endpoint_descriptor.fa, ohcist.endpoint_descriptor.en, pid, ohcist.buffer, mps); + // if receiving ... + if (pid == InPid) { + // ... store mps bytes + for (int c = 0; c < mps; c++) { + ohcist.space->write_byte(b,ohcist.buffer[c]); + b++; + if ((b & 0xfff) == 0) + b = ohcist.transfer_descriptor.be & 0xfffff000; + } + } + // status writeback (CompletionCode field, DataToggleControl field, CurrentBufferPointer field, ErrorCount field) + ohcist.transfer_descriptor.cc = NoError; + ohcist.transfer_descriptor.t = (ohcist.transfer_descriptor.t ^ 1) | 2; + ohcist.transfer_descriptor.cbp = b; + ohcist.transfer_descriptor.ec = 0; + if ((remain == mps) || (mps == 0)) { + // retire transfer descriptor + a = ohcist.endpoint_descriptor.headp; + ohcist.endpoint_descriptor.headp = ohcist.transfer_descriptor.nexttd; + ohcist.transfer_descriptor.nexttd = ohcist.hc_regs[HcDoneHead]; + ohcist.hc_regs[HcDoneHead] = a; + ohcist.endpoint_descriptor.c = ohcist.transfer_descriptor.t & 1; + if (ohcist.transfer_descriptor.di != 7) { + if (ohcist.transfer_descriptor.di < ohcist.writebackdonehadcounter) + ohcist.writebackdonehadcounter = ohcist.transfer_descriptor.di; + } + usb_ohci_writeback_transfer_descriptor(a); + usb_ohci_writeback_endpoint_descriptor(ohcist.hc_regs[HcControlCurrentED]); + } else { + usb_ohci_writeback_transfer_descriptor(ohcist.endpoint_descriptor.headp); + } + } else + ohcist.hc_regs[HcControlCurrentED] = ohcist.endpoint_descriptor.nexted; + } else + ohcist.hc_regs[HcControlCurrentED] = ohcist.endpoint_descriptor.nexted; + // one bulk every n control transfers + ohcist.interruptbulkratio--; + if (ohcist.interruptbulkratio <= 0) { + ohcist.interruptbulkratio = (ohcist.hc_regs[HcControl] & 3) + 1; + cont = false; + } + } + } + } + list = 2; + } + if (list == 2) { + // bulk + if (ohcist.hc_regs[HcControl] & (1 << 5)) { + ohcist.hc_regs[HcCommandStatus] &= ~(1 << 2); + if (ohcist.hc_regs[HcControlCurrentED] == 0) + list = 0; + else if (ohcist.hc_regs[HcControl] & (1 << 4)) + list = 1; + else + list = 0; + } + } + } + if (ohcist.framenumber == 0) + ohcist.hc_regs[HcInterruptStatus] |= FrameNumberOverflow; + ohcist.hc_regs[HcInterruptStatus] |= StartofFrame; + if ((ohcist.writebackdonehadcounter != 0) && (ohcist.writebackdonehadcounter != 7)) + ohcist.writebackdonehadcounter--; + if ((ohcist.writebackdonehadcounter == 0) && ((ohcist.hc_regs[HcInterruptStatus] & WritebackDoneHead) == 0)) { + UINT32 b = 0; + + if ((ohcist.hc_regs[HcInterruptStatus] & ohcist.hc_regs[HcInterruptEnable]) != WritebackDoneHead) + b = 1; + ohcist.hc_regs[HcInterruptStatus] |= WritebackDoneHead; + ohcist.space->write_dword(hcca + 0x84, ohcist.hc_regs[HcDoneHead] | b); + ohcist.hc_regs[HcDoneHead] = 0; + ohcist.writebackdonehadcounter = 7; + } + } + if (changed != 0) { + ohcist.hc_regs[HcInterruptStatus] |= RootHubStatusChange; + } + usb_ohci_interrupts(); +} + +void xbox_base_state::usb_ohci_plug(int port, ohci_function_device *function) +{ + if ((port > 0) && (port <= 4)) { + ohcist.ports[port].function = function; + ohcist.hc_regs[HcRhPortStatus1+port-1] = 1; + } +} + +static USBStandardDeviceDscriptor devdesc = {18,1,0x201,0xff,0x34,0x56,64,0x100,0x101,0x301,0,0,0,1}; + +ohci_function_device::ohci_function_device() +{ + address = 0; + controldir = 0; + remain = 0; + position = NULL; +} + +void ohci_function_device::execute_reset() +{ + address = 0; +} + +int ohci_function_device::execute_transfer(int address, int endpoint, int pid, UINT8 *buffer, int size) +{ + if (endpoint == 0) { + if (pid == SetupPid) { + struct USBSetupPacket *p=(struct USBSetupPacket *)buffer; + // define direction + controldir = p->bmRequestType & 128; + // case !=0, in data stage and out status stage + // case ==0, out data stage and in status stage + position = NULL; + remain = p->wLength; + if ((p->bmRequestType & 0x60) == 0) { + switch (p->bRequest) { + case GET_DESCRIPTOR: + if ((p->wValue >> 8) == 1) { // device descriptor + //p->wValue & 255; + position = (UINT8 *)&devdesc; + remain = sizeof(devdesc); + } + break; + case SET_ADDRESS: + //p->wValue; + break; + default: + break; + } + } + } + else if (pid == InPid) { + // case !=0, give data + // case ==0, nothing + if (size > remain) + size = remain; + if (controldir != 0) { + if (position != NULL) + memcpy(buffer, position, size); + position = position + size; + remain = remain - size; + } + } + else if (pid == OutPid) { + // case !=0, nothing + // case ==0, give data + if (size > remain) + size = remain; + if (controldir == 0) { + if (position != NULL) + memcpy(position, buffer, size); + position = position + size; + remain = remain - size; + } + } + } + return size; +} + +void xbox_base_state::usb_ohci_interrupts() +{ + if (((ohcist.hc_regs[HcInterruptStatus] & ohcist.hc_regs[HcInterruptEnable]) != 0) && ((ohcist.hc_regs[HcInterruptEnable] & MasterInterruptEnable) != 0)) + xbox_base_devs.pic8259_1->ir1_w(1); + else + xbox_base_devs.pic8259_1->ir1_w(0); +} + +void xbox_base_state::usb_ohci_read_endpoint_descriptor(UINT32 address) +{ + UINT32 w; + + w = ohcist.space->read_dword(address); + ohcist.endpoint_descriptor.word0 = w; + ohcist.endpoint_descriptor.fa = w & 0x7f; + ohcist.endpoint_descriptor.en = (w >> 7) & 15; + ohcist.endpoint_descriptor.d = (w >> 11) & 3; + ohcist.endpoint_descriptor.s = (w >> 13) & 1; + ohcist.endpoint_descriptor.k = (w >> 14) & 1; + ohcist.endpoint_descriptor.f = (w >> 15) & 1; + ohcist.endpoint_descriptor.mps = (w >> 16) & 0x7ff; + ohcist.endpoint_descriptor.tailp = ohcist.space->read_dword(address + 4); + w = ohcist.space->read_dword(address + 8); + ohcist.endpoint_descriptor.headp = w & 0xfffffffc; + ohcist.endpoint_descriptor.h = w & 1; + ohcist.endpoint_descriptor.c = (w >> 1) & 1; + ohcist.endpoint_descriptor.nexted = ohcist.space->read_dword(address + 12); +} + +void xbox_base_state::usb_ohci_writeback_endpoint_descriptor(UINT32 address) +{ + UINT32 w; + + w = ohcist.endpoint_descriptor.word0 & 0xf8000000; + w = w | (ohcist.endpoint_descriptor.mps << 16) | (ohcist.endpoint_descriptor.f << 15) | (ohcist.endpoint_descriptor.k << 14) | (ohcist.endpoint_descriptor.s << 13) | (ohcist.endpoint_descriptor.d << 11) | (ohcist.endpoint_descriptor.en << 7) | ohcist.endpoint_descriptor.fa; + ohcist.space->write_dword(address, w); + w = ohcist.endpoint_descriptor.headp | (ohcist.endpoint_descriptor.c << 1) | ohcist.endpoint_descriptor.h; + ohcist.space->write_dword(address + 8, w); +} + +void xbox_base_state::usb_ohci_read_transfer_descriptor(UINT32 address) +{ + UINT32 w; + + w = ohcist.space->read_dword(address); + ohcist.transfer_descriptor.word0 = w; + ohcist.transfer_descriptor.cc = (w >> 28) & 15; + ohcist.transfer_descriptor.ec= (w >> 26) & 3; + ohcist.transfer_descriptor.t= (w >> 24) & 3; + ohcist.transfer_descriptor.di= (w >> 21) & 7; + ohcist.transfer_descriptor.dp= (w >> 19) & 3; + ohcist.transfer_descriptor.r = (w >> 18) & 1; + ohcist.transfer_descriptor.cbp = ohcist.space->read_dword(address + 4); + ohcist.transfer_descriptor.nexttd = ohcist.space->read_dword(address + 8); + ohcist.transfer_descriptor.be = ohcist.space->read_dword(address + 12); +} + +void xbox_base_state::usb_ohci_writeback_transfer_descriptor(UINT32 address) +{ + UINT32 w; + + w = ohcist.transfer_descriptor.word0 & 0x0003ffff; + w = w | (ohcist.transfer_descriptor.cc << 28) | (ohcist.transfer_descriptor.ec << 26) | (ohcist.transfer_descriptor.t << 24) | (ohcist.transfer_descriptor.di << 21) | (ohcist.transfer_descriptor.dp << 19) | (ohcist.transfer_descriptor.r << 18); + ohcist.space->write_dword(address, w); + ohcist.space->write_dword(address + 4, ohcist.transfer_descriptor.cbp); + ohcist.space->write_dword(address + 8, ohcist.transfer_descriptor.nexttd); +} + +void xbox_base_state::usb_ohci_read_isochronous_transfer_descriptor(UINT32 address) +{ + UINT32 w; + + w = ohcist.space->read_dword(address); + ohcist.isochronous_transfer_descriptor.cc = (w >> 28) & 15; + ohcist.isochronous_transfer_descriptor.fc = (w >> 24) & 7; + ohcist.isochronous_transfer_descriptor.di = (w >> 21) & 7; + ohcist.isochronous_transfer_descriptor.sf = w & 0xffff; + ohcist.isochronous_transfer_descriptor.bp0 = ohcist.space->read_dword(address + 4) & 0xfffff000; + ohcist.isochronous_transfer_descriptor.nexttd = ohcist.space->read_dword(address + 8); + ohcist.isochronous_transfer_descriptor.be = ohcist.space->read_dword(address + 12); + w = ohcist.space->read_dword(address + 16); + ohcist.isochronous_transfer_descriptor.offset[0] = w & 0xffff; + ohcist.isochronous_transfer_descriptor.offset[1] = (w >> 16) & 0xffff; + w = ohcist.space->read_dword(address + 20); + ohcist.isochronous_transfer_descriptor.offset[2] = w & 0xffff; + ohcist.isochronous_transfer_descriptor.offset[3] = (w >> 16) & 0xffff; + w = ohcist.space->read_dword(address + 24); + ohcist.isochronous_transfer_descriptor.offset[4] = w & 0xffff; + ohcist.isochronous_transfer_descriptor.offset[5] = (w >> 16) & 0xffff; + w = ohcist.space->read_dword(address + 28); + ohcist.isochronous_transfer_descriptor.offset[6] = w & 0xffff; + ohcist.isochronous_transfer_descriptor.offset[7] = (w >> 16) & 0xffff; +} + +/* + * Audio + */ + +READ32_MEMBER(xbox_base_state::audio_apu_r) +{ + logerror("Audio_APU: read from %08X mask %08X\n", 0xfe800000 + offset * 4, mem_mask); + if (offset == 0x20010 / 4) // some kind of internal counter or state value + return 0x20 + 4 + 8 + 0x48 + 0x80; + return apust.memory[offset]; +} + +WRITE32_MEMBER(xbox_base_state::audio_apu_w) +{ + //UINT32 old; + UINT32 v; + + logerror("Audio_APU: write at %08X mask %08X value %08X\n", 0xfe800000 + offset * 4, mem_mask, data); + //old = apust.memory[offset]; + apust.memory[offset] = data; + if (offset == 0x02040 / 4) // address of memory area with scatter-gather info (gpdsp scratch dma) + apust.gpdsp_sgaddress = data; + if (offset == 0x020d4 / 4) { // block count (gpdsp) + apust.gpdsp_sgblocks = data; + apust.gpdsp_address = apust.space->read_dword(apust.gpdsp_sgaddress); // memory address of first block + apust.timer->enable(); + apust.timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1)); + } + if (offset == 0x02048 / 4) // (epdsp scratch dma) + apust.epdsp_sgaddress = data; + if (offset == 0x020dc / 4) // (epdsp) + apust.epdsp_sgblocks = data; + if (offset == 0x0204c / 4) // address of memory area with information about blocks + apust.unknown_sgaddress = data; + if (offset == 0x020e0 / 4) // block count - 1 + apust.unknown_sgblocks = data; + if (offset == 0x0202c / 4) { // address of memory area with 0x80 bytes for each voice + apust.voicedata_address = data; + return; + } + if (offset == 0x04024 / 4) // offset in memory area indicated by 0x204c (analog output ?) + return; + if (offset == 0x04034 / 4) // size + return; + if (offset == 0x04028 / 4) // offset in memory area indicated by 0x204c (digital output ?) + return; + if (offset == 0x04038 / 4) // size + return; + if (offset == 0x20804 / 4) { // block number for scatter-gather heap that stores sampled audio to be played + if (data >= 1024) { + logerror("Audio_APU: sg block number too high, increase size of voices_heap_blockaddr\n"); + apust.memory[offset] = 1023; + } + return; + } + if (offset == 0x20808 / 4) { // block address for scatter-gather heap that stores sampled audio to be played + apust.voices_heap_blockaddr[apust.memory[0x20804 / 4]] = data; + return; + } + if (offset == 0x202f8 / 4) { // voice number for parameters ? + apust.voice_number = data; + return; + } + if (offset == 0x202fc / 4) // 1 when accessing voice parameters 0 otherwise + return; + if (offset == 0x20304 / 4) { // format + /* + bits 28-31 sample format: + 0 8-bit pcm + 5 16-bit pcm + 10 adpcm ? + 14 24-bit pcm + 15 32-bit pcm + bits 16-20 number of channels - 1: + 0 mono + 1 stereo + */ + return; + } + if (offset == 0x2037c / 4) { // value related to sample rate + INT16 v = (INT16)(data >> 16); // upper 16 bits as a signed 16 bit value + float vv = ((float)v) / 4096.0f; // divide by 4096 + float vvv = powf(2, vv); // two to the vv + int f = vvv*48000.0f; // sample rate + apust.voices_frequency[apust.voice_number] = f; + return; + } + if (offset == 0x203a0 / 4) // start offset of data in scatter-gather heap + return; + if (offset == 0x203a4 / 4) { // first sample to play + apust.voices_position_start[apust.voice_number] = data * 1000; + return; + } + if (offset == 0x203dc / 4) { // last sample to play + apust.voices_position_end[apust.voice_number] = data * 1000; + return; + } + if (offset == 0x2010c / 4) // voice processor 0 idle 1 not idle ? + return; + if (offset == 0x20124 / 4) { // voice number to activate ? + v = apust.voice_number; + apust.voices_active[v >> 6] |= ((UINT64)1 << (v & 63)); + apust.voices_position[v] = apust.voices_position_start[apust.voice_number]; + apust.voices_position_increment[apust.voice_number] = apust.voices_frequency[apust.voice_number]; + return; + } + if (offset == 0x20128 / 4) { // voice number to deactivate ? + v = apust.voice_number; + apust.voices_active[v >> 6] &= ~(1 << (v & 63)); + return; + } + if (offset == 0x20140 / 4) // voice number to ? + return; + if ((offset >= 0x20200 / 4) && (offset < 0x20280 / 4)) // headroom for each of the 32 mixbins + return; + if (offset == 0x20280 / 4) // hrtf headroom ? + return; +} + +READ32_MEMBER(xbox_base_state::audio_ac93_r) +{ + UINT32 ret = 0; + + logerror("Audio_AC3: read from %08X mask %08X\n", 0xfec00000 + offset * 4, mem_mask); + if (offset < 0x80 / 4) + { + ret = ac97st.mixer_regs[offset]; + } + if ((offset >= 0x100 / 4) && (offset <= 0x138 / 4)) + { + offset = offset - 0x100 / 4; + if (offset == 0x18 / 4) + { + ac97st.controller_regs[offset] &= ~0x02000000; // REGRST: register reset + } + if (offset == 0x30 / 4) + { + ac97st.controller_regs[offset] |= 0x100; // PCRDY: primary codec ready + } + if (offset == 0x34 / 4) + { + ac97st.controller_regs[offset] &= ~1; // CAS: codec access semaphore + } + ret = ac97st.controller_regs[offset]; + } + return ret; +} + +WRITE32_MEMBER(xbox_base_state::audio_ac93_w) +{ + logerror("Audio_AC3: write at %08X mask %08X value %08X\n", 0xfec00000 + offset * 4, mem_mask, data); + if (offset < 0x80 / 4) + { + COMBINE_DATA(ac97st.mixer_regs + offset); + } + if ((offset >= 0x100 / 4) && (offset <= 0x138 / 4)) + { + offset = offset - 0x100 / 4; + COMBINE_DATA(ac97st.controller_regs + offset); + } +} + +TIMER_CALLBACK_MEMBER(xbox_base_state::audio_apu_timer) +{ + int cmd; + int bb, b, v; + UINT64 bv; + UINT32 phys; + + cmd = apust.space->read_dword(apust.gpdsp_address + 0x800 + 0x10); + if (cmd == 3) + apust.space->write_dword(apust.gpdsp_address + 0x800 + 0x10, 0); + /*else + logerror("Audio_APU: unexpected value at address %d\n",apust.gpdsp_address+0x800+0x10);*/ + for (b = 0; b < 4; b++) { + bv = 1; + for (bb = 0; bb < 64; bb++) { + if (apust.voices_active[b] & bv) { + v = bb + (b << 6); + apust.voices_position[v] += apust.voices_position_increment[v]; + while (apust.voices_position[v] >= apust.voices_position_end[v]) + apust.voices_position[v] = apust.voices_position_start[v] + apust.voices_position[v] - apust.voices_position_end[v] - 1000; + phys = apust.voicedata_address + 0x80 * v; + apust.space->write_dword(phys + 0x58, apust.voices_position[v] / 1000); + } + bv = bv << 1; + } + } +} + +static UINT32 hubintiasbridg_pci_r(device_t *busdevice, device_t *device, int function, int reg, UINT32 mem_mask) +{ +#ifdef LOG_PCI + // logerror(" bus:0 function:%d register:%d mask:%08X\n",function,reg,mem_mask); +#endif + if ((function == 0) && (reg == 8)) + return 0xb4; // 0:1:0 revision id must be at least 0xb4, otherwise usb will require a hub + return 0; +} + +static void hubintiasbridg_pci_w(device_t *busdevice, device_t *device, int function, int reg, UINT32 data, UINT32 mem_mask) +{ +#ifdef LOG_PCI + if (reg >= 16) logerror(" bus:0 function:%d register:%d data:%08X mask:%08X\n", function, reg, data, mem_mask); +#endif +} + +/* + * dummy for non connected devices + */ + +static UINT32 dummy_pci_r(device_t *busdevice, device_t *device, int function, int reg, UINT32 mem_mask) +{ +#ifdef LOG_PCI + // logerror(" bus:0 function:%d register:%d mask:%08X\n",function,reg,mem_mask); +#endif + return 0; +} + +static void dummy_pci_w(device_t *busdevice, device_t *device, int function, int reg, UINT32 data, UINT32 mem_mask) +{ +#ifdef LOG_PCI + if (reg >= 16) logerror(" bus:0 function:%d register:%d data:%08X mask:%08X\n", function, reg, data, mem_mask); +#endif +} + +READ32_MEMBER(xbox_base_state::dummy_r) +{ + return 0; +} + +WRITE32_MEMBER(xbox_base_state::dummy_w) +{ +} + +/* + * PIC & PIT + */ + +WRITE_LINE_MEMBER(xbox_base_state::xbox_pic8259_1_set_int_line) +{ + m_maincpu->set_input_line(0, state ? HOLD_LINE : CLEAR_LINE); +} + +READ8_MEMBER(xbox_base_state::get_slave_ack) +{ + if (offset == 2) { // IRQ = 2 + return xbox_base_devs.pic8259_2->acknowledge(); + } + return 0x00; +} + +IRQ_CALLBACK_MEMBER(xbox_base_state::irq_callback) +{ + int r = 0; + r = xbox_base_devs.pic8259_2->acknowledge(); + if (r == 0) + { + r = xbox_base_devs.pic8259_1->acknowledge(); + } + if (debug_irq_active) + debug_generate_irq(debug_irq_number, false); + return r; +} + +WRITE_LINE_MEMBER(xbox_base_state::xbox_pit8254_out0_changed) +{ + if (xbox_base_devs.pic8259_1) + { + xbox_base_devs.pic8259_1->ir0_w(state); + } +} + +WRITE_LINE_MEMBER(xbox_base_state::xbox_pit8254_out2_changed) +{ + //xbox_speaker_set_input( state ? 1 : 0 ); +} + +/* + * SMbus devices + */ + +int smbus_callback_pic16lc(xbox_base_state &chs, int command, int rw, int data) +{ + return chs.smbus_pic16lc(command, rw, data); +} + +int xbox_base_state::smbus_pic16lc(int command, int rw, int data) +{ + if (rw == 1) { // read + if (command == 0) { + if (pic16lc_buffer[0] == 'D') + pic16lc_buffer[0] = 'X'; + else if (pic16lc_buffer[0] == 'X') + pic16lc_buffer[0] = 'B'; + else if (pic16lc_buffer[0] == 'B') + pic16lc_buffer[0] = 'D'; + } + logerror("pic16lc: %d %d %d\n", command, rw, pic16lc_buffer[command]); + return pic16lc_buffer[command]; + } + else + if (command == 0) + pic16lc_buffer[0] = 'B'; + else + pic16lc_buffer[command] = (UINT8)data; + logerror("pic16lc: %d %d %d\n", command, rw, data); + return 0; +} + +int smbus_callback_cx25871(xbox_base_state &chs, int command, int rw, int data) +{ + return chs.smbus_cx25871(command, rw, data); +} + +int xbox_base_state::smbus_cx25871(int command, int rw, int data) +{ + logerror("cx25871: %d %d %d\n", command, rw, data); + return 0; +} + +// let's try to fake the missing eeprom +static int dummyeeprom[256] = { 0x94,0x18,0x10,0x59,0x83,0x58,0x15,0xDA,0xDF,0xCC,0x1D,0x78,0x20,0x8A,0x61,0xB8,0x08,0xB4,0xD6,0xA8, +0x9E,0x77,0x9C,0xEB,0xEA,0xF8,0x93,0x6E,0x3E,0xD6,0x9C,0x49,0x6B,0xB5,0x6E,0xAB,0x6D,0xBC,0xB8,0x80,0x68,0x9D,0xAA,0xCD,0x0B,0x83, +0x17,0xEC,0x2E,0xCE,0x35,0xA8,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x00,0x00, +0x4F,0x6E,0x6C,0x69,0x6E,0x65,0x6B,0x65,0x79,0x69,0x6E,0x76,0x61,0x6C,0x69,0x64,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF, +0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + +int smbus_callback_eeprom(xbox_base_state &chs, int command, int rw, int data) +{ + return chs.smbus_eeprom(command, rw, data); +} + +int xbox_base_state::smbus_eeprom(int command, int rw, int data) +{ + if (command >= 112) + return 0; + if (rw == 1) { // if reading + // hack to avoid hanging if eeprom contents are not correct + // this would need dumping the serial eeprom on the xbox board + if (command == 0) { + hack_eeprom(); + } + data = dummyeeprom[command] + dummyeeprom[command + 1] * 256; + logerror("eeprom: %d %d %d\n", command, rw, data); + return data; + } + logerror("eeprom: %d %d %d\n", command, rw, data); + dummyeeprom[command] = data; + return 0; +} + +/* + * SMbus controller + */ + +void xbox_base_state::smbus_register_device(int address, int(*handler)(xbox_base_state &chs, int command, int rw, int data)) +{ + if (address < 128) + smbusst.devices[address] = handler; +} + +READ32_MEMBER(xbox_base_state::smbus_r) +{ + if ((offset == 0) && (mem_mask == 0xff)) // 0 smbus status + smbusst.words[offset] = (smbusst.words[offset] & ~mem_mask) | ((smbusst.status << 0) & mem_mask); + if ((offset == 1) && ((mem_mask == 0x00ff0000) || (mem_mask == 0xffff0000))) // 6 smbus data + smbusst.words[offset] = (smbusst.words[offset] & ~mem_mask) | ((smbusst.data << 16) & mem_mask); + return smbusst.words[offset]; +} + +WRITE32_MEMBER(xbox_base_state::smbus_w) +{ + COMBINE_DATA(smbusst.words); + if ((offset == 0) && (mem_mask == 0xff)) // 0 smbus status + { + if (!((smbusst.status ^ data) & 0x10)) // clearing interrupt + xbox_base_devs.pic8259_2->ir3_w(0); // IRQ 11 + smbusst.status &= ~data; + } + if ((offset == 0) && (mem_mask == 0xff0000)) // 2 smbus control + { + data = data >> 16; + smbusst.control = data; + int cycletype = smbusst.control & 7; + if (smbusst.control & 8) { // start + if ((cycletype & 6) == 2) + { + if (smbusst.devices[smbusst.address]) + if (smbusst.rw == 0) + smbusst.devices[smbusst.address](*this, smbusst.command, smbusst.rw, smbusst.data); + else + smbusst.data = smbusst.devices[smbusst.address](*this, smbusst.command, smbusst.rw, smbusst.data); + else + logerror("SMBUS: access to missing device at address %d\n", smbusst.address); + smbusst.status |= 0x10; + if (smbusst.control & 0x10) + { + xbox_base_devs.pic8259_2->ir3_w(1); // IRQ 11 + } + } + } + } + if ((offset == 1) && (mem_mask == 0xff)) // 4 smbus address + { + smbusst.address = data >> 1; + smbusst.rw = data & 1; + } + if ((offset == 1) && ((mem_mask == 0x00ff0000) || (mem_mask == 0xffff0000))) // 6 smbus data + { + data = data >> 16; + smbusst.data = data; + } + if ((offset == 2) && (mem_mask == 0xff)) // 8 smbus command + smbusst.command = data; +} + +ADDRESS_MAP_START(xbox_base_map, AS_PROGRAM, 32, xbox_base_state) + AM_RANGE(0x00000000, 0x07ffffff) AM_RAM // 128 megabytes + AM_RANGE(0xf0000000, 0xf0ffffff) AM_RAM + AM_RANGE(0xfd000000, 0xfdffffff) AM_RAM AM_READWRITE(geforce_r, geforce_w) + AM_RANGE(0xfed00000, 0xfed003ff) AM_READWRITE(usbctrl_r, usbctrl_w) + AM_RANGE(0xfe800000, 0xfe85ffff) AM_READWRITE(audio_apu_r, audio_apu_w) + AM_RANGE(0xfec00000, 0xfec001ff) AM_READWRITE(audio_ac93_r, audio_ac93_w) + AM_RANGE(0xff000000, 0xff07ffff) AM_ROM AM_REGION("bios", 0) AM_MIRROR(0x00f80000) +ADDRESS_MAP_END + +ADDRESS_MAP_START(xbox_base_map_io, AS_IO, 32, xbox_base_state) + AM_RANGE(0x0020, 0x0023) AM_DEVREADWRITE8("pic8259_1", pic8259_device, read, write, 0xffffffff) + AM_RANGE(0x0040, 0x0043) AM_DEVREADWRITE8("pit8254", pit8254_device, read, write, 0xffffffff) + AM_RANGE(0x00a0, 0x00a3) AM_DEVREADWRITE8("pic8259_2", pic8259_device, read, write, 0xffffffff) + AM_RANGE(0x01f0, 0x01f7) AM_DEVREADWRITE("ide", bus_master_ide_controller_device, read_cs0, write_cs0) + AM_RANGE(0x0cf8, 0x0cff) AM_DEVREADWRITE("pcibus", pci_bus_legacy_device, read, write) + AM_RANGE(0x8000, 0x80ff) AM_READWRITE(dummy_r, dummy_w) + AM_RANGE(0xc000, 0xc0ff) AM_READWRITE(smbus_r, smbus_w) + AM_RANGE(0xff60, 0xff67) AM_DEVREADWRITE("ide", bus_master_ide_controller_device, bmdma_r, bmdma_w) +ADDRESS_MAP_END + +void xbox_base_state::machine_start() +{ + nvidia_nv2a = auto_alloc(machine(), nv2a_renderer(machine())); + memset(pic16lc_buffer, 0, sizeof(pic16lc_buffer)); + pic16lc_buffer[0] = 'B'; + pic16lc_buffer[4] = 0; // A/V connector, 2=vga + smbus_register_device(0x10, smbus_callback_pic16lc); + smbus_register_device(0x45, smbus_callback_cx25871); + smbus_register_device(0x54, smbus_callback_eeprom); + xbox_base_devs.pic8259_1 = machine().device("pic8259_1"); + xbox_base_devs.pic8259_2 = machine().device("pic8259_2"); + xbox_base_devs.ide = machine().device("ide"); + memset(apust.memory, 0, sizeof(apust.memory)); + memset(apust.voices_heap_blockaddr, 0, sizeof(apust.voices_heap_blockaddr)); + memset(apust.voices_active, 0, sizeof(apust.voices_active)); + memset(apust.voices_position, 0, sizeof(apust.voices_position)); + memset(apust.voices_position_start, 0, sizeof(apust.voices_position_start)); + memset(apust.voices_position_end, 0, sizeof(apust.voices_position_end)); + memset(apust.voices_position_increment, 0, sizeof(apust.voices_position_increment)); + apust.space = &m_maincpu->space(); + apust.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(xbox_base_state::audio_apu_timer), this), (void *)"APU Timer"); + apust.timer->enable(false); + if (machine().debug_flags & DEBUG_FLAG_ENABLED) + debug_console_register_command(machine(), "xbox", CMDFLAG_NONE, 0, 1, 4, xbox_debug_commands); + memset(&ohcist, 0, sizeof(ohcist)); +#ifdef USB_ENABLED + ohcist.hc_regs[HcRevision] = 0x10; + ohcist.hc_regs[HcFmInterval] = 0x2edf; + ohcist.hc_regs[HcLSThreshold] = 0x628; + ohcist.hc_regs[HcRhDescriptorA] = 4; + ohcist.interruptbulkratio = 1; + ohcist.writebackdonehadcounter = 7; + ohcist.space = &m_maincpu->space(); + ohcist.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(xbox_base_state::usb_ohci_timer), this), (void *)"USB OHCI Timer"); + ohcist.timer->enable(false); + usb_ohci_plug(1, new ohci_function_device()); // test connect +#endif + // savestates + save_item(NAME(debug_irq_active)); + save_item(NAME(debug_irq_number)); + save_item(NAME(smbusst.status)); + save_item(NAME(smbusst.control)); + save_item(NAME(smbusst.address)); + save_item(NAME(smbusst.data)); + save_item(NAME(smbusst.command)); + save_item(NAME(smbusst.rw)); + save_item(NAME(smbusst.words)); + save_item(NAME(pic16lc_buffer)); + nvidia_nv2a->start(&m_maincpu->space()); + nvidia_nv2a->savestate_items(); +} + +MACHINE_CONFIG_START(xbox_base, xbox_base_state) + + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", PENTIUM3, 733333333) /* Wrong! family 6 model 8 stepping 10 */ + MCFG_CPU_PROGRAM_MAP(xbox_base_map) + MCFG_CPU_IO_MAP(xbox_base_map_io) + MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(xbox_base_state, irq_callback) + + MCFG_QUANTUM_TIME(attotime::from_hz(6000)) + + MCFG_PCI_BUS_LEGACY_ADD("pcibus", 0) + MCFG_PCI_BUS_LEGACY_DEVICE(0, "PCI Bridge Device - Host Bridge", dummy_pci_r, dummy_pci_w) + MCFG_PCI_BUS_LEGACY_DEVICE(1, "HUB Interface - ISA Bridge", hubintiasbridg_pci_r, hubintiasbridg_pci_w) + MCFG_PCI_BUS_LEGACY_DEVICE(2, "OHCI USB Controller 1", dummy_pci_r, dummy_pci_w) + MCFG_PCI_BUS_LEGACY_DEVICE(3, "OHCI USB Controller 2", dummy_pci_r, dummy_pci_w) + MCFG_PCI_BUS_LEGACY_DEVICE(4, "MCP Networking Adapter", dummy_pci_r, dummy_pci_w) + MCFG_PCI_BUS_LEGACY_DEVICE(5, "MCP APU", dummy_pci_r, dummy_pci_w) + MCFG_PCI_BUS_LEGACY_DEVICE(6, "AC`97 Audio Codec Interface", dummy_pci_r, dummy_pci_w) + MCFG_PCI_BUS_LEGACY_DEVICE(9, "IDE Controller", dummy_pci_r, dummy_pci_w) + MCFG_PCI_BUS_LEGACY_DEVICE(30, "AGP Host to PCI Bridge", dummy_pci_r, dummy_pci_w) + MCFG_PCI_BUS_LEGACY_ADD("agpbus", 1) + MCFG_PCI_BUS_LEGACY_SIBLING("pcibus") + MCFG_PCI_BUS_LEGACY_DEVICE(0, "NV2A GeForce 3MX Integrated GPU/Northbridge", geforce_pci_r, geforce_pci_w) + MCFG_PIC8259_ADD("pic8259_1", WRITELINE(xbox_base_state, xbox_pic8259_1_set_int_line), VCC, READ8(xbox_base_state, get_slave_ack)) + MCFG_PIC8259_ADD("pic8259_2", DEVWRITELINE("pic8259_1", pic8259_device, ir2_w), GND, NULL) + + MCFG_DEVICE_ADD("pit8254", PIT8254, 0) + MCFG_PIT8253_CLK0(1125000) /* heartbeat IRQ */ + MCFG_PIT8253_OUT0_HANDLER(WRITELINE(xbox_base_state, xbox_pit8254_out0_changed)) + MCFG_PIT8253_CLK1(1125000) /* (unused) dram refresh */ + MCFG_PIT8253_CLK2(1125000) /* (unused) pio port c pin 4, and speaker polling enough */ + MCFG_PIT8253_OUT2_HANDLER(WRITELINE(xbox_base_state, xbox_pit8254_out2_changed)) + + MCFG_DEVICE_ADD("ide", BUS_MASTER_IDE_CONTROLLER, 0) + MCFG_ATA_INTERFACE_IRQ_HANDLER(DEVWRITELINE("pic8259_2", pic8259_device, ir6_w)) + MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE("maincpu", AS_PROGRAM) + + /* video hardware */ + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(60) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ + MCFG_SCREEN_SIZE(640, 480) + MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 479) + MCFG_SCREEN_UPDATE_DRIVER(xbox_base_state, screen_update_callback) + MCFG_SCREEN_VBLANK_DRIVER(xbox_base_state, vblank_callback) +MACHINE_CONFIG_END + +#if (defined(__MINGW32__) && (__GNUC__ >= 5)) +#pragma GCC diagnostic pop +#endif