// license:BSD-3-Clause // copyright-holders:Phill Harvey-Smith /* machine/mbc55x.c Machine driver for the Sanyo MBC-550 and MBC-555. Phill Harvey-Smith 2011-01-29. *****************************************************************************/ #include "includes/mbc55x.h" /*-------------------------------------------------------------------------*/ /* Defines, constants, and global variables */ /*-------------------------------------------------------------------------*/ /* Debugging */ #define DEBUG_SET(flags) ((state->m_debug_machine & (flags))==(flags)) #define DEBUG_NONE 0x0000000 #define DMA_BREAK 0x0000001 #define DECODE_BIOS 0x0000002 #define DECODE_BIOS_RAW 0x0000004 #define DECODE_DOS21 0x0000008 #define LOG_KEYBOARD 1 static void decode_dos21(device_t *device,offs_t pc); //static void mbc55x_recalculate_ints(running_machine &machine); static void mbc55x_debug(running_machine &machine, int ref, int params, const char *param[]); static int instruction_hook(device_t &device, offs_t curpc); //static void fdc_reset(running_machine &machine); //static void set_disk_int(running_machine &machine, int state); /* 8255 Configuration */ READ8_MEMBER( mbc55x_state::ppi8255_r ) { return m_ppi->read(space, offset>>1); } WRITE8_MEMBER( mbc55x_state::ppi8255_w ) { m_ppi->write(space, offset>>1, data); } READ8_MEMBER( mbc55x_state::mbc55x_ppi_porta_r ) { return 0xff; } READ8_MEMBER( mbc55x_state::mbc55x_ppi_portb_r ) { return 0xff; } READ8_MEMBER( mbc55x_state::mbc55x_ppi_portc_r ) { return 0xff; } WRITE8_MEMBER( mbc55x_state::mbc55x_ppi_porta_w ) { } WRITE8_MEMBER( mbc55x_state::mbc55x_ppi_portb_w ) { } WRITE8_MEMBER( mbc55x_state::mbc55x_ppi_portc_w ) { m_fdc->set_drive((data & 0x03)); m_fdc->set_side(BIT(data, 2)); } /* Serial port USART, unimplemented as yet */ READ8_MEMBER( mbc55x_state::mbc55x_usart_r ) { return 0; } WRITE8_MEMBER( mbc55x_state::mbc55x_usart_w ) { } /* PIC 8259 Configuration */ READ8_MEMBER(mbc55x_state::mbcpic8259_r) { return m_pic->read(space, offset>>1); } WRITE8_MEMBER(mbc55x_state::mbcpic8259_w) { m_pic->write(space, offset>>1, data); } READ8_MEMBER(mbc55x_state::mbcpit8253_r) { return m_pit->read(space, offset >> 1); } WRITE8_MEMBER(mbc55x_state::mbcpit8253_w) { m_pit->write(space, offset >> 1, data); } WRITE_LINE_MEMBER( mbc55x_state::pit8253_t2 ) { m_kb_uart->write_txc(state); m_kb_uart->write_rxc(state); } /* Video ram page register */ READ8_MEMBER( mbc55x_state::vram_page_r ) { return m_vram_page; } WRITE8_MEMBER( mbc55x_state::vram_page_w ) { logerror("%s : set vram page to %02X\n", machine().describe_context(),data); m_vram_page=data; } READ8_MEMBER(mbc55x_state::mbc55x_disk_r) { return m_fdc->read(space, offset>>1); } WRITE8_MEMBER(mbc55x_state::mbc55x_disk_w) { m_fdc->write(space, offset>>1, data); } WRITE_LINE_MEMBER( mbc55x_state::mbc55x_fdc_intrq_w ) { } WRITE_LINE_MEMBER( mbc55x_state::mbc55x_fdc_drq_w ) { } /* Keyboard emulation */ void mbc55x_state::keyboard_reset() { logerror("keyboard_reset()\n"); memset(m_keyboard.keyrows,0xFF,MBC55X_KEYROWS); m_keyboard.key_special=0; // Setup timer to scan keyboard. m_keyboard.keyscan_timer->adjust(attotime::zero, 0, attotime::from_hz(50)); } void mbc55x_state::scan_keyboard() { UINT8 keyrow; UINT8 row; UINT8 bitno; UINT8 mask; char key; static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5", "KEY6", "KEY7", "KEY8", "KEY9", "KEY10" }; static const char keyvalues_normal[MBC55X_KEYROWS][8] = { { '1', '2', '3', '4' , '5', '6', '7', '8' }, { '9', '0', '-', '=', '\\', 'q', 'w', 'e' }, { 'r', 't', 'y', 'u', 'i', 'o', 'p', '[' }, { ']', 'a', 's', 'd', 'f', 'g', 'h', 'j' }, { 'k', 'l', ';', '\'', '`', 0x0D, 'z', 'x' }, { 'c', 'v', 'b', 'n', 'm', ',', '.', '/', }, { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', } }; static const char keyvalues_shift[MBC55X_KEYROWS][8] = { { '!', '@', '#', '$' , '%', '^', '&', '*' }, { '(', ')', '_', '+', '|', 'Q', 'W', 'E' }, { 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{' }, { '}', 'A', 'S', 'D', 'F', 'G', 'H', 'J' }, { 'K', 'L', ':', '"', '~', 0x0d, 'Z', 'X' }, { 'C', 'V', 'B', 'N', 'M', ',', '?', '/' }, { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }; // First read shift, control and graph m_keyboard.key_special = ioport(KEY_SPECIAL_TAG)->read(); for(row=0; rowread(); for(mask=0x80, bitno=7;mask>0;mask=mask>>1, bitno-=1) { if(!(keyrow & mask) && (m_keyboard.keyrows[row] & mask)) { if(m_keyboard.key_special & (KEY_BIT_LSHIFT | KEY_BIT_RSHIFT)) key=keyvalues_shift[row][bitno]; else key=keyvalues_normal[row][bitno]; if (LOG_KEYBOARD) logerror("keypress %c\n",key); m_kb_uart->receive_character(key); } } m_keyboard.keyrows[row]=keyrow; } } TIMER_CALLBACK_MEMBER(mbc55x_state::keyscan_callback) { scan_keyboard(); } READ8_MEMBER(mbc55x_state::mbc55x_kb_usart_r) { UINT8 result = 0; offset>>=1; switch (offset) { case 0: //logerror("%s read kb_uart\n",machine().describe_context()); result = m_kb_uart->data_r(space,0); break; case 1: result = m_kb_uart->status_r(space,0); if (m_keyboard.key_special & KEY_BIT_CTRL) // Parity error used to flag control down result |= i8251_device::I8251_STATUS_PARITY_ERROR; break; } return result; } WRITE8_MEMBER(mbc55x_state::mbc55x_kb_usart_w) { offset>>=1; switch (offset) { case 0 : m_kb_uart->data_w(space, 0, data); break; case 1 : m_kb_uart->control_w(space, 0, data); break; } } void mbc55x_state::set_ram_size() { address_space &space = m_maincpu->space( AS_PROGRAM ); int ramsize = m_ram->size(); int nobanks = ramsize / RAM_BANK_SIZE; char bank[10]; int bankno; UINT8 *ram = &m_ram->pointer()[0]; UINT8 *map_base; int bank_base; logerror("Ramsize is %d bytes\n",ramsize); logerror("RAM_BANK_SIZE=%d, nobanks=%d\n",RAM_BANK_SIZE,nobanks); // Main memory mapping for(bankno=0; banknoset_base(map_base); space.install_readwrite_bank(bank_base, bank_base+(RAM_BANK_SIZE-1), bank); logerror("Mapping bank %d at %05X to RAM\n",bankno,bank_base); } else { space.nop_readwrite(bank_base, bank_base+(RAM_BANK_SIZE-1)); logerror("Mapping bank %d at %05X to NOP\n",bankno,bank_base); } } // Graphics red and blue plane memory mapping, green is in main memory membank(RED_PLANE_TAG)->set_base(&m_video_mem[RED_PLANE_OFFSET]); space.install_readwrite_bank(RED_PLANE_MEMBASE, RED_PLANE_MEMBASE+(COLOUR_PLANE_SIZE-1), RED_PLANE_TAG); membank(BLUE_PLANE_TAG)->set_base(&m_video_mem[BLUE_PLANE_OFFSET]); space.install_readwrite_bank(BLUE_PLANE_MEMBASE, BLUE_PLANE_MEMBASE+(COLOUR_PLANE_SIZE-1), BLUE_PLANE_TAG); } DRIVER_INIT_MEMBER(mbc55x_state,mbc55x) { } void mbc55x_state::machine_reset() { set_ram_size(); keyboard_reset(); } void mbc55x_state::machine_start() { /* init cpu */ // mbc55x_cpu_init(); /* setup debug commands */ if (machine().debug_flags & DEBUG_FLAG_ENABLED) { debug_console_register_command(machine(), "mbc55x_debug", CMDFLAG_NONE, 0, 0, 1, mbc55x_debug); /* set up the instruction hook */ m_maincpu->debug()->set_instruction_hook(instruction_hook); } m_debug_machine=DEBUG_NONE; // Allocate keyscan timer m_keyboard.keyscan_timer=machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mbc55x_state::keyscan_callback),this)); } static void mbc55x_debug(running_machine &machine, int ref, int params, const char *param[]) { mbc55x_state *state = machine.driver_data(); if(params>0) { sscanf(param[0],"%d",&state->m_debug_machine); } else { debug_console_printf(machine,"Error usage : mbc55x_debug \n"); debug_console_printf(machine,"Current debuglevel=%02X\n",state->m_debug_machine); } } /*----------------------------------------------- instruction_hook - per-instruction hook -----------------------------------------------*/ static int instruction_hook(device_t &device, offs_t curpc) { mbc55x_state *state = device.machine().driver_data(); address_space &space = device.memory().space(AS_PROGRAM); UINT8 *addr_ptr; addr_ptr = (UINT8*)space.get_read_ptr(curpc); if ((addr_ptr !=NULL) && (addr_ptr[0]==0xCD)) { // logerror("int %02X called\n",addr_ptr[1]); if(DEBUG_SET(DECODE_DOS21) && (addr_ptr[1]==0x21)) decode_dos21(&device,curpc); } return 0; } static void decode_dos21(device_t *device,offs_t pc) { mbc55x_state *state = device->machine().driver_data(); UINT16 ax = state->m_maincpu->state_int(I8086_AX); UINT16 bx = state->m_maincpu->state_int(I8086_BX); UINT16 cx = state->m_maincpu->state_int(I8086_CX); UINT16 dx = state->m_maincpu->state_int(I8086_DX); UINT16 cs = state->m_maincpu->state_int(I8086_CS); UINT16 ds = state->m_maincpu->state_int(I8086_DS); UINT16 es = state->m_maincpu->state_int(I8086_ES); UINT16 ss = state->m_maincpu->state_int(I8086_SS); UINT16 si = state->m_maincpu->state_int(I8086_SI); UINT16 di = state->m_maincpu->state_int(I8086_DI); UINT16 bp = state->m_maincpu->state_int(I8086_BP); logerror("=======================================================================\n"); logerror("DOS Int 0x21 call at %05X\n",pc); logerror("AX=%04X, BX=%04X, CX=%04X, DX=%04X\n",ax,bx,cx,dx); logerror("CS=%04X, DS=%04X, ES=%04X, SS=%04X\n",cs,ds,es,ss); logerror("SI=%04X, DI=%04X, BP=%04X\n",si,di,bp); logerror("=======================================================================\n"); if((ax & 0xff00)==0x0900) debugger_break(device->machine()); }