trunk/src/mame/drivers/osborne1.c
r249959 | r249960 | |
37 | 37 | 02 - Set BIT 9 signal (map bank 3 into F000-FFFF) |
38 | 38 | 03 - Clear BIT 9 signal (map bank 1/2 into F000-FFFF) |
39 | 39 | |
| 40 | Selecting between bank 1 and bank 2 is also affected by M1 and IRQACK |
| 41 | conditions using a set of three flipflops. |
| 42 | |
40 | 43 | TODO: |
41 | | - Implement ROM/IO bank selection properly |
42 | 44 | - Implement serial port |
43 | | - Implement reset key (generates NMI and affects bank selection) |
44 | 45 | - Verify frequency of the beep/audio alarm. |
45 | 46 | |
46 | 47 | ***************************************************************************/ |
r249959 | r249960 | |
52 | 53 | |
53 | 54 | |
54 | 55 | static ADDRESS_MAP_START( osborne1_mem, AS_PROGRAM, 8, osborne1_state ) |
55 | | AM_RANGE( 0x0000, 0x0FFF ) AM_READ_BANK("bank1") AM_WRITE( osborne1_0000_w ) |
56 | | AM_RANGE( 0x1000, 0x1FFF ) AM_READ_BANK("bank2") AM_WRITE( osborne1_1000_w ) |
57 | | AM_RANGE( 0x2000, 0x3FFF ) AM_READWRITE( osborne1_2000_r, osborne1_2000_w ) |
| 56 | AM_RANGE( 0x0000, 0x0FFF ) AM_READ_BANK("bank_0xxx") AM_WRITE(bank_0xxx_w) |
| 57 | AM_RANGE( 0x1000, 0x1FFF ) AM_READ_BANK("bank_1xxx") AM_WRITE(bank_1xxx_w) |
| 58 | AM_RANGE( 0x2000, 0x3FFF ) AM_READWRITE(bank_2xxx_3xxx_r, bank_2xxx_3xxx_w) |
58 | 59 | AM_RANGE( 0x4000, 0xEFFF ) AM_RAM |
59 | | AM_RANGE( 0xF000, 0xFFFF ) AM_READ_BANK("bank3") AM_WRITE( osborne1_videoram_w ) |
| 60 | AM_RANGE( 0xF000, 0xFFFF ) AM_READ_BANK("bank_fxxx") AM_WRITE(videoram_w) |
60 | 61 | ADDRESS_MAP_END |
61 | 62 | |
62 | 63 | |
| 64 | static ADDRESS_MAP_START( osborne1_op, AS_DECRYPTED_OPCODES, 8, osborne1_state ) |
| 65 | AM_RANGE( 0x0000, 0xFFFF ) AM_READ(opcode_r) |
| 66 | ADDRESS_MAP_END |
| 67 | |
| 68 | |
63 | 69 | static ADDRESS_MAP_START( osborne1_io, AS_IO, 8, osborne1_state ) |
64 | 70 | ADDRESS_MAP_UNMAP_HIGH |
65 | 71 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
66 | | AM_RANGE( 0x00, 0xff ) AM_WRITE( osborne1_bankswitch_w ) |
| 72 | AM_RANGE( 0x00, 0xff ) AM_WRITE(bankswitch_w) |
67 | 73 | ADDRESS_MAP_END |
68 | 74 | |
69 | 75 | |
70 | 76 | static INPUT_PORTS_START( osborne1 ) |
71 | 77 | PORT_START("ROW0") |
72 | | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('[') PORT_CHAR(']') |
| 78 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('[') PORT_CHAR(']') |
73 | 79 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('\'') PORT_CHAR('"') |
74 | 80 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) |
75 | 81 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) |
76 | 82 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) |
77 | | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) |
| 83 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) |
78 | 84 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') |
79 | 85 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) |
80 | 86 | |
r249959 | r249960 | |
150 | 156 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) |
151 | 157 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) |
152 | 158 | |
| 159 | PORT_START("RESET") |
| 160 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RESET") PORT_CODE(KEYCODE_F12) |
| 161 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) |
| 162 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) |
| 163 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 164 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) |
| 165 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) |
| 166 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) |
| 167 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) |
| 168 | |
153 | 169 | PORT_START("CNF") |
154 | 170 | PORT_CONFNAME(0x01, 0x00, "Video Output") |
155 | 171 | PORT_CONFSETTING(0x00, "Standard") |
r249959 | r249960 | |
157 | 173 | INPUT_PORTS_END |
158 | 174 | |
159 | 175 | |
160 | | static const z80_daisy_config osborne1_daisy_chain[] = |
161 | | { |
162 | | /* { osborne1_z80_reset, osborne1_z80_irq_state, osborne1_z80_irq_ack, osborne1_z80_irq_reti, 0 }, */ |
163 | | { "osborne1_daisy" }, |
164 | | { NULL } |
165 | | }; |
166 | | |
167 | | |
168 | 176 | /* |
169 | 177 | * The Osborne-1 supports the following disc formats: |
170 | 178 | * - Osborne single density: 40 tracks, 10 sectors per track, 256-byte sectors (100 KByte) |
r249959 | r249960 | |
176 | 184 | */ |
177 | 185 | |
178 | 186 | static SLOT_INTERFACE_START( osborne1_floppies ) |
179 | | SLOT_INTERFACE( "525sssd", FLOPPY_525_SSSD ) // Siemens FDD 100-5, custom Osborne electronics |
180 | | SLOT_INTERFACE( "525ssdd", FLOPPY_525_SSDD ) // MPI 52(?), custom Osborne electronics |
| 187 | SLOT_INTERFACE("525sssd", FLOPPY_525_SSSD) // Siemens FDD 100-5, custom Osborne electronics |
| 188 | SLOT_INTERFACE("525ssdd", FLOPPY_525_SSDD) // MPI 52(?), custom Osborne electronics |
181 | 189 | SLOT_INTERFACE_END |
182 | 190 | |
183 | 191 | |
184 | 192 | /* F4 Character Displayer */ |
185 | 193 | static const gfx_layout osborne1_charlayout = |
186 | 194 | { |
187 | | 8, 10, /* 8 x 10 characters */ |
188 | | 128, /* 128 characters */ |
189 | | 1, /* 1 bits per pixel */ |
190 | | { 0 }, /* no bitplanes */ |
191 | | /* x offsets */ |
| 195 | 8, 10, // 8 x 10 characters |
| 196 | 128, // 128 characters |
| 197 | 1, // 1 bits per pixel |
| 198 | { 0 }, // no bitplanes |
| 199 | // x offsets |
192 | 200 | { 0, 1, 2, 3, 4, 5, 6, 7 }, |
193 | | /* y offsets */ |
| 201 | // y offsets |
194 | 202 | { 0*128*8, 1*128*8, 2*128*8, 3*128*8, 4*128*8, 5*128*8, 6*128*8, 7*128*8, 8*128*8, 9*128*8 }, |
195 | | 8 /* every char takes 16 x 1 bytes */ |
| 203 | 8 // every char takes 16 x 1 bytes |
196 | 204 | }; |
197 | 205 | |
198 | 206 | static GFXDECODE_START( osborne1 ) |
199 | | GFXDECODE_ENTRY( "chargen", 0x0000, osborne1_charlayout, 0, 1 ) |
| 207 | GFXDECODE_ENTRY("chargen", 0x0000, osborne1_charlayout, 0, 1) |
200 | 208 | GFXDECODE_END |
201 | 209 | |
202 | 210 | |
203 | 211 | static MACHINE_CONFIG_START( osborne1, osborne1_state ) |
204 | | MCFG_CPU_ADD( "maincpu", Z80, MAIN_CLOCK/4 ) |
205 | | MCFG_CPU_PROGRAM_MAP( osborne1_mem) |
206 | | MCFG_CPU_IO_MAP( osborne1_io) |
207 | | MCFG_CPU_CONFIG( osborne1_daisy_chain ) |
| 212 | MCFG_CPU_ADD("maincpu", Z80, MAIN_CLOCK/4) |
| 213 | MCFG_CPU_PROGRAM_MAP(osborne1_mem) |
| 214 | MCFG_CPU_DECRYPTED_OPCODES_MAP(osborne1_op) |
| 215 | MCFG_CPU_IO_MAP(osborne1_io) |
| 216 | MCFG_Z80_SET_IRQACK_CALLBACK(WRITELINE(osborne1_state, irqack_w)) |
208 | 217 | |
209 | | MCFG_DEVICE_ADD( "osborne1_daisy", OSBORNE1_DAISY, 0 ) |
210 | | |
211 | 218 | MCFG_SCREEN_ADD("screen", RASTER) |
212 | 219 | MCFG_SCREEN_UPDATE_DRIVER(osborne1_state, screen_update) |
213 | 220 | MCFG_SCREEN_RAW_PARAMS( MAIN_CLOCK, 1024, 0, 104*8, 260, 0, 24*10 ) |
trunk/src/mame/includes/osborne1.h
r249959 | r249960 | |
11 | 11 | |
12 | 12 | #include "emu.h" |
13 | 13 | #include "cpu/z80/z80.h" |
14 | | #include "cpu/z80/z80daisy.h" |
15 | 14 | #include "sound/beep.h" |
16 | 15 | #include "machine/6821pia.h" |
17 | 16 | #include "machine/6850acia.h" |
r249959 | r249960 | |
39 | 38 | m_ieee(*this, IEEE488_TAG), |
40 | 39 | m_floppy0(*this, "mb8877:0:525ssdd"), |
41 | 40 | m_floppy1(*this, "mb8877:1:525ssdd"), |
42 | | m_row0(*this, "ROW0"), |
43 | | m_row1(*this, "ROW1"), |
44 | | m_row2(*this, "ROW2"), |
45 | | m_row3(*this, "ROW3"), |
46 | | m_row4(*this, "ROW4"), |
47 | | m_row5(*this, "ROW5"), |
48 | | m_row6(*this, "ROW6"), |
49 | | m_row7(*this, "ROW7"), |
| 41 | m_keyb_row0(*this, "ROW0"), |
| 42 | m_keyb_row1(*this, "ROW1"), |
| 43 | m_keyb_row2(*this, "ROW2"), |
| 44 | m_keyb_row3(*this, "ROW3"), |
| 45 | m_keyb_row4(*this, "ROW4"), |
| 46 | m_keyb_row5(*this, "ROW5"), |
| 47 | m_keyb_row6(*this, "ROW6"), |
| 48 | m_keyb_row7(*this, "ROW7"), |
| 49 | m_btn_reset(*this, "RESET"), |
50 | 50 | m_cnf(*this, "CNF"), |
51 | | m_bank1(*this, "bank1"), |
52 | | m_bank2(*this, "bank2"), |
53 | | m_bank3(*this, "bank3"), |
| 51 | m_bank_0xxx(*this, "bank_0xxx"), |
| 52 | m_bank_1xxx(*this, "bank_1xxx"), |
| 53 | m_bank_fxxx(*this, "bank_fxxx"), |
54 | 54 | m_region_maincpu(*this, "maincpu") { } |
55 | 55 | |
56 | 56 | virtual void video_start(); |
r249959 | r249960 | |
69 | 69 | required_device<floppy_image_device> m_floppy0; |
70 | 70 | required_device<floppy_image_device> m_floppy1; |
71 | 71 | |
72 | | DECLARE_WRITE8_MEMBER(osborne1_0000_w); |
73 | | DECLARE_WRITE8_MEMBER(osborne1_1000_w); |
74 | | DECLARE_READ8_MEMBER(osborne1_2000_r); |
75 | | DECLARE_WRITE8_MEMBER(osborne1_2000_w); |
76 | | DECLARE_WRITE8_MEMBER(osborne1_videoram_w); |
77 | | DECLARE_WRITE8_MEMBER(osborne1_bankswitch_w); |
78 | | DECLARE_WRITE_LINE_MEMBER(ieee_pia_irq_a_func); |
| 72 | DECLARE_WRITE8_MEMBER(bank_0xxx_w); |
| 73 | DECLARE_WRITE8_MEMBER(bank_1xxx_w); |
| 74 | DECLARE_READ8_MEMBER(bank_2xxx_3xxx_r); |
| 75 | DECLARE_WRITE8_MEMBER(bank_2xxx_3xxx_w); |
| 76 | DECLARE_WRITE8_MEMBER(videoram_w); |
| 77 | DECLARE_READ8_MEMBER(opcode_r); |
| 78 | DECLARE_WRITE8_MEMBER(bankswitch_w); |
| 79 | DECLARE_WRITE_LINE_MEMBER(irqack_w); |
| 80 | |
79 | 81 | DECLARE_READ8_MEMBER(ieee_pia_pb_r); |
80 | 82 | DECLARE_WRITE8_MEMBER(ieee_pia_pb_w); |
81 | | DECLARE_WRITE_LINE_MEMBER(video_pia_out_cb2_dummy); |
| 83 | DECLARE_WRITE_LINE_MEMBER(ieee_pia_irq_a_func); |
| 84 | |
82 | 85 | DECLARE_WRITE8_MEMBER(video_pia_port_a_w); |
83 | 86 | DECLARE_WRITE8_MEMBER(video_pia_port_b_w); |
| 87 | DECLARE_WRITE_LINE_MEMBER(video_pia_out_cb2_dummy); |
84 | 88 | DECLARE_WRITE_LINE_MEMBER(video_pia_irq_a_func); |
85 | | DECLARE_DIRECT_UPDATE_MEMBER(osborne1_opbase); |
86 | 89 | |
87 | | bool m_bank2_enabled; |
88 | | UINT8 m_bit_9; |
89 | | /* IRQ states */ |
90 | | bool m_pia_0_irq_state; |
91 | | bool m_pia_1_irq_state; |
92 | 90 | /* video related */ |
93 | 91 | UINT8 m_screen_pac; |
94 | 92 | UINT8 m_resolution; |
r249959 | r249960 | |
97 | 95 | UINT8 m_new_start_y; |
98 | 96 | emu_timer *m_video_timer; |
99 | 97 | UINT8 *m_p_chargen; |
100 | | /* bankswitch setting */ |
101 | | UINT8 m_bankswitch; |
102 | | bool m_in_irq_handler; |
103 | 98 | bool m_beep_state; |
104 | 99 | DECLARE_DRIVER_INIT(osborne1); |
105 | 100 | virtual void machine_reset(); |
r249959 | r249960 | |
107 | 102 | TIMER_CALLBACK_MEMBER(setup_osborne1); |
108 | 103 | |
109 | 104 | protected: |
110 | | required_ioport m_row0; |
111 | | required_ioport m_row1; |
112 | | required_ioport m_row2; |
113 | | required_ioport m_row3; |
114 | | required_ioport m_row4; |
115 | | required_ioport m_row5; |
116 | | required_ioport m_row6; |
117 | | required_ioport m_row7; |
| 105 | required_ioport m_keyb_row0; |
| 106 | required_ioport m_keyb_row1; |
| 107 | required_ioport m_keyb_row2; |
| 108 | required_ioport m_keyb_row3; |
| 109 | required_ioport m_keyb_row4; |
| 110 | required_ioport m_keyb_row5; |
| 111 | required_ioport m_keyb_row6; |
| 112 | required_ioport m_keyb_row7; |
| 113 | required_ioport m_btn_reset; |
| 114 | |
118 | 115 | required_ioport m_cnf; |
119 | | required_memory_bank m_bank1; |
120 | | required_memory_bank m_bank2; |
121 | | required_memory_bank m_bank3; |
122 | | required_memory_region m_region_maincpu; |
123 | 116 | |
124 | | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
125 | | }; |
| 117 | required_memory_bank m_bank_0xxx; |
| 118 | required_memory_bank m_bank_1xxx; |
| 119 | required_memory_bank m_bank_fxxx; |
126 | 120 | |
| 121 | required_memory_region m_region_maincpu; |
127 | 122 | |
128 | | // ======================> osborne1_daisy_device |
| 123 | // bank switch control bits |
| 124 | UINT8 m_ub4a_q; |
| 125 | UINT8 m_ub6a_q; |
| 126 | UINT8 m_rom_mode; |
| 127 | UINT8 m_bit_9; |
129 | 128 | |
130 | | class osborne1_daisy_device : public device_t, |
131 | | public device_z80daisy_interface |
132 | | { |
133 | | public: |
134 | | // construction/destruction |
135 | | osborne1_daisy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 129 | bool set_rom_mode(UINT8 value); |
| 130 | bool set_bit_9(UINT8 value); |
| 131 | void update_irq(); |
136 | 132 | |
137 | | private: |
138 | | virtual void device_start(); |
139 | | // z80daisy_interface overrides |
140 | | virtual int z80daisy_irq_state(); |
141 | | virtual int z80daisy_irq_ack(); |
142 | | virtual void z80daisy_irq_reti(); |
| 133 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
143 | 134 | }; |
144 | 135 | |
145 | | extern const device_type OSBORNE1_DAISY; |
146 | | |
147 | 136 | #endif /* OSBORNE1_H_ */ |
trunk/src/mame/machine/osborne1.c
r249959 | r249960 | |
3 | 3 | /*************************************************************************** |
4 | 4 | |
5 | 5 | There are three IRQ sources: |
6 | | - IRQ0 |
| 6 | - IRQ0 = IRQ from the serial ACIA |
7 | 7 | - IRQ1 = IRQA from the video PIA |
8 | 8 | - IRQ2 = IRQA from the IEEE488 PIA |
9 | 9 | |
10 | | Interrupt handling on the Osborne-1 is a bit awkward. When an interrupt is |
11 | | taken by the Z80 the ROMMODE is enabled on each fetch of an instruction |
12 | | byte. During execution of an instruction the previous ROMMODE setting seems |
13 | | to be used. Side effect of this is that when an interrupt is taken and the |
14 | | stack pointer is pointing to 0000-3FFF then the return address will still |
15 | | be written to RAM if RAM was switched in. |
16 | | |
17 | 10 | ***************************************************************************/ |
18 | 11 | |
19 | 12 | #include "includes/osborne1.h" |
20 | 13 | |
21 | | #define RAMMODE (0x01) |
22 | 14 | |
23 | | |
24 | | WRITE8_MEMBER( osborne1_state::osborne1_0000_w ) |
| 15 | WRITE8_MEMBER( osborne1_state::bank_0xxx_w ) |
25 | 16 | { |
26 | | /* Check whether regular RAM is enabled */ |
27 | | if ( !m_bank2_enabled || ( m_in_irq_handler && m_bankswitch == RAMMODE) ) |
28 | | { |
29 | | m_ram->pointer()[ offset ] = data; |
30 | | } |
| 17 | if (!m_rom_mode) |
| 18 | m_ram->pointer()[offset] = data; |
31 | 19 | } |
32 | 20 | |
33 | | |
34 | | WRITE8_MEMBER( osborne1_state::osborne1_1000_w ) |
| 21 | WRITE8_MEMBER( osborne1_state::bank_1xxx_w ) |
35 | 22 | { |
36 | | /* Check whether regular RAM is enabled */ |
37 | | if ( !m_bank2_enabled || ( m_in_irq_handler && m_bankswitch == RAMMODE) ) |
38 | | { |
39 | | m_ram->pointer()[ 0x1000 + offset ] = data; |
40 | | } |
| 23 | if (!m_rom_mode) |
| 24 | m_ram->pointer()[0x1000 + offset] = data; |
41 | 25 | } |
42 | 26 | |
43 | | |
44 | | READ8_MEMBER( osborne1_state::osborne1_2000_r ) |
| 27 | READ8_MEMBER( osborne1_state::bank_2xxx_3xxx_r ) |
45 | 28 | { |
46 | | UINT8 data = 0xFF; |
| 29 | if (!m_rom_mode) |
| 30 | return m_ram->pointer()[0x2000 + offset]; |
47 | 31 | |
48 | | /* Check whether regular RAM is enabled */ |
49 | | if ( !m_bank2_enabled ) |
| 32 | // This isn't really accurate - bus fighting will occur for many values |
| 33 | // since each peripheral only checks two bits. We just return 0xFF for |
| 34 | // any undocumented address. |
| 35 | UINT8 data = 0xFF; |
| 36 | switch (offset & 0x0F00) |
50 | 37 | { |
51 | | data = m_ram->pointer()[ 0x2000 + offset ]; |
| 38 | case 0x100: /* Floppy */ |
| 39 | data = m_fdc->read(space, offset & 0x03); |
| 40 | break; |
| 41 | case 0x200: /* Keyboard */ |
| 42 | if (offset & 0x01) data &= m_keyb_row0->read(); |
| 43 | if (offset & 0x02) data &= m_keyb_row1->read(); |
| 44 | if (offset & 0x04) data &= m_keyb_row3->read(); |
| 45 | if (offset & 0x08) data &= m_keyb_row4->read(); |
| 46 | if (offset & 0x10) data &= m_keyb_row5->read(); |
| 47 | if (offset & 0x20) data &= m_keyb_row2->read(); |
| 48 | if (offset & 0x40) data &= m_keyb_row6->read(); |
| 49 | if (offset & 0x80) data &= m_keyb_row7->read(); |
| 50 | break; |
| 51 | case 0x400: /* SCREEN-PAC */ |
| 52 | if (m_screen_pac) data &= 0xFB; |
| 53 | break; |
| 54 | case 0x900: /* IEEE488 PIA */ |
| 55 | data = m_pia0->read(space, offset & 0x03); |
| 56 | break; |
| 57 | case 0xA00: /* Serial */ |
| 58 | break; |
| 59 | case 0xC00: /* Video PIA */ |
| 60 | data = m_pia1->read(space, offset & 0x03); |
| 61 | break; |
52 | 62 | } |
53 | | else |
54 | | { |
55 | | // This isn't really accurate - bus fighting will occur for many values |
56 | | // since each peripheral only checks two bits. We just return 0xFF for |
57 | | // any undocumented address. |
58 | | switch ( offset & 0x0F00 ) |
59 | | { |
60 | | case 0x100: /* Floppy */ |
61 | | data = m_fdc->read( space, offset & 0x03 ); |
62 | | break; |
63 | | case 0x200: /* Keyboard */ |
64 | | /* Row 0 */ |
65 | | if ( offset & 0x01 ) data &= m_row0->read(); |
66 | | /* Row 1 */ |
67 | | if ( offset & 0x02 ) data &= m_row1->read(); |
68 | | /* Row 2 */ |
69 | | if ( offset & 0x04 ) data &= m_row3->read(); |
70 | | /* Row 3 */ |
71 | | if ( offset & 0x08 ) data &= m_row4->read(); |
72 | | /* Row 4 */ |
73 | | if ( offset & 0x10 ) data &= m_row5->read(); |
74 | | /* Row 5 */ |
75 | | if ( offset & 0x20 ) data &= m_row2->read(); |
76 | | /* Row 6 */ |
77 | | if ( offset & 0x40 ) data &= m_row6->read(); |
78 | | /* Row 7 */ |
79 | | if ( offset & 0x80 ) data &= m_row7->read(); |
80 | | break; |
81 | | case 0x400: /* SCREEN-PAC */ |
82 | | if (m_screen_pac) data &= 0xFB; |
83 | | break; |
84 | | case 0x900: /* IEEE488 PIA */ |
85 | | data = m_pia0->read(space, offset & 0x03); |
86 | | break; |
87 | | case 0xA00: /* Serial */ |
88 | | break; |
89 | | case 0xC00: /* Video PIA */ |
90 | | data = m_pia1->read(space, offset & 0x03); |
91 | | break; |
92 | | } |
93 | | } |
94 | 63 | return data; |
95 | 64 | } |
96 | 65 | |
97 | | |
98 | | WRITE8_MEMBER( osborne1_state::osborne1_2000_w ) |
| 66 | WRITE8_MEMBER( osborne1_state::bank_2xxx_3xxx_w ) |
99 | 67 | { |
100 | | #if 0 |
101 | | /* Check whether regular RAM is enabled */ |
102 | | if ( !m_bank2_enabled || (m_in_irq_handler && m_bankswitch == RAMMODE) ) |
| 68 | if (!m_rom_mode) |
103 | 69 | { |
104 | | m_ram->pointer()[ 0x2000 + offset ] = data; |
| 70 | m_ram->pointer()[0x2000 + offset] = data; |
105 | 71 | } |
106 | 72 | else |
107 | 73 | { |
108 | | /* Handle writes to the I/O area */ |
109 | | if ( 0x100 == (offset & 0x900) ) /* Floppy */ |
| 74 | // Handle writes to the I/O area |
| 75 | if ((offset & 0x900) == 0x100) // Floppy |
110 | 76 | m_fdc->write(space, offset & 0x03, data); |
111 | | if ( 0x400 == (offset & 0xC00) ) /* SCREEN-PAC */ |
112 | | { |
113 | | m_resolution = data & 0x01; |
114 | | m_hc_left = (data >> 1) & 0x01; |
115 | | } |
116 | | if ( 0x900 == (offset & 0x900) ) /* IEEE488 PIA */ |
| 77 | if ((offset & 0x900) == 0x900) // IEEE488 PIA |
117 | 78 | m_pia0->write(space, offset & 0x03, data); |
118 | | if ( 0xA00 == (offset & 0xA00) ) /* Serial */ |
| 79 | if ((offset & 0xA00) == 0xA00) // Serial |
119 | 80 | /* not implemented */; |
120 | | if ( 0xC00 == (offset & 0xC00) ) /* Video PIA */ |
121 | | m_pia1->write(space, offset & 0x03, data); |
122 | | } |
123 | | #else |
124 | | // This code is a nasty hack that doesn't reflect hardware operation, |
125 | | // but it gets us by while the bank selection implementation is inadequate |
126 | | if ( ! m_bank2_enabled ) |
127 | | { |
128 | | m_ram->pointer()[ 0x2000 + offset ] = data; |
129 | | } |
130 | | else |
131 | | { |
132 | | if ( m_in_irq_handler && m_bankswitch == RAMMODE ) |
| 81 | if ((offset & 0xC00) == 0x400) // SCREEN-PAC |
133 | 82 | { |
134 | | m_ram->pointer()[ 0x2000 + offset ] = data; |
135 | | } |
136 | | /* Handle writes to the I/O area */ |
137 | | switch( offset & 0x1F00 ) |
138 | | { |
139 | | case 0x100: /* Floppy */ |
140 | | m_fdc->write(space, offset & 0x03, data); |
141 | | break; |
142 | | case 0x400: /* SCREEN-PAC */ |
143 | 83 | m_resolution = data & 0x01; |
144 | 84 | m_hc_left = (data >> 1) & 0x01; |
145 | | break; |
146 | | case 0x900: /* IEEE488 PIA */ |
147 | | m_pia0->write(space, offset & 0x03, data ); |
148 | | break; |
149 | | case 0xA00: /* Serial */ |
150 | | break; |
151 | | case 0xC00: /* Video PIA */ |
152 | | m_pia1->write(space, offset & 0x03, data ); |
153 | | break; |
154 | 85 | } |
| 86 | if ((offset & 0xC00) == 0xC00) // Video PIA |
| 87 | m_pia1->write(space, offset & 0x03, data); |
155 | 88 | } |
156 | | #endif |
157 | 89 | } |
158 | 90 | |
| 91 | WRITE8_MEMBER( osborne1_state::videoram_w ) |
| 92 | { |
| 93 | // Attribute RAM is only one bit wide - low seven bits are discarded and read back high |
| 94 | if (m_bit_9) data |= 0x7F; |
| 95 | reinterpret_cast<UINT8 *>(m_bank_fxxx->base())[offset] = data; |
| 96 | } |
159 | 97 | |
160 | | WRITE8_MEMBER( osborne1_state::osborne1_videoram_w ) |
| 98 | READ8_MEMBER( osborne1_state::opcode_r ) |
161 | 99 | { |
162 | | /* Check whether the video attribute section is enabled */ |
163 | | if ( m_bit_9 ) |
164 | | data |= 0x7F; |
| 100 | // Update the flipflops that control bank selection and NMI |
| 101 | UINT8 const new_ub6a_q = (m_btn_reset->read() & 0x80) ? 1 : 0; |
| 102 | if (!m_rom_mode) |
| 103 | { |
| 104 | set_rom_mode(m_ub4a_q ? 0 : 1); |
| 105 | m_ub4a_q = m_ub6a_q; |
| 106 | } |
| 107 | m_ub6a_q = new_ub6a_q; |
| 108 | m_maincpu->set_input_line(INPUT_LINE_NMI, m_ub6a_q ? CLEAR_LINE : ASSERT_LINE); |
165 | 109 | |
166 | | reinterpret_cast<UINT8 *>(m_bank3->base())[offset] = data; |
| 110 | // Now that's sorted out we can call the normal read handler |
| 111 | return m_maincpu->space(AS_PROGRAM).read_byte(offset); |
167 | 112 | } |
168 | 113 | |
169 | | |
170 | | WRITE8_MEMBER( osborne1_state::osborne1_bankswitch_w ) |
| 114 | WRITE8_MEMBER( osborne1_state::bankswitch_w ) |
171 | 115 | { |
172 | | switch ( offset & 0x03 ) |
| 116 | switch (offset & 0x03) |
173 | 117 | { |
174 | 118 | case 0x00: |
175 | | m_bank2_enabled = 1; |
176 | | m_bankswitch = 0x00; |
| 119 | if (set_rom_mode(1)) |
| 120 | m_ub4a_q = m_ub6a_q; |
177 | 121 | break; |
178 | 122 | case 0x01: |
179 | | m_bank2_enabled = 0; |
180 | | m_bankswitch = 0x01; |
| 123 | m_ub4a_q = 1; |
| 124 | m_ub6a_q = 1; |
| 125 | set_rom_mode(0); |
| 126 | m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); |
181 | 127 | break; |
182 | 128 | case 0x02: |
183 | | m_bit_9 = 1; |
| 129 | set_bit_9(1); |
184 | 130 | break; |
185 | 131 | case 0x03: |
186 | | m_bit_9 = 0; |
| 132 | set_bit_9(0); |
187 | 133 | break; |
188 | 134 | } |
189 | | if ( m_bank2_enabled ) |
190 | | { |
191 | | m_bank1->set_base(m_region_maincpu->base()); |
192 | | m_bank2->set_base(m_region_maincpu->base()); |
193 | | } |
194 | | else |
195 | | { |
196 | | m_bank1->set_base(m_ram->pointer()); |
197 | | m_bank2->set_base(m_ram->pointer() + 0x1000); |
198 | | } |
199 | | m_bank3->set_base(m_ram->pointer() + (m_bit_9 ? 0x10000 : 0xF000)); |
200 | | m_in_irq_handler = 0; |
201 | 135 | } |
202 | 136 | |
203 | | |
204 | | DIRECT_UPDATE_MEMBER(osborne1_state::osborne1_opbase) |
| 137 | WRITE_LINE_MEMBER( osborne1_state::irqack_w ) |
205 | 138 | { |
206 | | if ( ( address & 0xF000 ) == 0x2000 ) |
207 | | { |
208 | | if ( ! m_bank2_enabled ) |
209 | | { |
210 | | direct.explicit_configure(0x2000, 0x2fff, 0x0fff, m_ram->pointer() + 0x2000); |
211 | | return ~0; |
212 | | } |
213 | | } |
214 | | return address; |
| 139 | // Update the flipflops that control bank selection and NMI |
| 140 | if (!m_rom_mode) set_rom_mode(m_ub4a_q ? 0 : 1); |
| 141 | m_ub4a_q = 0; |
| 142 | m_ub6a_q = (m_btn_reset->read() & 0x80) ? 1 : 0; |
| 143 | m_maincpu->set_input_line(INPUT_LINE_NMI, m_ub6a_q ? CLEAR_LINE : ASSERT_LINE); |
215 | 144 | } |
216 | 145 | |
217 | 146 | |
218 | | WRITE_LINE_MEMBER( osborne1_state::ieee_pia_irq_a_func ) |
219 | | { |
220 | | m_pia_0_irq_state = state; |
221 | | m_maincpu->set_input_line(0, ( m_pia_1_irq_state ) ? ASSERT_LINE : CLEAR_LINE); |
222 | | } |
223 | | |
224 | | |
225 | 147 | READ8_MEMBER( osborne1_state::ieee_pia_pb_r ) |
226 | 148 | { |
227 | 149 | /* |
228 | | |
229 | 150 | bit description |
230 | 151 | |
231 | 152 | 0 |
r249959 | r249960 | |
236 | 157 | 5 DAV |
237 | 158 | 6 NDAC |
238 | 159 | 7 NRFD |
239 | | |
240 | 160 | */ |
241 | | |
242 | 161 | UINT8 data = 0; |
243 | 162 | |
244 | 163 | data |= m_ieee->eoi_r() << 3; |
r249959 | r249960 | |
249 | 168 | return data; |
250 | 169 | } |
251 | 170 | |
252 | | |
253 | 171 | WRITE8_MEMBER( osborne1_state::ieee_pia_pb_w ) |
254 | 172 | { |
255 | 173 | /* |
256 | | |
257 | 174 | bit description |
258 | 175 | |
259 | 176 | 0 |
r249959 | r249960 | |
264 | 181 | 5 DAV |
265 | 182 | 6 NDAC |
266 | 183 | 7 NRFD |
267 | | |
268 | 184 | */ |
269 | | |
270 | 185 | m_ieee->eoi_w(BIT(data, 3)); |
271 | 186 | m_ieee->atn_w(BIT(data, 4)); |
272 | 187 | m_ieee->dav_w(BIT(data, 5)); |
r249959 | r249960 | |
274 | 189 | m_ieee->nrfd_w(BIT(data, 7)); |
275 | 190 | } |
276 | 191 | |
| 192 | WRITE_LINE_MEMBER( osborne1_state::ieee_pia_irq_a_func ) |
| 193 | { |
| 194 | update_irq(); |
| 195 | } |
277 | 196 | |
| 197 | |
278 | 198 | WRITE_LINE_MEMBER( osborne1_state::video_pia_out_cb2_dummy ) |
279 | 199 | { |
280 | 200 | } |
281 | 201 | |
282 | | |
283 | 202 | WRITE8_MEMBER( osborne1_state::video_pia_port_a_w ) |
284 | 203 | { |
285 | 204 | m_fdc->dden_w(BIT(data, 0)); |
r249959 | r249960 | |
293 | 212 | //logerror("Video pia port a write: %02X, density set to %s\n", data, data & 1 ? "FM" : "MFM" ); |
294 | 213 | } |
295 | 214 | |
296 | | |
297 | 215 | WRITE8_MEMBER( osborne1_state::video_pia_port_b_w ) |
298 | 216 | { |
299 | 217 | m_new_start_y = data & 0x1F; |
r249959 | r249960 | |
317 | 235 | //logerror("Video pia port b write: %02X\n", data ); |
318 | 236 | } |
319 | 237 | |
320 | | |
321 | 238 | WRITE_LINE_MEMBER( osborne1_state::video_pia_irq_a_func ) |
322 | 239 | { |
323 | | m_pia_1_irq_state = state; |
324 | | m_maincpu->set_input_line(0, ( m_pia_1_irq_state ) ? ASSERT_LINE : CLEAR_LINE); |
| 240 | update_irq(); |
325 | 241 | } |
326 | 242 | |
327 | 243 | |
r249959 | r249960 | |
357 | 273 | TIMER_CALLBACK_MEMBER(osborne1_state::osborne1_video_callback) |
358 | 274 | { |
359 | 275 | int const y = machine().first_screen()->vpos(); |
360 | | UINT8 ra=0; |
| 276 | UINT8 ra = 0; |
361 | 277 | |
362 | | /* Check for start of frame */ |
363 | | if ( y == 0 ) |
364 | | { |
365 | | /* Clear CA1 on video PIA */ |
| 278 | // Check for start/end of visible area and clear/set CA1 on video PIA |
| 279 | if (y == 0) |
366 | 280 | m_pia1->ca1_w(0); |
367 | | } |
368 | | if ( y == 240 ) |
369 | | { |
370 | | /* Set CA1 on video PIA */ |
| 281 | else if (y == 240) |
371 | 282 | m_pia1->ca1_w(1); |
372 | | } |
373 | | if ( y < 240 ) |
| 283 | |
| 284 | if (y < 240) |
374 | 285 | { |
375 | 286 | ra = y % 10; |
376 | | /* Draw a line of the display */ |
| 287 | // Draw a line of the display |
377 | 288 | bool const hires = m_screen_pac & m_resolution; |
378 | 289 | UINT16 const row = (m_new_start_y + (y/10)) * 128 & 0xF80; |
379 | 290 | UINT16 const col = (m_new_start_x & (hires ? 0x60 : 0x7F)) - ((hires && m_hc_left) ? 8 : 0); |
r249959 | r249960 | |
382 | 293 | for ( UINT16 x = 0; x < (hires ? 104 : 52); x++ ) |
383 | 294 | { |
384 | 295 | UINT16 offs = row | ((col + x) & 0x7F); |
385 | | UINT8 const chr = m_ram->pointer()[ 0xF000 + offs ]; |
386 | | UINT8 const dim = m_ram->pointer()[ 0x10000 + offs ] & 0x80; |
| 296 | UINT8 const chr = m_ram->pointer()[0xF000 + offs]; |
| 297 | UINT8 const dim = m_ram->pointer()[0x10000 + offs] & 0x80; |
387 | 298 | |
388 | | UINT8 const gfx = ((chr & 0x80) && (ra == 9)) ? 0xFF : m_p_chargen[ (ra << 7) | (chr & 0x7F) ]; |
| 299 | UINT8 const gfx = ((chr & 0x80) && (ra == 9)) ? 0xFF : m_p_chargen[(ra << 7) | (chr & 0x7F)]; |
389 | 300 | |
390 | | /* Display a scanline of a character */ |
| 301 | // Display a scanline of a character |
391 | 302 | *p++ = BIT(gfx, 7) ? ( dim ? 2 : 1 ) : 0; |
392 | 303 | if (!hires) { p[0] = p[-1]; p++; } |
393 | 304 | *p++ = BIT(gfx, 6) ? ( dim ? 2 : 1 ) : 0; |
r249959 | r249960 | |
407 | 318 | } |
408 | 319 | } |
409 | 320 | |
410 | | if ( (ra==2) || (ra==6) ) |
411 | | { |
412 | | m_beep->set_state( m_beep_state ); |
413 | | } |
| 321 | if ((ra == 2) || (ra == 6)) |
| 322 | m_beep->set_state(m_beep_state); |
414 | 323 | else |
415 | | { |
416 | | m_beep->set_state( 0 ); |
417 | | } |
| 324 | m_beep->set_state(0); |
418 | 325 | |
419 | | m_video_timer->adjust(machine().first_screen()->time_until_pos(y + 1, 0 )); |
| 326 | // Check reset key if necessary - it affects NMI |
| 327 | if (!m_ub6a_q) |
| 328 | m_maincpu->set_input_line(INPUT_LINE_NMI, (m_btn_reset->read() && 0x80) ? CLEAR_LINE : ASSERT_LINE); |
| 329 | |
| 330 | m_video_timer->adjust(machine().first_screen()->time_until_pos(y + 1, 0)); |
420 | 331 | } |
421 | 332 | |
422 | 333 | TIMER_CALLBACK_MEMBER(osborne1_state::setup_osborne1) |
r249959 | r249960 | |
428 | 339 | |
429 | 340 | void osborne1_state::machine_reset() |
430 | 341 | { |
431 | | /* Initialize memory configuration */ |
432 | | osborne1_bankswitch_w( m_maincpu->space(AS_IO), 0x00, 0 ); |
| 342 | // Initialize memory configuration |
| 343 | m_rom_mode = 0; |
| 344 | m_bit_9 = 1; |
| 345 | set_rom_mode(1); |
| 346 | set_bit_9(0); |
433 | 347 | |
434 | | m_pia_0_irq_state = FALSE; |
435 | | m_pia_1_irq_state = FALSE; |
436 | | m_in_irq_handler = 0; |
437 | | |
438 | 348 | m_screen_pac = 0 != (m_cnf->read() & 0x01); |
439 | 349 | m_resolution = 0; |
440 | 350 | m_hc_left = 0; |
441 | 351 | m_p_chargen = memregion( "chargen" )->base(); |
442 | 352 | |
443 | | memset( m_ram->pointer() + 0x10000, 0xFF, 0x1000 ); |
444 | | |
445 | | address_space& space = m_maincpu->space(AS_PROGRAM); |
446 | | space.set_direct_update_handler(direct_update_delegate(FUNC(osborne1_state::osborne1_opbase), this)); |
| 353 | memset(m_ram->pointer() + 0x10000, 0xFF, 0x1000); |
447 | 354 | } |
448 | 355 | |
449 | 356 | |
r249959 | r249960 | |
452 | 359 | /* Configure the 6850 ACIA */ |
453 | 360 | // acia6850_config( 0, &osborne1_6850_config ); |
454 | 361 | m_video_timer = timer_alloc(TIMER_VIDEO); |
455 | | m_video_timer->adjust(machine().first_screen()->time_until_pos(1, 0 )); |
| 362 | m_video_timer->adjust(machine().first_screen()->time_until_pos(1, 0)); |
456 | 363 | |
457 | 364 | timer_set(attotime::zero, TIMER_SETUP); |
458 | 365 | } |
r249959 | r249960 | |
463 | 370 | machine().first_screen()->register_screen_bitmap(m_bitmap); |
464 | 371 | } |
465 | 372 | |
| 373 | |
466 | 374 | UINT32 osborne1_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
467 | 375 | { |
468 | 376 | copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); |
469 | 377 | return 0; |
470 | 378 | } |
471 | 379 | |
472 | | /**************************************************************** |
473 | | Osborne1 specific daisy chain code |
474 | | ****************************************************************/ |
475 | 380 | |
476 | | const device_type OSBORNE1_DAISY = &device_creator<osborne1_daisy_device>; |
477 | | |
478 | | //************************************************************************** |
479 | | // LIVE DEVICE |
480 | | //************************************************************************** |
481 | | |
482 | | //------------------------------------------------- |
483 | | // z80ctc_device - constructor |
484 | | //------------------------------------------------- |
485 | | osborne1_daisy_device::osborne1_daisy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
486 | | : device_t(mconfig, OSBORNE1_DAISY, "Osborne 1 daisy", tag, owner, clock, "osborne1_daisy", __FILE__), |
487 | | device_z80daisy_interface(mconfig, *this) |
| 381 | bool osborne1_state::set_rom_mode(UINT8 value) |
488 | 382 | { |
| 383 | if (value != m_rom_mode) |
| 384 | { |
| 385 | m_rom_mode = value; |
| 386 | if (m_rom_mode) |
| 387 | { |
| 388 | m_bank_0xxx->set_base(m_region_maincpu->base()); |
| 389 | m_bank_1xxx->set_base(m_region_maincpu->base()); |
| 390 | } |
| 391 | else |
| 392 | { |
| 393 | m_bank_0xxx->set_base(m_ram->pointer()); |
| 394 | m_bank_1xxx->set_base(m_ram->pointer() + 0x1000); |
| 395 | } |
| 396 | return true; |
| 397 | } |
| 398 | else |
| 399 | { |
| 400 | return false; |
| 401 | } |
489 | 402 | } |
490 | 403 | |
491 | | //------------------------------------------------- |
492 | | // device_start - device-specific startup |
493 | | //------------------------------------------------- |
494 | | |
495 | | void osborne1_daisy_device::device_start() |
| 404 | bool osborne1_state::set_bit_9(UINT8 value) |
496 | 405 | { |
| 406 | if (value != m_bit_9) |
| 407 | { |
| 408 | m_bit_9 = value; |
| 409 | m_bank_fxxx->set_base(m_ram->pointer() + (m_bit_9 ? 0x10000 : 0xF000)); |
| 410 | return true; |
| 411 | } |
| 412 | else |
| 413 | { |
| 414 | return false; |
| 415 | } |
497 | 416 | } |
498 | 417 | |
499 | | //************************************************************************** |
500 | | // DAISY CHAIN INTERFACE |
501 | | //************************************************************************** |
502 | | |
503 | | //------------------------------------------------- |
504 | | // z80daisy_irq_state - return the overall IRQ |
505 | | // state for this device |
506 | | //------------------------------------------------- |
507 | | |
508 | | int osborne1_daisy_device::z80daisy_irq_state() |
| 418 | void osborne1_state::update_irq() |
509 | 419 | { |
510 | | osborne1_state *state = machine().driver_data<osborne1_state>(); |
511 | | return ( state->m_pia_1_irq_state ? Z80_DAISY_INT : 0 ); |
| 420 | if (m_pia0->irq_a_state()) |
| 421 | m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xF0); |
| 422 | else if (m_pia1->irq_a_state()) |
| 423 | m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xF8); |
| 424 | else |
| 425 | m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, CLEAR_LINE, 0xFE); |
512 | 426 | } |
513 | | |
514 | | |
515 | | //------------------------------------------------- |
516 | | // z80daisy_irq_ack - acknowledge an IRQ and |
517 | | // return the appropriate vector |
518 | | //------------------------------------------------- |
519 | | |
520 | | int osborne1_daisy_device::z80daisy_irq_ack() |
521 | | { |
522 | | osborne1_state *state = machine().driver_data<osborne1_state>(); |
523 | | /* Enable ROM and I/O when IRQ is acknowledged */ |
524 | | UINT8 old_bankswitch = state->m_bankswitch; |
525 | | |
526 | | state->osborne1_bankswitch_w( state->m_maincpu->space(AS_IO), 0, 0 ); |
527 | | state->m_bankswitch = old_bankswitch; |
528 | | state->m_in_irq_handler = 1; |
529 | | return 0xF8; |
530 | | } |
531 | | |
532 | | //------------------------------------------------- |
533 | | // z80daisy_irq_reti - clear the interrupt |
534 | | // pending state to allow other interrupts through |
535 | | //------------------------------------------------- |
536 | | |
537 | | void osborne1_daisy_device::z80daisy_irq_reti() |
538 | | { |
539 | | } |