trunk/src/mess/includes/a7800.h
| r31777 | r31778 | |
| 1 | | /***************************************************************************** |
| 2 | | * |
| 3 | | * includes/a7800.h |
| 4 | | * |
| 5 | | ****************************************************************************/ |
| 6 | | |
| 7 | | #ifndef A7800_H_ |
| 8 | | #define A7800_H_ |
| 9 | | |
| 10 | | #include "machine/6532riot.h" |
| 11 | | #include "sound/tiasound.h" |
| 12 | | #include "sound/tiaintf.h" |
| 13 | | #include "bus/a7800/a78_slot.h" |
| 14 | | |
| 15 | | |
| 16 | | class a7800_state : public driver_device |
| 17 | | { |
| 18 | | public: |
| 19 | | a7800_state(const machine_config &mconfig, device_type type, const char *tag) |
| 20 | | : driver_device(mconfig, type, tag), |
| 21 | | m_maincpu(*this, "maincpu"), |
| 22 | | m_tia(*this, "tia"), |
| 23 | | m_io_joysticks(*this, "joysticks"), |
| 24 | | m_io_buttons(*this, "buttons"), |
| 25 | | m_io_vblank(*this, "vblank"), |
| 26 | | m_io_console_buttons(*this, "console_buttons"), |
| 27 | | m_cartslot(*this, "cartslot"), |
| 28 | | m_screen(*this, "screen") { } |
| 29 | | |
| 30 | | int m_lines; |
| 31 | | int m_ispal; |
| 32 | | |
| 33 | | int m_ctrl_lock; |
| 34 | | int m_ctrl_reg; |
| 35 | | int m_maria_flag; |
| 36 | | int m_p1_one_button; |
| 37 | | int m_p2_one_button; |
| 38 | | int m_bios_enabled; |
| 39 | | |
| 40 | | UINT8 *m_bios; |
| 41 | | |
| 42 | | int m_maria_palette[32]; |
| 43 | | int m_line_ram[2][160]; |
| 44 | | int m_active_buffer; |
| 45 | | int m_maria_write_mode; |
| 46 | | unsigned int m_maria_dll; |
| 47 | | unsigned int m_maria_dl; |
| 48 | | int m_maria_holey; |
| 49 | | int m_maria_offset; |
| 50 | | int m_maria_vblank; |
| 51 | | int m_maria_dli; |
| 52 | | int m_maria_dmaon; |
| 53 | | int m_maria_dpp; |
| 54 | | int m_maria_wsync; |
| 55 | | int m_maria_backcolor; |
| 56 | | int m_maria_color_kill; |
| 57 | | int m_maria_cwidth; |
| 58 | | int m_maria_bcntl; |
| 59 | | int m_maria_kangaroo; |
| 60 | | int m_maria_rm; |
| 61 | | int m_maria_nmi; |
| 62 | | unsigned int m_maria_charbase; |
| 63 | | bitmap_ind16 m_bitmap; |
| 64 | | |
| 65 | | DECLARE_READ8_MEMBER(bios_or_cart_r); |
| 66 | | DECLARE_WRITE8_MEMBER(ram0_w); |
| 67 | | DECLARE_READ8_MEMBER(tia_r); |
| 68 | | DECLARE_WRITE8_MEMBER(tia_w); |
| 69 | | DECLARE_READ8_MEMBER(maria_r); |
| 70 | | DECLARE_WRITE8_MEMBER(maria_w); |
| 71 | | DECLARE_DRIVER_INIT(a7800_pal); |
| 72 | | DECLARE_DRIVER_INIT(a7800_ntsc); |
| 73 | | virtual void machine_start(); |
| 74 | | virtual void machine_reset(); |
| 75 | | virtual void video_start(); |
| 76 | | DECLARE_PALETTE_INIT(a7800); |
| 77 | | DECLARE_PALETTE_INIT(a7800p); |
| 78 | | UINT32 screen_update_a7800(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 79 | | TIMER_DEVICE_CALLBACK_MEMBER(a7800_interrupt); |
| 80 | | TIMER_CALLBACK_MEMBER(a7800_maria_startdma); |
| 81 | | DECLARE_READ8_MEMBER(riot_joystick_r); |
| 82 | | DECLARE_READ8_MEMBER(riot_console_button_r); |
| 83 | | DECLARE_WRITE8_MEMBER(riot_button_pullup_w); |
| 84 | | |
| 85 | | protected: |
| 86 | | required_device<cpu_device> m_maincpu; |
| 87 | | required_device<tia_device> m_tia; |
| 88 | | required_ioport m_io_joysticks; |
| 89 | | required_ioport m_io_buttons; |
| 90 | | required_ioport m_io_vblank; |
| 91 | | required_ioport m_io_console_buttons; |
| 92 | | required_device<a78_cart_slot_device> m_cartslot; |
| 93 | | required_device<screen_device> m_screen; |
| 94 | | |
| 95 | | void maria_draw_scanline(); |
| 96 | | int is_holey(unsigned int addr); |
| 97 | | int write_line_ram(int addr, UINT8 offset, int pal); |
| 98 | | }; |
| 99 | | |
| 100 | | #endif |
trunk/src/mess/video/a7800.c
| r31777 | r31778 | |
| 1 | | /*************************************************************************** |
| 2 | | |
| 3 | | video/a7800.c |
| 4 | | |
| 5 | | Routines to control the Atari 7800 video hardware |
| 6 | | |
| 7 | | 2014-05-06 Mike Saarna Added interrupts to DMA cycle eating. Updates to |
| 8 | | LL, OL, and spin accounting for HALT behavior. |
| 9 | | |
| 10 | | 2014-03-24 Mike Saarna Fixed DMA regarding startup, shutdown and |
| 11 | | cycle stealing. |
| 12 | | |
| 13 | | 2013-05-08 huygens rewrite to emulate line ram buffers (mostly fixes Kung-Fu Master |
| 14 | | Started DMA cycle stealing implementation |
| 15 | | |
| 16 | | 2003-06-23 ericball Kangaroo mode & 320 mode & other stuff |
| 17 | | |
| 18 | | 2002-05-14 kubecj vblank dma stop fix |
| 19 | | |
| 20 | | 2002-05-13 kubecj fixed 320C mode (displayed 2 pixels instead of one!) |
| 21 | | noticed that Jinks uses 0x02-320D mode |
| 22 | | implemented the mode - completely unsure if good! |
| 23 | | implemented some Maria CTRL variables |
| 24 | | |
| 25 | | 2002-05-12 kubecj added cases for 0x01-160A, 0x05-160B as stated by docs |
| 26 | | |
| 27 | | ***************************************************************************/ |
| 28 | | |
| 29 | | #include "emu.h" |
| 30 | | #include "cpu/m6502/m6502.h" |
| 31 | | #include "includes/a7800.h" |
| 32 | | |
| 33 | | |
| 34 | | #define TRIGGER_HSYNC 64717 |
| 35 | | |
| 36 | | #define READ_MEM(x) space.read_byte(x) |
| 37 | | |
| 38 | | /********** Maria ***********/ |
| 39 | | |
| 40 | | /*************************************************************************** |
| 41 | | |
| 42 | | Start the video hardware emulation. |
| 43 | | |
| 44 | | ***************************************************************************/ |
| 45 | | void a7800_state::video_start() |
| 46 | | { |
| 47 | | int i,j; |
| 48 | | for(i=0; i<32; i++) |
| 49 | | { |
| 50 | | m_maria_palette[i]=0; |
| 51 | | } |
| 52 | | |
| 53 | | for(i=0; i<2; i++) |
| 54 | | { |
| 55 | | for(j=0; j<160; j++) |
| 56 | | m_line_ram[i][j] = 0; |
| 57 | | } |
| 58 | | |
| 59 | | m_active_buffer = 0; |
| 60 | | |
| 61 | | m_maria_write_mode=0; |
| 62 | | m_maria_dmaon=0; |
| 63 | | m_maria_vblank=0x80; |
| 64 | | m_maria_dll=0; |
| 65 | | m_maria_wsync=0; |
| 66 | | |
| 67 | | m_maria_color_kill = 0; |
| 68 | | m_maria_cwidth = 0; |
| 69 | | m_maria_bcntl = 0; |
| 70 | | m_maria_kangaroo = 0; |
| 71 | | m_maria_rm = 0; |
| 72 | | |
| 73 | | machine().first_screen()->register_screen_bitmap(m_bitmap); |
| 74 | | } |
| 75 | | |
| 76 | | /*************************************************************************** |
| 77 | | |
| 78 | | Stop the video hardware emulation. |
| 79 | | |
| 80 | | ***************************************************************************/ |
| 81 | | |
| 82 | | int a7800_state::is_holey(unsigned int addr) |
| 83 | | { |
| 84 | | if (((m_maria_holey & 0x02) && ((addr & 0x9000) == 0x9000)) || ( (m_maria_holey & 0x01) && ((addr & 0x8800) == 0x8800))) |
| 85 | | return 1; |
| 86 | | else |
| 87 | | return 0; |
| 88 | | } |
| 89 | | |
| 90 | | int a7800_state::write_line_ram(int addr, UINT8 offset, int pal) |
| 91 | | { |
| 92 | | address_space& space = m_maincpu->space(AS_PROGRAM); |
| 93 | | int data, c; |
| 94 | | |
| 95 | | data = READ_MEM(addr); |
| 96 | | pal = pal << 2; |
| 97 | | |
| 98 | | if (m_maria_write_mode) |
| 99 | | { |
| 100 | | c = (pal & 0x10) | (data & 0x0C) | (data >> 6); // P2 D3 D2 D7 D6 |
| 101 | | if (((c & 3) || m_maria_kangaroo) && (offset < 160)) |
| 102 | | m_line_ram[m_active_buffer][offset] = c; |
| 103 | | offset++; |
| 104 | | c = (pal & 0x10) | ((data & 0x03) << 2) | ((data & 0x30) >> 4); // P2 D1 D0 D5 D4 |
| 105 | | if (((c & 3) || m_maria_kangaroo) && (offset < 160)) |
| 106 | | m_line_ram[m_active_buffer][offset] = c; |
| 107 | | } |
| 108 | | else |
| 109 | | { |
| 110 | | for (int i=0; i<4; i++, offset++) |
| 111 | | { |
| 112 | | c = pal | ((data >> (6 - 2*i)) & 0x03); |
| 113 | | if (((c & 3) || m_maria_kangaroo) && (offset < 160)) |
| 114 | | m_line_ram[m_active_buffer][offset] = c; |
| 115 | | } |
| 116 | | } |
| 117 | | return m_maria_write_mode ? 2 : 4; |
| 118 | | } |
| 119 | | |
| 120 | | |
| 121 | | void a7800_state::maria_draw_scanline() |
| 122 | | { |
| 123 | | address_space& space = m_maincpu->space(AS_PROGRAM); |
| 124 | | unsigned int graph_adr,data_addr; |
| 125 | | int width,pal,ind; |
| 126 | | UINT8 hpos; |
| 127 | | unsigned int dl; |
| 128 | | int x, d, c, i, pixel_cell, cells; |
| 129 | | int maria_cycles; |
| 130 | | |
| 131 | | if ( m_maria_offset == 0 ) |
| 132 | | { |
| 133 | | if(READ_MEM(m_maria_dll+3) & 0x80) |
| 134 | | maria_cycles=40; // DMA + maria interrupt overhead |
| 135 | | else |
| 136 | | maria_cycles=19; // DMA |
| 137 | | } |
| 138 | | else |
| 139 | | { |
| 140 | | maria_cycles = 16; // DMA |
| 141 | | } |
| 142 | | |
| 143 | | cells = 0; |
| 144 | | |
| 145 | | /* Process this DLL entry */ |
| 146 | | dl = m_maria_dl; |
| 147 | | |
| 148 | | /* DMA */ |
| 149 | | /* Step through DL's */ |
| 150 | | while ((READ_MEM(dl + 1) & 0x5F) != 0) |
| 151 | | { |
| 152 | | /* Extended header */ |
| 153 | | if (!(READ_MEM(dl+1) & 0x1F)) |
| 154 | | { |
| 155 | | graph_adr = (READ_MEM(dl+2) << 8) | READ_MEM(dl); |
| 156 | | width = ((READ_MEM(dl+3) ^ 0xff) & 0x1F) + 1; |
| 157 | | hpos = READ_MEM(dl+4); |
| 158 | | pal = READ_MEM(dl+3) >> 5; |
| 159 | | m_maria_write_mode = (READ_MEM(dl+1) & 0x80) >> 5; |
| 160 | | ind = READ_MEM(dl+1) & 0x20; |
| 161 | | dl+=5; |
| 162 | | maria_cycles += 10; |
| 163 | | } |
| 164 | | /* Normal header */ |
| 165 | | else |
| 166 | | { |
| 167 | | graph_adr = (READ_MEM(dl+2) << 8) | READ_MEM(dl); |
| 168 | | width = ((READ_MEM(dl+1) ^ 0xff) & 0x1F) + 1; |
| 169 | | hpos = READ_MEM(dl+3); |
| 170 | | pal = READ_MEM(dl+1) >> 5; |
| 171 | | ind = 0x00; |
| 172 | | dl+=4; |
| 173 | | maria_cycles += 8; |
| 174 | | } |
| 175 | | |
| 176 | | /*logerror("%x DL: ADR=%x width=%x hpos=%x pal=%x mode=%x ind=%x\n",m_screen->vpos(),graph_adr,width,hpos,pal,m_maria_write_mode,ind );*/ |
| 177 | | |
| 178 | | for (x=0; x<width; x++) |
| 179 | | { |
| 180 | | /* Do indirect mode */ |
| 181 | | if (ind) |
| 182 | | { |
| 183 | | c = READ_MEM(graph_adr + x) & 0xFF; |
| 184 | | data_addr = (m_maria_charbase | c) + (m_maria_offset << 8); |
| 185 | | if (is_holey(data_addr)) |
| 186 | | continue; |
| 187 | | maria_cycles += 3; |
| 188 | | if( m_maria_cwidth ) // two data bytes per map byte |
| 189 | | { |
| 190 | | cells = write_line_ram(data_addr, hpos, pal); |
| 191 | | hpos += cells; |
| 192 | | cells = write_line_ram(data_addr+1, hpos, pal); |
| 193 | | hpos += cells; |
| 194 | | maria_cycles += 6; |
| 195 | | } |
| 196 | | else |
| 197 | | { |
| 198 | | cells = write_line_ram(data_addr, hpos, pal); |
| 199 | | hpos += cells; |
| 200 | | maria_cycles += 3; |
| 201 | | } |
| 202 | | } |
| 203 | | else // direct mode |
| 204 | | { |
| 205 | | data_addr = graph_adr + x + (m_maria_offset << 8); |
| 206 | | if (is_holey(data_addr)) |
| 207 | | continue; |
| 208 | | cells = write_line_ram(data_addr, hpos, pal); |
| 209 | | hpos += cells; |
| 210 | | maria_cycles += 3; |
| 211 | | } |
| 212 | | } |
| 213 | | } |
| 214 | | // Spin the CPU for Maria DMA, if it's not already spinning for WSYNC. |
| 215 | | // MARIA generates the 6502 clock by dividing its own clock by 4. It needs to HALT and unHALT |
| 216 | | // the 6502 on ths same clock phase, so MARIA will wait until its clock divides evenly by 4. |
| 217 | | // To spin until an even divisor, we just round-up any would-be truncations by adding 3. |
| 218 | | if ( ! m_maria_wsync ) |
| 219 | | m_maincpu->spin_until_time(m_maincpu->cycles_to_attotime((maria_cycles+3)/4)); |
| 220 | | |
| 221 | | // draw line buffer to screen |
| 222 | | m_active_buffer = !m_active_buffer; // switch buffers |
| 223 | | UINT16 *scanline; |
| 224 | | scanline = &m_bitmap.pix16(m_screen->vpos()); |
| 225 | | |
| 226 | | |
| 227 | | for ( i = 0; i<160; i++ ) |
| 228 | | { |
| 229 | | switch (m_maria_rm) |
| 230 | | { |
| 231 | | case 0x00: /* 160A, 160B */ |
| 232 | | case 0x01: /* 160A, 160B */ |
| 233 | | pixel_cell = m_line_ram[m_active_buffer][i]; |
| 234 | | scanline[2*i] = m_maria_palette[pixel_cell]; |
| 235 | | scanline[2*i+1] = m_maria_palette[pixel_cell]; |
| 236 | | break; |
| 237 | | |
| 238 | | case 0x02: /* 320B, 320D */ |
| 239 | | pixel_cell = m_line_ram[m_active_buffer][i]; |
| 240 | | d = (pixel_cell & 0x10) | (pixel_cell & 0x02) | ((pixel_cell >> 3) & 1); // b4 0 0 b1 b3 |
| 241 | | scanline[2*i] = m_maria_palette[d]; |
| 242 | | d = (pixel_cell & 0x10) | ((pixel_cell << 1) & 0x02) | ((pixel_cell >> 2) & 1); // b4 0 0 b0 b2 |
| 243 | | scanline[2*i+1] = m_maria_palette[d]; |
| 244 | | break; |
| 245 | | |
| 246 | | case 0x03: /* 320A, 320C */ |
| 247 | | pixel_cell = m_line_ram[m_active_buffer][i]; |
| 248 | | d = (pixel_cell & 0x1C) | (pixel_cell & 0x02); // b4 b3 b2 b1 0 |
| 249 | | scanline[2*i] = m_maria_palette[d]; |
| 250 | | d = (pixel_cell & 0x1C) | ((pixel_cell << 1) & 0x02); // b4 b3 b2 b0 0 |
| 251 | | scanline[2*i+1] = m_maria_palette[d]; |
| 252 | | break; |
| 253 | | } |
| 254 | | } |
| 255 | | |
| 256 | | for(i=0; i<160; i++) // buffer automaticaly cleared once displayed |
| 257 | | m_line_ram[m_active_buffer][i] = 0; |
| 258 | | } |
| 259 | | |
| 260 | | |
| 261 | | |
| 262 | | TIMER_DEVICE_CALLBACK_MEMBER(a7800_state::a7800_interrupt) |
| 263 | | { |
| 264 | | // DMA Begins 7 cycles after hblank |
| 265 | | machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(7), timer_expired_delegate(FUNC(a7800_state::a7800_maria_startdma),this)); |
| 266 | | if( m_maria_wsync ) |
| 267 | | { |
| 268 | | machine().scheduler().trigger( TRIGGER_HSYNC ); |
| 269 | | m_maria_wsync = 0; |
| 270 | | } |
| 271 | | |
| 272 | | int frame_scanline = m_screen->vpos() % ( m_lines + 1 ); |
| 273 | | if (frame_scanline == 16) |
| 274 | | m_maria_vblank = 0x00; |
| 275 | | |
| 276 | | if ( frame_scanline == ( m_lines - 5 ) ) |
| 277 | | { |
| 278 | | m_maria_vblank = 0x80; |
| 279 | | } |
| 280 | | } |
| 281 | | |
| 282 | | |
| 283 | | TIMER_CALLBACK_MEMBER(a7800_state::a7800_maria_startdma) |
| 284 | | { |
| 285 | | int frame_scanline; |
| 286 | | address_space& space = m_maincpu->space(AS_PROGRAM); |
| 287 | | int maria_scanline = m_screen->vpos(); |
| 288 | | |
| 289 | | frame_scanline = maria_scanline % ( m_lines + 1 ); |
| 290 | | |
| 291 | | if( (frame_scanline == 16) && m_maria_dmaon ) |
| 292 | | { |
| 293 | | /* end of vblank */ |
| 294 | | |
| 295 | | m_maria_dll = m_maria_dpp; // currently only handle changes to dll during vblank |
| 296 | | m_maria_dl = (READ_MEM(m_maria_dll+1) << 8) | READ_MEM(m_maria_dll+2); |
| 297 | | m_maria_offset = READ_MEM(m_maria_dll) & 0x0f; |
| 298 | | m_maria_holey = (READ_MEM(m_maria_dll) & 0x60) >> 5; |
| 299 | | m_maria_nmi = READ_MEM(m_maria_dll) & 0x80; |
| 300 | | /* logerror("DLL=%x\n",m_maria_dll); */ |
| 301 | | maria_draw_scanline(); |
| 302 | | } |
| 303 | | |
| 304 | | |
| 305 | | if( ( frame_scanline > 16 ) && (frame_scanline < (m_lines - 5)) && m_maria_dmaon ) |
| 306 | | { |
| 307 | | maria_draw_scanline(); |
| 308 | | |
| 309 | | if( m_maria_offset == 0 ) |
| 310 | | { |
| 311 | | m_maria_dll+=3; |
| 312 | | m_maria_dl = (READ_MEM(m_maria_dll+1) << 8) | READ_MEM(m_maria_dll+2); |
| 313 | | m_maria_offset = READ_MEM(m_maria_dll) & 0x0f; |
| 314 | | m_maria_holey = (READ_MEM(m_maria_dll) & 0x60) >> 5; |
| 315 | | if ( READ_MEM(m_maria_dll & 0x10) ) |
| 316 | | logerror("dll bit 5 set!\n"); |
| 317 | | m_maria_nmi = READ_MEM(m_maria_dll) & 0x80; |
| 318 | | } |
| 319 | | else |
| 320 | | { |
| 321 | | m_maria_offset--; |
| 322 | | } |
| 323 | | } |
| 324 | | |
| 325 | | if( m_maria_nmi ) |
| 326 | | { |
| 327 | | m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); |
| 328 | | m_maria_nmi = 0; |
| 329 | | } |
| 330 | | } |
| 331 | | |
| 332 | | /*************************************************************************** |
| 333 | | |
| 334 | | Refresh the video screen |
| 335 | | |
| 336 | | ***************************************************************************/ |
| 337 | | /* This routine is called at the start of vblank to refresh the screen */ |
| 338 | | UINT32 a7800_state::screen_update_a7800(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 339 | | { |
| 340 | | copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); |
| 341 | | return 0; |
| 342 | | } |
| 343 | | |
| 344 | | |
| 345 | | /****** MARIA ***************************************/ |
| 346 | | |
| 347 | | READ8_MEMBER(a7800_state::maria_r) |
| 348 | | { |
| 349 | | switch (offset) |
| 350 | | { |
| 351 | | case 0x08: |
| 352 | | return m_maria_vblank; |
| 353 | | |
| 354 | | default: |
| 355 | | logerror("undefined MARIA read %x\n",offset); |
| 356 | | return 0x00; // don't know if this should be 0x00 or 0xff |
| 357 | | } |
| 358 | | } |
| 359 | | |
| 360 | | WRITE8_MEMBER(a7800_state::maria_w) |
| 361 | | { |
| 362 | | int i; |
| 363 | | |
| 364 | | if ((offset & 3) != 0) |
| 365 | | m_maria_palette[offset] = data; |
| 366 | | |
| 367 | | switch (offset) |
| 368 | | { |
| 369 | | case 0x00: |
| 370 | | // all color ram addresses with 00 for their least significant bits point to the background color |
| 371 | | for (i = 0; i<8; i++) |
| 372 | | m_maria_palette[4*i] = data; |
| 373 | | break; |
| 374 | | case 0x04: |
| 375 | | m_maincpu->spin_until_trigger(TRIGGER_HSYNC); |
| 376 | | m_maria_wsync=1; |
| 377 | | break; |
| 378 | | case 0x0C: // DPPH |
| 379 | | m_maria_dpp = (m_maria_dpp & 0x00ff) | (data << 8); |
| 380 | | break; |
| 381 | | case 0x10: // DPPL |
| 382 | | m_maria_dpp = (m_maria_dpp & 0xff00) | data; |
| 383 | | break; |
| 384 | | case 0x14: |
| 385 | | m_maria_charbase = (data << 8); |
| 386 | | break; |
| 387 | | case 0x1C: |
| 388 | | /*logerror("MARIA CTRL=%x\n",data);*/ |
| 389 | | m_maria_color_kill = data & 0x80; |
| 390 | | switch ((data >> 5) & 3) |
| 391 | | { |
| 392 | | case 0x00: case 01: |
| 393 | | logerror("dma test mode, do not use.\n"); |
| 394 | | break; |
| 395 | | case 0x02: |
| 396 | | m_maria_dmaon = 1; |
| 397 | | break; |
| 398 | | case 0x03: |
| 399 | | m_maria_dmaon = 0; |
| 400 | | break; |
| 401 | | } |
| 402 | | m_maria_cwidth = data & 0x10; |
| 403 | | m_maria_bcntl = data & 0x08; // Currently unimplemented as we don't display the border |
| 404 | | m_maria_kangaroo = data & 0x04; |
| 405 | | m_maria_rm = data & 0x03; |
| 406 | | |
| 407 | | /*logerror( "MARIA CTRL: CK:%d DMA:%d CW:%d BC:%d KM:%d RM:%d\n", |
| 408 | | m_maria_color_kill ? 1 : 0, |
| 409 | | ( data & 0x60 ) >> 5, |
| 410 | | m_maria_cwidth ? 1 : 0, |
| 411 | | m_maria_bcntl ? 1 : 0, |
| 412 | | m_maria_kangaroo ? 1 : 0, |
| 413 | | m_maria_rm );*/ |
| 414 | | |
| 415 | | break; |
| 416 | | } |
| 417 | | } |
trunk/src/mess/video/maria.c
| r0 | r31778 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | Atari MARIA video emulation |
| 4 | |
| 5 | |
| 6 | - some history: |
| 7 | |
| 8 | 2014-08-26 Fabio Priuli Converted to device |
| 9 | |
| 10 | 2014-05-06 Mike Saarna Added interrupts to DMA cycle eating. Updates to |
| 11 | LL, OL, and spin accounting for HALT behavior. |
| 12 | |
| 13 | 2014-03-24 Mike Saarna Fixed DMA regarding startup, shutdown and |
| 14 | cycle stealing. |
| 15 | |
| 16 | 2013-05-08 huygens rewrite to emulate line ram buffers (mostly fixes Kung-Fu Master |
| 17 | Started DMA cycle stealing implementation |
| 18 | |
| 19 | 2003-06-23 ericball Kangaroo mode & 320 mode & other stuff |
| 20 | |
| 21 | 2002-05-14 kubecj vblank dma stop fix |
| 22 | |
| 23 | 2002-05-13 kubecj fixed 320C mode (displayed 2 pixels instead of one!) |
| 24 | noticed that Jinks uses 0x02-320D mode |
| 25 | implemented the mode - completely unsure if good! |
| 26 | implemented some Maria CTRL variables |
| 27 | |
| 28 | 2002-05-12 kubecj added cases for 0x01-160A, 0x05-160B as stated by docs |
| 29 | |
| 30 | ***************************************************************************/ |
| 31 | |
| 32 | #include "emu.h" |
| 33 | #include "maria.h" |
| 34 | |
| 35 | |
| 36 | #define TRIGGER_HSYNC 64717 |
| 37 | |
| 38 | #define READ_MEM(x) space.read_byte(x) |
| 39 | |
| 40 | const device_type ATARI_MARIA = &device_creator<atari_maria_device>; |
| 41 | |
| 42 | |
| 43 | |
| 44 | atari_maria_device::atari_maria_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 45 | : device_t(mconfig, ATARI_MARIA, "Atari MARIA", tag, owner, clock, "atari_maria", __FILE__) |
| 46 | { |
| 47 | } |
| 48 | |
| 49 | |
| 50 | void atari_maria_device::device_start() |
| 51 | { |
| 52 | m_cpu = machine().device<cpu_device>(m_cpu_tag); |
| 53 | m_screen = machine().first_screen(); |
| 54 | m_screen->register_screen_bitmap(m_bitmap); |
| 55 | |
| 56 | save_item(NAME(m_maria_palette)); |
| 57 | save_item(NAME(m_line_ram)); |
| 58 | save_item(NAME(m_active_buffer)); |
| 59 | save_item(NAME(m_write_mode)); |
| 60 | save_item(NAME(m_dll)); |
| 61 | save_item(NAME(m_dl)); |
| 62 | save_item(NAME(m_holey)); |
| 63 | save_item(NAME(m_offset)); |
| 64 | save_item(NAME(m_vblank)); |
| 65 | save_item(NAME(m_dmaon)); |
| 66 | save_item(NAME(m_dpp)); |
| 67 | save_item(NAME(m_wsync)); |
| 68 | save_item(NAME(m_color_kill)); |
| 69 | save_item(NAME(m_cwidth)); |
| 70 | save_item(NAME(m_bcntl)); |
| 71 | save_item(NAME(m_kangaroo)); |
| 72 | save_item(NAME(m_rm)); |
| 73 | save_item(NAME(m_nmi)); |
| 74 | save_item(NAME(m_charbase)); |
| 75 | } |
| 76 | |
| 77 | void atari_maria_device::device_reset() |
| 78 | { |
| 79 | for (int i = 0; i < 32; i++) |
| 80 | m_maria_palette[i] = 0; |
| 81 | |
| 82 | for (int i = 0; i < 2; i++) |
| 83 | for (int j = 0; j < 160; j++) |
| 84 | m_line_ram[i][j] = 0; |
| 85 | |
| 86 | m_active_buffer = 0; |
| 87 | |
| 88 | m_write_mode = 0; |
| 89 | m_dmaon = 0; |
| 90 | m_vblank = 0x80; |
| 91 | m_dll = 0; |
| 92 | m_wsync = 0; |
| 93 | |
| 94 | m_color_kill = 0; |
| 95 | m_cwidth = 0; |
| 96 | m_bcntl = 0; |
| 97 | m_kangaroo = 0; |
| 98 | m_rm = 0; |
| 99 | |
| 100 | m_dl = 0; |
| 101 | m_holey = 0; |
| 102 | m_offset = 0; |
| 103 | m_dpp = 0; |
| 104 | m_nmi = 0; |
| 105 | m_charbase = 0; |
| 106 | } |
| 107 | |
| 108 | /*************************************************************************** |
| 109 | |
| 110 | Stop the video hardware emulation. |
| 111 | |
| 112 | ***************************************************************************/ |
| 113 | |
| 114 | int atari_maria_device::is_holey(unsigned int addr) |
| 115 | { |
| 116 | if (((m_holey & 0x02) && ((addr & 0x9000) == 0x9000)) || ( (m_holey & 0x01) && ((addr & 0x8800) == 0x8800))) |
| 117 | return 1; |
| 118 | else |
| 119 | return 0; |
| 120 | } |
| 121 | |
| 122 | int atari_maria_device::write_line_ram(int addr, UINT8 offset, int pal) |
| 123 | { |
| 124 | address_space& space = m_cpu->space(AS_PROGRAM); |
| 125 | int c; |
| 126 | |
| 127 | int data = READ_MEM(addr); |
| 128 | pal <<= 2; |
| 129 | |
| 130 | if (m_write_mode) |
| 131 | { |
| 132 | c = (pal & 0x10) | (data & 0x0c) | (data >> 6); // P2 D3 D2 D7 D6 |
| 133 | if (((c & 3) || m_kangaroo) && (offset < 160)) |
| 134 | m_line_ram[m_active_buffer][offset] = c; |
| 135 | offset++; |
| 136 | |
| 137 | c = (pal & 0x10) | ((data & 0x03) << 2) | ((data & 0x30) >> 4); // P2 D1 D0 D5 D4 |
| 138 | if (((c & 3) || m_kangaroo) && (offset < 160)) |
| 139 | m_line_ram[m_active_buffer][offset] = c; |
| 140 | } |
| 141 | else |
| 142 | { |
| 143 | for (int i = 0; i < 4; i++, offset++) |
| 144 | { |
| 145 | c = pal | ((data >> (6 - 2 * i)) & 0x03); |
| 146 | if (((c & 3) || m_kangaroo) && (offset < 160)) |
| 147 | m_line_ram[m_active_buffer][offset] = c; |
| 148 | } |
| 149 | } |
| 150 | return m_write_mode ? 2 : 4; |
| 151 | } |
| 152 | |
| 153 | |
| 154 | void atari_maria_device::draw_scanline() |
| 155 | { |
| 156 | address_space& space = m_cpu->space(AS_PROGRAM); |
| 157 | UINT16 graph_adr, data_addr; |
| 158 | int width, pal, ind; |
| 159 | UINT8 hpos; |
| 160 | UINT16 dl; |
| 161 | int d, c, pixel_cell, cells; |
| 162 | int maria_cycles; |
| 163 | |
| 164 | if (m_offset == 0) |
| 165 | { |
| 166 | if (READ_MEM(m_dll + 3) & 0x80) |
| 167 | maria_cycles = 40; // DMA + maria interrupt overhead |
| 168 | else |
| 169 | maria_cycles = 19; // DMA |
| 170 | } |
| 171 | else |
| 172 | { |
| 173 | maria_cycles = 16; // DMA |
| 174 | } |
| 175 | |
| 176 | cells = 0; |
| 177 | |
| 178 | /* Process this DLL entry */ |
| 179 | dl = m_dl; |
| 180 | |
| 181 | /* DMA */ |
| 182 | /* Step through DL's */ |
| 183 | while ((READ_MEM(dl + 1) & 0x5f) != 0) |
| 184 | { |
| 185 | /* Extended header */ |
| 186 | if (!(READ_MEM(dl + 1) & 0x1f)) |
| 187 | { |
| 188 | graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl); |
| 189 | width = ((READ_MEM(dl + 3) ^ 0xff) & 0x1f) + 1; |
| 190 | hpos = READ_MEM(dl + 4); |
| 191 | pal = READ_MEM(dl + 3) >> 5; |
| 192 | m_write_mode = (READ_MEM(dl + 1) & 0x80) >> 5; |
| 193 | ind = READ_MEM(dl + 1) & 0x20; |
| 194 | dl += 5; |
| 195 | maria_cycles += 10; |
| 196 | } |
| 197 | /* Normal header */ |
| 198 | else |
| 199 | { |
| 200 | graph_adr = (READ_MEM(dl + 2) << 8) | READ_MEM(dl); |
| 201 | width = ((READ_MEM(dl + 1) ^ 0xff) & 0x1f) + 1; |
| 202 | hpos = READ_MEM(dl + 3); |
| 203 | pal = READ_MEM(dl + 1) >> 5; |
| 204 | ind = 0x00; |
| 205 | dl += 4; |
| 206 | maria_cycles += 8; |
| 207 | } |
| 208 | |
| 209 | /*logerror("%x DL: ADR=%x width=%x hpos=%x pal=%x mode=%x ind=%x\n", m_screen->vpos(), graph_adr, width, hpos, pal, m_write_mode, ind);*/ |
| 210 | |
| 211 | for (int x = 0; x < width; x++) |
| 212 | { |
| 213 | /* Do indirect mode */ |
| 214 | if (ind) |
| 215 | { |
| 216 | c = READ_MEM(graph_adr + x) & 0xff; |
| 217 | data_addr = (m_charbase | c) + (m_offset << 8); |
| 218 | if (is_holey(data_addr)) |
| 219 | continue; |
| 220 | |
| 221 | maria_cycles += 3; |
| 222 | if (m_cwidth) // two data bytes per map byte |
| 223 | { |
| 224 | cells = write_line_ram(data_addr, hpos, pal); |
| 225 | hpos += cells; |
| 226 | cells = write_line_ram(data_addr+1, hpos, pal); |
| 227 | hpos += cells; |
| 228 | maria_cycles += 6; |
| 229 | } |
| 230 | else |
| 231 | { |
| 232 | cells = write_line_ram(data_addr, hpos, pal); |
| 233 | hpos += cells; |
| 234 | maria_cycles += 3; |
| 235 | } |
| 236 | } |
| 237 | else // direct mode |
| 238 | { |
| 239 | data_addr = graph_adr + x + (m_offset << 8); |
| 240 | if (is_holey(data_addr)) |
| 241 | continue; |
| 242 | cells = write_line_ram(data_addr, hpos, pal); |
| 243 | hpos += cells; |
| 244 | maria_cycles += 3; |
| 245 | } |
| 246 | } |
| 247 | } |
| 248 | // Spin the CPU for Maria DMA, if it's not already spinning for WSYNC. |
| 249 | // MARIA generates the 6502 clock by dividing its own clock by 4. It needs to HALT and unHALT |
| 250 | // the 6502 on ths same clock phase, so MARIA will wait until its clock divides evenly by 4. |
| 251 | // To spin until an even divisor, we just round-up any would-be truncations by adding 3. |
| 252 | if (!m_wsync) |
| 253 | m_cpu->spin_until_time(m_cpu->cycles_to_attotime((maria_cycles+3)/4)); |
| 254 | |
| 255 | // draw line buffer to screen |
| 256 | m_active_buffer = !m_active_buffer; // switch buffers |
| 257 | UINT16 *scanline; |
| 258 | scanline = &m_bitmap.pix16(m_screen->vpos()); |
| 259 | |
| 260 | |
| 261 | for (int i = 0; i < 160; i++) |
| 262 | { |
| 263 | switch (m_rm) |
| 264 | { |
| 265 | case 0x00: /* 160A, 160B */ |
| 266 | case 0x01: /* 160A, 160B */ |
| 267 | pixel_cell = m_line_ram[m_active_buffer][i]; |
| 268 | scanline[2 * i] = m_maria_palette[pixel_cell]; |
| 269 | scanline[2 * i + 1] = m_maria_palette[pixel_cell]; |
| 270 | break; |
| 271 | |
| 272 | case 0x02: /* 320B, 320D */ |
| 273 | pixel_cell = m_line_ram[m_active_buffer][i]; |
| 274 | d = (pixel_cell & 0x10) | (pixel_cell & 0x02) | ((pixel_cell >> 3) & 1); // b4 0 0 b1 b3 |
| 275 | scanline[2 * i] = m_maria_palette[d]; |
| 276 | d = (pixel_cell & 0x10) | ((pixel_cell << 1) & 0x02) | ((pixel_cell >> 2) & 1); // b4 0 0 b0 b2 |
| 277 | scanline[2 * i + 1] = m_maria_palette[d]; |
| 278 | break; |
| 279 | |
| 280 | case 0x03: /* 320A, 320C */ |
| 281 | pixel_cell = m_line_ram[m_active_buffer][i]; |
| 282 | d = (pixel_cell & 0x1c) | (pixel_cell & 0x02); // b4 b3 b2 b1 0 |
| 283 | scanline[2 * i] = m_maria_palette[d]; |
| 284 | d = (pixel_cell & 0x1c) | ((pixel_cell << 1) & 0x02); // b4 b3 b2 b0 0 |
| 285 | scanline[2 * i + 1] = m_maria_palette[d]; |
| 286 | break; |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | for (int i = 0; i < 160; i++) // buffer automaticaly cleared once displayed |
| 291 | m_line_ram[m_active_buffer][i] = 0; |
| 292 | } |
| 293 | |
| 294 | |
| 295 | void atari_maria_device::interrupt(int lines) |
| 296 | { |
| 297 | if (m_wsync) |
| 298 | { |
| 299 | machine().scheduler().trigger(TRIGGER_HSYNC); |
| 300 | m_wsync = 0; |
| 301 | } |
| 302 | |
| 303 | int frame_scanline = m_screen->vpos() % (lines + 1); |
| 304 | if (frame_scanline == 16) |
| 305 | m_vblank = 0x00; |
| 306 | |
| 307 | if (frame_scanline == (lines - 5)) |
| 308 | m_vblank = 0x80; |
| 309 | } |
| 310 | |
| 311 | |
| 312 | void atari_maria_device::startdma(int lines) |
| 313 | { |
| 314 | address_space& space = m_cpu->space(AS_PROGRAM); |
| 315 | int maria_scanline = m_screen->vpos(); |
| 316 | int frame_scanline = maria_scanline % (lines + 1); |
| 317 | |
| 318 | if ((frame_scanline == 16) && m_dmaon) |
| 319 | { |
| 320 | /* end of vblank */ |
| 321 | m_dll = m_dpp; // currently only handle changes to dll during vblank |
| 322 | m_dl = (READ_MEM(m_dll + 1) << 8) | READ_MEM(m_dll+2); |
| 323 | m_offset = READ_MEM(m_dll) & 0x0f; |
| 324 | m_holey = (READ_MEM(m_dll) & 0x60) >> 5; |
| 325 | m_nmi = READ_MEM(m_dll) & 0x80; |
| 326 | /* logerror("DLL=%x\n",m_dll); */ |
| 327 | draw_scanline(); |
| 328 | } |
| 329 | |
| 330 | |
| 331 | if ((frame_scanline > 16) && (frame_scanline < (lines - 5)) && m_dmaon) |
| 332 | { |
| 333 | draw_scanline(); |
| 334 | if (m_offset == 0) |
| 335 | { |
| 336 | m_dll += 3; |
| 337 | m_dl = (READ_MEM(m_dll + 1) << 8) | READ_MEM(m_dll + 2); |
| 338 | m_offset = READ_MEM(m_dll) & 0x0f; |
| 339 | m_holey = (READ_MEM(m_dll) & 0x60) >> 5; |
| 340 | if (READ_MEM(m_dll & 0x10)) |
| 341 | logerror("dll bit 5 set!\n"); |
| 342 | m_nmi = READ_MEM(m_dll) & 0x80; |
| 343 | } |
| 344 | else |
| 345 | { |
| 346 | m_offset--; |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | if (m_nmi) |
| 351 | { |
| 352 | m_cpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); |
| 353 | m_nmi = 0; |
| 354 | } |
| 355 | } |
| 356 | |
| 357 | /*************************************************************************** |
| 358 | |
| 359 | Refresh the video screen |
| 360 | |
| 361 | ***************************************************************************/ |
| 362 | |
| 363 | /* This routine is called at the start of vblank to refresh the screen */ |
| 364 | UINT32 atari_maria_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 365 | { |
| 366 | copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); |
| 367 | return 0; |
| 368 | } |
| 369 | |
| 370 | |
| 371 | READ8_MEMBER(atari_maria_device::read) |
| 372 | { |
| 373 | switch (offset) |
| 374 | { |
| 375 | case 0x08: |
| 376 | return m_vblank; |
| 377 | |
| 378 | default: |
| 379 | logerror("undefined MARIA read %x\n",offset); |
| 380 | return 0x00; // don't know if this should be 0x00 or 0xff |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | WRITE8_MEMBER(atari_maria_device::write) |
| 385 | { |
| 386 | if ((offset & 3) != 0) |
| 387 | m_maria_palette[offset] = data; |
| 388 | |
| 389 | switch (offset) |
| 390 | { |
| 391 | case 0x00: |
| 392 | // all color ram addresses with 00 for their least significant bits point to the background color |
| 393 | for (int i = 0; i < 8; i++) |
| 394 | m_maria_palette[4 * i] = data; |
| 395 | break; |
| 396 | case 0x04: |
| 397 | m_cpu->spin_until_trigger(TRIGGER_HSYNC); |
| 398 | m_wsync = 1; |
| 399 | break; |
| 400 | case 0x0C: // DPPH |
| 401 | m_dpp = (m_dpp & 0x00ff) | (data << 8); |
| 402 | break; |
| 403 | case 0x10: // DPPL |
| 404 | m_dpp = (m_dpp & 0xff00) | data; |
| 405 | break; |
| 406 | case 0x14: |
| 407 | m_charbase = (data << 8); |
| 408 | break; |
| 409 | case 0x1C: |
| 410 | /*logerror("MARIA CTRL=%x\n",data);*/ |
| 411 | m_color_kill = data & 0x80; |
| 412 | switch ((data >> 5) & 3) |
| 413 | { |
| 414 | case 0x00: |
| 415 | case 01: |
| 416 | logerror("dma test mode, do not use.\n"); |
| 417 | break; |
| 418 | |
| 419 | case 0x02: |
| 420 | m_dmaon = 1; |
| 421 | break; |
| 422 | |
| 423 | case 0x03: |
| 424 | m_dmaon = 0; |
| 425 | break; |
| 426 | } |
| 427 | m_cwidth = data & 0x10; |
| 428 | m_bcntl = data & 0x08; // Currently unimplemented as we don't display the border |
| 429 | m_kangaroo = data & 0x04; |
| 430 | m_rm = data & 0x03; |
| 431 | |
| 432 | /*logerror( "MARIA CTRL: CK:%d DMA:%d CW:%d BC:%d KM:%d RM:%d\n", |
| 433 | m_color_kill ? 1 : 0, |
| 434 | (data & 0x60) >> 5, |
| 435 | m_cwidth ? 1 : 0, |
| 436 | m_bcntl ? 1 : 0, |
| 437 | m_kangaroo ? 1 : 0, |
| 438 | m_rm );*/ |
| 439 | |
| 440 | break; |
| 441 | } |
| 442 | } |
trunk/src/mess/drivers/a7800.c
| r31777 | r31778 | |
| 97 | 97 | #include "emu.h" |
| 98 | 98 | #include "cpu/m6502/m6502.h" |
| 99 | 99 | #include "sound/tiaintf.h" |
| 100 | #include "sound/tiasound.h" |
| 101 | #include "machine/6532riot.h" |
| 102 | #include "video/maria.h" |
| 100 | 103 | #include "bus/a7800/a78_carts.h" |
| 101 | | #include "machine/6532riot.h" |
| 102 | | #include "includes/a7800.h" |
| 103 | 104 | |
| 104 | 105 | |
| 105 | 106 | #define A7800_NTSC_Y1 XTAL_14_31818MHz |
| 106 | 107 | #define CLK_PAL 1773447 |
| 107 | 108 | |
| 108 | 109 | |
| 110 | class a7800_state : public driver_device |
| 111 | { |
| 112 | public: |
| 113 | a7800_state(const machine_config &mconfig, device_type type, const char *tag) |
| 114 | : driver_device(mconfig, type, tag), |
| 115 | m_maincpu(*this, "maincpu"), |
| 116 | m_tia(*this, "tia"), |
| 117 | m_maria(*this, "maria"), |
| 118 | m_io_joysticks(*this, "joysticks"), |
| 119 | m_io_buttons(*this, "buttons"), |
| 120 | m_io_vblank(*this, "vblank"), |
| 121 | m_io_console_buttons(*this, "console_buttons"), |
| 122 | m_cartslot(*this, "cartslot"), |
| 123 | m_screen(*this, "screen") { } |
| 124 | |
| 125 | int m_lines; |
| 126 | int m_ispal; |
| 127 | |
| 128 | int m_ctrl_lock; |
| 129 | int m_ctrl_reg; |
| 130 | int m_maria_flag; |
| 131 | int m_p1_one_button; |
| 132 | int m_p2_one_button; |
| 133 | int m_bios_enabled; |
| 134 | |
| 135 | UINT8 *m_bios; |
| 136 | |
| 137 | DECLARE_READ8_MEMBER(bios_or_cart_r); |
| 138 | DECLARE_WRITE8_MEMBER(ram0_w); |
| 139 | DECLARE_READ8_MEMBER(tia_r); |
| 140 | DECLARE_WRITE8_MEMBER(tia_w); |
| 141 | DECLARE_READ8_MEMBER(maria_r); |
| 142 | DECLARE_WRITE8_MEMBER(maria_w); |
| 143 | DECLARE_DRIVER_INIT(a7800_pal); |
| 144 | DECLARE_DRIVER_INIT(a7800_ntsc); |
| 145 | virtual void machine_start(); |
| 146 | virtual void machine_reset(); |
| 147 | DECLARE_PALETTE_INIT(a7800); |
| 148 | DECLARE_PALETTE_INIT(a7800p); |
| 149 | TIMER_DEVICE_CALLBACK_MEMBER(interrupt); |
| 150 | TIMER_CALLBACK_MEMBER(maria_startdma); |
| 151 | DECLARE_READ8_MEMBER(riot_joystick_r); |
| 152 | DECLARE_READ8_MEMBER(riot_console_button_r); |
| 153 | DECLARE_WRITE8_MEMBER(riot_button_pullup_w); |
| 154 | |
| 155 | protected: |
| 156 | required_device<cpu_device> m_maincpu; |
| 157 | required_device<tia_device> m_tia; |
| 158 | required_device<atari_maria_device> m_maria; |
| 159 | required_ioport m_io_joysticks; |
| 160 | required_ioport m_io_buttons; |
| 161 | required_ioport m_io_vblank; |
| 162 | required_ioport m_io_console_buttons; |
| 163 | required_device<a78_cart_slot_device> m_cartslot; |
| 164 | required_device<screen_device> m_screen; |
| 165 | }; |
| 166 | |
| 167 | |
| 109 | 168 | /*************************************************************************** |
| 110 | 169 | MEMORY HANDLERS |
| 111 | 170 | ***************************************************************************/ |
| r31777 | r31778 | |
| 191 | 250 | } |
| 192 | 251 | |
| 193 | 252 | |
| 253 | // TIMERS |
| 254 | |
| 255 | TIMER_DEVICE_CALLBACK_MEMBER(a7800_state::interrupt) |
| 256 | { |
| 257 | // DMA Begins 7 cycles after hblank |
| 258 | machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(7), timer_expired_delegate(FUNC(a7800_state::maria_startdma),this)); |
| 259 | m_maria->interrupt(m_lines); |
| 260 | } |
| 261 | |
| 262 | TIMER_CALLBACK_MEMBER(a7800_state::maria_startdma) |
| 263 | { |
| 264 | m_maria->startdma(m_lines); |
| 265 | } |
| 266 | |
| 267 | |
| 268 | |
| 194 | 269 | // ROM |
| 195 | 270 | READ8_MEMBER(a7800_state::bios_or_cart_r) |
| 196 | 271 | { |
| r31777 | r31778 | |
| 206 | 281 | |
| 207 | 282 | static ADDRESS_MAP_START( a7800_mem, AS_PROGRAM, 8, a7800_state ) |
| 208 | 283 | AM_RANGE(0x0000, 0x001f) AM_MIRROR(0x300) AM_READWRITE(tia_r, tia_w) |
| 209 | | AM_RANGE(0x0020, 0x003f) AM_MIRROR(0x300) AM_READWRITE(maria_r, maria_w) |
| 284 | AM_RANGE(0x0020, 0x003f) AM_MIRROR(0x300) AM_DEVREADWRITE("maria", atari_maria_device, read, write) |
| 210 | 285 | AM_RANGE(0x0040, 0x00ff) AM_RAMBANK("ram0") // RAM (6116 block 0) |
| 211 | 286 | AM_RANGE(0x0140, 0x01ff) AM_RAMBANK("ram1") // RAM (6116 block 1) |
| 212 | 287 | AM_RANGE(0x0280, 0x02ff) AM_DEVREADWRITE("riot", riot6532_device, read, write) |
| r31777 | r31778 | |
| 1272 | 1347 | /* basic machine hardware */ |
| 1273 | 1348 | MCFG_CPU_ADD("maincpu", M6502, A7800_NTSC_Y1/8) /* 1.79 MHz (switches to 1.19 MHz on TIA or RIOT access) */ |
| 1274 | 1349 | MCFG_CPU_PROGRAM_MAP(a7800_mem) |
| 1275 | | MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", a7800_state, a7800_interrupt, "screen", 0, 1) |
| 1350 | MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", a7800_state, interrupt, "screen", 0, 1) |
| 1276 | 1351 | |
| 1277 | 1352 | /* video hardware */ |
| 1278 | 1353 | MCFG_SCREEN_ADD("screen", RASTER) |
| 1279 | 1354 | MCFG_SCREEN_RAW_PARAMS( 7159090, 454, 0, 320, 263, 27, 27 + 192 + 32 ) |
| 1280 | | MCFG_SCREEN_UPDATE_DRIVER(a7800_state, screen_update_a7800) |
| 1355 | MCFG_SCREEN_UPDATE_DEVICE("maria", atari_maria_device, screen_update) |
| 1281 | 1356 | MCFG_SCREEN_PALETTE("palette") |
| 1282 | 1357 | |
| 1283 | 1358 | MCFG_PALETTE_ADD("palette", ARRAY_LENGTH(a7800_palette) / 3) |
| 1284 | 1359 | MCFG_PALETTE_INIT_OWNER(a7800_state, a7800) |
| 1285 | 1360 | |
| 1361 | MCFG_DEVICE_ADD("maria", ATARI_MARIA, 0) |
| 1362 | MCFG_MARIA_DMACPU("maincpu") |
| 1363 | |
| 1286 | 1364 | /* sound hardware */ |
| 1287 | 1365 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 1288 | 1366 | MCFG_SOUND_TIA_ADD("tia", 31400) |