diff options
Diffstat (limited to 'src/mess/drivers/a7000.c')
-rw-r--r-- | src/mess/drivers/a7000.c | 836 |
1 files changed, 836 insertions, 0 deletions
diff --git a/src/mess/drivers/a7000.c b/src/mess/drivers/a7000.c new file mode 100644 index 00000000000..63b52c3879a --- /dev/null +++ b/src/mess/drivers/a7000.c @@ -0,0 +1,836 @@ +/*************************************************************************** + + Acorn Archimedes 7000/7000+ + + preliminary driver by Angelo Salese, + based on work by Tomasz Slanina and Tom Walker + + ??? + bp (0382827C) (second trigger) + do R13 = SR13 + +****************************************************************************/ + +#include "emu.h" +#include "cpu/arm7/arm7.h" +#include "cpu/arm7/arm7core.h" + +#define MACHINE_RESET_MEMBER(name) void name::machine_reset() +#define MACHINE_START_MEMBER(name) void name::machine_start() + +class a7000_state : public driver_device +{ +public: + a7000_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu") + { } + + required_device<cpu_device> m_maincpu; + DECLARE_READ32_MEMBER(a7000_iomd_r); + DECLARE_WRITE32_MEMBER(a7000_iomd_w); + DECLARE_WRITE32_MEMBER(a7000_vidc20_w); + + UINT8 m_vidc20_pal_index; + UINT16 m_vidc20_horz_reg[0x10]; + UINT16 m_vidc20_vert_reg[0x10]; + UINT8 m_vidc20_bpp_mode; + emu_timer *m_flyback_timer; + UINT16 m_timer_in[2]; + UINT16 m_timer_out[2]; + int m_timer_counter[2]; + emu_timer *m_IOMD_timer[2]; + UINT8 m_IRQ_status_A; + UINT8 m_IRQ_mask_A; + UINT8 m_IOMD_IO_ctrl; + UINT8 m_IOMD_keyb_ctrl; + UINT16 m_io_id; + UINT8 m_viddma_status; + UINT32 m_viddma_addr_start; + UINT32 m_viddma_addr_end; + UINT8 m_t0readinc; + UINT8 m_t1readinc; + void fire_iomd_timer(int timer); + void viddma_transfer_start(); + void vidc20_dynamic_screen_change(); + virtual void machine_reset(); + virtual void machine_start(); + + UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); +}; + + +/* + * + * VIDC20 chip emulation + * + */ + + +static const char *const vidc20_regnames[] = +{ + "Video Palette", // 0 + "Video Palette Address", // 1 + "RESERVED", // 2 + "LCD offset", // 3 + "Border Colour", // 4 + "Cursor Palette Logical Colour 1", // 5 + "Cursor Palette Logical Colour 2", // 6 + "Cursor Palette Logical Colour 3", // 7 + "Horizontal", // 8 + "Vertical", // 9 + "Stereo Image", // A + "Sound", // B + "External", // C + "Frequency Synthesis", // D + "Control", // E + "Data Control" // F +}; + +static const char *const vidc20_horz_regnames[] = +{ + "Horizontal Cycle", // 0x80 HCR + "Horizontal Sync Width", // 0x81 HSWR + "Horizontal Border Start", // 0x82 HBSR + "Horizontal Display Start", // 0x83 HDSR + "Horizontal Display End", // 0x84 HDER + "Horizontal Border End", // 0x85 HBER + "Horizontal Cursor Start", // 0x86 HCSR + "Horizontal Interlace", // 0x87 HIR + "Horizontal Counter TEST", // 0x88 + "Horizontal <UNDEFINED>", // 0x89 + "Horizontal <UNDEFINED>", // 0x8a + "Horizontal <UNDEFINED>", // 0x8b + "Horizontal All TEST", // 0x8c + "Horizontal <UNDEFINED>", // 0x8d + "Horizontal <UNDEFINED>", // 0x8e + "Horizontal <UNDEFINED>" // 0x8f +}; + +#define HCR 0 +#define HSWR 1 +#define HBSR 2 +#define HDSR 3 +#define HDER 4 +#define HBER 5 +#define HCSR 6 +#define HIR 7 + +static const char *const vidc20_vert_regnames[] = +{ + "Vertical Cycle", // 0x90 VCR + "Vertical Sync Width", // 0x91 VSWR + "Vertical Border Start", // 0x92 VBSR + "Vertical Display Start", // 0x93 VDSR + "Vertical Display End", // 0x94 VDER + "Vertical Border End", // 0x95 VBER + "Vertical Cursor Start", // 0x96 VCSR + "Vertical Cursor End", // 0x97 VCER + "Vertical Counter TEST", // 0x98 + "Horizontal <UNDEFINED>", // 0x99 + "Vertical Counter Increment TEST", // 0x9a + "Horizontal <UNDEFINED>", // 0x9b + "Vertical All TEST", // 0x9c + "Horizontal <UNDEFINED>", // 0x9d + "Horizontal <UNDEFINED>", // 0x9e + "Horizontal <UNDEFINED>" // 0x9f +}; + +#define VCR 0 +#define VSWR 1 +#define VBSR 2 +#define VDSR 3 +#define VDER 4 +#define VBER 5 +#define VCSR 6 +#define VCER 7 + +void a7000_state::vidc20_dynamic_screen_change() +{ + /* sanity checks - first pass */ + /* + total cycles + border start/end + */ + if(m_vidc20_horz_reg[HCR] && m_vidc20_horz_reg[HBSR] && m_vidc20_horz_reg[HBER] && + m_vidc20_vert_reg[VCR] && m_vidc20_vert_reg[VBSR] && m_vidc20_vert_reg[VBER]) + { + /* sanity checks - second pass */ + /* + total cycles > border end > border start + */ + if((m_vidc20_horz_reg[HCR] > m_vidc20_horz_reg[HBER]) && + (m_vidc20_horz_reg[HBER] > m_vidc20_horz_reg[HBSR]) && + (m_vidc20_vert_reg[VCR] > m_vidc20_vert_reg[VBER]) && + (m_vidc20_vert_reg[VBER] > m_vidc20_vert_reg[VBSR])) + { + /* finally ready to change the resolution */ + int hblank_period,vblank_period; + rectangle visarea = machine().primary_screen->visible_area(); + hblank_period = (m_vidc20_horz_reg[HCR] & 0x3ffc); + vblank_period = (m_vidc20_vert_reg[VCR] & 0x3fff); + /* note that we use the border registers as the visible area */ + visarea.min_x = (m_vidc20_horz_reg[HBSR] & 0x3ffe); + visarea.max_x = (m_vidc20_horz_reg[HBER] & 0x3ffe)-1; + visarea.min_y = (m_vidc20_vert_reg[VBSR] & 0x1fff); + visarea.max_y = (m_vidc20_vert_reg[VBER] & 0x1fff)-1; + + machine().primary_screen->configure(hblank_period, vblank_period, visarea, machine().primary_screen->frame_period().attoseconds ); + logerror("VIDC20: successfully changed the screen to:\n Display Size = %d x %d\n Border Size %d x %d\n Cycle Period %d x %d\n", + (m_vidc20_horz_reg[HDER]-m_vidc20_horz_reg[HDSR]),(m_vidc20_vert_reg[VDER]-m_vidc20_vert_reg[VDSR]), + (m_vidc20_horz_reg[HBER]-m_vidc20_horz_reg[HBSR]),(m_vidc20_vert_reg[VBER]-m_vidc20_vert_reg[VBSR]), + hblank_period,vblank_period); + } + } +} + +WRITE32_MEMBER( a7000_state::a7000_vidc20_w ) +{ + int r,g,b,cursor_index,horz_reg,vert_reg,reg = data >> 28; + + switch(reg) + { + case 0: // Video Palette + r = (data & 0x0000ff) >> 0; + g = (data & 0x00ff00) >> 8; + b = (data & 0xff0000) >> 16; + + palette_set_color_rgb(machine(),m_vidc20_pal_index & 0xff,r,g,b); + + /* auto-increment & wrap-around */ + m_vidc20_pal_index++; + m_vidc20_pal_index &= 0xff; + break; + + case 1: // Video Palette Address + + // according to RPCEmu, these mustn't be set + if (data & 0x0fffff00) + return; + + m_vidc20_pal_index = data & 0xff; + break; + + case 4: // Border Color + r = (data & 0x0000ff) >> 0; + g = (data & 0x00ff00) >> 8; + b = (data & 0xff0000) >> 16; + + palette_set_color_rgb(machine(),0x100,r,g,b); + break; + case 5: // Cursor Palette Logical Colour n + case 6: + case 7: + cursor_index = 0x100 + reg - 4; // 0x101,0x102 and 0x103 (plus 0x100 of above, 2bpp) + + r = (data & 0x0000ff) >> 0; + g = (data & 0x00ff00) >> 8; + b = (data & 0xff0000) >> 16; + + palette_set_color_rgb(machine(),cursor_index,r,g,b); + break; + case 8: // Horizontal + horz_reg = (data >> 24) & 0xf; + m_vidc20_horz_reg[horz_reg] = data & 0x3fff; + if(horz_reg == 0 || horz_reg == 2 || horz_reg == 5) + vidc20_dynamic_screen_change(); + + // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_horz_regnames[horz_reg],val,val); + break; + case 9: // Vertical + vert_reg = (data >> 24) & 0xf; + m_vidc20_vert_reg[vert_reg] = data & 0x1fff; + if(vert_reg == 0 || vert_reg == 2 || vert_reg == 5) + vidc20_dynamic_screen_change(); + + if(vert_reg == 4) + { + if(m_vidc20_vert_reg[VDER] != 0) + m_flyback_timer->adjust(machine().primary_screen->time_until_pos(m_vidc20_vert_reg[VDER])); + else + m_flyback_timer->adjust(attotime::never); + } + + // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_vert_regnames[vert_reg],val,val); + + break; + case 0x0e: // Control + m_vidc20_bpp_mode = (data & 0xe0) >> 5; + break; + default: logerror("VIDC20: %s Register write = %08x\n",vidc20_regnames[reg],data & 0xfffffff); + } +} + +UINT32 a7000_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int x_size,y_size,x_start,y_start; + int x,y,xi; + UINT32 count; + UINT8 *vram = memregion("vram")->base(); + + bitmap.fill(machine().pens[0x100], cliprect); + + x_size = (m_vidc20_horz_reg[HDER]-m_vidc20_horz_reg[HDSR]); + y_size = (m_vidc20_vert_reg[VDER]-m_vidc20_vert_reg[VDSR]); + x_start = m_vidc20_horz_reg[HDSR]; + y_start = m_vidc20_vert_reg[VDSR]; + + /* check if display is enabled */ + if(x_size <= 0 || y_size <= 0) + return 0; + +// popmessage("%d",m_vidc20_bpp_mode); + + count = 0; + + switch(m_vidc20_bpp_mode) + { + case 0: /* 1 bpp */ + { + for(y=0;y<y_size;y++) + { + for(x=0;x<x_size;x+=8) + { + for(xi=0;xi<8;xi++) + bitmap.pix32(y+y_start, x+xi+x_start) = machine().pens[(vram[count]>>(xi))&1]; + + count++; + } + } + } + break; + case 1: /* 2 bpp */ + { + for(y=0;y<y_size;y++) + { + for(x=0;x<x_size;x+=4) + { + for(xi=0;xi<4;xi++) + bitmap.pix32(y+y_start, x+xi+x_start) = machine().pens[(vram[count]>>(xi*2))&3]; + + count++; + } + } + } + break; + case 2: /* 4 bpp */ + { + for(y=0;y<y_size;y++) + { + for(x=0;x<x_size;x+=2) + { + for(xi=0;xi<2;xi++) + bitmap.pix32(y+y_start, x+xi+x_start) = machine().pens[(vram[count]>>(xi*4))&0xf]; + + count++; + } + } + } + break; + case 3: /* 8 bpp */ + { + for(y=0;y<y_size;y++) + { + for(x=0;x<x_size;x++) + { + bitmap.pix32(y+y_start, x+x_start) = machine().pens[(vram[count])&0xff]; + + count++; + } + } + } + break; + case 4: /* 16 bpp */ + { + for(y=0;y<y_size;y++) + { + for(x=0;x<x_size;x++) + { + int r,g,b,pen; + + pen = ((vram[count]<<8)|(vram[count+1]))&0xffff; + r = (pen & 0x000f); + g = (pen & 0x00f0) >> 4; + b = (pen & 0x0f00) >> 8; + r = (r << 4) | (r & 0xf); + g = (g << 4) | (g & 0xf); + b = (b << 4) | (b & 0xf); + + bitmap.pix32(y+y_start, x+x_start) = b | g << 8 | r << 16; + + count+=2; + } + } + } + break; + case 6: /* 32 bpp */ + { + for(y=0;y<y_size;y++) + { + for(x=0;x<x_size;x++) + { + int r,g,b,pen; + + pen = ((vram[count]<<24)|(vram[count+1]<<16)|(vram[count+2]<<8)|(vram[count+3]<<0)); + r = (pen & 0x0000ff); + g = (pen & 0x00ff00) >> 8; + b = (pen & 0xff0000) >> 16; + + bitmap.pix32(y+y_start, x+x_start) = b | g << 8 | r << 16; + + count+=4; + } + } + } + break; + default: + //fatalerror("VIDC20 %08x BPP mode not supported\n",m_vidc20_bpp_mode); + break; + } + + return 0; +} + +/* +* +* IOMD / ARM7500 / ARM7500FE chip emulation +* +*/ + +/* TODO: some of these registers are actually ARM7500 specific */ +static const char *const iomd_regnames[] = +{ + "I/O Control", // 0x000 IOCR + "Keyboard Data", // 0x004 KBDDAT + "Keyboard Control", // 0x008 KBDCR + "General Purpose I/O Lines", // 0x00c IOLINES + "IRQA Status", // 0x010 IRQSTA + "IRQA Request/clear", // 0x014 IRQRQA + "IRQA Mask", // 0x018 IRQMSKA + "Enter SUSPEND Mode", // 0x01c SUSMODE + "IRQB Status", // 0x020 IRQSTB + "IRQB Request/clear", // 0x024 IRQRQB + "IRQB Mask", // 0x028 IRQMSKB + "Enter STOP Mode", // 0x02c STOPMODE + "FIQ Status", // 0x030 FIQST + "FIQ Request/clear", // 0x034 FIQRQ + "FIQ Mask", // 0x038 FIQMSK + "Clock divider control", // 0x03c CLKCTL + "Timer 0 Low Bits", // 0x040 T0LOW + "Timer 0 High Bits", // 0x044 T0HIGH + "Timer 0 Go Command", // 0x048 T0GO + "Timer 0 Latch Command", // 0x04c T0LATCH + "Timer 1 Low Bits", // 0x050 T1LOW + "Timer 1 High Bits", // 0x054 T1HIGH + "Timer 1 Go Command", // 0x058 T1GO + "Timer 1 Latch Command", // 0x05c T1LATCH + "IRQC Status", // 0x060 IRQSTC + "IRQC Request/clear", // 0x064 IRQRQC + "IRQC Mask", // 0x068 IRQMSKC + "LCD and IIS Control Bits", // 0x06c VIDIMUX + "IRQD Status", // 0x070 IRQSTD + "IRQD Request/clear", // 0x074 IRQRQD + "IRQD Mask", // 0x078 IRQMSKD + "<RESERVED>", // 0x07c + "ROM Control Bank 0", // 0x080 ROMCR0 + "ROM Control Bank 1", // 0x084 ROMCR1 + "DRAM Control (IOMD)", // 0x088 DRAMCR + "VRAM and Refresh Control", // 0x08c VREFCR + "Flyback Line Size", // 0x090 FSIZE + "Chip ID no. Low Byte", // 0x094 ID0 + "Chip ID no. High Byte", // 0x098 ID1 + "Chip Version Number", // 0x09c VERSION + "Mouse X Position", // 0x0a0 MOUSEX + "Mouse Y Position", // 0x0a4 MOUSEY + "Mouse Data", // 0x0a8 MSEDAT + "Mouse Control", // 0x0ac MSECR + "<RESERVED>", // 0x0b0 + "<RESERVED>", // 0x0b4 + "<RESERVED>", // 0x0b8 + "<RESERVED>", // 0x0bc + "DACK Timing Control", // 0x0c0 DMATCR + "I/O Timing Control", // 0x0c4 IOTCR + "Expansion Card Timing", // 0x0c8 ECTCR + "DMA External Control", // 0x0cc DMAEXT (IOMD) / ASTCR (ARM7500) + "DRAM Width Control", // 0x0d0 DRAMWID + "Force CAS/RAS Lines Low", // 0x0d4 SELFREF + "<RESERVED>", // 0x0d8 + "<RESERVED>", // 0x0dc + "A to D IRQ Control", // 0x0e0 ATODICR + "A to D IRQ Status", // 0x0e4 ATODCC + "A to D IRQ Converter Control", // 0x0e8 ATODICR + "A to D IRQ Counter 1", // 0x0ec ATODCNT1 + "A to D IRQ Counter 2", // 0x0f0 ATODCNT2 + "A to D IRQ Counter 3", // 0x0f4 ATODCNT3 + "A to D IRQ Counter 4", // 0x0f8 ATODCNT4 + "<RESERVED>", // 0x0fc + "I/O DMA 0 CurA", // 0x100 IO0CURA + "I/O DMA 0 EndA", // 0x104 IO0ENDA + "I/O DMA 0 CurB", // 0x108 IO0CURB + "I/O DMA 0 EndB", // 0x10c IO0ENDB + "I/O DMA 0 Control", // 0x110 IO0CR + "I/O DMA 0 Status", // 0x114 IO0ST + "<RESERVED>", // 0x118 + "<RESERVED>", // 0x11c + "I/O DMA 1 CurA", // 0x120 IO1CURA + "I/O DMA 1 EndA", // 0x124 IO1ENDA + "I/O DMA 1 CurB", // 0x128 IO1CURB + "I/O DMA 1 EndB", // 0x12c IO1ENDB + "I/O DMA 1 Control", // 0x130 IO1CR + "I/O DMA 1 Status", // 0x134 IO1ST + "<RESERVED>", // 0x138 + "<RESERVED>", // 0x13c + "I/O DMA 2 CurA", // 0x140 IO2CURA + "I/O DMA 2 EndA", // 0x144 IO2ENDA + "I/O DMA 2 CurB", // 0x148 IO2CURB + "I/O DMA 2 EndB", // 0x14c IO2ENDB + "I/O DMA 2 Control", // 0x150 IO2CR + "I/O DMA 2 Status", // 0x154 IO2ST + "<RESERVED>", // 0x158 + "<RESERVED>", // 0x15c + "I/O DMA 3 CurA", // 0x160 IO3CURA + "I/O DMA 3 EndA", // 0x164 IO3ENDA + "I/O DMA 3 CurB", // 0x168 IO3CURB + "I/O DMA 3 EndB", // 0x16c IO3ENDB + "I/O DMA 3 Control", // 0x170 IO3CR + "I/O DMA 3 Status", // 0x174 IO3ST + "<RESERVED>", // 0x178 + "<RESERVED>", // 0x17c + "Sound DMA 0 CurA", // 0x180 SD0CURA + "Sound DMA 0 EndA", // 0x184 SD0ENDA + "Sound DMA 0 CurB", // 0x188 SD0CURB + "Sound DMA 0 EndB", // 0x18c SD0ENDB + "Sound DMA 0 Control", // 0x190 SD0CR + "Sound DMA 0 Status", // 0x194 SD0ST + "<RESERVED>", // 0x198 + "<RESERVED>", // 0x19c + "Sound DMA 1 CurA", // 0x1a0 SD1CURA + "Sound DMA 1 EndA", // 0x1a4 SD1ENDA + "Sound DMA 1 CurB", // 0x1a8 SD1CURB + "Sound DMA 1 EndB", // 0x1ac SD1ENDB + "Sound DMA 1 Control", // 0x1b0 SD1CR + "Sound DMA 1 Status", // 0x1b4 SD1ST + "<RESERVED>", // 0x1b8 + "<RESERVED>", // 0x1bc + "Cursor DMA Current", // 0x1c0 CURSCUR + "Cursor DMA Init", // 0x1c4 CURSINIT + "Duplex LCD Current B", // 0x1c8 VIDCURB + "<RESERVED>", // 0x1cc + "Video DMA Current", // 0x1d0 VIDCUR + "Video DMA End", // 0x1d4 VIDEND + "Video DMA Start", // 0x1d8 VIDSTART + "Video DMA Init", // 0x1dc VIDINIT + "Video DMA Control", // 0x1e0 VIDCR + "<RESERVED>", // 0x1e4 + "Duplex LCD Init B", // 0x1e8 VIDINITB + "<RESERVED>", // 0x1ec + "DMA IRQ Status", // 0x1f0 DMAST + "DMA IRQ Request", // 0x1f4 DMARQ + "DMA IRQ Mask", // 0x1f8 DMAMSK + "<RESERVED>" // 0x1fc +}; + +#define IOMD_IOCR 0x000/4 +#define IOMD_KBDDAT 0x004/4 +#define IOMD_KBDCR 0x008/4 + +#define IOMD_IRQSTA 0x010/4 +#define IOMD_IRQRQA 0x014/4 +#define IOMD_IRQMSKA 0x018/4 + +#define IOMD_T0LOW 0x040/4 +#define IOMD_T0HIGH 0x044/4 +#define IOMD_T0GO 0x048/4 +#define IOMD_T0LATCH 0x04c/4 + +#define IOMD_T1LOW 0x050/4 +#define IOMD_T1HIGH 0x054/4 +#define IOMD_T1GO 0x058/4 +#define IOMD_T1LATCH 0x05c/4 + +#define IOMD_ID0 0x094/4 +#define IOMD_ID1 0x098/4 +#define IOMD_VERSION 0x09c/4 + +#define IOMD_VIDCUR 0x1d0/4 +#define IOMD_VIDEND 0x1d4/4 +#define IOMD_VIDSTART 0x1d8/4 +#define IOMD_VIDINIT 0x1dc/4 +#define IOMD_VIDCR 0x1e0/4 + + + +void a7000_state::fire_iomd_timer(int timer) +{ + int timer_count = m_timer_counter[timer]; + int val = timer_count / 2; // correct? + + if(val==0) + m_IOMD_timer[timer]->adjust(attotime::never); + else + m_IOMD_timer[timer]->adjust(attotime::from_usec(val), 0, attotime::from_usec(val)); +} + +static TIMER_CALLBACK( IOMD_timer0_callback ) +{ + a7000_state *state = machine.driver_data<a7000_state>(); + state->m_IRQ_status_A|=0x20; + if(state->m_IRQ_mask_A&0x20) + { + generic_pulse_irq_line(machine.device("maincpu"), ARM7_IRQ_LINE,1); + } +} + +static TIMER_CALLBACK( IOMD_timer1_callback ) +{ + a7000_state *state = machine.driver_data<a7000_state>(); + state->m_IRQ_status_A|=0x40; + if(state->m_IRQ_mask_A&0x40) + { + generic_pulse_irq_line(machine.device("maincpu"), ARM7_IRQ_LINE,1); + } +} + +static TIMER_CALLBACK( flyback_timer_callback ) +{ + a7000_state *state = machine.driver_data<a7000_state>(); + state->m_IRQ_status_A|=0x08; + if(state->m_IRQ_mask_A&0x08) + { + generic_pulse_irq_line(machine.device("maincpu"), ARM7_IRQ_LINE,1); + } + + state->m_flyback_timer->adjust(machine.primary_screen->time_until_pos(state->m_vidc20_vert_reg[VDER])); +} + +void a7000_state::viddma_transfer_start() +{ + address_space *mem = m_maincpu->memory().space(AS_PROGRAM); + UINT32 src = m_viddma_addr_start; + UINT32 dst = 0; + UINT32 size = m_viddma_addr_end; + UINT32 dma_index; + UINT8 *vram = memregion("vram")->base(); + + /* TODO: this should actually be a qword transfer */ + for(dma_index = 0;dma_index < size;dma_index++) + { + vram[dst] = mem->read_byte(src); + + src++; + dst++; + } +} + +READ32_MEMBER( a7000_state::a7000_iomd_r ) +{ +// if(offset != IOMD_KBDCR) +// logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); + + + switch(offset) + { + case IOMD_IOCR: + { + UINT8 flyback; + int vert_pos; + + vert_pos = machine().primary_screen->vpos(); + flyback = (vert_pos <= m_vidc20_vert_reg[VDSR] || vert_pos >= m_vidc20_vert_reg[VDER]) ? 0x80 : 0x00; + + return m_IOMD_IO_ctrl | 0x34 | flyback; + } + case IOMD_KBDCR: return m_IOMD_keyb_ctrl | 0x80; //IOMD Keyb status + + /* + 1--- ---- always high + -x-- ---- Timer 1 + --x- ---- Timer 0 + ---x ---- Power On Reset + ---- x--- Flyback + ---- -x-- nINT1 + ---- --0- always low + ---- ---x INT2 + */ + case IOMD_IRQSTA: return (m_IRQ_status_A & ~2) | 0x80; + case IOMD_IRQRQA: return (m_IRQ_status_A & m_IRQ_mask_A) | 0x80; + case IOMD_IRQMSKA: return m_IRQ_mask_A; + + case IOMD_T0LOW: return m_timer_out[0] & 0xff; + case IOMD_T0HIGH: return (m_timer_out[0] >> 8) & 0xff; + + case IOMD_T1LOW: return m_timer_out[1] & 0xff; + case IOMD_T1HIGH: return (m_timer_out[1] >> 8) & 0xff; + + case IOMD_ID0: return m_io_id & 0xff; // IOMD ID low + case IOMD_ID1: return (m_io_id >> 8) & 0xff; // IOMD ID high + case IOMD_VERSION: return 0; + + case IOMD_VIDEND: return m_viddma_addr_end & 0x00fffff8; //bits 31:24 undefined + case IOMD_VIDSTART: return m_viddma_addr_start & 0x1ffffff8; //bits 31, 30, 29 undefined + case IOMD_VIDCR: return (m_viddma_status & 0xa0) | 0x50; //bit 6 = DRAM mode, bit 4 = QWORD transfer + + default: logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); break; + } + + return 0; +} + +WRITE32_MEMBER( a7000_state::a7000_iomd_w ) +{ +// logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data); + + switch(offset) + { + case IOMD_IOCR: m_IOMD_IO_ctrl = data & ~0xf4; break; + + case IOMD_KBDCR: + m_IOMD_keyb_ctrl = data & ~0xf4; + //keyboard_ctrl_write(data & 0x08); + break; + + case IOMD_IRQRQA: m_IRQ_status_A &= ~data; break; + case IOMD_IRQMSKA: m_IRQ_mask_A = (data & ~2) | 0x80; break; + + case IOMD_T0LOW: m_timer_in[0] = (m_timer_in[0] & 0xff00) | (data & 0xff); break; + case IOMD_T0HIGH: m_timer_in[0] = (m_timer_in[0] & 0x00ff) | ((data & 0xff) << 8); break; + case IOMD_T0GO: + m_timer_counter[0] = m_timer_in[0]; + fire_iomd_timer(0); + break; + case IOMD_T0LATCH: + { + m_t0readinc^=1; + m_timer_out[0] = m_timer_counter[0]; + if(m_t0readinc) + { + m_timer_counter[0]--; + if(m_timer_counter[0] < 0) + m_timer_counter[0]+= m_timer_in[0]; + } + } + break; + + case IOMD_T1LOW: m_timer_in[1] = (m_timer_in[1] & 0xff00) | (data & 0xff); break; + case IOMD_T1HIGH: m_timer_in[1] = (m_timer_in[1] & 0x00ff) | ((data & 0xff) << 8); break; + case IOMD_T1GO: + m_timer_counter[1] = m_timer_in[1]; + fire_iomd_timer(1); + break; + case IOMD_T1LATCH: + { + m_t1readinc^=1; + m_timer_out[1] = m_timer_counter[1]; + if(m_t1readinc) + { + m_timer_counter[1]--; + if(m_timer_counter[1] < 0) + m_timer_counter[1]+= m_timer_in[1]; + } + } + break; + + case IOMD_VIDEND: m_viddma_addr_end = data & 0x00fffff8; //bits 31:24 unused + case IOMD_VIDSTART: m_viddma_addr_start = data & 0x1ffffff8; //bits 31, 30, 29 unused + case IOMD_VIDCR: + m_viddma_status = data & 0xa0; if(data & 0x20) { viddma_transfer_start(); } + break; + + + default: logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data); + } +} + +static ADDRESS_MAP_START( a7000_mem, AS_PROGRAM, 32, a7000_state) + AM_RANGE(0x00000000, 0x003fffff) AM_MIRROR(0x00800000) AM_ROM AM_REGION("user1", 0) +// AM_RANGE(0x01000000, 0x01ffffff) AM_NOP //expansion ROM +// AM_RANGE(0x02000000, 0x02ffffff) AM_RAM //VRAM +// I/O 03000000 - 033fffff +// AM_RANGE(0x03010000, 0x03011fff) //Super IO +// AM_RANGE(0x03012000, 0x03029fff) //FDC +// AM_RANGE(0x0302b000, 0x0302bfff) //Network podule +// AM_RANGE(0x03040000, 0x0304ffff) //podule space 0,1,2,3 +// AM_RANGE(0x03070000, 0x0307ffff) //podule space 4,5,6,7 + AM_RANGE(0x03200000, 0x032001ff) AM_READWRITE(a7000_iomd_r,a7000_iomd_w) //IOMD Registers //mirrored at 0x03000000-0x1ff? +// AM_RANGE(0x03310000, 0x03310003) //Mouse Buttons + + AM_RANGE(0x03400000, 0x037fffff) AM_WRITE(a7000_vidc20_w) +// AM_RANGE(0x08000000, 0x08ffffff) AM_MIRROR(0x07000000) //EASI space + AM_RANGE(0x10000000, 0x13ffffff) AM_RAM //SIMM 0 bank 0 + AM_RANGE(0x14000000, 0x17ffffff) AM_RAM //SIMM 0 bank 1 +// AM_RANGE(0x18000000, 0x18ffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 1 bank 0 +// AM_RANGE(0x1c000000, 0x1cffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 1 bank 1 +ADDRESS_MAP_END + + +/* Input ports */ +static INPUT_PORTS_START( a7000 ) +INPUT_PORTS_END + +MACHINE_START_MEMBER( a7000_state ) +{ + m_IOMD_timer[0] = machine().scheduler().timer_alloc(FUNC(IOMD_timer0_callback)); + m_IOMD_timer[1] = machine().scheduler().timer_alloc(FUNC(IOMD_timer1_callback)); + m_flyback_timer = machine().scheduler().timer_alloc(FUNC(flyback_timer_callback)); + + m_io_id = 0xd4e7; +} + +MACHINE_RESET_MEMBER( a7000_state ) +{ + m_IOMD_IO_ctrl = 0x0b | 0x34; //bit 0,1 and 3 set high on reset plus 2,4,5 always high +// m_IRQ_status_A = 0x10; // set POR bit ON + m_IRQ_mask_A = 0x00; + + m_IOMD_keyb_ctrl = 0x00; + + m_IOMD_timer[0]->adjust( attotime::never); + m_IOMD_timer[1]->adjust( attotime::never); + m_flyback_timer->adjust( attotime::never); +} + +static MACHINE_CONFIG_START( a7000, a7000_state ) + /* Basic machine hardware */ + MCFG_CPU_ADD( "maincpu", ARM7, XTAL_32MHz ) + MCFG_CPU_PROGRAM_MAP(a7000_mem) + + /* video hardware */ + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(60) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ + MCFG_SCREEN_SIZE(1900, 1080) //max available size + MCFG_SCREEN_VISIBLE_AREA(0, 1900-1, 0, 1080-1) + MCFG_SCREEN_UPDATE_DRIVER(a7000_state, screen_update) + MCFG_PALETTE_LENGTH(0x200) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( a7000p, a7000 ) + MCFG_CPU_MODIFY("maincpu") + MCFG_CPU_CLOCK(XTAL_48MHz) +MACHINE_CONFIG_END + +ROM_START(a7000) + ROM_REGION( 0x800000, "user1", ROMREGION_ERASEFF ) + ROM_LOAD( "rom1.bin", 0x000000, 0x100000, CRC(ff0e3d12) SHA1(fa489bebede3d13dc43cddec5b5c9b6829a28914) ) + ROM_LOAD( "rom2.bin", 0x100000, 0x100000, CRC(4ae4fd8b) SHA1(1b30d5905d5364dfa48bad69257b0ef8190e9bf6) ) + ROM_LOAD( "rom3.bin", 0x200000, 0x100000, CRC(3108fb2b) SHA1(865b01583f3fb5f4ed5e9201676db327cdeb40b3) ) + ROM_LOAD( "rom4.bin", 0x300000, 0x100000, CRC(55a51980) SHA1(a7191727edd5babf679ebbdea6585833a1fb34e6) ) + + ROM_REGION( 0x800000, "vram", ROMREGION_ERASE00 ) +ROM_END + +ROM_START(a7000p) + ROM_REGION( 0x800000, "user1", ROMREGION_ERASEFF ) + ROM_LOAD( "riscos-3.71.rom", 0x000000, 0x400000, CRC(211cf888) SHA1(c5fe0645e48894fb4b245abeefdc9a65d659af59)) + + ROM_REGION( 0x800000, "vram", ROMREGION_ERASE00 ) +ROM_END + +/*************************************************************************** + + Game driver(s) + +***************************************************************************/ + +/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ +COMP( 1995, a7000, 0, 0, a7000, a7000, driver_device, 0, "Acorn", "Archimedes A7000", GAME_NOT_WORKING | GAME_NO_SOUND ) +COMP( 1997, a7000p, a7000, 0, a7000p, a7000, driver_device, 0, "Acorn", "Archimedes A7000+", GAME_NOT_WORKING | GAME_NO_SOUND ) |