/*************************************************************************** Atari 400/800 Machine driver Juergen Buchmueller, June 1998 ***************************************************************************/ #include "driver.h" #include "cpu/m6502/m6502.h" #include "includes/atari.h" #include "sound/pokey.h" #include "machine/6821pia.h" #include "sound/dac.h" #include "video/gtia.h" #define VERBOSE_POKEY 0 #define VERBOSE_SERIAL 0 #define VERBOSE_TIMERS 0 //#define LOG(x) if (errorlog) fprintf x static int atari = 0; #define ATARI_5200 0 #define ATARI_400 1 #define ATARI_800 2 #define ATARI_600XL 3 #define ATARI_800XL 4 #ifdef MESS static int a800_cart_loaded = 0; static int a800_cart_is_16k = 0; #endif static void a800xl_mmu(UINT8 new_mmu); static void a600xl_mmu(UINT8 new_mmu); static void pokey_reset(running_machine *machine); void atari_interrupt_cb(int mask) { #if VERBOSE_POKEY if (mask & 0x80) logerror("atari interrupt_cb BREAK\n"); if (mask & 0x40) logerror("atari interrupt_cb KBCOD\n"); #endif #if VERBOSE_SERIAL if (mask & 0x20) logerror("atari interrupt_cb SERIN\n"); if (mask & 0x10) logerror("atari interrupt_cb SEROR\n"); if (mask & 0x08) logerror("atari interrupt_cb SEROC\n"); #endif #if VERBOSE_TIMERS if (mask & 0x04) logerror("atari interrupt_cb TIMR4\n"); if (mask & 0x02) logerror("atari interrupt_cb TIMR2\n"); if (mask & 0x01) logerror("atari interrupt_cb TIMR1\n"); #endif cpunum_set_input_line(0, 0, HOLD_LINE); } /************************************************************** * * PIA interface * **************************************************************/ static READ8_HANDLER(atari_pia_pa_r) { return atari_input_disabled() ? 0xFF : readinputportbytag_safe("djoy_0_1", 0); } static READ8_HANDLER(atari_pia_pb_r) { return atari_input_disabled() ? 0xFF : readinputportbytag_safe("djoy_2_3", 0); } static WRITE8_HANDLER(a600xl_pia_pb_w) { a600xl_mmu(data); } static WRITE8_HANDLER(a800xl_pia_pb_w) { a800xl_mmu(data); } #ifdef MESS extern WRITE8_HANDLER(atari_pia_cb2_w); #else #define atari_pia_cb2_w (0) #endif static const pia6821_interface atari_pia_interface = { /*inputs : A/B,CA/B1,CA/B2 */ atari_pia_pa_r, atari_pia_pb_r, 0, 0, 0, 0, /*outputs: A/B,CA/B2 */ 0, 0, 0, atari_pia_cb2_w, /*irqs : A/B */ 0, 0 }; static const pia6821_interface a600xl_pia_interface = { /*inputs : A/B,CA/B1,CA/B2 */ atari_pia_pa_r, atari_pia_pb_r, 0, 0, 0, 0, /*outputs: A/B,CA/B2 */ 0, a600xl_pia_pb_w, 0, atari_pia_cb2_w, /*irqs : A/B */ 0, 0 }; static const pia6821_interface a800xl_pia_interface = { /*inputs : A/B,CA/B1,CA/B2 */ atari_pia_pa_r, atari_pia_pb_r, 0, 0, 0, 0, /*outputs: A/B,CA/B2 */ 0, a800xl_pia_pb_w, 0, atari_pia_cb2_w, /*irqs : A/B */ 0, 0 }; /************************************************************** * * Reset hardware * **************************************************************/ void a600xl_mmu(UINT8 new_mmu) { read8_handler rbank2; write8_handler wbank2; /* check if self-test ROM changed */ if ( new_mmu & 0x80 ) { logerror("%s MMU SELFTEST RAM\n", Machine->gamedrv->name); rbank2 = MRA8_NOP; wbank2 = MWA8_NOP; } else { logerror("%s MMU SELFTEST ROM\n", Machine->gamedrv->name); rbank2 = MRA8_BANK2; wbank2 = MWA8_ROM; } memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5000, 0x57ff, 0, 0, rbank2); memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5000, 0x57ff, 0, 0, wbank2); if (rbank2 == MRA8_BANK2) memory_set_bankptr(2, memory_region(REGION_CPU1)+0x5000); } void a800xl_mmu(UINT8 new_mmu) { read8_handler rbank1, rbank2, rbank3, rbank4; write8_handler wbank1, wbank2, wbank3, wbank4; UINT8 *base1, *base2, *base3, *base4; /* check if memory C000-FFFF changed */ if( new_mmu & 0x01 ) { logerror("%s MMU BIOS ROM\n", Machine->gamedrv->name); rbank3 = MRA8_BANK3; wbank3 = MWA8_ROM; base3 = memory_region(REGION_CPU1)+0x14000; /* 8K lo BIOS */ rbank4 = MRA8_BANK4; wbank4 = MWA8_ROM; base4 = memory_region(REGION_CPU1)+0x15800; /* 4K FP ROM + 8K hi BIOS */ } else { logerror("%s MMU BIOS RAM\n", Machine->gamedrv->name); rbank3 = MRA8_BANK3; wbank3 = MWA8_BANK3; base3 = memory_region(REGION_CPU1)+0x0c000; /* 8K RAM */ rbank4 = MRA8_BANK4; wbank4 = MWA8_BANK4; base4 = memory_region(REGION_CPU1)+0x0d800; /* 4K RAM + 8K RAM */ } memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, rbank3); memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, wbank3); memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xd800, 0xffff, 0, 0, rbank4); memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xd800, 0xffff, 0, 0, wbank4); memory_set_bankptr(3, base3); memory_set_bankptr(4, base4); /* check if BASIC changed */ if( new_mmu & 0x02 ) { logerror("%s MMU BASIC RAM\n", Machine->gamedrv->name); rbank1 = MRA8_BANK1; wbank1 = MWA8_BANK1; base1 = memory_region(REGION_CPU1)+0x0a000; /* 8K RAM */ } else { logerror("%s MMU BASIC ROM\n", Machine->gamedrv->name); rbank1 = MRA8_BANK1; wbank1 = MWA8_ROM; base1 = memory_region(REGION_CPU1)+0x10000; /* 8K BASIC */ } memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa000, 0xbfff, 0, 0, rbank1); memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa000, 0xbfff, 0, 0, wbank1); memory_set_bankptr(1, base1); /* check if self-test ROM changed */ if( new_mmu & 0x80 ) { logerror("%s MMU SELFTEST RAM\n", Machine->gamedrv->name); rbank2 = MRA8_BANK2; wbank2 = MWA8_BANK2; base2 = memory_region(REGION_CPU1)+0x05000; /* 0x0800 bytes */ } else { logerror("%s MMU SELFTEST ROM\n", Machine->gamedrv->name); rbank2 = MRA8_BANK2; wbank2 = MWA8_ROM; base2 = memory_region(REGION_CPU1)+0x15000; /* 0x0800 bytes */ } memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5000, 0x57ff, 0, 0, rbank2); memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5000, 0x57ff, 0, 0, wbank2); memory_set_bankptr(2, base2); } /************************************************************** * * Keyboard * **************************************************************/ #define AKEY_L 0x00 #define AKEY_J 0x01 #define AKEY_SEMICOLON 0x02 #define AKEY_BREAK 0x03 /* this not really a scancode */ #define AKEY_K 0x05 #define AKEY_PLUS 0x06 #define AKEY_ASTERISK 0x07 #define AKEY_O 0x08 #define AKEY_NONE 0x09 #define AKEY_P 0x0a #define AKEY_U 0x0b #define AKEY_ENTER 0x0c #define AKEY_I 0x0d #define AKEY_MINUS 0x0e #define AKEY_EQUALS 0x0f #define AKEY_V 0x10 #define AKEY_C 0x12 #define AKEY_B 0x15 #define AKEY_X 0x16 #define AKEY_Z 0x17 #define AKEY_4 0x18 #define AKEY_3 0x1a #define AKEY_6 0x1b #define AKEY_ESC 0x1c #define AKEY_5 0x1d #define AKEY_2 0x1e #define AKEY_1 0x1f #define AKEY_COMMA 0x20 #define AKEY_SPACE 0x21 #define AKEY_STOP 0x22 #define AKEY_N 0x23 #define AKEY_M 0x25 #define AKEY_SLASH 0x26 #define AKEY_ATARI 0x27 #define AKEY_R 0x28 #define AKEY_E 0x2a #define AKEY_Y 0x2b #define AKEY_TAB 0x2c #define AKEY_T 0x2d #define AKEY_W 0x2e #define AKEY_Q 0x2f #define AKEY_9 0x30 #define AKEY_0 0x32 #define AKEY_7 0x33 #define AKEY_BSP 0x34 #define AKEY_8 0x35 #define AKEY_LESSER 0x36 #define AKEY_GREATER 0x37 #define AKEY_F 0x38 #define AKEY_H 0x39 #define AKEY_D 0x3a #define AKEY_CAPS 0x3c #define AKEY_G 0x3d #define AKEY_S 0x3e #define AKEY_A 0x3f #define ASHF_L 0x40 #define ASHF_J 0x41 #define ASHF_COLON 0x42 #define ASHF_BREAK 0x43 /* this not really a scancode */ #define ASHF_K 0x45 #define ASHF_BACKSLASH 0x46 #define ASHF_TILDE 0x47 #define ASHF_O 0x48 #define ASHF_SHIFT 0x49 #define ASHF_P 0x4a #define ASHF_U 0x4b #define ASHF_ENTER 0x4c #define ASHF_I 0x4d #define ASHF_UNDERSCORE 0x4e #define ASHF_BAR 0x4f #define ASHF_V 0x50 #define ASHF_C 0x52 #define ASHF_B 0x55 #define ASHF_X 0x56 #define ASHF_Z 0x57 #define ASHF_DOLLAR 0x58 #define ASHF_HASH 0x5a #define ASHF_AMPERSAND 0x5b #define ASHF_ESC 0x5c #define ASHF_PERCENT 0x5d #define ASHF_DQUOTE 0x5e #define ASHF_EXCLAM 0x5f #define ASHF_LBRACE 0x60 #define ASHF_SPACE 0x61 #define ASHF_RBRACE 0x62 #define ASHF_N 0x63 #define ASHF_M 0x65 #define ASHF_QUESTION 0x66 #define ASHF_ATARI 0x67 #define ASHF_R 0x68 #define ASHF_E 0x6a #define ASHF_Y 0x6b #define ASHF_TAB 0x6c #define ASHF_T 0x6d #define ASHF_W 0x6e #define ASHF_Q 0x6f #define ASHF_LPAREN 0x70 #define ASHF_RPAREN 0x72 #define ASHF_QUOTE 0x73 #define ASHF_BSP 0x74 #define ASHF_AT 0x75 #define ASHF_CLEAR 0x76 #define ASHF_INSERT 0x77 #define ASHF_F 0x78 #define ASHF_H 0x79 #define ASHF_D 0x7a #define ASHF_CAPS 0x7c #define ASHF_G 0x7d #define ASHF_S 0x7e #define ASHF_A 0x7f #define ACTL_L 0x80 #define ACTL_J 0x81 #define ACTL_SEMICOLON 0x82 #define ACTL_BREAK 0x83 /* this not really a scancode */ #define ACTL_K 0x85 #define ACTL_PLUS 0x86 #define ACTL_ASTERISK 0x87 #define ACTL_O 0x88 #define ACTL_CONTROL 0x89 #define ACTL_P 0x8a #define ACTL_U 0x8b #define ACTL_ENTER 0x8c #define ACTL_I 0x8d #define ACTL_MINUS 0x8e #define ACTL_EQUALS 0x8f #define ACTL_V 0x90 #define ACTL_C 0x92 #define ACTL_B 0x95 #define ACTL_X 0x96 #define ACTL_Z 0x97 #define ACTL_4 0x98 #define ACTL_3 0x9a #define ACTL_6 0x9b #define ACTL_ESC 0x9c #define ACTL_5 0x9d #define ACTL_2 0x9e #define ACTL_1 0x9f #define ACTL_COMMA 0xa0 #define ACTL_SPACE 0xa1 #define ACTL_STOP 0xa2 #define ACTL_N 0xa3 #define ACTL_M 0xa5 #define ACTL_SLASH 0xa6 #define ACTL_ATARI 0xa7 #define ACTL_R 0xa8 #define ACTL_E 0xaa #define ACTL_Y 0xab #define ACTL_TAB 0xac #define ACTL_T 0xad #define ACTL_W 0xae #define ACTL_Q 0xaf #define ACTL_9 0xb0 #define ACTL_0 0xb2 #define ACTL_7 0xb3 #define ACTL_BSP 0xb4 #define ACTL_8 0xb5 #define ACTL_LESSER 0xb6 #define ACTL_GREATER 0xb7 #define ACTL_F 0xb8 #define ACTL_H 0xb9 #define ACTL_D 0xba #define ACTL_CAPS 0xbc #define ACTL_G 0xbd #define ACTL_S 0xbe #define ACTL_A 0xbf #define ACSH_L 0xc0 #define ACSH_J 0xc1 #define ACSH_COLON 0xc2 #define ACSH_BREAK 0xc3 /* this not really a scancode */ #define ACSH_K 0xc5 #define ACSH_BACKSLASH 0xc6 #define ACSH_TILDE 0xc7 #define ACSH_O 0xc8 #define ACSH_CTRLSHIFT 0xc9 #define ACSH_P 0xca #define ACSH_U 0xcb #define ACSH_ENTER 0xcc #define ACSH_I 0xcd #define ACSH_UNDERSCORE 0xce #define ACSH_BAR 0xcf #define ACSH_V 0xd0 #define ACSH_C 0xd2 #define ACSH_B 0xd5 #define ACSH_X 0xd6 #define ACSH_Z 0xd7 #define ACSH_DOLLAR 0xd8 #define ACSH_HASH 0xda #define ACSH_AMPERSAND 0xdb #define ACSH_ESC 0xdc #define ACSH_PERCENT 0xdd #define ACSH_DQUOTE 0xde #define ACSH_EXCLAM 0xdf #define ACSH_LBRACE 0xe0 #define ACSH_SPACE 0xe1 #define ACSH_RBRACE 0xe2 #define ACSH_N 0xe3 #define ACSH_M 0xe5 #define ACSH_QUESTION 0xe6 #define ACSH_ATARI 0xe7 #define ACSH_R 0xe8 #define ACSH_E 0xea #define ACSH_Y 0xeb #define ACSH_TAB 0xec #define ACSH_T 0xed #define ACSH_W 0xee #define ACSH_Q 0xef #define ACSH_LPAREN 0xf0 #define ACSH_RPAREN 0xf2 #define ACSH_QUOTE 0xf3 #define ACSH_BSP 0xf4 #define ACSH_AT 0xf5 #define ACSH_CLEAR 0xf6 #define ACSH_INSERT 0xf7 #define ACSH_F 0xf8 #define ACSH_H 0xf9 #define ACSH_D 0xfa #define ACSH_CAPS 0xfc #define ACSH_G 0xfd #define ACSH_S 0xfe #define ACSH_A 0xff static const UINT8 keys[64][4] = { {AKEY_NONE ,AKEY_NONE ,AKEY_NONE ,AKEY_NONE }, /* "" CODE_NONE */ {AKEY_ESC ,ASHF_ESC ,ACTL_ESC ,ACSH_ESC }, /*"Escape" KEYCODE_ESC */ {AKEY_1 ,ASHF_EXCLAM ,ACTL_1 ,ACSH_EXCLAM }, /* "1 !" KEYCODE_1 */ {AKEY_2 ,ASHF_DQUOTE ,ACTL_2 ,ACSH_DQUOTE }, /* "2 \"" KEYCODE_2 */ {AKEY_3 ,ASHF_HASH ,ACTL_3 ,ACSH_HASH }, /* "3 #" KEYCODE_3 */ {AKEY_4 ,ASHF_DOLLAR ,ACTL_4 ,ACSH_DOLLAR }, /* "4 $" KEYCODE_4 */ {AKEY_5 ,ASHF_PERCENT ,ACTL_5 ,ACSH_PERCENT }, /* "5 %" KEYCODE_5 */ {AKEY_6 ,ASHF_TILDE ,ACTL_6 ,ACSH_AMPERSAND }, /* "6 ^" KEYCODE_6 */ {AKEY_7 ,ASHF_AMPERSAND ,ACTL_7 ,ACSH_N }, /* "7 &" KEYCODE_7 */ {AKEY_8 ,AKEY_ASTERISK ,ACTL_8 ,ACSH_M }, /* "8 *" KEYCODE_8 */ {AKEY_9 ,ASHF_LPAREN ,ACTL_9 ,ACSH_LBRACE }, /* "9 (" KEYCODE_9 */ {AKEY_0 ,ASHF_RPAREN ,ACTL_0 ,ACSH_RBRACE }, /* "0 )" KEYCODE_0 */ {AKEY_MINUS ,ASHF_UNDERSCORE ,ACTL_MINUS ,ACSH_UNDERSCORE }, /* "- _" KEYCODE_MINUS */ {AKEY_EQUALS ,AKEY_PLUS ,ACTL_EQUALS ,ACTL_PLUS }, /* "= +" KEYCODE_EQUALS */ {AKEY_BSP ,ASHF_BSP ,ACTL_BSP ,ACSH_BSP }, /* "Backsp" KEYCODE_BACKSPACE */ {AKEY_TAB ,ASHF_TAB ,ACTL_TAB ,ACSH_TAB }, /* "Tab" KEYCODE_TAB */ {AKEY_Q ,ASHF_Q ,ACTL_Q ,ACSH_Q }, /* "q Q" KEYCODE_Q */ {AKEY_W ,ASHF_W ,ACTL_W ,ACSH_W }, /* "w W" KEYCODE_W */ {AKEY_E ,ASHF_E ,ACTL_E ,ACSH_E }, /* "e E" KEYCODE_E */ {AKEY_R ,ASHF_R ,ACTL_R ,ACSH_R }, /* "r R" KEYCODE_R */ {AKEY_T ,ASHF_T ,ACTL_T ,ACSH_T }, /* "t T" KEYCODE_T */ {AKEY_Y ,ASHF_Y ,ACTL_Y ,ACSH_Y }, /* "y Y" KEYCODE_Y */ {AKEY_U ,ASHF_U ,ACTL_U ,ACTL_U }, /* "u U" KEYCODE_U */ {AKEY_I ,ASHF_I ,ACTL_I ,ACTL_I }, /* "i I" KEYCODE_I */ {AKEY_O ,ASHF_O ,ACTL_O ,ACTL_O }, /* "o O" KEYCODE_O */ {AKEY_P ,ASHF_P ,ACTL_P ,ACTL_P }, /* "p P" KEYCODE_P */ {ASHF_LBRACE ,ACTL_COMMA ,ACTL_COMMA ,ACSH_LBRACE }, /* "[ {" KEYCODE_LBRACE */ {ASHF_RBRACE ,ACTL_STOP ,ACTL_STOP ,ACSH_RBRACE }, /* "] }" KEYCODE_RBRACE */ {AKEY_ENTER ,ASHF_ENTER ,ACTL_ENTER ,ACSH_ENTER }, /* "Enter" KEYCODE_ENTER */ {AKEY_A ,ASHF_A ,ACTL_A ,ACSH_A }, /* "a A" KEYCODE_A */ {AKEY_S ,ASHF_S ,ACTL_S ,ACSH_S }, /* "s S" KEYCODE_S */ {AKEY_D ,ASHF_D ,ACTL_D ,ACSH_D }, /* "d D" KEYCODE_D */ {AKEY_F ,ASHF_F ,ACTL_F ,ACSH_F }, /* "f F" KEYCODE_F */ {AKEY_G ,ASHF_G ,ACTL_G ,ACSH_G }, /* "g G" KEYCODE_G */ {AKEY_H ,ASHF_H ,ACTL_H ,ACSH_H }, /* "h H" KEYCODE_H */ {AKEY_J ,ASHF_J ,ACTL_J ,ACSH_J }, /* "j J" KEYCODE_J */ {AKEY_K ,ASHF_K ,ACTL_K ,ACSH_K }, /* "k K" KEYCODE_K */ {AKEY_L ,ASHF_L ,ACTL_L ,ACSH_L }, /* "l L" KEYCODE_L */ {AKEY_SEMICOLON ,ASHF_COLON ,ACTL_SEMICOLON ,ACSH_COLON }, /* "; :" KEYCODE_COLON */ {ASHF_QUOTE ,ACSH_QUOTE ,ASHF_DQUOTE ,ACSH_DQUOTE }, /* "+ \\" KEYCODE_QUOTE */ {ASHF_QUOTE ,ACSH_QUOTE ,ACTL_ASTERISK ,ACSH_TILDE }, /* "* ^" KEYCODE_TILDE */ {ASHF_BACKSLASH ,ASHF_BAR ,ACSH_BACKSLASH ,ACSH_BAR }, /* "\ |" KEYCODE_BACKSLASH */ {AKEY_Z ,ASHF_Z ,ACTL_Z ,ACSH_Z }, /* "z Z" KEYCODE_Z */ {AKEY_X ,ASHF_X ,ACTL_X ,ACTL_X }, /* "x X" KEYCODE_X */ {AKEY_C ,ASHF_C ,ACTL_C ,ACTL_C }, /* "c C" KEYCODE_C */ {AKEY_V ,ASHF_V ,ACTL_V ,ACTL_V }, /* "v V" KEYCODE_V */ {AKEY_B ,ASHF_B ,ACTL_B ,ACTL_B }, /* "b B" KEYCODE_B */ {AKEY_N ,ASHF_N ,ACTL_N ,ACTL_N }, /* "n N" KEYCODE_N */ {AKEY_M ,ASHF_M ,ACTL_M ,ACTL_M }, /* "m M" KEYCODE_M */ {AKEY_COMMA ,AKEY_LESSER ,ACTL_COMMA ,ACTL_LESSER }, /* ", [" KEYCODE_COMMA */ {AKEY_STOP ,AKEY_GREATER ,ACTL_STOP ,ACTL_GREATER }, /* ". ]" KEYCODE_STOP */ {AKEY_SLASH ,ASHF_QUESTION ,ACTL_SLASH ,ACSH_QUESTION }, /* "/ ?" KEYCODE_SLASH */ {ASHF_BACKSLASH ,ASHF_BAR ,ACSH_BACKSLASH ,ACSH_BAR }, /* "\ |" KEYCODE_BACKSLASH2 */ {AKEY_ATARI ,ASHF_ATARI ,ACTL_ATARI ,ACSH_ATARI }, /* "Atari" KEYCODE_LALT */ {AKEY_SPACE ,ASHF_SPACE ,ACTL_SPACE ,ACSH_SPACE }, /* "Space" KEYCODE_SPACE */ {AKEY_CAPS ,ASHF_CAPS ,ACTL_CAPS ,ACSH_CAPS }, /* "Caps" KEYCODE_CAPSLOCK */ {ASHF_CLEAR ,ASHF_CLEAR ,ACSH_CLEAR ,ACSH_CLEAR }, /* "Clear" KEYCODE_HOME */ {ASHF_INSERT ,ASHF_INSERT ,ASHF_INSERT ,ASHF_INSERT }, /* "Insert" KEYCODE_INSERT */ {AKEY_BSP ,AKEY_BSP ,AKEY_BSP ,AKEY_BSP }, /* "Delete" KEYCODE_DEL */ {AKEY_BREAK ,ASHF_BREAK ,ACTL_BREAK ,ACSH_BREAK }, /* "Break" KEYCODE_PGUP */ {ACTL_PLUS ,ACTL_PLUS ,ACTL_PLUS ,ACTL_PLUS }, /* "(Left)" KEYCODE_LEFT */ {ACTL_ASTERISK ,ACTL_ASTERISK ,ACTL_ASTERISK ,ACTL_ASTERISK }, /* "(Right)"KEYCODE_RIGHT */ {ACTL_MINUS ,ACTL_MINUS ,ACTL_MINUS ,ACTL_MINUS }, /* "(Up)" KEYCODE_UP */ {ACTL_EQUALS ,ACTL_EQUALS ,ACTL_EQUALS ,ACTL_EQUALS } /* "(Down)" KEYCODE_DOWN */ }; void a800_handle_keyboard(void) { static int atari_last = 0xff; int i, modifiers, atari_code; char tag[64]; modifiers = 0; /* with shift ? */ if( input_code_pressed(KEYCODE_LSHIFT) || input_code_pressed(KEYCODE_RSHIFT) ) modifiers |= 1; /* with control ? */ if( input_code_pressed(KEYCODE_LCONTROL) || input_code_pressed(KEYCODE_RCONTROL) ) modifiers |= 2; for( i = 0; i < 64; i++ ) { sprintf(tag, "keyboard_%d", i / 16); if( readinputportbytag_safe(tag, 0) & (1 << (i&15)) ) { atari_code = keys[i][modifiers]; if( atari_code != AKEY_NONE ) { if( atari_code == atari_last ) return; atari_last = atari_code; if( (atari_code & 0x3f) == AKEY_BREAK ) { pokey1_break_w(atari_code & 0x40); return; } pokey1_kbcode_w(atari_code, 1); return; } } } /* remove key pressed status bit from skstat */ pokey1_kbcode_w(AKEY_NONE, 0); atari_last = AKEY_NONE; } #define VKEY_BREAK 0x10 /* absolutely no clue what to do here :((( */ void a5200_handle_keypads(void) { int i, modifiers; static int atari_last = 0xff; modifiers = 0; /* with shift ? */ if (input_code_pressed(KEYCODE_LSHIFT) || input_code_pressed(KEYCODE_RSHIFT)) modifiers |= 1; /* with control ? */ if (input_code_pressed(KEYCODE_LCONTROL) || input_code_pressed(KEYCODE_RCONTROL)) modifiers |= 2; /* check keypad */ for (i = 0; i < 16; i++) { if( readinputportbytag("keypad") & (1 << i) ) { if( i == atari_last ) return; atari_last = i; if( i == 0 ) { pokey1_break_w(i & 0x40); return; } pokey1_kbcode_w((i << 1) | 0x21, 1); return; } } /* check top button */ if ((readinputportbytag("djoy_b") & 0x10) == 0) { if (atari_last == 0xFE) return; pokey1_kbcode_w(0x61, 1); //pokey1_break_w(0x40); atari_last = 0xFE; return; } else if (atari_last == 0xFE) pokey1_kbcode_w(0x21, 1); /* remove key pressed status bit from skstat */ pokey1_kbcode_w(0xFF, 0); atari_last = 0xff; } #ifdef MESS DRIVER_INIT( atari ) { offs_t ram_top; offs_t ram_size; if (!strcmp(machine->gamedrv->name, "a400") || !strcmp(machine->gamedrv->name, "a400pal") || !strcmp(machine->gamedrv->name, "a800") || !strcmp(machine->gamedrv->name, "a800pal") || !strcmp(machine->gamedrv->name, "a800xl")) { ram_size = 0xA000; } else { ram_size = 0x8000; } /* install RAM */ ram_top = MIN(mess_ram_size, ram_size) - 1; memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, ram_top, 0, 0, MRA8_BANK2); memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, ram_top, 0, 0, MWA8_BANK2); memory_set_bankptr(2, mess_ram); } #endif /************************************* * * Generic Atari Code * *************************************/ #ifdef MESS static void a800_setbank(int n) { void *read_addr; void *write_addr; UINT8 *mem = memory_region(REGION_CPU1); switch (n) { case 1: read_addr = &mem[0x10000]; write_addr = NULL; break; default: if( atari <= ATARI_400 ) { /* Atari 400 has no RAM here, so install the NOP handler */ read_addr = NULL; write_addr = NULL; } else { read_addr = &mess_ram[0x08000]; write_addr = &mess_ram[0x08000]; } break; } memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xbfff, 0, 0, read_addr ? MRA8_BANK1 : MRA8_NOP); memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xbfff, 0, 0, write_addr ? MWA8_BANK1 : MWA8_NOP); if (read_addr) memory_set_bankptr(1, read_addr); if (write_addr) memory_set_bankptr(1, write_addr); } #endif static void pokey_reset(running_machine *machine) { pokey1_w(15,0); } static void cart_reset(running_machine *machine) { #ifdef MESS if (a800_cart_loaded) a800_setbank(1); #endif /* MESS */ } static UINT8 console_read(void) { return readinputportbytag("console"); } static void console_write(UINT8 data) { if (data & 0x08) DAC_data_w(0, -120); else DAC_data_w(0, +120); } static void _pia_reset(running_machine *machine) { pia_reset(); } static void _antic_reset(running_machine *machine) { antic_reset(); } static void atari_machine_start(int type, const pia6821_interface *pia_intf, int has_cart) { gtia_interface gtia_intf; atari = type; /* GTIA */ memset(>ia_intf, 0, sizeof(gtia_intf)); if (port_tag_to_index("console") >= 0) gtia_intf.console_read = console_read; if (sndti_exists(SOUND_DAC, 0)) gtia_intf.console_write = console_write; gtia_init(>ia_intf); /* pokey */ add_reset_callback(Machine, pokey_reset); /* PIA */ if (pia_intf) { pia_config(0, pia_intf); add_reset_callback(Machine, _pia_reset); } /* ANTIC */ add_reset_callback(Machine, _antic_reset); /* cartridge */ if (has_cart) add_reset_callback(Machine, cart_reset); #ifdef MESS { offs_t ram_top; offs_t ram_size; if (!strcmp(Machine->gamedrv->name, "a400") || !strcmp(Machine->gamedrv->name, "a400pal") || !strcmp(Machine->gamedrv->name, "a800") || !strcmp(Machine->gamedrv->name, "a800pal") || !strcmp(Machine->gamedrv->name, "a800xl")) { ram_size = 0xA000; } else { ram_size = 0x8000; } /* install RAM */ ram_top = MIN(mess_ram_size, ram_size) - 1; memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, ram_top, 0, 0, MRA8_BANK2); memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, ram_top, 0, 0, MWA8_BANK2); memory_set_bankptr(2, mess_ram); } #endif /* MESS */ /* save states */ state_save_register_global_pointer(((UINT8 *) &antic.r), sizeof(antic.r)); state_save_register_global_pointer(((UINT8 *) &antic.w), sizeof(antic.w)); } /************************************* * * Atari 400 * Atari 600XL * *************************************/ MACHINE_START( a400 ) { atari_machine_start(ATARI_400, &atari_pia_interface, TRUE); } MACHINE_START( a600xl ) { atari_machine_start(ATARI_600XL, &a600xl_pia_interface, TRUE); } /************************************* * * Atari 800 * *************************************/ MACHINE_START( a800 ) { atari_machine_start(ATARI_800, &atari_pia_interface, TRUE); } #ifdef MESS DEVICE_LOAD( a800_cart ) { UINT8 *mem = memory_region(REGION_CPU1); int size; /* load an optional (dual) cartridge (e.g. basic.rom) */ if( image_index_in_device(image) > 0 ) { size = image_fread(image, &mem[0x12000], 0x2000); a800_cart_is_16k = (size == 0x2000); logerror("%s loaded right cartridge '%s' size 16K\n", Machine->gamedrv->name, image_filename(image) ); } else { size = image_fread(image, &mem[0x10000], 0x2000); a800_cart_loaded = size > 0x0000; size = image_fread(image, &mem[0x12000], 0x2000); a800_cart_is_16k = size > 0x2000; logerror("%s loaded left cartridge '%s' size %s\n", Machine->gamedrv->name, image_filename(image) , (a800_cart_is_16k) ? "16K":"8K"); } return INIT_PASS; } DEVICE_UNLOAD( a800_cart ) { if( image_index_in_device(image) > 0 ) { a800_cart_is_16k = 0; a800_setbank(1); } else { a800_cart_loaded = 0; a800_setbank(0); } } #endif /************************************* * * Atari 800XL * *************************************/ MACHINE_START( a800xl ) { atari_machine_start(ATARI_800XL, &a800xl_pia_interface, TRUE); } #ifdef MESS DEVICE_LOAD( a800xl_cart ) { UINT8 *mem = memory_region(REGION_CPU1); astring *fname; mame_file *basic_fp; file_error filerr; unsigned size; fname = astring_assemble_3(astring_alloc(), Machine->gamedrv->name, PATH_SEPARATOR, "basic.rom"); filerr = mame_fopen(SEARCHPATH_ROM, astring_c(fname), OPEN_FLAG_READ, &basic_fp); astring_free(fname); if (filerr != FILERR_NONE) { size = mame_fread(basic_fp, &mem[0x14000], 0x2000); if( size < 0x2000 ) { logerror("%s image '%s' load failed (less than 8K)\n", Machine->gamedrv->name, astring_c(fname)); mame_fclose(basic_fp); return 2; } } /* load an optional (dual) cartidge (e.g. basic.rom) */ if (filerr != FILERR_NONE) { { size = image_fread(image, &mem[0x14000], 0x2000); a800_cart_loaded = size / 0x2000; size = image_fread(image, &mem[0x16000], 0x2000); a800_cart_is_16k = size / 0x2000; logerror("%s loaded cartridge '%s' size %s\n", Machine->gamedrv->name, image_filename(image), (a800_cart_is_16k) ? "16K":"8K"); } mame_fclose(basic_fp); } return INIT_PASS; } #endif /************************************* * * Atari 5200 console * *************************************/ MACHINE_START( a5200 ) { atari_machine_start(ATARI_800XL, NULL, FALSE); } #ifdef MESS DEVICE_LOAD( a5200_cart ) { UINT8 *mem = memory_region(REGION_CPU1); int size; /* load an optional (dual) cartidge */ size = image_fread(image, &mem[0x4000], 0x8000); if (size<0x8000) memmove(mem+0x4000+0x8000-size, mem+0x4000, size); // mirroring of smaller cartridges if (size <= 0x1000) memcpy(mem+0xa000, mem+0xb000, 0x1000); if (size <= 0x2000) memcpy(mem+0x8000, mem+0xa000, 0x2000); if (size <= 0x4000) { const char *info; memcpy(&mem[0x4000], &mem[0x8000], 0x4000); info = image_extrainfo(image); if (info!=NULL && strcmp(info, "A13MIRRORING")==0) { memcpy(&mem[0x8000], &mem[0xa000], 0x2000); memcpy(&mem[0x6000], &mem[0x4000], 0x2000); } } logerror("%s loaded cartridge '%s' size %dK\n", Machine->gamedrv->name, image_filename(image) , size/1024); return INIT_PASS; } DEVICE_UNLOAD( a5200_cart ) { UINT8 *mem = memory_region(REGION_CPU1); /* zap the cartridge memory (again) */ memset(&mem[0x4000], 0x00, 0x8000); } #endif