// license:MAME // copyright-holders:Kevin Thacker, Robbbert /****************************************************************************** Exidy Sorcerer system driver The UART controls rs232 and cassette i/o. The chip is a AY-3-1014A or AY-3-1015. port fc: ======== input/output: uart data port fd: ======== input: uart status bit 4: parity error (RPE) bit 3: framing error (RFE) bit 2: over-run (RDP) bit 1: data available (RDA) bit 0: transmit buffer empty (TPMT) output: bit 4: no parity (NPB) bit 3: parity type (POE) bit 2: number of stop bits (NSB) bit 1: number of bits per char bit 2 (NDB2) bit 0: number of bits per char bit 1 (NDB1) port fe: ======== output: bit 7: rs232 enable (1=rs232, 0=cassette) bit 6: baud rate (1=1200, 0=300) bit 5: cassette motor 2 bit 4: cassette motor 1 bit 3..0: keyboard line select input: bit 7..6: parallel control (not emulated) 7: must be 1 to read data from parallel port via PARIN 6: must be 1 to send data out of parallel port via PAROUT bit 5: vsync bit 4..0: keyboard line data port ff: ======== parallel port in/out ------------------------------------------------------------------------------------- When cassette is selected, it is connected to the uart data input via the cassette interface hardware. The cassette interface hardware converts square-wave pulses into bits which the uart receives. 1. the cassette format: "frequency shift" is converted into the uart data format "non-return to zero" 2. on cassette a 1 data bit is stored as a high frequency and a 0 data bit as a low frequency - At 1200 baud, a logic 1 is 1 cycle of 1200 Hz and a logic 0 is 1/2 cycle of 600 Hz. - At 300 baud, a logic 1 is 8 cycles of 2400 Hz and a logic 0 is 4 cycles of 1200 Hz. Attenuation is applied to the signal and the square wave edges are rounded. A manchester encoder is used. A flip-flop synchronises input data on the positive-edge of the clock pulse. Interestingly the data on cassette is stored in xmodem-checksum. Due to bugs in the hardware and software of a real Sorcerer, the serial interface misbehaves. 1. Sorcerer I had a hardware problem causing rs232 idle to be a space (+9v) instead of mark (-9v). Fixed in Sorcerer II. 2. When you select a different baud for rs232, it was "remembered" but not sent to port fe. It only gets sent when motor on was requested. Motor on is only meaningful in a cassette operation. 3. The monitor software always resets the device to cassette whenever the keyboard is scanned, motors altered, or an error occurred. 4. The above problems make rs232 communication impractical unless you write your own routines or create a corrected monitor rom. Sound: External speaker connected to the parallel port. There was a dac you could make instead, this is supported. Kevin Thacker [MESS driver] Robbbert [Various corrections and additions over the years] ****************************************************************************** The CPU clock speed is 2.106 MHz, which was increased to 4.0 MHz on the last production runs. The Sorcerer has a bus connection for S100 equipment. This allows the connection of disk drives, provided that suitable driver/boot software is loaded. ******************************************************************************* Real machines had optional RAM sizes of 8k, 16k, 32k, 48k (officially). Unofficially, the cart could hold another 8k of static RAM (4x 6116), giving 56k total. On the back of the machine is a 50-pin expansion port, which could be hooked to the expansion unit. Also is a 25-pin parallel port, allowing inwards and outwards communication. It was often hooked to a printer, a joystick, a music card, or a speaker. We emulate the printer and the speaker. Another 25-pin port provided two-way serial communications. Only two speeds are available - 300 baud and 1200 baud. There is no handshaking. This protocol is currently not emulated. Other pins on this connector provided for two cassette players. The connections for cassette unit 1 are duplicated on a set of phono plugs. We emulate the use of two cassette units. An option allows you to hear the sound of the tape during playback. ******************************************************************************** NOTES (2011-01-09) 1. Converted to MODERN driver as much as possible. 2. Added 2 defines for work that needs doing at some time: - SORCERER_USING_RS232 - this is for when we can connect a serial interface. - SORCERER_USING_DISKS - the disk controller I believe most likely to be a 'Micropolis Floppy Disk System' at 143KB on 13cm disks. There was a hard-sector system (top of ram = BBFF), and a soft-sector system (top of RAM = BDFF). You could use alternate systems (since you could attach a S-100 unit), so not sure how this could be developed. The Micropolis seems completely undocumented in the technical sense. When using the hard-sector system, in the monitor enter GO BC00 to boot the disk. No idea how in other disk systems. Note that the code within the defines has NOT been compiled or tested. You are on your own! NOTES (2011-08-08) 1. SORCERER_USING_DISKS removed, replaced with a new driver "sorcererd". This is disk-enabled, allowing CP/M to run. To initialise the disk system, you must enter GO BC00 after the computer has booted. It is not particularly stable, so be prepared to cold boot whenever something goes wrong. ********************************************************************************/ #include "includes/sorcerer.h" static ADDRESS_MAP_START( sorcerer_mem, AS_PROGRAM, 8, sorcerer_state) ADDRESS_MAP_UNMAP_HIGH AM_RANGE(0x0000, 0x07ff) AM_RAMBANK("boot") AM_RANGE(0x0800, 0xbfff) AM_RAM AM_RANGE(0xc000, 0xefff) AM_ROM /* rom pac and bios */ AM_RANGE(0xf000, 0xf7ff) AM_RAM AM_REGION("maincpu", 0xf000) /* screen ram */ AM_RANGE(0xf800, 0xfbff) AM_ROM /* char rom */ AM_RANGE(0xfc00, 0xffff) AM_RAM AM_REGION("maincpu", 0xfc00) /* programmable chars */ ADDRESS_MAP_END static ADDRESS_MAP_START( sorcererd_mem, AS_PROGRAM, 8, sorcerer_state) ADDRESS_MAP_UNMAP_HIGH AM_RANGE(0x0000, 0x07ff) AM_RAMBANK("boot") AM_RANGE(0x0800, 0xbbff) AM_RAM AM_RANGE(0xbc00, 0xbcff) AM_ROM AM_RANGE(0xbe00, 0xbe03) AM_DEVREADWRITE("fdc", micropolis_device, read, write) AM_RANGE(0xc000, 0xefff) AM_ROM /* rom pac and bios */ AM_RANGE(0xf000, 0xf7ff) AM_RAM AM_REGION("maincpu", 0xf000) /* screen ram */ AM_RANGE(0xf800, 0xfbff) AM_ROM /* char rom */ AM_RANGE(0xfc00, 0xffff) AM_RAM AM_REGION("maincpu", 0xfc00) /* programmable chars */ ADDRESS_MAP_END static ADDRESS_MAP_START( sorcerer_io, AS_IO, 8, sorcerer_state) ADDRESS_MAP_GLOBAL_MASK(0xff) ADDRESS_MAP_UNMAP_HIGH AM_RANGE(0xfc, 0xfc) AM_READWRITE( sorcerer_fc_r, sorcerer_fc_w ) AM_RANGE(0xfd, 0xfd) AM_READWRITE( sorcerer_fd_r, sorcerer_fd_w ) AM_RANGE(0xfe, 0xfe) AM_READWRITE( sorcerer_fe_r, sorcerer_fe_w ) AM_RANGE(0xff, 0xff) AM_DEVREAD("cent_status_in", input_buffer_device, read) AM_RANGE(0xff, 0xff) AM_WRITE( sorcerer_ff_w ) ADDRESS_MAP_END static INPUT_PORTS_START(sorcerer) PORT_START("VS") /* vblank */ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_VBLANK("screen") /* line 0 */ PORT_START("X0") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift Lock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Control") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Graphic") PORT_CODE(KEYCODE_F1) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Stop") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) /* line 1 */ PORT_START("X1") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(Sel)") PORT_CODE(KEYCODE_F2) PORT_CHAR(27) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Skip") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Repeat") PORT_CODE(KEYCODE_F4) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Clear") PORT_CODE(KEYCODE_F5) PORT_CHAR(12) /* line 2 */ PORT_START("X2") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHAR('q') PORT_CHAR(0x11) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('a') PORT_CHAR(0x01) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHAR('z') PORT_CHAR(0x1a) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x') PORT_CHAR(0x18) /* line 3 */ PORT_START("X3") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('\"') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHAR('w') PORT_CHAR(0x17) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHAR('s') PORT_CHAR(0x13) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d') PORT_CHAR(0x04) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('c') PORT_CHAR(0x03) /* line 4 */ PORT_START("X4") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHAR('e') PORT_CHAR(0x05) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHAR('r') PORT_CHAR(0x12) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHAR('f') PORT_CHAR(0x06) /* line 5 */ PORT_START("X5") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHAR('t') PORT_CHAR(0x14) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHAR('g') PORT_CHAR(0x07) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHAR('v') PORT_CHAR(0x16) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHAR('b') PORT_CHAR(0x02) /* line 6 */ PORT_START("X6") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHAR('y') PORT_CHAR(0x19) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHAR('h') PORT_CHAR(0x08) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHAR('n') PORT_CHAR(0x0e) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHAR('m') PORT_CHAR(0x0d) /* line 7 */ PORT_START("X7") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHAR('u') PORT_CHAR(0x15) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j') PORT_CHAR(0x0a) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('i') PORT_CHAR(0x09) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('k') PORT_CHAR(0x0b) /* line 8 */ PORT_START("X8") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('o') PORT_CHAR(0x0f) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('l') PORT_CHAR(0x0c) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') /* line 9 */ PORT_START("X9") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p') PORT_CHAR(0x10) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("; +") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') /* line 10 */ PORT_START("XA") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(": *") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[ {") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("] }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("@ `") PORT_CODE(KEYCODE_F7) PORT_CHAR('@') PORT_CHAR('`') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') /* line 11 */ PORT_START("XB") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^ ~") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^') PORT_CHAR('~') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LINE FEED") PORT_CODE(KEYCODE_F6) PORT_CHAR(10) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(13) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("_ Rub") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR('_') PORT_CHAR(8) /* line 12 */ PORT_START("XC") PORT_BIT(0x10, 0x10, IPT_UNUSED) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- (PAD)") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/ (PAD)") PORT_CODE(KEYCODE_SLASH_PAD) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("* (PAD)") PORT_CODE(KEYCODE_ASTERISK) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("+ (PAD)") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) /* line 13 */ PORT_START("XD") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 (PAD)") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 (PAD)") PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 (PAD)") PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 (PAD)") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0 (PAD)") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) /* line 14 */ PORT_START("XE") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 (PAD)") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 (PAD)") PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 (PAD)") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 (PAD)") PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". (PAD)") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) /* line 15 */ PORT_START("XF") PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 (PAD)") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("= (PAD)") PORT_CODE(KEYCODE_NUMLOCK) PORT_BIT(0x04, 0x04, IPT_UNUSED) PORT_BIT(0x02, 0x02, IPT_UNUSED) PORT_BIT(0x01, 0x01, IPT_UNUSED) /* Enhanced options not available on real hardware */ PORT_START("CONFIG") PORT_CONFNAME( 0x01, 0x01, "Autorun on Quickload") PORT_CONFSETTING( 0x00, DEF_STR(No)) PORT_CONFSETTING( 0x01, DEF_STR(Yes)) /* hardware connected to printer port */ PORT_CONFNAME( 0x02, 0x02, "Parallel port" ) PORT_CONFSETTING( 0x00, "7-bit" ) PORT_CONFSETTING( 0x02, "8-bit" ) PORT_CONFNAME( 0x08, 0x08, "Cassette Speaker") PORT_CONFSETTING( 0x08, DEF_STR(On)) PORT_CONFSETTING( 0x00, DEF_STR(Off)) INPUT_PORTS_END /**************************** F4 CHARACTER DISPLAYER ******************************************************/ static const gfx_layout sorcerer_charlayout = { 8, 8, /* 8 x 8 characters */ 256, /* 256 characters */ 1, /* 1 bits per pixel */ { 0 }, /* no bitplanes */ /* x offsets */ { 0, 1, 2, 3, 4, 5, 6, 7 }, /* y offsets */ { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }, 8*8 /* every char takes 8 bytes */ }; /* This will show the 128 characters in the ROM + whatever happens to be in the PCG */ static GFXDECODE_START( sorcerer ) GFXDECODE_ENTRY( "maincpu", 0xf800, sorcerer_charlayout, 0, 1 ) GFXDECODE_END void sorcerer_state::video_start() { m_p_videoram = memregion("maincpu")->base()+0xf000; } UINT32 sorcerer_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { UINT8 y,ra,chr,gfx; UINT16 sy=0,ma=0x80,x; UINT16 *p; for (y = 0; y < 30; y++) { for (ra = 0; ra < 8; ra++) { p = &bitmap.pix16(sy++); for (x = ma; x < ma+64; x++) { chr = m_p_videoram[x]; /* get pattern of pixels for that character scanline */ gfx = m_p_videoram[0x800 | (chr<<3) | ra]; /* Display a scanline of a character */ *p++ = BIT(gfx, 7); *p++ = BIT(gfx, 6); *p++ = BIT(gfx, 5); *p++ = BIT(gfx, 4); *p++ = BIT(gfx, 3); *p++ = BIT(gfx, 2); *p++ = BIT(gfx, 1); *p++ = BIT(gfx, 0); } } ma+=64; } return 0; } /**********************************************************************************************************/ static const ay31015_config sorcerer_ay31015_config = { 4800.0, 4800.0, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL }; static const cassette_interface sorcerer_cassette_interface = { sorcerer_cassette_formats, NULL, (cassette_state)(CASSETTE_PLAY | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED), "sorcerer_cass", NULL }; static const floppy_interface sorcerer_floppy_interface = { DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, FLOPPY_STANDARD_8_SSSD, LEGACY_FLOPPY_OPTIONS_NAME(sorcerer), "floppy_8", NULL }; static MACHINE_CONFIG_START( sorcerer, sorcerer_state ) /* basic machine hardware */ MCFG_CPU_ADD("maincpu", Z80, 12638000/6) MCFG_CPU_PROGRAM_MAP(sorcerer_mem) MCFG_CPU_IO_MAP(sorcerer_io) /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(50) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(200)) MCFG_SCREEN_SIZE(64*8, 30*8) MCFG_SCREEN_VISIBLE_AREA(0, 64*8-1, 0, 30*8-1) MCFG_SCREEN_UPDATE_DRIVER(sorcerer_state, screen_update) MCFG_GFXDECODE_ADD("gfxdecode", sorcerer) MCFG_PALETTE_ADD_BLACK_AND_WHITE("palette") /* sound hardware */ MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette") MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) // cass1 speaker MCFG_SOUND_WAVE_ADD(WAVE2_TAG, "cassette2") MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) // cass2 speaker MCFG_AY31015_ADD( "uart", sorcerer_ay31015_config ) /* printer */ MCFG_CENTRONICS_ADD("centronics", centronics_printers, "covox") MCFG_SLOT_OPTION_ADD( "covox", CENTRONICS_COVOX ) /* The use of the parallel port as a general purpose port is not emulated. Currently the only use is to read the printer status in the Centronics CENDRV bios routine. */ MCFG_CENTRONICS_BUSY_HANDLER(DEVWRITELINE("cent_status_in", input_buffer_device, write_bit7)) MCFG_DEVICE_ADD("cent_status_in", INPUT_BUFFER, 0) /* quickload */ MCFG_SNAPSHOT_ADD("snapshot", sorcerer_state, sorcerer, "snp", 2) MCFG_QUICKLOAD_ADD("quickload", sorcerer_state, sorcerer, "bin", 3) MCFG_CASSETTE_ADD( "cassette", sorcerer_cassette_interface ) MCFG_CASSETTE_ADD( "cassette2", sorcerer_cassette_interface ) /* cartridge */ MCFG_CARTSLOT_ADD("cart") MCFG_CARTSLOT_EXTENSION_LIST("rom,bin") MCFG_CARTSLOT_INTERFACE("sorcerer_cart") /* software lists */ MCFG_SOFTWARE_LIST_ADD("cart_list","sorcerer_cart") MCFG_SOFTWARE_LIST_ADD("cass_list","sorcerer_cass") // internal ram MCFG_RAM_ADD(RAM_TAG) MCFG_RAM_DEFAULT_SIZE("48K") MCFG_RAM_EXTRA_OPTIONS("8K,16K,32K") MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( sorcererd, sorcerer ) MCFG_CPU_MODIFY("maincpu") MCFG_CPU_PROGRAM_MAP(sorcererd_mem) MCFG_MACHINE_START_OVERRIDE(sorcerer_state, sorcererd ) MCFG_MICROPOLIS_ADD("fdc", default_micropolis_interface ) MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(sorcerer_floppy_interface) MCFG_SOFTWARE_LIST_ADD("flop_list","sorcerer_flop") MACHINE_CONFIG_END DRIVER_INIT_MEMBER(sorcerer_state,sorcerer) { UINT8 *RAM = memregion("maincpu")->base(); membank("boot")->configure_entries(0, 2, &RAM[0x0000], 0xe000); } /*************************************************************************** Game driver(s) ***************************************************************************/ ROM_START(sorcerer) ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF ) ROM_LOAD("exmo1-1.dat", 0xe000, 0x0800, CRC(ac924f67) SHA1(72fcad6dd1ed5ec0527f967604401284d0e4b6a1) ) /* monitor roms */ ROM_LOAD("exmo1-2.dat", 0xe800, 0x0800, CRC(ead1d0f6) SHA1(c68bed7344091bca135e427b4793cc7d49ca01be) ) ROM_LOAD("exchr-1.dat", 0xf800, 0x0400, CRC(4a7e1cdd) SHA1(2bf07a59c506b6e0c01ec721fb7b747b20f5dced) ) /* char rom */ ROM_CART_LOAD("cart", 0xc000, 0x2000, ROM_OPTIONAL) ROM_END ROM_START(sorcererd) ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF ) ROM_LOAD("diskboot.dat",0xbc00, 0x0100, CRC(d82a40d6) SHA1(cd1ef5fb0312cd1640e0853d2442d7d858bc3e3b) ) ROM_LOAD("exmo1-1.dat", 0xe000, 0x0800, CRC(ac924f67) SHA1(72fcad6dd1ed5ec0527f967604401284d0e4b6a1) ) /* monitor roms */ ROM_LOAD("exmo1-2.dat", 0xe800, 0x0800, CRC(ead1d0f6) SHA1(c68bed7344091bca135e427b4793cc7d49ca01be) ) ROM_LOAD("exchr-1.dat", 0xf800, 0x0400, CRC(4a7e1cdd) SHA1(2bf07a59c506b6e0c01ec721fb7b747b20f5dced) ) /* char rom */ ROM_CART_LOAD("cart", 0xc000, 0x2000, ROM_OPTIONAL) ROM_REGION( 0x200, "proms", 0 ) ROM_LOAD_OPTIONAL("bruce.dat", 0x0000, 0x0020, CRC(fae922cb) SHA1(470a86844cfeab0d9282242e03ff1d8a1b2238d1) ) /* video prom */ ROM_END /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */ COMP(1979, sorcerer, 0, 0, sorcerer, sorcerer, sorcerer_state, sorcerer, "Exidy Inc", "Sorcerer", 0 ) COMP(1979, sorcererd, sorcerer, 0, sorcererd, sorcerer, sorcerer_state, sorcerer, "Exidy Inc", "Sorcerer (with floppy disks)", 0 )