summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/amiga.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/amiga.cpp')
-rw-r--r--src/mame/machine/amiga.cpp1718
1 files changed, 0 insertions, 1718 deletions
diff --git a/src/mame/machine/amiga.cpp b/src/mame/machine/amiga.cpp
deleted file mode 100644
index 62da9267548..00000000000
--- a/src/mame/machine/amiga.cpp
+++ /dev/null
@@ -1,1718 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ernesto Corvi, Aaron Giles, Mariusz Wojcieszek
-/***************************************************************************
-
- Amiga Computer / Arcadia Game System
-
- Driver by:
-
- Aaron Giles, Ernesto Corvi & Mariusz Wojcieszek
-
-***************************************************************************/
-
-#include "emu.h"
-#include "includes/amiga.h"
-#include "cpu/m68000/m68000.h"
-
-
-/*************************************
- *
- * Debugging
- *
- *************************************/
-
-#define LOG_CUSTOM 0
-#define LOG_CIA 0
-#define LOG_BLITS 0
-#define LOG_SERIAL 1
-
-
-
-/*************************************
- *
- * Constants
- *
- *************************************/
-
-/* How many CPU cycles we delay until we fire a pending interrupt */
-#define AMIGA_IRQ_DELAY_CYCLES 24
-
-/* How many CPU cycles we wait until we process a blit when the blitter-nasty bit is set */
-#define BLITTER_NASTY_DELAY 16
-
-
-
-/*************************************
- *
- * Globals
- *
- *************************************/
-
-const char *const amiga_state::s_custom_reg_names[0x100] =
-{
- /* 0x000 */
- "BLTDDAT", "DMACONR", "VPOSR", "VHPOSR",
- "DSKDATR", "JOY0DAT", "JOY1DAT", "CLXDAT",
- "ADKCONR", "POT0DAT", "POT1DAT", "POTGOR",
- "SERDATR", "DSKBYTR", "INTENAR", "INTREQR",
- /* 0x020 */
- "DSKPTH", "DSKPTL", "DSKLEN", "DSKDAT",
- "REFPTR", "VPOSW", "VHPOSW", "COPCON",
- "SERDAT", "SERPER", "POTGO", "JOYTEST",
- "STREQU", "STRVBL", "STRHOR", "STRLONG",
- /* 0x040 */
- "BLTCON0", "BLTCON1", "BLTAFWM", "BLTALWM",
- "BLTCPTH", "BLTCPTL", "BLTBPTH", "BLTBPTL",
- "BLTAPTH", "BLTAPTL", "BLTDPTH", "BLTDPTL",
- "BLTSIZE", "BLTCON0L", "BLTSIZV", "BLTSIZH",
- /* 0x060 */
- "BLTCMOD", "BLTBMOD", "BLTAMOD", "BLTDMOD",
- "UNK068", "UNK06A", "UNK06C", "UNK06E",
- "BLTCDAT", "BLTBDAT", "BLTADAT", "UNK076",
- "SPRHDAT", "BPLHDAT", "LISAID", "DSRSYNC",
- /* 0x080 */
- "COP1LCH", "COP1LCL", "COP2LCH", "COP2LCL",
- "COPJMP1", "COPJMP2", "COPINS", "DIWSTRT",
- "DIWSTOP", "DDFSTRT", "DDFSTOP", "DMACON",
- "CLXCON", "INTENA", "INTREQ", "ADKCON",
- /* 0x0A0 */
- "AUD0LCH", "AUD0LCL", "AUD0LEN", "AUD0PER",
- "AUD0VOL", "AUD0DAT", "UNK0AC", "UNK0AE",
- "AUD1LCH", "AUD1LCL", "AUD1LEN", "AUD1PER",
- "AUD1VOL", "AUD1DAT", "UNK0BC", "UNK0BE",
- /* 0x0C0 */
- "AUD2LCH", "AUD2LCL", "AUD2LEN", "AUD2PER",
- "AUD2VOL", "AUD2DAT", "UNK0CC", "UNK0CE",
- "AUD3LCH", "AUD3LCL", "AUD3LEN", "AUD3PER",
- "AUD3VOL", "AUD3DAT", "UNK0DC", "UNK0DE",
- /* 0x0E0 */
- "BPL1PTH", "BPL1PTL", "BPL2PTH", "BPL2PTL",
- "BPL3PTH", "BPL3PTL", "BPL4PTH", "BPL4PTL",
- "BPL5PTH", "BPL5PTL", "BPL6PTH", "BPL6PTL",
- "BPL7PTH", "BPL7PTL", "BPL8PTH", "BPL8PTL",
- /* 0x100 */
- "BPLCON0", "BPLCON1", "BPLCON2", "BPLCON3",
- "BPL1MOD", "BPL2MOD", "BPLCON4", "CLXCON2",
- "BPL1DAT", "BPL2DAT", "BPL3DAT", "BPL4DAT",
- "BPL5DAT", "BPL6DAT", "BPL7DAT", "BPL8DAT",
- /* 0x120 */
- "SPR0PTH", "SPR0PTL", "SPR1PTH", "SPR1PTL",
- "SPR2PTH", "SPR2PTL", "SPR3PTH", "SPR3PTL",
- "SPR4PTH", "SPR4PTL", "SPR5PTH", "SPR5PTL",
- "SPR6PTH", "SPR6PTL", "SPR7PTH", "SPR7PTL",
- /* 0x140 */
- "SPR0POS", "SPR0CTL", "SPR0DATA", "SPR0DATB",
- "SPR1POS", "SPR1CTL", "SPR1DATA", "SPR1DATB",
- "SPR2POS", "SPR2CTL", "SPR2DATA", "SPR2DATB",
- "SPR3POS", "SPR3CTL", "SPR3DATA", "SPR3DATB",
- /* 0x160 */
- "SPR4POS", "SPR4CTL", "SPR4DATA", "SPR4DATB",
- "SPR5POS", "SPR5CTL", "SPR5DATA", "SPR5DATB",
- "SPR6POS", "SPR6CTL", "SPR6DATA", "SPR6DATB",
- "SPR7POS", "SPR7CTL", "SPR7DATA", "SPR7DATB",
- /* 0x180 */
- "COLOR00", "COLOR01", "COLOR02", "COLOR03",
- "COLOR04", "COLOR05", "COLOR06", "COLOR07",
- "COLOR08", "COLOR09", "COLOR10", "COLOR11",
- "COLOR12", "COLOR13", "COLOR14", "COLOR15",
- /* 0x1A0 */
- "COLOR16", "COLOR17", "COLOR18", "COLOR19",
- "COLOR20", "COLOR21", "COLOR22", "COLOR23",
- "COLOR24", "COLOR25", "COLOR26", "COLOR27",
- "COLOR28", "COLOR29", "COLOR30", "COLOR31",
- /* 0x1C0 */
- "HTOTAL", "HSSTOP", "HBSTRT", "HBSTOP",
- "VTOTAL", "VSSTOP", "VBSTRT", "VBSTOP",
- "SPRHSTRT", "SPRHSTOP", "BPLHSTRT", "BPLHSTOP",
- "HHPOSW", "HHPOSR", "BEAMCON0", "HSSTRT",
- /* 0x1E0 */
- "VSSTRT", "HCENTER", "DIWHIGH", "BPLHMOD",
- "SPRHPTH", "SPRHPTL", "BPLHPTH", "BPLHPTL",
- "UNK1F0", "UNK1F2", "UNK1F4", "UNK1F6",
- "UNK1F8", "UNK1FA", "FMODE", "UNK1FE"
-};
-
-constexpr XTAL amiga_state::CLK_28M_PAL;
-constexpr XTAL amiga_state::CLK_7M_PAL;
-constexpr XTAL amiga_state::CLK_C1_PAL;
-constexpr XTAL amiga_state::CLK_E_PAL;
-
-constexpr XTAL amiga_state::CLK_28M_NTSC;
-constexpr XTAL amiga_state::CLK_7M_NTSC;
-constexpr XTAL amiga_state::CLK_C1_NTSC;
-constexpr XTAL amiga_state::CLK_E_NTSC;
-
-
-/*************************************
- *
- * Machine reset
- *
- *************************************/
-
-void amiga_state::machine_start()
-{
- m_power_led.resolve();
-
- // add callback for RESET instruction
- m_maincpu->set_reset_callback(*this, FUNC(amiga_state::m68k_reset));
-
- // set up chip RAM access
- memory_share *share = memshare("chip_ram");
- if (share == nullptr)
- fatalerror("Unable to find Amiga chip RAM\n");
- m_chip_ram.set(*share, 2);
- m_chip_ram_mask = (m_chip_ram.bytes() - 1) & ~1;
-
- // set up the timers
- m_irq_timer = timer_alloc(TIMER_AMIGA_IRQ);
- m_blitter_timer = timer_alloc(TIMER_AMIGA_BLITTER);
- m_serial_timer = timer_alloc(TIMER_SERIAL);
- m_scanline_timer = timer_alloc(TIMER_SCANLINE);
-
- // start the scanline timer
- m_scanline_timer->adjust(m_screen->time_until_pos(0));
-}
-
-WRITE_LINE_MEMBER( amiga_state::m68k_reset )
-{
- logerror("%s: Executed RESET\n", machine().describe_context());
- machine_reset();
-}
-
-void amiga_state::machine_reset()
-{
- // reset cia chips
- m_cia_0->reset();
- m_cia_1->reset();
-
- // reset custom chip registers
- custom_chip_reset();
-
- // map kickstart rom to location 0
- // this either done by reseting the cia chips
- // or directly by gayle where available
- m_gayle_reset = true;
- m_overlay->set_bank(1);
-}
-
-WRITE_LINE_MEMBER(amiga_state::fdc_dskblk_w)
-{
- set_interrupt(INTENA_SETCLR | INTENA_DSKBLK);
-}
-
-WRITE_LINE_MEMBER(amiga_state::fdc_dsksyn_w)
-{
- set_interrupt((state ? INTENA_SETCLR : 0) | INTENA_DSKSYN);
-}
-
-WRITE_LINE_MEMBER( amiga_state::kbreset_w )
-{
- // this is connected to the gary chip, gary then resets the 68k, agnus, paula and the cias
- if (!state)
- {
- m_paula->reset();
- machine_reset();
- m_maincpu->reset();
- }
-}
-
-// simple mirror of region 0xf80000 to 0xfbffff
-uint16_t amiga_state::rom_mirror_r(offs_t offset, uint16_t mem_mask)
-{
- return m_maincpu->space(AS_PROGRAM).read_word(offset + 0xf80000, mem_mask);
-}
-
-uint32_t amiga_state::rom_mirror32_r(offs_t offset, uint32_t mem_mask)
-{
- return m_maincpu->space(AS_PROGRAM).read_dword(offset + 0xf80000, mem_mask);
-}
-
-void amiga_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_SCANLINE:
- scanline_callback(ptr, param);
- break;
- case TIMER_AMIGA_IRQ:
- amiga_irq_proc(ptr, param);
- break;
- case TIMER_AMIGA_BLITTER:
- amiga_blitter_proc(ptr, param);
- break;
- case TIMER_SERIAL:
- serial_shift();
- break;
- default:
- fatalerror("Invalid timer: %d\n", id);
- }
-}
-
-
-/*************************************
- *
- * Per scanline callback
- *
- *************************************/
-
-void amiga_state::vblank()
-{
-}
-
-// todo: cia a clock can be connected to either a fixed 50/60hz signal from the power supply, or the vblank
-TIMER_CALLBACK_MEMBER( amiga_state::scanline_callback )
-{
- int scanline = param;
-
- // vblank start
- if (scanline == 0)
- {
- // signal vblank irq
- set_interrupt(INTENA_SETCLR | INTENA_VERTB);
-
- // clock tod
- m_cia_0->tod_w(1);
-
- // additional bookkeeping by drivers
- vblank();
- }
-
- // vblank end
- if (scanline == m_screen->visible_area().top())
- {
- m_cia_0->tod_w(0);
- }
-
- if (m_potgo_port.found())
- {
- // pot counters (start counting at 7 (ntsc) or 8 (pal))
- if (BIT(CUSTOM_REG(REG_POTGO), 0) && (scanline /2 ) > 7)
- {
- m_pot0x += !(m_potgo_port->read() & 0x0100);
- m_pot0y += !(m_potgo_port->read() & 0x0400);
- m_pot1x += !(m_potgo_port->read() & 0x1000);
- m_pot1y += !(m_potgo_port->read() & 0x4000);
- }
- }
-
- // render up to this scanline
- if (!m_screen->update_partial(scanline))
- {
- bitmap_rgb32 dummy_bitmap;
- if (IS_AGA())
- aga_render_scanline(dummy_bitmap, scanline);
- else
- render_scanline(dummy_bitmap, scanline);
- }
-
- // clock tod (if we actually render this scanline)
- m_cia_1->tod_w((scanline & 1) ^ BIT(CUSTOM_REG(REG_VPOSR), 15));
-
- // force a sound update
- m_paula->update();
-
- // set timer for next line
- scanline = (scanline + 1) % m_screen->height();
- m_scanline_timer->adjust(m_screen->time_until_pos(scanline), scanline);
-}
-
-
-
-/*************************************
- *
- * Interrupt management
- *
- *************************************/
-
-void amiga_state::set_interrupt(int interrupt)
-{
- custom_chip_w(REG_INTREQ, interrupt);
-}
-
-bool amiga_state::int2_pending()
-{
- return m_cia_0_irq;
-}
-
-bool amiga_state::int6_pending()
-{
- return m_cia_1_irq;
-}
-
-void amiga_state::update_int2()
-{
- set_interrupt((int2_pending() ? INTENA_SETCLR : 0x0000) | INTENA_PORTS);
-}
-
-void amiga_state::update_int6()
-{
- set_interrupt((int6_pending() ? INTENA_SETCLR : 0x0000) | INTENA_EXTER);
-}
-
-void amiga_state::update_irqs()
-{
- // if the external interrupt line is still active, set the interrupt request bit
- if (int2_pending())
- CUSTOM_REG(REG_INTREQ) |= INTENA_PORTS;
-
- if (int6_pending())
- CUSTOM_REG(REG_INTREQ) |= INTENA_EXTER;
-
- int ints = CUSTOM_REG(REG_INTENA) & CUSTOM_REG(REG_INTREQ);
-
- // master interrupt switch
- if (CUSTOM_REG(REG_INTENA) & INTENA_INTEN)
- {
- m_maincpu->set_input_line(1, ints & (INTENA_TBE | INTENA_DSKBLK | INTENA_SOFT) ? ASSERT_LINE : CLEAR_LINE);
- m_maincpu->set_input_line(2, ints & (INTENA_PORTS) ? ASSERT_LINE : CLEAR_LINE);
- m_maincpu->set_input_line(3, ints & (INTENA_COPER | INTENA_VERTB | INTENA_BLIT) ? ASSERT_LINE : CLEAR_LINE);
- m_maincpu->set_input_line(4, ints & (INTENA_AUD0 | INTENA_AUD1 | INTENA_AUD2 | INTENA_AUD3) ? ASSERT_LINE : CLEAR_LINE);
- m_maincpu->set_input_line(5, ints & (INTENA_RBF | INTENA_DSKSYN) ? ASSERT_LINE : CLEAR_LINE);
- m_maincpu->set_input_line(6, ints & (INTENA_EXTER) ? ASSERT_LINE : CLEAR_LINE);
- }
- else
- {
- m_maincpu->set_input_line(1, CLEAR_LINE);
- m_maincpu->set_input_line(2, CLEAR_LINE);
- m_maincpu->set_input_line(3, CLEAR_LINE);
- m_maincpu->set_input_line(4, CLEAR_LINE);
- m_maincpu->set_input_line(5, CLEAR_LINE);
- m_maincpu->set_input_line(6, CLEAR_LINE);
- }
-}
-
-TIMER_CALLBACK_MEMBER( amiga_state::amiga_irq_proc )
-{
- update_irqs();
- m_irq_timer->reset();
-}
-
-void amiga_state::paula_int_w (offs_t channel, u8 state)
-{
- set_interrupt(INTENA_SETCLR | (0x80 << channel));
-}
-
-
-//**************************************************************************
-// INPUTS
-//**************************************************************************
-
-uint16_t amiga_state::joy0dat_r()
-{
- if (!m_input_device.found() || (m_input_device->read() & 0x10))
- return m_joy0dat_port.read_safe(0xffff);
- else
- return (m_p1_mouse_y.read_safe(0xff) << 8) | m_p1_mouse_x.read_safe(0xff);
-}
-
-uint16_t amiga_state::joy1dat_r()
-{
- if (!m_input_device.found() || m_input_device->read() & 0x20)
- return m_joy1dat_port.read_safe(0xffff);
- else
- return (m_p2_mouse_y.read_safe(0xff) << 8) | m_p2_mouse_x.read_safe(0xff);
-}
-
-
-
-/*************************************
- *
- * Ascending blitter variant
- *
- *************************************/
-
-uint32_t amiga_state::blit_ascending()
-{
- uint32_t shifta = (CUSTOM_REG(REG_BLTCON0) >> 12) & 0xf;
- uint32_t shiftb = (CUSTOM_REG(REG_BLTCON1) >> 12) & 0xf;
- uint32_t height = CUSTOM_REG(REG_BLTSIZV);
- uint32_t width = CUSTOM_REG(REG_BLTSIZH);
- uint32_t acca = 0, accb = 0;
- uint32_t blitsum = 0;
- uint32_t x, y;
-
- /* iterate over the height */
- for (y = 0; y < height; y++)
- {
- /* iterate over the width */
- for (x = 0; x < width; x++)
- {
- uint16_t abc0, abc1, abc2, abc3;
- uint32_t tempa, tempd = 0;
- uint32_t b;
-
- /* fetch data for A */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
- {
- //CUSTOM_REG(REG_BLTADAT) = m_maincpu->space(AS_PROGRAM).read_word(CUSTOM_REG_LONG(REG_BLTAPTH));
- CUSTOM_REG(REG_BLTADAT) = read_chip_ram(CUSTOM_REG_LONG(REG_BLTAPTH));
- CUSTOM_REG_LONG(REG_BLTAPTH) += 2;
- }
-
- /* fetch data for B */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
- {
- CUSTOM_REG(REG_BLTBDAT) = read_chip_ram(CUSTOM_REG_LONG(REG_BLTBPTH));
- CUSTOM_REG_LONG(REG_BLTBPTH) += 2;
- }
-
- /* fetch data for C */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
- {
- CUSTOM_REG(REG_BLTCDAT) = read_chip_ram(CUSTOM_REG_LONG(REG_BLTCPTH));
- CUSTOM_REG_LONG(REG_BLTCPTH) += 2;
- }
-
- /* apply start/end masks to the A data */
- tempa = CUSTOM_REG(REG_BLTADAT);
- if (x == 0)
- tempa &= CUSTOM_REG(REG_BLTAFWM);
- if (x == width - 1)
- tempa &= CUSTOM_REG(REG_BLTALWM);
-
- /* update the B accumulator applying shifts */
- acca = (acca << 16) | (tempa << (16 - shifta));
- accb = (accb << 16) | (CUSTOM_REG(REG_BLTBDAT) << (16 - shiftb));
-
- /* build up 4 16-bit words containing 4 pixels each in 0ABC bit order */
- abc0 = ((acca >> 17) & 0x4444) | ((accb >> 18) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 3) & 0x1111);
- abc1 = ((acca >> 16) & 0x4444) | ((accb >> 17) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 2) & 0x1111);
- abc2 = ((acca >> 15) & 0x4444) | ((accb >> 16) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 1) & 0x1111);
- abc3 = ((acca >> 14) & 0x4444) | ((accb >> 15) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 0) & 0x1111);
-
- /* now loop over bits and compute the destination value */
- for (b = 0; b < 4; b++)
- {
- uint32_t bit;
-
- /* shift previous data up 4 bits */
- tempd <<= 4;
-
- /* lookup first bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc0 >> 12)) & 1;
- abc0 <<= 4;
- tempd |= bit << 3;
-
- /* lookup second bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc1 >> 12)) & 1;
- abc1 <<= 4;
- tempd |= bit << 2;
-
- /* lookup third bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc2 >> 12)) & 1;
- abc2 <<= 4;
- tempd |= bit << 1;
-
- /* lookup fourth bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc3 >> 12)) & 1;
- abc3 <<= 4;
- tempd |= bit << 0;
- }
-
- /* accumulate the sum */
- blitsum |= tempd;
-
- /* write to the destination */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
- {
- write_chip_ram(CUSTOM_REG_LONG(REG_BLTDPTH), tempd);
- CUSTOM_REG_LONG(REG_BLTDPTH) += 2;
- }
- }
-
- /* apply end of line modulos */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
- CUSTOM_REG_LONG(REG_BLTAPTH) += CUSTOM_REG_SIGNED(REG_BLTAMOD) & ~1;
- if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
- CUSTOM_REG_LONG(REG_BLTBPTH) += CUSTOM_REG_SIGNED(REG_BLTBMOD) & ~1;
- if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
- CUSTOM_REG_LONG(REG_BLTCPTH) += CUSTOM_REG_SIGNED(REG_BLTCMOD) & ~1;
- if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
- CUSTOM_REG_LONG(REG_BLTDPTH) += CUSTOM_REG_SIGNED(REG_BLTDMOD) & ~1;
- }
-
- /* return the blit sum */
- return blitsum;
-}
-
-
-
-/*************************************
- *
- * Descending blitter variant
- *
- *************************************/
-
-uint32_t amiga_state::blit_descending()
-{
- uint32_t fill_exclusive = (CUSTOM_REG(REG_BLTCON1) >> 4);
- uint32_t fill_inclusive = (CUSTOM_REG(REG_BLTCON1) >> 3);
- uint32_t shifta = (CUSTOM_REG(REG_BLTCON0) >> 12) & 0xf;
- uint32_t shiftb = (CUSTOM_REG(REG_BLTCON1) >> 12) & 0xf;
- uint32_t height = CUSTOM_REG(REG_BLTSIZV);
- uint32_t width = CUSTOM_REG(REG_BLTSIZH);
- uint32_t acca = 0, accb = 0;
- uint32_t blitsum = 0;
- uint32_t x, y;
-
- /* iterate over the height */
- for (y = 0; y < height; y++)
- {
- uint32_t fill_state = (CUSTOM_REG(REG_BLTCON1) >> 2) & 1;
-
- /* iterate over the width */
- for (x = 0; x < width; x++)
- {
- uint16_t abc0, abc1, abc2, abc3;
- uint32_t tempa, tempd = 0;
- uint32_t b;
-
- /* fetch data for A */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
- {
- CUSTOM_REG(REG_BLTADAT) = read_chip_ram(CUSTOM_REG_LONG(REG_BLTAPTH));
- CUSTOM_REG_LONG(REG_BLTAPTH) -= 2;
- }
-
- /* fetch data for B */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
- {
- CUSTOM_REG(REG_BLTBDAT) = read_chip_ram(CUSTOM_REG_LONG(REG_BLTBPTH));
- CUSTOM_REG_LONG(REG_BLTBPTH) -= 2;
- }
-
- /* fetch data for C */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
- {
- CUSTOM_REG(REG_BLTCDAT) = read_chip_ram(CUSTOM_REG_LONG(REG_BLTCPTH));
- CUSTOM_REG_LONG(REG_BLTCPTH) -= 2;
- }
-
- /* apply start/end masks to the A data */
- tempa = CUSTOM_REG(REG_BLTADAT);
- if (x == 0)
- tempa &= CUSTOM_REG(REG_BLTAFWM);
- if (x == width - 1)
- tempa &= CUSTOM_REG(REG_BLTALWM);
-
- /* update the B accumulator applying shifts */
- acca = (acca >> 16) | (tempa << shifta);
- accb = (accb >> 16) | (CUSTOM_REG(REG_BLTBDAT) << shiftb);
-
- /* build up 4 16-bit words containing 4 pixels each in 0ABC bit order */
- abc0 = ((acca >> 1) & 0x4444) | ((accb >> 2) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 3) & 0x1111);
- abc1 = ((acca >> 0) & 0x4444) | ((accb >> 1) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 2) & 0x1111);
- abc2 = ((acca << 1) & 0x4444) | ((accb >> 0) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 1) & 0x1111);
- abc3 = ((acca << 2) & 0x4444) | ((accb << 1) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 0) & 0x1111);
-
- /* now loop over bits and compute the destination value */
- for (b = 0; b < 4; b++)
- {
- uint32_t prev_fill_state;
- uint32_t bit;
-
- /* shift previous data up 4 bits */
- tempd >>= 4;
-
- /* lookup fourth bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc3 & 0xf)) & 1;
- abc3 >>= 4;
- prev_fill_state = fill_state;
- fill_state ^= bit;
- bit ^= prev_fill_state & fill_exclusive;
- bit |= prev_fill_state & fill_inclusive;
- tempd |= bit << 12;
-
- /* lookup third bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc2 & 0xf)) & 1;
- abc2 >>= 4;
- prev_fill_state = fill_state;
- fill_state ^= bit;
- bit ^= prev_fill_state & fill_exclusive;
- bit |= prev_fill_state & fill_inclusive;
- tempd |= bit << 13;
-
- /* lookup second bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc1 & 0xf)) & 1;
- abc1 >>= 4;
- prev_fill_state = fill_state;
- fill_state ^= bit;
- bit ^= prev_fill_state & fill_exclusive;
- bit |= prev_fill_state & fill_inclusive;
- tempd |= bit << 14;
-
- /* lookup first bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc0 & 0xf)) & 1;
- abc0 >>= 4;
- prev_fill_state = fill_state;
- fill_state ^= bit;
- bit ^= prev_fill_state & fill_exclusive;
- bit |= prev_fill_state & fill_inclusive;
- tempd |= bit << 15;
- }
-
- /* accumulate the sum */
- blitsum |= tempd;
-
- /* write to the destination */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
- {
- write_chip_ram(CUSTOM_REG_LONG(REG_BLTDPTH), tempd);
- CUSTOM_REG_LONG(REG_BLTDPTH) -= 2;
- }
- }
-
- /* apply end of line modulos */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
- CUSTOM_REG_LONG(REG_BLTAPTH) -= CUSTOM_REG_SIGNED(REG_BLTAMOD) & ~1;
- if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
- CUSTOM_REG_LONG(REG_BLTBPTH) -= CUSTOM_REG_SIGNED(REG_BLTBMOD) & ~1;
- if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
- CUSTOM_REG_LONG(REG_BLTCPTH) -= CUSTOM_REG_SIGNED(REG_BLTCMOD) & ~1;
- if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
- CUSTOM_REG_LONG(REG_BLTDPTH) -= CUSTOM_REG_SIGNED(REG_BLTDMOD) & ~1;
- }
-
- /* return the blit sum */
- return blitsum;
-}
-
-
-
-/*************************************
- *
- * Line drawing blitter variant
- *
- *************************************/
-
-/*
- The exact line drawing algorithm is not known, but based on the cryptic
- setup instructions, it is clear that it is a basic Bresenham line
- algorithm. A standard Bresenham algorithm looks like this:
-
- epsilon = 0;
- while (length--)
- {
- plot(x, y);
- x++;
- epsilon += dy;
- if ((2 * epsilon) >= dx)
- {
- y++;
- epsilon -= dx;
- }
- }
-
- If you multiply the epsilon term by 4 and shuffle the logic a bit, the
- equivalent logic is:
-
- epsilon = 4 * dy - 2 * dx;
- while (length--)
- {
- plot(x, y);
- x++;
- if (epsilon >= 0)
- {
- y++;
- epsilon += 4 * (dy - dx);
- }
- else
- epsilon += 4 * dy;
- }
-
- With this refactoring, you can see that BLTAPT = epsilon,
- BLTAMOD = 4 * (dy - dx) and BLTBMOD = 4 * dy.
-*/
-
-uint32_t amiga_state::blit_line()
-{
- uint32_t singlemode = (CUSTOM_REG(REG_BLTCON1) & 0x0002) ? 0x0000 : 0xffff;
- uint32_t singlemask = 0xffff;
- uint32_t blitsum = 0;
- uint32_t height;
-
- /* see if folks are breaking the rules */
- if (CUSTOM_REG(REG_BLTSIZH) != 0x0002)
- logerror("Blitter: Blit width != 2 in line mode!\n");
- if ((CUSTOM_REG(REG_BLTCON0) & 0x0a00) != 0x0a00)
- logerror("Blitter: Channel selection incorrect in line mode!\n" );
-
- /* extract the length of the line */
- height = CUSTOM_REG(REG_BLTSIZV);
-
- /* iterate over the line height */
- while (height--)
- {
- uint16_t abc0, abc1, abc2, abc3;
- uint32_t tempa, tempb, tempd = 0;
- int b, dx, dy;
-
- /* fetch data for C */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
- CUSTOM_REG(REG_BLTCDAT) = read_chip_ram(CUSTOM_REG_LONG(REG_BLTCPTH));
-
- /* rotate the A data according to the shift */
- tempa = CUSTOM_REG(REG_BLTADAT) >> (CUSTOM_REG(REG_BLTCON0) >> 12);
-
- /* apply single bit mask */
- tempa &= singlemask;
- singlemask &= singlemode;
-
- /* rotate the B data according to the shift and expand to 16 bits */
- tempb = -((CUSTOM_REG(REG_BLTBDAT) >> (CUSTOM_REG(REG_BLTCON1) >> 12)) & 1);
-
- /* build up 4 16-bit words containing 4 pixels each in 0ABC bit order */
- abc0 = ((tempa >> 1) & 0x4444) | (tempb & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 3) & 0x1111);
- abc1 = ((tempa >> 0) & 0x4444) | (tempb & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 2) & 0x1111);
- abc2 = ((tempa << 1) & 0x4444) | (tempb & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 1) & 0x1111);
- abc3 = ((tempa << 2) & 0x4444) | (tempb & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 0) & 0x1111);
-
- /* now loop over bits and compute the destination value */
- for (b = 0; b < 4; b++)
- {
- uint32_t bit;
-
- /* shift previous data up 4 bits */
- tempd <<= 4;
-
- /* lookup first bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc0 >> 12)) & 1;
- abc0 <<= 4;
- tempd |= bit << 3;
-
- /* lookup second bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc1 >> 12)) & 1;
- abc1 <<= 4;
- tempd |= bit << 2;
-
- /* lookup third bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc2 >> 12)) & 1;
- abc2 <<= 4;
- tempd |= bit << 1;
-
- /* lookup fourth bit in series */
- bit = (CUSTOM_REG(REG_BLTCON0) >> (abc3 >> 12)) & 1;
- abc3 <<= 4;
- tempd |= bit << 0;
- }
-
- /* accumulate the sum */
- blitsum |= tempd;
-
- /* write to the destination */
- write_chip_ram(CUSTOM_REG_LONG(REG_BLTDPTH), tempd);
-
- /* always increment along the major axis */
- if (CUSTOM_REG(REG_BLTCON1) & 0x0010)
- {
- dx = (CUSTOM_REG(REG_BLTCON1) & 0x0004) ? -1 : 1;
- dy = 0;
- }
- else
- {
- dx = 0;
- dy = (CUSTOM_REG(REG_BLTCON1) & 0x0004) ? -1 : 1;
- }
-
- /* is the sign bit clear? */
- if (!(CUSTOM_REG(REG_BLTCON1) & 0x0040))
- {
- /* add 4 * (dy-dx) */
- CUSTOM_REG_LONG(REG_BLTAPTH) += CUSTOM_REG_SIGNED(REG_BLTAMOD) & ~1;
-
- /* increment along the minor axis */
- if (CUSTOM_REG(REG_BLTCON1) & 0x0010)
- dy = (CUSTOM_REG(REG_BLTCON1) & 0x0008) ? -1 : 1;
- else
- dx = (CUSTOM_REG(REG_BLTCON1) & 0x0008) ? -1 : 1;
- }
-
- /* else add 4 * dy and don't increment along the minor axis */
- else
- CUSTOM_REG_LONG(REG_BLTAPTH) += CUSTOM_REG_SIGNED(REG_BLTBMOD) & ~1;
-
- /* adjust X if necessary */
- if (dx)
- {
- /* adjust the A shift value */
- uint32_t temp = CUSTOM_REG(REG_BLTCON0) + (int32_t)(dx << 12);
- CUSTOM_REG(REG_BLTCON0) = temp;
-
- /* if we went from 0xf to 0x0 or vice-versa, adjust the actual pointers */
- if (temp & 0x10000)
- {
- CUSTOM_REG_LONG(REG_BLTCPTH) += 2 * dx;
- CUSTOM_REG_LONG(REG_BLTDPTH) += 2 * dx;
- }
- }
-
- /* adjust Y if necessary */
- if (dy)
- {
- /* BLTCMOD seems to be used for both C and D pointers */
- CUSTOM_REG_LONG(REG_BLTCPTH) += dy * (int16_t)(CUSTOM_REG_SIGNED(REG_BLTCMOD) & ~1);
- CUSTOM_REG_LONG(REG_BLTDPTH) += dy * (int16_t)(CUSTOM_REG_SIGNED(REG_BLTCMOD) & ~1);
-
- /* reset the single mask since we're on a new line */
- singlemask = 0xffff;
- }
-
- /* set the new sign bit value */
- CUSTOM_REG(REG_BLTCON1) = (CUSTOM_REG(REG_BLTCON1) & ~0x0040) | ((CUSTOM_REG(REG_BLTAPTL) >> 9) & 0x0040);
-
- /* increment texture shift on every pixel */
- CUSTOM_REG(REG_BLTCON1) += 0x1000;
- }
-
- return blitsum;
-}
-
-
-
-/*************************************
- *
- * Blitter deferred callback
- *
- *************************************/
-
-TIMER_CALLBACK_MEMBER( amiga_state::amiga_blitter_proc )
-{
- uint32_t blitsum = 0;
-
- /* logging */
- if (LOG_BLITS)
- {
- static const char *const type[] = { "ASCENDING", "LINE", "DESCENDING", "LINE" };
- logerror("BLIT %s: %dx%d %04x %04x\n", type[CUSTOM_REG(REG_BLTCON1) & 0x0003], CUSTOM_REG(REG_BLTSIZH), CUSTOM_REG(REG_BLTSIZV), CUSTOM_REG(REG_BLTCON0), CUSTOM_REG(REG_BLTCON1));
- if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
- logerror(" A: addr=%06X mod=%3d shift=%2d maskl=%04x maskr=%04x\n", CUSTOM_REG_LONG(REG_BLTAPTH), CUSTOM_REG_SIGNED(REG_BLTAMOD), CUSTOM_REG(REG_BLTCON0) >> 12, CUSTOM_REG(REG_BLTAFWM), CUSTOM_REG(REG_BLTALWM));
- if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
- logerror(" B: addr=%06X mod=%3d shift=%2d\n", CUSTOM_REG_LONG(REG_BLTBPTH), CUSTOM_REG_SIGNED(REG_BLTBMOD), CUSTOM_REG(REG_BLTCON1) >> 12);
- if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
- logerror(" C: addr=%06X mod=%3d\n", CUSTOM_REG_LONG(REG_BLTCPTH), CUSTOM_REG_SIGNED(REG_BLTCMOD));
- if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
- logerror(" D: addr=%06X mod=%3d\n", CUSTOM_REG_LONG(REG_BLTDPTH), CUSTOM_REG_SIGNED(REG_BLTDMOD));
- }
-
- /* set the zero flag */
- CUSTOM_REG(REG_DMACON) |= 0x2000;
-
- /* switch off the type of blit */
- switch (CUSTOM_REG(REG_BLTCON1) & 0x0003)
- {
- case 0: /* ascending */
- blitsum = blit_ascending();
- break;
-
- case 2: /* descending */
- blitsum = blit_descending();
- break;
-
- case 1: /* line */
- case 3:
- blitsum = blit_line();
- break;
- }
-
- /* clear the zero flag if we actually wrote data */
- if (blitsum)
- CUSTOM_REG(REG_DMACON) &= ~0x2000;
-
- /* no longer busy */
- CUSTOM_REG(REG_DMACON) &= ~0x4000;
-
- // signal an interrupt
- set_interrupt(INTENA_SETCLR | INTENA_BLIT);
-
- /* reset the blitter timer */
- m_blitter_timer->reset();
-}
-
-
-
-/*************************************
- *
- * Blitter setup
- *
- *************************************/
-
-void amiga_state::blitter_setup()
-{
- int ticks, width, height, blittime;
-
- /* is there another blitting in progress? */
- if (CUSTOM_REG(REG_DMACON) & 0x4000)
- {
- logerror("%s - This program is playing tricks with the blitter\n", machine().describe_context() );
- return;
- }
-
- /* line mode is 8 ticks/pixel */
- if (CUSTOM_REG(REG_BLTCON1) & 1)
- ticks = 8;
-
- /* standard mode is 4 ticks base */
- else
- {
- ticks = 4;
-
- /* plus 2 ticks if channel B is involved */
- if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
- ticks += 2;
-
- /* plus 2 ticks if both channel C and D are involved */
- if ((CUSTOM_REG(REG_BLTCON0) & 0x0300) == 0x0300)
- ticks += 2;
- }
-
- /* extract height/width */
- width = CUSTOM_REG(REG_BLTSIZH);
- height = CUSTOM_REG(REG_BLTSIZV);
-
- /* compute the blit time */
- blittime = ticks * height * width;
-
- /* if 'blitter-nasty' is set, then the blitter takes over the bus. Make the blit semi-immediate */
- if ( CUSTOM_REG(REG_DMACON) & 0x0400 )
- {
- /* simulate the 68k not running while the blit is going */
- m_maincpu->adjust_icount(-(blittime/2) );
-
- blittime = BLITTER_NASTY_DELAY;
- }
-
- /* AGA has twice the bus bandwidth, so blits take half the time */
- if (IS_AGA())
- blittime /= 2;
-
- /* signal blitter busy */
- CUSTOM_REG(REG_DMACON) |= 0x4000;
-
- /* set a timer */
- m_blitter_timer->adjust( m_maincpu->cycles_to_attotime( blittime ));
-}
-
-
-//**************************************************************************
-// CENTRONICS
-//**************************************************************************
-
-WRITE_LINE_MEMBER( amiga_state::centronics_ack_w )
-{
- m_cia_0->flag_w(state);
-}
-
-WRITE_LINE_MEMBER( amiga_state::centronics_busy_w )
-{
- m_centronics_busy = state;
- m_cia_1->sp_w(state);
-}
-
-WRITE_LINE_MEMBER( amiga_state::centronics_perror_w )
-{
- m_centronics_perror = state;
- m_cia_1->cnt_w(state);
-}
-
-WRITE_LINE_MEMBER( amiga_state::centronics_select_w )
-{
- m_centronics_select = state;
-}
-
-
-//**************************************************************************
-// 8520 CIA
-//**************************************************************************
-
-// CIA-A access: 101x xxxx xxx0 oooo xxxx xxx1
-// CIA-B access: 101x xxxx xx0x oooo xxxx xxx0
-
-uint16_t amiga_state::cia_r(offs_t offset, uint16_t mem_mask)
-{
- uint16_t data = 0;
-
- if ((offset & 0x1000/2) == 0 && ACCESSING_BITS_0_7)
- data |= m_cia_0->read(offset >> 7);
-
- if ((offset & 0x2000/2) == 0 && ACCESSING_BITS_8_15)
- data |= m_cia_1->read(offset >> 7) << 8;
-
- if (LOG_CIA)
- logerror("%s: cia_r(%06x) = %04x & %04x\n", machine().describe_context(), offset, data, mem_mask);
-
- return data;
-}
-
-void amiga_state::cia_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- if (LOG_CIA)
- logerror("%s: cia_w(%06x) = %04x & %04x\n", machine().describe_context(), offset, data, mem_mask);
-
- if ((offset & 0x1000/2) == 0 && ACCESSING_BITS_0_7)
- m_cia_0->write(offset >> 7, data & 0xff);
-
- if ((offset & 0x2000/2) == 0 && ACCESSING_BITS_8_15)
- m_cia_1->write(offset >> 7, data >> 8);
-}
-
-void amiga_state::gayle_cia_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- // the first write to cia 0 after a reset switches in chip ram
- if (m_gayle_reset && (offset & 0x1000/2) == 0 && ACCESSING_BITS_0_7)
- {
- m_gayle_reset = false;
- m_overlay->set_bank(0);
- }
-
- // hand down to the standard cia handler
- cia_w(offset, data, mem_mask);
-}
-
-CUSTOM_INPUT_MEMBER( amiga_state::floppy_drive_status )
-{
- return m_fdc->ciaapra_r();
-}
-
-void amiga_state::cia_0_port_a_write(uint8_t data)
-{
- // bit 0, kickstart overlay
- m_overlay->set_bank(BIT(data, 0));
-
- // bit 1, power led
- m_power_led = BIT(~data, 1);
-}
-
-WRITE_LINE_MEMBER( amiga_state::cia_0_irq )
-{
- if (LOG_CIA)
- logerror("%s: cia_0_irq: %d\n", machine().describe_context(), state);
-
- m_cia_0_irq = state;
- update_int2();
-}
-
-uint8_t amiga_state::cia_1_port_a_read()
-{
- uint8_t data = 0;
-
- // bit 0 to 2, centronics
- data |= m_centronics_busy << 0;
- data |= m_centronics_perror << 1;
- data |= m_centronics_select << 2;
-
- // bit 2 to 7, serial line
- data |= m_rs232_ri << 2;
- data |= m_rs232_dsr << 3;
- data |= m_rs232_cts << 4;
- data |= m_rs232_dcd << 5;
-
- return data;
-}
-
-void amiga_state::cia_1_port_a_write(uint8_t data)
-{
- if (m_rs232)
- {
- m_rs232->write_rts(BIT(data, 6));
- m_rs232->write_dtr(BIT(data, 7));
- }
-}
-
-WRITE_LINE_MEMBER( amiga_state::cia_1_irq )
-{
- if (LOG_CIA)
- logerror("%s: cia_1_irq: %d\n", machine().describe_context(), state);
-
- m_cia_1_irq = state;
- update_int6();
-}
-
-
-//**************************************************************************
-// CUSTOM CHIPS
-//**************************************************************************
-
-void amiga_state::custom_chip_reset()
-{
- CUSTOM_REG(REG_DENISEID) = m_denise_id;
- CUSTOM_REG(REG_VPOSR) = m_agnus_id << 8;
- CUSTOM_REG(REG_DDFSTRT) = 0x18;
- CUSTOM_REG(REG_DDFSTOP) = 0xd8;
- CUSTOM_REG(REG_INTENA) = 0x0000;
- CUSTOM_REG(REG_SERDATR) = SERDATR_RXD | SERDATR_TSRE | SERDATR_TBE;
- CUSTOM_REG(REG_BEAMCON0) = (m_agnus_id & 0x10) ? 0x0000 : 0x0020;
-}
-
-uint16_t amiga_state::custom_chip_r(offs_t offset)
-{
- uint16_t temp;
-
- if (LOG_CUSTOM)
- logerror("%06X:read from custom %s\n", m_maincpu->pc(), s_custom_reg_names[offset & 0xff]);
-
- switch (offset & 0xff)
- {
- case REG_BLTDDAT:
- return CUSTOM_REG(REG_BLTDDAT);
-
- case REG_DMACONR:
- return CUSTOM_REG(REG_DMACON);
-
- case REG_VPOSR:
- CUSTOM_REG(REG_VPOSR) &= 0xff00;
- CUSTOM_REG(REG_VPOSR) |= amiga_gethvpos() >> 16;
-
- return CUSTOM_REG(REG_VPOSR);
-
- case REG_VHPOSR:
- return amiga_gethvpos() & 0xffff;
-
- case REG_SERDATR:
- if (LOG_SERIAL)
- logerror("r SERDATR: %04x\n", CUSTOM_REG(REG_SERDATR));
-
- return CUSTOM_REG(REG_SERDATR);
-
- case REG_JOY0DAT:
- if (m_joy0dat_port.found())
- return joy0dat_r();
- [[fallthrough]]; // FIXME: Really? Fall through to potentially reading the other joystick?
- case REG_JOY1DAT:
- if (m_joy1dat_port.found())
- return joy1dat_r();
- [[fallthrough]]; // TODO: check that this is correct
- case REG_POTGOR:
- return m_potgo_port.read_safe(0x5500);
-
- case REG_POT0DAT:
- if (m_pot0dat_port.found())
- {
- return m_pot0dat_port->read();
- }
- else
- {
- int scale = m_agnus_id & 0x10 ? 525 : 625;
-
- m_pot0dat = (int) ((double) m_pot0x / scale) * 0xff;
- m_pot0dat |= (int)(((double) m_pot0y / scale) * 0xff) << 8;
-
- return m_pot0dat;
- }
-
- case REG_POT1DAT:
- if (m_pot1dat_port.found())
- {
- return m_pot1dat_port->read();
- }
- else
- {
- int scale = m_agnus_id & 0x10 ? 525 : 625;
-
- m_pot1dat = (int) ((double) m_pot1x / scale) * 0xff;
- m_pot1dat |= (int)(((double) m_pot1y / scale) * 0xff) << 8;
-
- return m_pot1dat;
- }
-
- case REG_DSKBYTR:
- return m_fdc->dskbytr_r();
-
- case REG_INTENAR:
- return CUSTOM_REG(REG_INTENA);
-
- case REG_INTREQR:
- return CUSTOM_REG(REG_INTREQ);
-
- case REG_COPJMP1:
- copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
- break;
-
- case REG_COPJMP2:
- copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
- break;
-
- case REG_CLXDAT:
- temp = CUSTOM_REG(REG_CLXDAT);
- CUSTOM_REG(REG_CLXDAT) = 0;
- return temp;
-
- case REG_DENISEID:
- return CUSTOM_REG(REG_DENISEID);
-
- case REG_DSKPTH:
- return m_fdc->dskpth_r();
-
- case REG_DSKPTL:
- return m_fdc->dskptl_r();
-
- case REG_ADKCONR:
- return m_fdc->adkcon_r();
-
- case REG_DSKDATR:
- popmessage("DSKDAT R, contact MESSdev");
- break;
- }
-
- return 0xffff;
-}
-
-void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
-{
- uint16_t temp;
- offset &= 0xff;
-
- if (LOG_CUSTOM)
- logerror("%06X:write to custom %s = %04X\n", m_maincpu->pc(), s_custom_reg_names[offset & 0xff], data);
-
- // paula will handle some of those registers
- m_paula->reg_w(offset, data);
-
- switch (offset)
- {
- case REG_BLTDDAT: case REG_DMACONR: case REG_VPOSR: case REG_VHPOSR:
- case REG_DSKDATR: case REG_JOY0DAT: case REG_JOY1DAT: case REG_CLXDAT:
- case REG_ADKCONR: case REG_POT0DAT: case REG_POT1DAT: case REG_POTGOR:
- case REG_SERDATR: case REG_DSKBYTR: case REG_INTENAR: case REG_INTREQR:
- // read-only registers
- return;
-
- case REG_DSKDAT:
- popmessage("DSKDAT W %04x, contact MESSdev",data);
- break;
-
- case REG_DSKSYNC:
- m_fdc->dsksync_w(data);
- break;
-
- case REG_DSKPTH:
- m_fdc->dskpth_w(data);
- break;
-
- case REG_DSKPTL:
- m_fdc->dskptl_w(data);
- break;
-
- case REG_DSKLEN:
- m_fdc->dsklen_w(data);
- break;
-
- case REG_POTGO:
- if (BIT(data, 0))
- {
- // start counters
- m_pot0x = 0;
- m_pot0y = 0;
- m_pot1x = 0;
- m_pot1y = 0;
- }
- potgo_w(data);
- break;
-
- case REG_SERDAT:
- if (LOG_SERIAL)
- logerror("w SERDAT: %04x\n", data);
-
- CUSTOM_REG(REG_SERDAT) = data;
-
- // transmit shift register currently empty?
- if (CUSTOM_REG(REG_SERDATR) & SERDATR_TSRE)
- {
- // transfer new data to shift register
- m_tx_shift = CUSTOM_REG(REG_SERDAT);
- CUSTOM_REG(REG_SERDAT) = 0;
-
- // and signal transmit buffer empty
- CUSTOM_REG(REG_SERDATR) &= ~SERDATR_TSRE;
- CUSTOM_REG(REG_SERDATR) |= SERDATR_TBE;
- set_interrupt(INTENA_SETCLR | INTENA_TBE);
- }
- else
- {
- // transmit buffer now full
- CUSTOM_REG(REG_SERDATR) &= ~SERDATR_TBE;
- }
-
- return;
-
- case REG_SERPER:
- if (LOG_SERIAL)
- logerror("w SERPER: %04x\n", data);
-
- CUSTOM_REG(REG_SERPER) = data;
- serial_adjust();
-
- return;
-
- case REG_BLTSIZE:
- CUSTOM_REG(REG_BLTSIZE) = data;
- CUSTOM_REG(REG_BLTSIZV) = (data >> 6) & 0x3ff;
- CUSTOM_REG(REG_BLTSIZH) = data & 0x3f;
- if ( CUSTOM_REG(REG_BLTSIZV) == 0 ) CUSTOM_REG(REG_BLTSIZV) = 0x400;
- if ( CUSTOM_REG(REG_BLTSIZH) == 0 ) CUSTOM_REG(REG_BLTSIZH) = 0x40;
- blitter_setup();
- break;
-
- case REG_BLTSIZV:
- if (IS_ECS() || IS_AGA())
- {
- CUSTOM_REG(REG_BLTSIZV) = data & 0x7fff;
- if ( CUSTOM_REG(REG_BLTSIZV) == 0 ) CUSTOM_REG(REG_BLTSIZV) = 0x8000;
- }
- break;
-
- case REG_BLTSIZH:
- if (IS_ECS() || IS_AGA())
- {
- CUSTOM_REG(REG_BLTSIZH) = data & 0x7ff;
- if ( CUSTOM_REG(REG_BLTSIZH) == 0 ) CUSTOM_REG(REG_BLTSIZH) = 0x800;
- blitter_setup();
- }
- break;
-
- case REG_BLTCON0L:
- if (IS_ECS() || IS_AGA())
- {
- CUSTOM_REG(REG_BLTCON0) &= 0xff00;
- CUSTOM_REG(REG_BLTCON0) |= data & 0xff;
- }
- break;
-
- case REG_SPR0PTH: case REG_SPR1PTH: case REG_SPR2PTH: case REG_SPR3PTH:
- case REG_SPR4PTH: case REG_SPR5PTH: case REG_SPR6PTH: case REG_SPR7PTH:
- data &= ( m_chip_ram_mask >> 16 );
- break;
-
- case REG_SPR0PTL: case REG_SPR1PTL: case REG_SPR2PTL: case REG_SPR3PTL:
- case REG_SPR4PTL: case REG_SPR5PTL: case REG_SPR6PTL: case REG_SPR7PTL:
- sprite_dma_reset((offset - REG_SPR0PTL) / 2);
- break;
-
- case REG_SPR0CTL: case REG_SPR1CTL: case REG_SPR2CTL: case REG_SPR3CTL:
- case REG_SPR4CTL: case REG_SPR5CTL: case REG_SPR6CTL: case REG_SPR7CTL:
- /* disable comparitor on writes here */
- sprite_enable_comparitor((offset - REG_SPR0CTL) / 4, false);
- break;
-
- case REG_SPR0DATA: case REG_SPR1DATA: case REG_SPR2DATA: case REG_SPR3DATA:
- case REG_SPR4DATA: case REG_SPR5DATA: case REG_SPR6DATA: case REG_SPR7DATA:
- /* enable comparitor on writes here */
- sprite_enable_comparitor((offset - REG_SPR0DATA) / 4, true);
- break;
-
- case REG_COP1LCH:
- case REG_COP2LCH:
- data &= ( m_chip_ram_mask >> 16 );
- break;
-
- case REG_COPJMP1:
- copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
- break;
-
- case REG_COPJMP2:
- copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
- break;
-
- case REG_DDFSTRT:
- /* impose hardware limits ( HRM, page 75 ) */
- data &= 0xfe;
- if (data < 0x18)
- data = 0x18;
- break;
-
- case REG_DDFSTOP:
- /* impose hardware limits ( HRM, page 75 ) */
- data &= 0xfe;
- if (data > 0xd8)
- data = 0xd8;
- break;
-
- case REG_DMACON:
- /* bits BBUSY (14) and BZERO (13) are read-only */
- data &= 0x9fff;
- data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
- m_fdc->dmacon_set(data);
-
- /* if 'blitter-nasty' has been turned on and we have a blit pending, reschedule it */
- if ( ( data & 0x400 ) && ( CUSTOM_REG(REG_DMACON) & 0x4000 ) )
- m_blitter_timer->adjust(m_maincpu->cycles_to_attotime(BLITTER_NASTY_DELAY));
-
- break;
-
- case REG_INTENA:
- temp = data;
-
- data = (data & INTENA_SETCLR) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
- CUSTOM_REG(offset) = data;
- if (temp & INTENA_SETCLR)
- // if we're enabling irq's, delay a bit
- m_irq_timer->adjust(m_maincpu->cycles_to_attotime(AMIGA_IRQ_DELAY_CYCLES));
- else
- // if we're disabling irq's, process right away
- update_irqs();
- break;
-
- case REG_INTREQ:
- temp = data;
-
- // clear receive buffer full?
- if (!(data & INTENA_SETCLR) && (data & INTENA_RBF))
- {
- CUSTOM_REG(REG_SERDATR) &= ~SERDATR_OVRUN;
- CUSTOM_REG(REG_SERDATR) &= ~SERDATR_RBF;
- }
-
- // clear transmit buffer empty?
- if (!(data & INTENA_SETCLR) && (data & INTENA_TBE))
- CUSTOM_REG(REG_SERDATR) |= SERDATR_TBE;
-
- data = (data & INTENA_SETCLR) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
- CUSTOM_REG(offset) = data;
-
- if (temp & INTENA_SETCLR)
- // if we're generating irq's, delay a bit
- m_irq_timer->adjust(m_maincpu->cycles_to_attotime(AMIGA_IRQ_DELAY_CYCLES));
- else
- // if we're clearing irq's, process right away
- update_irqs();
- break;
-
- case REG_ADKCON:
- data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
- m_fdc->adkcon_set(data);
- break;
-
- case REG_BPL1PTH: case REG_BPL2PTH: case REG_BPL3PTH: case REG_BPL4PTH:
- case REG_BPL5PTH: case REG_BPL6PTH:
- data &= ( m_chip_ram_mask >> 16 );
- break;
-
- case REG_BPLCON0:
- if ((data & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) == (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2))
- {
- /* planes go from 0 to 6, inclusive */
- logerror( "This game is doing funky planes stuff. (planes > 6)\n" );
- data &= ~BPLCON0_BPU0;
- }
- CUSTOM_REG(offset) = data;
- break;
-
- case REG_BPL1MOD: case REG_BPL2MOD:
- // bit 0 is implicitly ignored on writes,
- // and wouldn't otherwise make sense with 68k inability of word reading with odd addresses.
- // hpoker/hpokera would otherwise draw misaligned bottom GFX area without this (writes 0x27)
- data &= ~1;
- break;
-
- case REG_COLOR00: case REG_COLOR01: case REG_COLOR02: case REG_COLOR03:
- case REG_COLOR04: case REG_COLOR05: case REG_COLOR06: case REG_COLOR07:
- case REG_COLOR08: case REG_COLOR09: case REG_COLOR10: case REG_COLOR11:
- case REG_COLOR12: case REG_COLOR13: case REG_COLOR14: case REG_COLOR15:
- case REG_COLOR16: case REG_COLOR17: case REG_COLOR18: case REG_COLOR19:
- case REG_COLOR20: case REG_COLOR21: case REG_COLOR22: case REG_COLOR23:
- case REG_COLOR24: case REG_COLOR25: case REG_COLOR26: case REG_COLOR27:
- case REG_COLOR28: case REG_COLOR29: case REG_COLOR30: case REG_COLOR31:
- if (IS_AGA())
- {
- aga_palette_write(offset - REG_COLOR00, data);
- }
- else
- {
- data &= 0xfff;
- CUSTOM_REG(offset + 32) = (data >> 1) & 0x777;
- }
- break;
-
- // display window start/stop
- case REG_DIWSTRT:
- case REG_DIWSTOP:
- m_diwhigh_valid = false;
- break;
-
- // display window high
- case REG_DIWHIGH:
- if (IS_ECS() || IS_AGA())
- {
- m_diwhigh_valid = true;
- CUSTOM_REG(REG_DIWHIGH) = data;
- }
- break;
-
- case REG_BEAMCON0:
- // only available on ecs agnus
- if (m_agnus_id >= AGNUS_HR_PAL)
- {
- CUSTOM_REG(REG_BEAMCON0) = data;
- update_screenmode();
- }
- break;
-
- default:
- break;
- }
-
- if (IS_AGA())
- CUSTOM_REG(offset) = data;
- else
- if (offset <= REG_COLOR31)
- CUSTOM_REG(offset) = data;
-}
-
-
-//**************************************************************************
-// SERIAL
-//**************************************************************************
-
-void amiga_state::serial_adjust()
-{
- uint32_t divisor = (CUSTOM_REG(REG_SERPER) & 0x7fff) + 1;
- uint32_t baud = m_paula->clock() / divisor;
-
- m_serial_timer->adjust(attotime::from_hz(baud) / 2, 0, attotime::from_hz(baud));
-}
-
-void amiga_state::serial_shift()
-{
- if (CUSTOM_REG(REG_ADKCON) & ADKCON_UARTBRK)
- {
- // break active, force low
- rs232_tx(0);
- }
- else
- {
- // transmit shift register not empty?
- if ((CUSTOM_REG(REG_SERDATR) & SERDATR_TSRE) == 0)
- {
- if (m_tx_state == 0)
- {
- // transmit start bit
- rs232_tx(0);
- m_tx_state++;
- }
- else if (m_tx_state <= 8 + BIT(CUSTOM_REG(REG_SERPER), 15))
- {
- // send data bits
- rs232_tx(m_tx_shift & 1);
- m_tx_shift >>= 1;
- m_tx_state++;
- }
- else
- {
- // send stop bits until we run out
- if (m_tx_shift & 1)
- {
- rs232_tx(m_tx_shift & 1);
- m_tx_shift >>= 1;
- }
- else
- {
- // more data?
- if (CUSTOM_REG(REG_SERDAT))
- {
- // transfer to shift register
- m_tx_shift = CUSTOM_REG(REG_SERDAT);
- CUSTOM_REG(REG_SERDAT) = 0;
-
- // signal buffer empty
- CUSTOM_REG(REG_SERDATR) |= SERDATR_TBE;
- set_interrupt(INTENA_SETCLR | INTENA_TBE);
- }
- else
- {
- // we're done
- CUSTOM_REG(REG_SERDATR) |= SERDATR_TSRE;
- }
-
- m_tx_state = 0;
- }
- }
- }
- else
- {
- // transmit register empty
- rs232_tx(1);
- }
- }
-
- // waiting for start bit?
- if (m_rx_state == 0)
- {
- // start bit seen (high to low transition)
- if (m_rx_previous && (CUSTOM_REG(REG_SERDATR) & SERDATR_RXD) == 0)
- {
- m_rx_state++;
- }
- }
- else if (m_rx_state <= 8 + BIT(CUSTOM_REG(REG_SERPER), 15))
- {
- // receive data
- m_rx_shift >>= 1;
- m_rx_shift = (m_rx_shift & 0x7fff) | (BIT(CUSTOM_REG(REG_SERDATR), 11) << 15);
- m_rx_state++;
- }
- else
- {
- // stop bit
- m_rx_shift >>= 1;
- m_rx_shift = (m_rx_shift & 0x7fff) | (BIT(CUSTOM_REG(REG_SERDATR), 11) << 15);
-
- // shift to start
- m_rx_shift >>= (15 - (8 + BIT(CUSTOM_REG(REG_SERPER), 15)));
-
- // save data
- CUSTOM_REG(REG_SERDATR) &= ~0x3ff;
- CUSTOM_REG(REG_SERDATR) |= m_rx_shift & 0x3ff;
-
- // overrun?
- if (CUSTOM_REG(REG_SERDATR) & SERDATR_RBF)
- CUSTOM_REG(REG_SERDATR) |= SERDATR_OVRUN;
-
- // set ready and signal interrupt
- CUSTOM_REG(REG_SERDATR) |= SERDATR_RBF;
- set_interrupt(INTENA_SETCLR | INTENA_RBF);
-
- m_rx_shift = 0;
- m_rx_state = 0;
- }
-}
-
-void amiga_state::rs232_tx(int state)
-{
- if (m_rs232)
- m_rs232->write_txd(state);
-}
-
-void amiga_state::rx_write(int level)
-{
- m_rx_previous = BIT(CUSTOM_REG(REG_SERDATR), 11);
- CUSTOM_REG(REG_SERDATR) &= ~SERDATR_RXD;
- CUSTOM_REG(REG_SERDATR) |= level << 11;
-}
-
-WRITE_LINE_MEMBER( amiga_state::rs232_rx_w )
-{
- rx_write(state);
-
- // start bit received?
- if (m_rx_state == 1)
- serial_adjust();
-}
-
-WRITE_LINE_MEMBER( amiga_state::rs232_dcd_w )
-{
- m_rs232_dcd = state;
-}
-
-WRITE_LINE_MEMBER( amiga_state::rs232_dsr_w )
-{
- m_rs232_dsr = state;
-}
-
-WRITE_LINE_MEMBER( amiga_state::rs232_ri_w )
-{
- m_rs232_ri = state;
-}
-
-WRITE_LINE_MEMBER( amiga_state::rs232_cts_w )
-{
- m_rs232_cts = state;
-}