summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/archimds.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/archimds.cpp')
-rw-r--r--src/mame/machine/archimds.cpp1017
1 files changed, 0 insertions, 1017 deletions
diff --git a/src/mame/machine/archimds.cpp b/src/mame/machine/archimds.cpp
deleted file mode 100644
index d940cb4a11c..00000000000
--- a/src/mame/machine/archimds.cpp
+++ /dev/null
@@ -1,1017 +0,0 @@
-// license:LGPL-2.1+
-// copyright-holders:Angelo Salese, R. Belmont, Juergen Buchmueller
-/******************************************************************************
- *
- * Acorn Archimedes custom chips (IOC, MEMC, VIDC)
- *
- * Memory map (from http://b-em.bbcmicro.com/arculator/archdocs.txt)
- *
- * 0000000 - 1FFFFFF - logical RAM (32 meg)
- * 2000000 - 2FFFFFF - physical RAM (supervisor only - max 16MB - requires quad MEMCs)
- * 3000000 - 33FFFFF - IOC (IO controllers - supervisor only)
- * 3310000 - FDC - WD1772
- * 33A0000 - Econet - 6854
- * 33B0000 - Serial - 6551
- * 3240000 - 33FFFFF - internal expansion cards
- * 32D0000 - hard disc controller (not IDE) - HD63463
- * 3350010 - printer
- * 3350018 - latch A
- * 3350040 - latch B
- * 3270000 - external expansion cards
- *
- * 3400000 - 3FFFFFF - ROM (read - 12 meg - Arthur and RiscOS 2 512k, RiscOS 3 2MB)
- * 3400000 - 37FFFFF - Low ROM (4 meg, I think this is expansion ROMs)
- * 3800000 - 3FFFFFF - High ROM (main OS ROM)
- *
- * 3400000 - 35FFFFF - VICD10 (write - supervisor only)
- * 3600000 - 3FFFFFF - MEMC (write - supervisor only)
- *
- *****************************************************************************/
-
-#include "emu.h"
-#include "includes/archimds.h"
-#include "cpu/arm/arm.h"
-#include "debugger.h"
-
-static const int page_sizes[4] = { 4096, 8192, 16384, 32768 };
-
-#define IOC_LOG 0
-#define CRTC_LOG 0
-
-/* TODO: fix pending irqs */
-void archimedes_state::archimedes_request_irq_a(int mask)
-{
- m_ioc_regs[IRQ_STATUS_A] |= mask;
-
- if ((m_ioc_regs[IRQ_STATUS_A] & m_ioc_regs[IRQ_MASK_A]) || (m_ioc_regs[IRQ_STATUS_B] & m_ioc_regs[IRQ_MASK_B]))
- m_maincpu->set_input_line(ARM_IRQ_LINE, ASSERT_LINE);
- else
- m_maincpu->set_input_line(ARM_IRQ_LINE, CLEAR_LINE);
-}
-
-void archimedes_state::archimedes_request_irq_b(int mask)
-{
- m_ioc_regs[IRQ_STATUS_B] |= mask;
-
- if ((m_ioc_regs[IRQ_STATUS_A] & m_ioc_regs[IRQ_MASK_A]) || (m_ioc_regs[IRQ_STATUS_B] & m_ioc_regs[IRQ_MASK_B]))
- m_maincpu->set_input_line(ARM_IRQ_LINE, ASSERT_LINE);
- else
- m_maincpu->set_input_line(ARM_IRQ_LINE, CLEAR_LINE);
-}
-
-void archimedes_state::archimedes_request_fiq(int mask)
-{
- m_ioc_regs[FIQ_STATUS] |= mask;
-
- //printf("STATUS:%02x IRQ:%02x MASK:%02x\n",m_ioc_regs[FIQ_STATUS],mask,m_ioc_regs[FIQ_MASK]);
-
- if (m_ioc_regs[FIQ_STATUS] & m_ioc_regs[FIQ_MASK])
- {
- m_maincpu->pulse_input_line(ARM_FIRQ_LINE, m_maincpu->minimum_quantum_time());
-
- //m_maincpu->set_input_line(ARM_FIRQ_LINE, CLEAR_LINE);
- //m_maincpu->set_input_line(ARM_FIRQ_LINE, ASSERT_LINE);
- }
-}
-
-void archimedes_state::archimedes_clear_irq_a(int mask)
-{
- m_ioc_regs[IRQ_STATUS_A] &= ~mask;
- archimedes_request_irq_a(0);
-}
-
-void archimedes_state::archimedes_clear_irq_b(int mask)
-{
- m_ioc_regs[IRQ_STATUS_B] &= ~mask;
- archimedes_request_irq_b(0);
-}
-
-void archimedes_state::archimedes_clear_fiq(int mask)
-{
- m_ioc_regs[FIQ_STATUS] &= ~mask;
- //archimedes_request_fiq(0);
-}
-
-void archimedes_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_IOC: ioc_timer(param); break;
- }
-}
-
-
-WRITE_LINE_MEMBER( archimedes_state::vblank_irq )
-{
- if (state)
- {
- archimedes_request_irq_a(ARCHIMEDES_IRQA_VBL);
- if (m_video_dma_on)
- vidc_video_tick();
- }
-}
-
-WRITE_LINE_MEMBER( archimedes_state::sound_drq )
-{
- if (state)
- vidc_audio_tick();
-}
-
-
-/* video DMA */
-// TODO: what type of DMA this is, burst or cycle steal? Docs doesn't explain it (4 usec is the DRAM refresh). */
-// TODO: Erotictac and Poizone sets up vidinit register AFTER vidend, for double buffering? (fixes Poizone "Eterna" logo display on attract)
-// TODO: understand how to make quazer to work (sets video DMA param in-flight)
-void archimedes_state::vidc_video_tick()
-{
- address_space &space = m_maincpu->space(AS_PROGRAM);
- uint32_t size;
- uint32_t offset_ptr;
-
- size = (m_vidc_vidend - m_vidc_vidstart + 0x10) & 0x1fffff;
-
- offset_ptr = m_vidc_vidinit;
- if(offset_ptr >= m_vidc_vidend+0x10) // TODO: correct?
- offset_ptr = m_vidc_vidstart;
-
- //popmessage("%08x %08x %08x",m_vidc_vidstart,m_vidc_vidinit,m_vidc_vidend);
-
- for(m_vidc_vidcur = 0;m_vidc_vidcur < size;m_vidc_vidcur++)
- {
- m_vidc->write_vram(m_vidc_vidcur, space.read_byte(offset_ptr));
- offset_ptr++;
- if(offset_ptr >= m_vidc_vidend+0x10) // TODO: correct?
- offset_ptr = m_vidc_vidstart;
- }
-
- if(m_cursor_enabled == true)
- {
- uint32_t ccur_size = m_vidc->get_cursor_size();
-
- for(uint32_t ccur = 0; ccur < ccur_size; ccur++)
- m_vidc->write_cram(ccur, space.read_byte(m_vidc_cinit+ccur));
- }
-}
-
-/* audio DMA */
-void archimedes_state::vidc_audio_tick()
-{
- address_space &space = m_maincpu->space(AS_PROGRAM);
- uint8_t ch;
-
- for(ch=0; ch<8; ch++)
- m_vidc->write_dac(ch, (space.read_byte(m_vidc_sndcur + ch)));
-
- m_vidc_sndcur+=8;
-
- if (m_vidc_sndcur >= m_vidc_sndendcur)
- {
- archimedes_request_irq_b(ARCHIMEDES_IRQB_SOUND_EMPTY);
-
- // TODO: nuke this implementation detail, repeated below
- m_vidc->update_sound_mode(m_audio_dma_on);
- if(!m_audio_dma_on)
- {
- for(ch=0; ch<8; ch++)
- m_vidc->clear_dac(ch);
- }
- else
- {
- //printf("Chaining to next: start %x end %x\n", m_vidc_sndstart, m_vidc_sndend);
- m_vidc_sndcur = m_vidc_sndstart;
- m_vidc_sndendcur = m_vidc_sndend;
- }
- }
-}
-
-void archimedes_state::a310_set_timer(int tmr)
-{
- double freq;
-
- switch(tmr)
- {
- case 0:
- case 1:
- m_timer[tmr]->adjust(attotime::from_usec(m_ioc_timercnt[tmr]/2), tmr); // TODO: ARM timings are quite off there, it should be latch and not latch/2
- break;
- case 2:
- freq = 1000000.0 / (double)(m_ioc_timercnt[tmr]+1);
- m_timer[tmr]->adjust(attotime::from_hz(freq), tmr);
- break;
- case 3:
- freq = 1000000.0 / (double)((m_ioc_timercnt[tmr]+1)*16);
- m_timer[tmr]->adjust(attotime::from_hz(freq), tmr);
- break;
- }
-}
-
-// param
-void archimedes_state::ioc_timer(int param)
-{
- // all timers always run
- a310_set_timer(param);
-
- // keep FIQ line ASSERTED if there are active requests
- if (m_ioc_regs[FIQ_STATUS] & m_ioc_regs[FIQ_MASK])
- archimedes_request_fiq(0);
-
- // but only timers 0 and 1 generate IRQs
- switch (param)
- {
- case 0:
- archimedes_request_irq_a(ARCHIMEDES_IRQA_TIMER0);
- break;
-
- case 1:
- archimedes_request_irq_a(ARCHIMEDES_IRQA_TIMER1);
- break;
- }
-}
-
-void archimedes_state::archimedes_reset()
-{
- int i;
-
- m_memc_latchrom = 1; // map in the boot ROM
-
- // kill all memc mappings
- for (i = 0; i < (32*1024*1024)/(4096); i++)
- {
- m_memc_pages[i] = -1; // indicate unmapped
- }
-
- m_ioc_regs[IRQ_STATUS_A] = 0x10 | 0x80; //set up POR (Power On Reset) and Force IRQ at start-up
- m_ioc_regs[IRQ_STATUS_B] = 0x00; //set up IL[1] On
- m_ioc_regs[FIQ_STATUS] = 0x80; //set up Force FIQ
- m_ioc_regs[CONTROL] = 0xff;
-}
-
-void archimedes_state::archimedes_init()
-{
- m_memc_pagesize = 0;
-
- m_timer[0] = timer_alloc(TIMER_IOC);
- m_timer[1] = timer_alloc(TIMER_IOC);
- m_timer[2] = timer_alloc(TIMER_IOC);
- m_timer[3] = timer_alloc(TIMER_IOC);
- m_timer[0]->adjust(attotime::never);
- m_timer[1]->adjust(attotime::never);
- m_timer[2]->adjust(attotime::never);
- m_timer[3]->adjust(attotime::never);
-}
-
-uint32_t archimedes_state::archimedes_memc_logical_r(offs_t offset)
-{
- uint32_t page, poffs;
-
- // are we mapping in the boot ROM?
- if (m_memc_latchrom)
- {
- uint32_t *rom;
-
- rom = (uint32_t *)m_region_maincpu->base();
-
- return rom[offset & 0x1fffff];
- }
- else
- {
- // figure out the page number and offset in the page
- page = (offset<<2) / page_sizes[m_memc_pagesize];
- poffs = (offset<<2) % page_sizes[m_memc_pagesize];
-
-// printf("Reading offset %x (addr %x): page %x (size %d %d) offset %x ==> %x %x\n", offset, offset<<2, page, memc_pagesize, page_sizes[memc_pagesize], poffs, memc_pages[page], memc_pages[page]*page_sizes[memc_pagesize]);
-
- if (m_memc_pages[page] != -1)
- {
- return m_archimedes_memc_physmem[((m_memc_pages[page] * page_sizes[m_memc_pagesize]) + poffs)>>2];
- }
- else
- {
- //printf("ARCHIMEDES_MEMC: Reading unmapped page %02x\n",page);
- return 0xdeadbeef;
- }
- }
-
- // never executed
- //return 0;
-}
-
-
-
-void archimedes_state::archimedes_memc_logical_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- uint32_t page, poffs;
-
- // if the boot ROM is mapped, ignore writes
- if (m_memc_latchrom)
- {
- return;
- }
- else
- {
- // figure out the page number and offset in the page
- page = (offset<<2) / page_sizes[m_memc_pagesize];
- poffs = (offset<<2) % page_sizes[m_memc_pagesize];
-
-// printf("Writing offset %x (addr %x): page %x (size %d %d) offset %x ==> %x %x\n", offset, offset<<2, page, memc_pagesize, page_sizes[memc_pagesize], poffs, memc_pages[page], memc_pages[page]*page_sizes[memc_pagesize]);
-
- if (m_memc_pages[page] != -1)
- {
- COMBINE_DATA(&m_archimedes_memc_physmem[((m_memc_pages[page] * page_sizes[m_memc_pagesize]) + poffs)>>2]);
- }
- else
- {
- //printf("ARCHIMEDES_MEMC: Writing unmapped page %02x, what do we do?\n",page);
- }
- }
-}
-
-/* Aristocrat Mark 5 - same as normal AA except with Dram emulator */
-uint32_t archimedes_state::aristmk5_drame_memc_logical_r(offs_t offset)
-{
- uint32_t page, poffs;
-
- // are we mapping in the boot ROM?
- if (m_memc_latchrom)
- {
- uint32_t *rom;
-
- rom = (uint32_t *)m_region_maincpu->base();
-
- return rom[offset & 0x1fffff];
- }
- else
- {
- // figure out the page number and offset in the page
- page = (offset<<2) / page_sizes[m_memc_pagesize];
- poffs = (offset<<2) % page_sizes[m_memc_pagesize];
-
-
-
- if (m_memc_pages[page] != -1)
- {
- /******************* DRAM Emulator - gal20v - Aristocrat Mark 5 ************************
- A Dynamic RAM emulator is provided which avoids the need to execute code
- in DRAM in those regulatory environments where it is not needed.
-
- When pin 5 of U36 ( gal20v ) is low, the pin 25 output is high and enables the
- logic buffer inputs and provides a fixed jmp address to a plurality
- of rom addresses ( 0xEAD0000A shown on logic buffer arrangement in schematics )
-
- In this state, DRAM memory space is disabled.
-
- ****************************************************************************************/
- if(!(m_memc_pages[page] & 0x10) && (offset <= 0x3ff))
- return 0xEAD0000A;
- return m_archimedes_memc_physmem[((m_memc_pages[page] * page_sizes[m_memc_pagesize]) + poffs)>>2];
- }
- else
- {
- //printf("ARCHIMEDES_MEMC: Reading unmapped page %02x\n",page);
- return 0xdeadbeef;
- }
- }
-
- // never executed
- //return 0;
-}
-
-void archimedes_state::archimedes_driver_init()
-{
- m_archimedes_memc_physmem = reinterpret_cast<uint32_t *>(memshare("physicalram")->ptr());
-// address_space &space = m_maincpu->space(AS_PROGRAM);
-// space.set_direct_update_handler(direct_update_delegate(&a310_setopbase, &machine));
-}
-
-static const char *const ioc_regnames[] =
-{
- "(rw) Control", // 0
- "(read) Keyboard receive (write) keyboard send", // 4
- "?",
- "?",
- "(read) IRQ status A", // 10
- "(read) IRQ request A (write) IRQ clear", // 14
- "(rw) IRQ mask A", // 18
- "?",
- "(read) IRQ status B", // 20
- "(read) IRQ request B", // 24
- "(rw) IRQ mask B", // 28
- "?",
- "(read) FIQ status", // 30
- "(read) FIQ request", // 34
- "(rw) FIQ mask", // 38
- "?",
- "(read) Timer 0 count low (write) Timer 0 latch low", // 40
- "(read) Timer 0 count high (write) Timer 0 latch high", // 44
- "(write) Timer 0 go command", // 48
- "(write) Timer 0 latch command", // 4c
- "(read) Timer 1 count low (write) Timer 1 latch low", // 50
- "(read) Timer 1 count high (write) Timer 1 latch high", // 54
- "(write) Timer 1 go command", // 58
- "(write) Timer 1 latch command", // 5c
- "(read) Timer 2 count low (write) Timer 2 latch low", // 60
- "(read) Timer 2 count high (write) Timer 2 latch high", // 64
- "(write) Timer 2 go command", // 68
- "(write) Timer 2 latch command", // 6c
- "(read) Timer 3 count low (write) Timer 3 latch low", // 70
- "(read) Timer 3 count high (write) Timer 3 latch high", // 74
- "(write) Timer 3 go command", // 78
- "(write) Timer 3 latch command" // 7c
-};
-
-void archimedes_state::latch_timer_cnt(int tmr)
-{
- double time = m_timer[tmr]->elapsed().as_double();
- time *= 2000000.0; // find out how many 2 MHz ticks have gone by
- m_ioc_timerout[tmr] = m_ioc_timercnt[tmr] - (uint32_t)time;
-}
-
-bool archimedes_state::check_floppy_ready()
-{
- floppy_image_device *floppy = nullptr;
-
- if(!m_fdc)
- return false;
-
- switch(m_floppy_select & 3)
- {
- case 0:
- floppy = m_floppy0->get_device(); break;
- case 1:
- floppy = m_floppy1->get_device(); break;
- }
-
- if(floppy)
- return !floppy->ready_r();
-
- return false;
-}
-
-/* TODO: should be a 8-bit handler */
-uint32_t archimedes_state::ioc_ctrl_r(offs_t offset)
-{
- if(IOC_LOG)
- logerror("IOC: R %s = %02x (PC=%x) %02x\n", ioc_regnames[offset&0x1f], m_ioc_regs[offset&0x1f], m_maincpu->pc(),offset & 0x1f);
-
- switch (offset & 0x1f)
- {
- case CONTROL:
- {
- uint8_t i2c_data = 1;
- bool floppy_ready_state;
-
- if ( m_i2cmem )
- {
- i2c_data = (m_i2cmem->read_sda() & 1);
- }
-
- floppy_ready_state = check_floppy_ready();
-
- return (m_vidc->flyback_r()<<7) | (m_ioc_regs[CONTROL] & 0x78) | (floppy_ready_state<<2) | (m_i2c_clk<<1) | i2c_data;
- }
-
- case KART: // keyboard read
- return m_kart->read();
-
- case IRQ_STATUS_A:
- return (m_ioc_regs[IRQ_STATUS_A] & 0x7f) | 0x80; // Force IRQ is always '1'
-
- case IRQ_REQUEST_A:
- return (m_ioc_regs[IRQ_STATUS_A] & m_ioc_regs[IRQ_MASK_A]);
-
- case IRQ_MASK_A:
- return (m_ioc_regs[IRQ_MASK_A]);
-
- case IRQ_STATUS_B:
- return (m_ioc_regs[IRQ_STATUS_B]);
-
- case IRQ_REQUEST_B:
- return (m_ioc_regs[IRQ_STATUS_B] & m_ioc_regs[IRQ_MASK_B]);
-
- case IRQ_MASK_B:
- return (m_ioc_regs[IRQ_MASK_B]);
-
- case FIQ_STATUS:
- return (m_ioc_regs[FIQ_STATUS] & 0x7f) | 0x80; // Force FIQ is always '1'
-
- case FIQ_REQUEST:
- return (m_ioc_regs[FIQ_STATUS] & m_ioc_regs[FIQ_MASK]);
-
- case FIQ_MASK:
- return (m_ioc_regs[FIQ_MASK]);
-
- case T0_LATCH_LO: return m_ioc_timerout[0]&0xff;
- case T0_LATCH_HI: return (m_ioc_timerout[0]>>8)&0xff;
-
- case T1_LATCH_LO: return m_ioc_timerout[1]&0xff;
- case T1_LATCH_HI: return (m_ioc_timerout[1]>>8)&0xff;
-
- case T2_LATCH_LO: return m_ioc_timerout[2]&0xff;
- case T2_LATCH_HI: return (m_ioc_timerout[2]>>8)&0xff;
-
- case T3_LATCH_LO: return m_ioc_timerout[3]&0xff;
- case T3_LATCH_HI: return (m_ioc_timerout[3]>>8)&0xff;
- default:
- if(!IOC_LOG)
- logerror("IOC: R %s = %02x (PC=%x) %02x\n", ioc_regnames[offset&0x1f], m_ioc_regs[offset&0x1f], m_maincpu->pc(), offset & 0x1f);
- break;
- }
-
- return m_ioc_regs[offset&0x1f];
-}
-
-/* TODO: should be a 8-bit handler */
-void archimedes_state::ioc_ctrl_w(offs_t offset, uint32_t data)
-{
- if(IOC_LOG)
- logerror("IOC: W %02x @ reg %s (PC=%x)\n", data&0xff, ioc_regnames[offset&0x1f], m_maincpu->pc());
-
- switch (offset&0x1f)
- {
- case CONTROL: // I2C bus control
- //logerror("IOC I2C: CLK %d DAT %d\n", (data>>1)&1, data&1);
- if ( m_i2cmem )
- {
- m_i2cmem->write_sda(data & 0x01);
- m_i2cmem->write_scl((data & 0x02) >> 1);
- }
- m_i2c_clk = (data & 2) >> 1;
- //TODO: does writing bit 2 here causes a fdc force ready?
- /*
- -x-- ---- Printer ack
- --x- ---- Sound mute
- ---x ---- Aux I/O connector
- ---- -x-- Floppy ready
- ---- --x- I2C clock
- ---- ---x I2C data
- */
-
- //m_ioc_regs[CONTROL] = data & 0x38;
- //if(data & 0x40)
- // popmessage("Muting sound, contact MAME/MESSdev");
- break;
-
- case KART:
- m_kart->write(data);
- break;
-
- case IRQ_MASK_A:
- m_ioc_regs[IRQ_MASK_A] = data & 0xff;
-
- /* bit 7 forces an IRQ trap */
- archimedes_request_irq_a((data & 0x80) ? ARCHIMEDES_IRQA_FORCE : 0);
-
- //if(data & 0x08) //set up the VBLANK timer
- // m_vbl_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time));
-
- break;
-
- case IRQ_MASK_B:
- m_ioc_regs[IRQ_MASK_B] = data & 0xff;
-
- archimedes_request_irq_b(0);
- break;
-
- case FIQ_MASK:
- m_ioc_regs[FIQ_MASK] = data & 0xff;
-
- /* bit 7 forces a FIRQ trap */
- archimedes_request_fiq((data & 0x80) ? ARCHIMEDES_FIQ_FORCE : 0);
- break;
-
- case IRQ_REQUEST_A: // IRQ clear A
- m_ioc_regs[IRQ_STATUS_A] &= ~(data&0xff);
-
- // check pending irqs
- archimedes_request_irq_a(0);
- break;
-
- case T0_LATCH_LO:
- case T0_LATCH_HI:
- m_ioc_regs[offset&0x1f] = data & 0xff;
- break;
-
- case T1_LATCH_LO:
- case T1_LATCH_HI:
- m_ioc_regs[offset&0x1f] = data & 0xff;
- break;
-
- case T2_LATCH_LO:
- case T2_LATCH_HI:
- m_ioc_regs[offset&0x1f] = data & 0xff;
- break;
-
- case T3_LATCH_LO:
- case T3_LATCH_HI:
- m_ioc_regs[offset&0x1f] = data & 0xff;
- break;
-
- case T0_LATCH: // Timer 0 latch
- latch_timer_cnt(0);
- break;
-
- case T1_LATCH: // Timer 1 latch
- latch_timer_cnt(1);
- break;
-
- case T2_LATCH: // Timer 2 latch
- latch_timer_cnt(2);
- break;
-
- case T3_LATCH: // Timer 3 latch
- latch_timer_cnt(3);
- break;
-
- case T0_GO: // Timer 0 start
- m_ioc_timercnt[0] = m_ioc_regs[T0_LATCH_HI]<<8 | m_ioc_regs[T0_LATCH_LO];
- a310_set_timer(0);
- break;
-
- case T1_GO: // Timer 1 start
- m_ioc_timercnt[1] = m_ioc_regs[T1_LATCH_HI]<<8 | m_ioc_regs[T1_LATCH_LO];
- a310_set_timer(1);
- break;
-
- case T2_GO: // Timer 2 start
- m_ioc_timercnt[2] = m_ioc_regs[T2_LATCH_HI]<<8 | m_ioc_regs[T2_LATCH_LO];
- a310_set_timer(2);
- break;
-
- case T3_GO: // Timer 3 start
- m_ioc_timercnt[3] = m_ioc_regs[T3_LATCH_HI]<<8 | m_ioc_regs[T3_LATCH_LO];
- a310_set_timer(3);
- break;
-
- default:
- if(!IOC_LOG)
- logerror("IOC: W %02x @ reg %s (PC=%x)\n", data&0xff, ioc_regnames[offset&0x1f], m_maincpu->pc());
-
- m_ioc_regs[offset&0x1f] = data & 0xff;
- break;
- }
-}
-
-uint32_t archimedes_state::archimedes_ioc_r(offs_t offset, uint32_t mem_mask)
-{
- uint32_t ioc_addr;
-
- ioc_addr = offset*4;
-
- switch((ioc_addr & 0x300000) >> 20)
- {
- /*82c711*/
- case 0:
- logerror("82c711 read at address %08x\n",ioc_addr);
- return 0;
- case 2:
- case 3:
- {
- switch((ioc_addr & 0x70000) >> 16)
- {
- case 0: return ioc_ctrl_r(offset);
- case 1:
- if (m_fdc)
- {
- //printf("17XX: R @ addr %x mask %08x\n", offset*4, mem_mask);
- return m_fdc->read((ioc_addr >> 2) & 0x03);
- } else {
- logerror("Read from FDC device?\n");
- return 0;
- }
- case 2:
- // RTFM joystick interface routes here
- // TODO: slot interface for econet (reads registers 0 and 1 during boot)
- switch(ioc_addr)
- {
- case 0x3a0000:
- return 0xed; // ID for econet
- case 0x3a0004:
- return m_joy[0].read_safe(0xff);
- case 0x3a0008:
- // Top Banana reads there and do various checks,
- // disallowing player 1 joy use if they fails (?)
- return m_joy[1].read_safe(0xff);
- }
-
- logerror("IOC: Econet Read %08x at PC=%08x\n",ioc_addr, m_maincpu->pc());
- return 0xffff;
- case 3:
- logerror("IOC: Serial Read\n");
- return 0xffff;
- case 4:
- logerror("IOC: Internal Podule Read\n");
- return 0xffff;
- case 5:
- if (m_fdc)
- {
- // TODO: IOEB slot interface
- switch(ioc_addr & 0xfffc)
- {
- case 0x18: return 0xff; // FDC latch B
- case 0x40: return 0xff; // FDC latch A
- case 0x50: return 0; //fdc type, an 82c711 returns 5 here
- case 0x70: return 0x0f; // monitor type, TBD
- case 0x74: return 0xff; // unknown
- case 0x78: // serial joystick?
- case 0x7c:
- logerror("FDC: reading Joystick port %04x at PC=%08x\n",ioc_addr, m_maincpu->pc());
- return 0xff;
-
- }
- }
-
- //printf("IOC: Internal Latches Read %08x\n",ioc_addr);
-
- return 0xffff;
- }
- }
- }
-
- logerror("IOC: Unknown read at %08x\n",ioc_addr);
-
- return 0;
-}
-
-void archimedes_state::archimedes_ioc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- uint32_t ioc_addr;
-
- ioc_addr = offset*4;
-
- switch((ioc_addr & 0x300000) >> 20)
- {
- /*82c711*/
- case 0:
- logerror("82c711 write %08x to address %08x\n",data,ioc_addr);
- return;
- case 2:
- case 3:
- {
- switch((ioc_addr & 0x70000) >> 16)
- {
- case 0: ioc_ctrl_w(offset,data); return;
- case 1:
- if (m_fdc)
- {
- //printf("17XX: %x to addr %x mask %08x\n", data, offset*4, mem_mask);
- m_fdc->write((ioc_addr >> 2) & 0x03, data);
- return;
- }
- else
- {
- logerror("Write to FDC device?\n");
- }
- return;
- case 2:
- logerror("IOC: Econet Write %02x at %08x\n",data,ioc_addr);
- return;
- case 3:
- logerror("IOC: Serial Write %02x (%c) at %08x\n",data,data,ioc_addr);
- return;
- case 4:
- logerror("IOC: Internal Podule Write\n");
- return;
- case 5:
- if (m_fdc)
- {
- switch(ioc_addr & 0xfffc)
- {
- // serial joy port (!JS application)
- case 0x10:
- {
- // compared to RTFM they reversed bits 0-3 (or viceversa, dunno what came out first)
- // for pragmatic convenience we bitswap here, but this should really be a slot option at some point.
- // TODO: understand how player 2 inputs routes, related somehow to CONTROL bit 6 (cfr. blitz in SW list)
- // TODO: paradr2k polls here with bit 7 and fails detection (Vertical Twist)
- uint8_t cur_joy_in = bitswap<8>(m_joy[0].read_safe(0xff),7,6,5,4,0,1,2,3);
-
- m_joy_serial_data = (data & 0xff) ^ 0xff;
- bool serial_on = false;
-
- if (m_joy_serial_data == 0x20)
- serial_on = true;
- else if (m_joy_serial_data & cur_joy_in)
- serial_on = true;
-
-
- // wants printer irq for some reason (connected on parallel?)
- if (serial_on == true)
- {
- archimedes_request_irq_a(ARCHIMEDES_IRQA_PRINTER_BUSY);
- //m_ioc_regs[CONTROL] |= 0x40;
- }
- else
- {
- archimedes_clear_irq_a(ARCHIMEDES_IRQA_PRINTER_BUSY);
- //m_ioc_regs[CONTROL] &= ~0x40;
- }
-
- return;
- }
- case 0x18: // latch B
- /*
- ---- x--- floppy controller reset
- ---x ---- printer strobe
- */
- m_fdc->dden_w(BIT(data, 1));
- m_fdc->mr_w(BIT(data, 3));
- if(data & ~0xa)
- printf("%02x Latch B\n",data);
- return;
-
- case 0x40: // latch A
- /*
- -x-- ---- In Use Control (floppy?)
- */
- floppy_image_device *floppy = nullptr;
-
- if (!(data & 1)) { m_floppy_select = 0; floppy = m_floppy0->get_device(); }
- if (!(data & 2)) { m_floppy_select = 1; floppy = m_floppy1->get_device(); }
- if (!(data & 4)) { m_floppy_select = 2; floppy = nullptr; } // floppy 2
- if (!(data & 8)) { m_floppy_select = 3; floppy = nullptr; } // floppy 3
-
- m_fdc->set_floppy(floppy);
-
- if(floppy)
- {
- floppy->mon_w(BIT(data, 5));
- floppy->ss_w(!(BIT(data, 4)));
- }
- //bit 5 is motor on
- return;
- }
-
- //printf("%08x\n",ioc_addr);
- }
- break;
- }
- }
- }
-
-
- logerror("(PC=%08x) I/O: W %x @ %x (mask %08x)\n", m_maincpu->pc(), data, (offset*4)+0x3000000, mem_mask);
-}
-
-void archimedes_state::archimedes_memc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- // is it a register?
- if ((data & 0x0fe00000) == 0x03600000)
- {
- switch ((data >> 17) & 7)
- {
- case 0: /* video init */
- m_vidc_vidinit = 0x2000000 | ((data>>2)&0x7fff)*16;
- //printf("MEMC: VIDINIT %08x\n",m_vidc_vidinit);
- break;
-
- case 1: /* video start */
- m_vidc_vidstart = 0x2000000 | (((data>>2)&0x7fff)*16);
- //printf("MEMC: VIDSTART %08x\n",m_vidc_vidstart);
- break;
-
- case 2: /* video end */
- m_vidc_vidend = 0x2000000 | (((data>>2)&0x7fff)*16);
- //printf("MEMC: VIDEND %08x\n",m_vidc_vidend);
- break;
-
- case 3: /* cursor init */
- m_cursor_enabled = true;
- m_vidc->set_cursor_enable(m_cursor_enabled);
- m_vidc_cinit = 0x2000000 | (((data>>2)&0x7fff)*16);
- //printf("MEMC: CURSOR INIT %08x\n",((data>>2)&0x7fff)*16);
- break;
-
- case 4: /* sound start */
- archimedes_clear_irq_b(ARCHIMEDES_IRQB_SOUND_EMPTY);
- m_vidc_sndstart = 0x2000000 | ((data>>2)&0x7fff)*16;
- //printf("MEMC: SNDSTART %08x\n",m_vidc_sndstart);
- break;
-
- case 5: /* sound end */
- // end buffer is actually +16 bytes wrt sound start
- // TODO: it actually don't apply for ertictac and poizone?
- m_vidc_sndend = 0x2000000 | (((data>>2)+1)&0x7fff)*16;
- //printf("MEMC: SNDEND %08x\n",m_vidc_sndend);
- break;
-
- case 6:
- //printf("MEMC: SNDPTR\n");
- m_vidc_sndcur = m_vidc_sndstart;
- m_vidc_sndendcur = m_vidc_sndend;
- archimedes_request_irq_b(ARCHIMEDES_IRQB_SOUND_EMPTY);
- break;
-
- case 7: /* Control */
- m_memc_pagesize = ((data>>2) & 3);
-
- logerror("(PC = %08x) MEMC: %x to Control (page size %d, %s, %s)\n", m_maincpu->pc(), data & 0x1ffc, page_sizes[m_memc_pagesize], ((data>>10)&1) ? "Video DMA on" : "Video DMA off", ((data>>11)&1) ? "Sound DMA on" : "Sound DMA off");
-
- m_video_dma_on = BIT(data, 10);
- m_audio_dma_on = BIT(data, 11);
-
- if (m_video_dma_on)
- {
- m_vidc_vidcur = 0;
- // TODO: update internally
- }
- else
- {
- m_cursor_enabled = false;
- m_vidc->set_cursor_enable(m_cursor_enabled);
- }
-
- m_vidc->update_sound_mode(m_audio_dma_on);
- if (m_audio_dma_on)
- {
- //printf("MEMC: Starting audio DMA at %d uSec, buffer from %x to %x\n", ((m_vidc_regs[0xc0]&0xff)-2)*8, m_vidc_sndstart, m_vidc_sndend);
-
- //printf("MEMC: audio DMA start, sound freq %d, sndhz = %f\n", (m_vidc_regs[0xc0] & 0xff)-2, sndhz);
-
- m_vidc_sndcur = m_vidc_sndstart;
- m_vidc_sndendcur = m_vidc_sndend;
- }
-
- break;
-
- default:
- logerror("MEMC: %x to Unk reg %d\n", data&0x1ffff, (data >> 17) & 7);
- break;
- }
- }
- else
- {
- logerror("MEMC non-reg: W %x @ %x (mask %08x)\n", data, offset, mem_mask);
- }
-}
-
-/*
- 22 2222 1111 1111 1100 0000 0000
- 54 3210 9876 5432 1098 7654 3210
-4k page: 11 1LLL LLLL LLLL LLAA MPPP PPPP
-8k page: 11 1LLL LLLL LLLM LLAA MPPP PPPP
-16k page: 11 1LLL LLLL LLxM LLAA MPPP PPPP
-32k page: 11 1LLL LLLL LxxM LLAA MPPP PPPP
- 3 8 2 9 0 f f
-
-L - logical page
-P - physical page
-A - access permissions
-M - MEMC number (for machines with multiple MEMCs)
-
-The logical page is encoded with bits 11+10 being the most significant bits
-(in that order), and the rest being bit 22 down.
-
-The physical page is encoded differently depending on the page size :
-
-4k page: bits 6-0 being bits 6-0
-8k page: bits 6-1 being bits 5-0, bit 0 being bit 6
-16k page: bits 6-2 being bits 4-0, bits 1-0 being bits 6-5
-32k page: bits 6-3 being bits 4-0, bit 0 being bit 4, bit 2 being bit 5, bit
- 1 being bit 6
-*/
-
-void archimedes_state::archimedes_memc_page_w(uint32_t data)
-{
- uint32_t log, phys, memc;
-
-// perms = (data & 0x300)>>8;
- log = phys = memc = 0;
-
- switch (m_memc_pagesize)
- {
- case 0:
- phys = data & 0x7f;
- log = ((data & 0x7ff000)>>12) | ((data & 0xc00)<<1);
- memc = (data & 0x80) ? 1 : 0;
- break;
-
- case 1:
- phys = ((data & 0x7f) >> 1) | ((data & 1) << 6);
- log = ((data & 0x7fe000)>>13) | (data & 0xc00);
- memc = ((data & 0x80) ? 1 : 0) | ((data & 0x1000) ? 2 : 0);
- break;
-
- case 2:
- phys = ((data & 0x7f) >> 2) | ((data & 3) << 5);
- log = ((data & 0x7fc000)>>14) | ((data & 0xc00)>>1);
- memc = ((data & 0x80) ? 1 : 0) | ((data & 0x1000) ? 2 : 0);
- break;
-
- case 3:
- phys = ((data & 0x7f) >> 3) | ((data & 1)<<4) | ((data & 2) << 5) | ((data & 4)<<3);
- log = ((data & 0x7f8000)>>15) | ((data & 0xc00)>>2);
- memc = ((data & 0x80) ? 1 : 0) | ((data & 0x1000) ? 2 : 0);
- //printf("Mapping %08X to %08X\n",0x2000000+(phys*32768),(((data >> 15)&0xff)|((data >> 2)&0x300)));
- break;
- }
-
-// log >>= (12 + memc_pagesize);
-
- // always make sure ROM mode is disconnected when this occurs
- m_memc_latchrom = 0;
-
- // now go ahead and set the mapping in the page table
- m_memc_pages[log] = phys + (memc*0x80);
-
-// printf("PC=%08x = MEMC_PAGE(%d): W %08x: log %x to phys %x, MEMC %d, perms %d\n", m_maincpu->pc(),memc_pagesize, data, log, phys, memc, perms);
-}