summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Scott Stone <tafoid@users.noreply.github.com>2011-10-09 23:09:13 +0000
committer Scott Stone <tafoid@users.noreply.github.com>2011-10-09 23:09:13 +0000
commit6d00689c35c7f0891857d413108d4ce1e5662e5f (patch)
tree31db75430b3cadd3322154a0f4a3fa9ebacc8748
parentf8aba531d3c7c43c01bdb32161b00f71f634d8ce (diff)
Preliminary hook up of sh3 dma from Haze + flash access code from Luca. (nw)
-rw-r--r--.gitattributes2
-rw-r--r--src/emu/cpu/cpu.mak12
-rw-r--r--src/emu/cpu/sh4/sh3comn.c41
-rw-r--r--src/emu/cpu/sh4/sh3comn.h20
-rw-r--r--src/emu/cpu/sh4/sh4.c9
-rw-r--r--src/emu/cpu/sh4/sh4comn.c629
-rw-r--r--src/emu/cpu/sh4/sh4comn.h23
-rw-r--r--src/emu/cpu/sh4/sh4dmac.c686
-rw-r--r--src/emu/cpu/sh4/sh4dmac.h63
-rw-r--r--src/emu/cpu/sh4/sh4regs.h57
-rw-r--r--src/mame/drivers/cavesh3.c359
11 files changed, 1226 insertions, 675 deletions
diff --git a/.gitattributes b/.gitattributes
index d64a8e3b918..467ee966547 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -451,6 +451,8 @@ src/emu/cpu/sh4/sh4.h svneol=native#text/plain
src/emu/cpu/sh4/sh4comn.c svneol=native#text/plain
src/emu/cpu/sh4/sh4comn.h svneol=native#text/plain
src/emu/cpu/sh4/sh4dasm.c svneol=native#text/plain
+src/emu/cpu/sh4/sh4dmac.c svneol=native#text/plain
+src/emu/cpu/sh4/sh4dmac.h svneol=native#text/plain
src/emu/cpu/sh4/sh4regs.h svneol=native#text/plain
src/emu/cpu/sh4/sh4tmu.c svneol=native#text/plain
src/emu/cpu/sh4/sh4tmu.h svneol=native#text/plain
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak
index 9b83197d3b5..31dc2a50210 100644
--- a/src/emu/cpu/cpu.mak
+++ b/src/emu/cpu/cpu.mak
@@ -532,7 +532,7 @@ $(CPUOBJ)/sh2/sh2fe.o: $(CPUSRC)/sh2/sh2fe.c \
ifneq ($(filter SH4,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/sh4
-CPUOBJS += $(CPUOBJ)/sh4/sh4.o $(CPUOBJ)/sh4/sh4comn.o $(CPUOBJ)/sh4/sh3comn.o $(CPUOBJ)/sh4/sh4tmu.o
+CPUOBJS += $(CPUOBJ)/sh4/sh4.o $(CPUOBJ)/sh4/sh4comn.o $(CPUOBJ)/sh4/sh3comn.o $(CPUOBJ)/sh4/sh4tmu.o $(CPUOBJ)/sh4/sh4dmac.o
DASMOBJS += $(CPUOBJ)/sh4/sh4dasm.o
endif
@@ -560,6 +560,16 @@ $(CPUOBJ)/sh4/sh4tmu.o: $(CPUSRC)/sh4/sh4tmu.c \
$(CPUSRC)/sh4/sh4comn.h \
$(CPUSRC)/sh4/sh3comn.h
+$(CPUOBJ)/sh4/sh4dmac.o: $(CPUSRC)/sh4/sh4dmac.c \
+ $(CPUSRC)/sh4/sh4dmac.h \
+ $(CPUSRC)/sh4/sh3comn.c \
+ $(CPUSRC)/sh4/sh3comn.h \
+ $(CPUSRC)/sh4/sh4.c \
+ $(CPUSRC)/sh4/sh4.h \
+ $(CPUSRC)/sh4/sh4regs.h \
+ $(CPUSRC)/sh4/sh4comn.h \
+ $(CPUSRC)/sh4/sh3comn.h
+
#-------------------------------------------------
# Hudsonsoft 6280
#-------------------------------------------------
diff --git a/src/emu/cpu/sh4/sh3comn.c b/src/emu/cpu/sh4/sh3comn.c
index 0b2dc4bf443..dbdaaaa3e4e 100644
--- a/src/emu/cpu/sh4/sh3comn.c
+++ b/src/emu/cpu/sh4/sh3comn.c
@@ -6,6 +6,8 @@
#include "sh4comn.h"
#include "sh3comn.h"
#include "sh4tmu.h"
+#include "sh4dmac.h"
+
/* High internal area (ffffxxxx) */
WRITE32_HANDLER( sh3_internal_high_w )
@@ -145,6 +147,26 @@ READ32_HANDLER( sh3_internal_r )
switch (offset)
{
+
+ case SH3_SAR0_ADDR: return sh4_handle_sar0_addr_r(sh4,mem_mask);
+ case SH3_SAR1_ADDR: return sh4_handle_sar1_addr_r(sh4,mem_mask);
+ case SH3_SAR2_ADDR: return sh4_handle_sar2_addr_r(sh4,mem_mask);
+ case SH3_SAR3_ADDR: return sh4_handle_sar3_addr_r(sh4,mem_mask);
+ case SH3_DAR0_ADDR: return sh4_handle_dar0_addr_r(sh4,mem_mask);
+ case SH3_DAR1_ADDR: return sh4_handle_dar1_addr_r(sh4,mem_mask);
+ case SH3_DAR2_ADDR: return sh4_handle_dar2_addr_r(sh4,mem_mask);
+ case SH3_DAR3_ADDR: return sh4_handle_dar3_addr_r(sh4,mem_mask);
+ case SH3_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(sh4,mem_mask);
+ case SH3_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(sh4,mem_mask);
+ case SH3_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(sh4,mem_mask);
+ case SH3_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(sh4,mem_mask);
+ case SH3_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(sh4,mem_mask);
+ case SH3_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(sh4,mem_mask);
+ case SH3_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(sh4,mem_mask);
+ case SH3_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(sh4,mem_mask);
+ case SH3_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(sh4,mem_mask)<<16;
+
+
case INTEVT2:
{
// logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (INTEVT2)\n",sh4->device->tag(), sh4->pc & AM,(offset *4)+0x4000000,mem_mask);
@@ -248,6 +270,25 @@ WRITE32_HANDLER( sh3_internal_w )
switch (offset)
{
+ case SH3_SAR0_ADDR: sh4_handle_sar0_addr_w(sh4,data,mem_mask); break;
+ case SH3_SAR1_ADDR: sh4_handle_sar1_addr_w(sh4,data,mem_mask); break;
+ case SH3_SAR2_ADDR: sh4_handle_sar2_addr_w(sh4,data,mem_mask); break;
+ case SH3_SAR3_ADDR: sh4_handle_sar3_addr_w(sh4,data,mem_mask); break;
+ case SH3_DAR0_ADDR: sh4_handle_dar0_addr_w(sh4,data,mem_mask); break;
+ case SH3_DAR1_ADDR: sh4_handle_dar1_addr_w(sh4,data,mem_mask); break;
+ case SH3_DAR2_ADDR: sh4_handle_dar2_addr_w(sh4,data,mem_mask); break;
+ case SH3_DAR3_ADDR: sh4_handle_dar3_addr_w(sh4,data,mem_mask); break;
+ case SH3_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(sh4,data,mem_mask); break;
+ case SH3_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(sh4,data,mem_mask); break;
+ case SH3_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(sh4,data,mem_mask); break;
+ case SH3_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(sh4,data,mem_mask); break;
+ case SH3_CHCR0_ADDR: sh4_handle_chcr0_addr_w(sh4,data,mem_mask); break;
+ case SH3_CHCR1_ADDR: sh4_handle_chcr1_addr_w(sh4,data,mem_mask); break;
+ case SH3_CHCR2_ADDR: sh4_handle_chcr2_addr_w(sh4,data,mem_mask); break;
+ case SH3_CHCR3_ADDR: sh4_handle_chcr3_addr_w(sh4,data,mem_mask); break;
+ case SH3_DMAOR_ADDR: sh4_handle_dmaor_addr_w(sh4,data>>16,mem_mask>>16); break;
+
+
case IRR0_IRR1:
{
{
diff --git a/src/emu/cpu/sh4/sh3comn.h b/src/emu/cpu/sh4/sh3comn.h
index 6c1271b68c2..f701f3f1bf6 100644
--- a/src/emu/cpu/sh4/sh3comn.h
+++ b/src/emu/cpu/sh4/sh3comn.h
@@ -11,6 +11,26 @@
#define INTEVT2 ((0x4000000 - SH3_LOWER_REGBASE)/4)
#define IRR0_IRR1 ((0x4000004 - SH3_LOWER_REGBASE)/4)
#define PINTER_IPRC ((0x4000014 - SH3_LOWER_REGBASE)/4)
+
+#define SH3_SAR0_ADDR ((0x4000020 - SH3_LOWER_REGBASE)/4)
+#define SH3_DAR0_ADDR ((0x4000024 - SH3_LOWER_REGBASE)/4)
+#define SH3_DMATCR0_ADDR ((0x4000028 - SH3_LOWER_REGBASE)/4)
+#define SH3_CHCR0_ADDR ((0x400002c - SH3_LOWER_REGBASE)/4)
+#define SH3_SAR1_ADDR ((0x4000030 - SH3_LOWER_REGBASE)/4)
+#define SH3_DAR1_ADDR ((0x4000034 - SH3_LOWER_REGBASE)/4)
+#define SH3_DMATCR1_ADDR ((0x4000038 - SH3_LOWER_REGBASE)/4)
+#define SH3_CHCR1_ADDR ((0x400003c - SH3_LOWER_REGBASE)/4)
+#define SH3_SAR2_ADDR ((0x4000040 - SH3_LOWER_REGBASE)/4)
+#define SH3_DAR2_ADDR ((0x4000044 - SH3_LOWER_REGBASE)/4)
+#define SH3_DMATCR2_ADDR ((0x4000048 - SH3_LOWER_REGBASE)/4)
+#define SH3_CHCR2_ADDR ((0x400004c - SH3_LOWER_REGBASE)/4)
+#define SH3_SAR3_ADDR ((0x4000050 - SH3_LOWER_REGBASE)/4)
+#define SH3_DAR3_ADDR ((0x4000054 - SH3_LOWER_REGBASE)/4)
+#define SH3_DMATCR3_ADDR ((0x4000058 - SH3_LOWER_REGBASE)/4)
+#define SH3_CHCR3_ADDR ((0x400005c - SH3_LOWER_REGBASE)/4)
+#define SH3_DMAOR_ADDR ((0x4000060 - SH3_LOWER_REGBASE)/4)
+
+
#define PCCR_PDCR ((0x4000104 - SH3_LOWER_REGBASE)/4)
#define PECR_PFCR ((0x4000108 - SH3_LOWER_REGBASE)/4)
#define PGCR_PHCR ((0x400010c - SH3_LOWER_REGBASE)/4)
diff --git a/src/emu/cpu/sh4/sh4.c b/src/emu/cpu/sh4/sh4.c
index 93735b5f9c2..2c383a7d474 100644
--- a/src/emu/cpu/sh4/sh4.c
+++ b/src/emu/cpu/sh4/sh4.c
@@ -3313,7 +3313,14 @@ static CPU_RESET( sh3 )
CPU_RESET_CALL(common_sh4_reset);
sh4->cpu_type = CPU_TYPE_SH3;
-
+
+ sh4->SH4_TCOR0 = 0xffffffff;
+ sh4->SH4_TCNT0 = 0xffffffff;
+ sh4->SH4_TCOR1 = 0xffffffff;
+ sh4->SH4_TCNT1 = 0xffffffff;
+ sh4->SH4_TCOR2 = 0xffffffff;
+ sh4->SH4_TCNT2 = 0xffffffff;
+
}
static CPU_RESET( sh4 )
diff --git a/src/emu/cpu/sh4/sh4comn.c b/src/emu/cpu/sh4/sh4comn.c
index 340e318555f..051576af4fb 100644
--- a/src/emu/cpu/sh4/sh4comn.c
+++ b/src/emu/cpu/sh4/sh4comn.c
@@ -13,11 +13,11 @@
#include "sh4comn.h"
#include "sh3comn.h"
#include "sh4tmu.h"
-
+#include "sh4dmac.h"
static const int rtcnt_div[8] = { 0, 4, 16, 64, 256, 1024, 2048, 4096 };
static const int daysmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 };
+
static const UINT32 exception_priority_default[] = {
@@ -627,280 +627,11 @@ static TIMER_CALLBACK( sh4_rtc_timer_callback )
}
-static TIMER_CALLBACK( sh4_dmac_callback )
-{
- sh4_state *sh4 = (sh4_state *)ptr;
- int channel = param;
-
- if (sh4->cpu_type != CPU_TYPE_SH4)
- fatalerror("sh4_dmac_callback uses sh4->m[] with SH3\n");
-
- LOG(("SH4 '%s': DMA %d complete\n", sh4->device->tag(), channel));
- sh4->dma_timer_active[channel] = 0;
- switch (channel)
- {
- case 0:
- sh4->m[DMATCR0] = 0;
- sh4->m[CHCR0] |= CHCR_TE;
- if (sh4->m[CHCR0] & CHCR_IE)
- sh4_exception_request(sh4, SH4_INTC_DMTE0);
- break;
- case 1:
- sh4->m[DMATCR1] = 0;
- sh4->m[CHCR1] |= CHCR_TE;
- if (sh4->m[CHCR1] & CHCR_IE)
- sh4_exception_request(sh4, SH4_INTC_DMTE1);
- break;
- case 2:
- sh4->m[DMATCR2] = 0;
- sh4->m[CHCR2] |= CHCR_TE;
- if (sh4->m[CHCR2] & CHCR_IE)
- sh4_exception_request(sh4, SH4_INTC_DMTE2);
- break;
- case 3:
- sh4->m[DMATCR3] = 0;
- sh4->m[CHCR3] |= CHCR_TE;
- if (sh4->m[CHCR3] & CHCR_IE)
- sh4_exception_request(sh4, SH4_INTC_DMTE3);
- break;
- }
-}
-
-static int sh4_dma_transfer(sh4_state *sh4, int channel, int timermode, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
-{
- int incs, incd, size;
- UINT32 src, dst, count;
-
- incd = (chcr & CHCR_DM) >> 14;
- incs = (chcr & CHCR_SM) >> 12;
- size = dmasize[(chcr & CHCR_TS) >> 4];
- if(incd == 3 || incs == 3)
- {
- logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
- return 0;
- }
- src = *sar;
- dst = *dar;
- count = *dmatcr;
- if (!count)
- count = 0x1000000;
-
- LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
-
- if (timermode == 1) // timer actvated after a time based on the number of words to transfer
- {
- sh4->dma_timer_active[channel] = 1;
- sh4->dma_timer[channel]->adjust(sh4->device->cycles_to_attotime(2*count+1), channel);
- }
- else if (timermode == 2) // timer activated immediately
- {
- sh4->dma_timer_active[channel] = 1;
- sh4->dma_timer[channel]->adjust(attotime::zero, channel);
- }
-
- src &= AM;
- dst &= AM;
-
- switch(size)
- {
- case 1: // 8 bit
- for(;count > 0; count --)
- {
- if(incs == 2)
- src --;
- if(incd == 2)
- dst --;
- sh4->program->write_byte(dst, sh4->program->read_byte(src));
- if(incs == 1)
- src ++;
- if(incd == 1)
- dst ++;
- }
- break;
- case 2: // 16 bit
- src &= ~1;
- dst &= ~1;
- for(;count > 0; count --)
- {
- if(incs == 2)
- src -= 2;
- if(incd == 2)
- dst -= 2;
- sh4->program->write_word(dst, sh4->program->read_word(src));
- if(incs == 1)
- src += 2;
- if(incd == 1)
- dst += 2;
- }
- break;
- case 8: // 64 bit
- src &= ~7;
- dst &= ~7;
- for(;count > 0; count --)
- {
- if(incs == 2)
- src -= 8;
- if(incd == 2)
- dst -= 8;
- sh4->program->write_qword(dst, sh4->program->read_qword(src));
- if(incs == 1)
- src += 8;
- if(incd == 1)
- dst += 8;
-
- }
- break;
- case 4: // 32 bit
- src &= ~3;
- dst &= ~3;
- for(;count > 0; count --)
- {
- if(incs == 2)
- src -= 4;
- if(incd == 2)
- dst -= 4;
- sh4->program->write_dword(dst, sh4->program->read_dword(src));
- if(incs == 1)
- src += 4;
- if(incd == 1)
- dst += 4;
-
- }
- break;
- case 32:
- src &= ~31;
- dst &= ~31;
- for(;count > 0; count --)
- {
- if(incs == 2)
- src -= 32;
- if(incd == 2)
- dst -= 32;
- sh4->program->write_qword(dst, sh4->program->read_qword(src));
- sh4->program->write_qword(dst+8, sh4->program->read_qword(src+8));
- sh4->program->write_qword(dst+16, sh4->program->read_qword(src+16));
- sh4->program->write_qword(dst+24, sh4->program->read_qword(src+24));
- if(incs == 1)
- src += 32;
- if(incd == 1)
- dst += 32;
- }
- break;
- }
- *sar = (*sar & !AM) | src;
- *dar = (*dar & !AM) | dst;
- *dmatcr = count;
- return 1;
-}
-
-static int sh4_dma_transfer_device(sh4_state *sh4, int channel, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
-{
- int incs, incd, size, mod;
- UINT32 src, dst, count;
-
- incd = (chcr & CHCR_DM) >> 14;
- incs = (chcr & CHCR_SM) >> 12;
- size = dmasize[(chcr & CHCR_TS) >> 4];
- mod = ((chcr & CHCR_RS) >> 8);
- if (incd == 3 || incs == 3)
- {
- logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
- return 0;
- }
- src = *sar;
- dst = *dar;
- count = *dmatcr;
- if (!count)
- count = 0x1000000;
-
- LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
-
- sh4->dma_timer_active[channel] = 1;
-
- src &= AM;
- dst &= AM;
-
- // remember parameters
- sh4->dma_source[channel]=src;
- sh4->dma_destination[channel]=dst;
- sh4->dma_count[channel]=count;
- sh4->dma_wordsize[channel]=size;
- sh4->dma_source_increment[channel]=incs;
- sh4->dma_destination_increment[channel]=incd;
- sh4->dma_mode[channel]=mod;
-
- // inform device its ready to transfer
- sh4->io->write_dword(SH4_IOPORT_DMA, channel | (mod << 16));
- return 1;
-}
-
-static void sh4_dmac_check(sh4_state *sh4, int channel)
-{
-UINT32 dmatcr, chcr, sar, dar;
-
- if (sh4->cpu_type != CPU_TYPE_SH4)
- fatalerror("sh4_dmac_check uses sh4->m[] with SH3\n");
-
- switch (channel)
- {
- case 0:
- sar = sh4->m[SAR0];
- dar = sh4->m[DAR0];
- chcr = sh4->m[CHCR0];
- dmatcr = sh4->m[DMATCR0];
- break;
- case 1:
- sar = sh4->m[SAR1];
- dar = sh4->m[DAR1];
- chcr = sh4->m[CHCR1];
- dmatcr = sh4->m[DMATCR1];
- break;
- case 2:
- sar = sh4->m[SAR2];
- dar = sh4->m[DAR2];
- chcr = sh4->m[CHCR2];
- dmatcr = sh4->m[DMATCR2];
- break;
- case 3:
- sar = sh4->m[SAR3];
- dar = sh4->m[DAR3];
- chcr = sh4->m[CHCR3];
- dmatcr = sh4->m[DMATCR3];
- break;
- default:
- return;
- }
- if (chcr & sh4->m[DMAOR] & DMAOR_DME)
- {
- if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6))
- return;
- if (!sh4->dma_timer_active[channel] && !(chcr & CHCR_TE) && !(sh4->m[DMAOR] & (DMAOR_AE | DMAOR_NMIF)))
- {
- if (((chcr & CHCR_RS) >> 8) > 3)
- sh4_dma_transfer(sh4, channel, 1, chcr, &sar, &dar, &dmatcr);
- else if ((sh4->m[DMAOR] & DMAOR_DDT) == 0)
- sh4_dma_transfer_device(sh4, channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer
- }
- }
- else
- {
- if (sh4->dma_timer_active[channel])
- {
- logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel);
- sh4->dma_timer[channel]->adjust(attotime::never, channel);
- sh4->dma_timer_active[channel] = 0;
- }
- }
-}
-
static void sh4_dmac_nmi(sh4_state *sh4) // manage dma when nmi gets asserted
{
-int s;
+ int s;
- if (sh4->cpu_type != CPU_TYPE_SH4)
- fatalerror("sh4_dmac_nmi uses sh4->m[] with SH3\n");
-
- sh4->m[DMAOR] |= DMAOR_NMIF;
+ sh4->SH4_DMAOR |= DMAOR_NMIF;
for (s = 0;s < 4;s++)
{
if (sh4->dma_timer_active[s])
@@ -935,6 +666,7 @@ void sh4_handler_ipra_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
sh4_exception_recompute(sh4);
}
+
WRITE32_HANDLER( sh4_internal_w )
{
sh4_state *sh4 = get_safe_token(&space->device());
@@ -1089,50 +821,35 @@ WRITE32_HANDLER( sh4_internal_w )
sh4->exception_priority[SH4_INTC_GPOI] = INTPRI((sh4->m[IPRC] & 0xf000) >> 12, SH4_INTC_GPOI);
sh4_exception_recompute(sh4);
break;
-
- // DMA
- case SAR0:
- case SAR1:
- case SAR2:
- case SAR3:
- case DAR0:
- case DAR1:
- case DAR2:
- case DAR3:
- case DMATCR0:
- case DMATCR1:
- case DMATCR2:
- case DMATCR3:
- break;
- case CHCR0:
- sh4_dmac_check(sh4, 0);
- break;
- case CHCR1:
- sh4_dmac_check(sh4, 1);
- break;
- case CHCR2:
- sh4_dmac_check(sh4, 2);
- break;
- case CHCR3:
- sh4_dmac_check(sh4, 3);
- break;
- case DMAOR:
- if ((sh4->m[DMAOR] & DMAOR_AE) && (~old & DMAOR_AE))
- sh4->m[DMAOR] &= ~DMAOR_AE;
- if ((sh4->m[DMAOR] & DMAOR_NMIF) && (~old & DMAOR_NMIF))
- sh4->m[DMAOR] &= ~DMAOR_NMIF;
- sh4_dmac_check(sh4, 0);
- sh4_dmac_check(sh4, 1);
- sh4_dmac_check(sh4, 2);
- sh4_dmac_check(sh4, 3);
- break;
-
- // Store Queues
+/*********************************************************************************************************************
+ DMAC (DMA Controller)
+*********************************************************************************************************************/
+ case SH4_SAR0_ADDR: sh4_handle_sar0_addr_w(sh4,data,mem_mask); break;
+ case SH4_SAR1_ADDR: sh4_handle_sar1_addr_w(sh4,data,mem_mask); break;
+ case SH4_SAR2_ADDR: sh4_handle_sar2_addr_w(sh4,data,mem_mask); break;
+ case SH4_SAR3_ADDR: sh4_handle_sar3_addr_w(sh4,data,mem_mask); break;
+ case SH4_DAR0_ADDR: sh4_handle_dar0_addr_w(sh4,data,mem_mask); break;
+ case SH4_DAR1_ADDR: sh4_handle_dar1_addr_w(sh4,data,mem_mask); break;
+ case SH4_DAR2_ADDR: sh4_handle_dar2_addr_w(sh4,data,mem_mask); break;
+ case SH4_DAR3_ADDR: sh4_handle_dar3_addr_w(sh4,data,mem_mask); break;
+ case SH4_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(sh4,data,mem_mask); break;
+ case SH4_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(sh4,data,mem_mask); break;
+ case SH4_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(sh4,data,mem_mask); break;
+ case SH4_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(sh4,data,mem_mask); break;
+ case SH4_CHCR0_ADDR: sh4_handle_chcr0_addr_w(sh4,data,mem_mask); break;
+ case SH4_CHCR1_ADDR: sh4_handle_chcr1_addr_w(sh4,data,mem_mask); break;
+ case SH4_CHCR2_ADDR: sh4_handle_chcr2_addr_w(sh4,data,mem_mask); break;
+ case SH4_CHCR3_ADDR: sh4_handle_chcr3_addr_w(sh4,data,mem_mask); break;
+ case SH4_DMAOR_ADDR: sh4_handle_dmaor_addr_w(sh4,data,mem_mask); break;
+/*********************************************************************************************************************
+ Store Queues
+*********************************************************************************************************************/
case QACR0:
case QACR1:
break;
-
- // I/O ports
+/*********************************************************************************************************************
+ I/O
+*********************************************************************************************************************/
case PCTRA:
sh4->ioport16_pullup = 0;
sh4->ioport16_direction = 0;
@@ -1235,6 +952,26 @@ READ32_HANDLER( sh4_internal_r )
case SH4_TOCR_ADDR: return sh4_handle_tocr_addr_r(sh4, mem_mask); // not supported
case SH4_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(sh4, mem_mask); // not supported
/*********************************************************************************************************************
+ DMAC (DMA Controller)
+*********************************************************************************************************************/
+ case SH4_SAR0_ADDR: return sh4_handle_sar0_addr_r(sh4,mem_mask);
+ case SH4_SAR1_ADDR: return sh4_handle_sar1_addr_r(sh4,mem_mask);
+ case SH4_SAR2_ADDR: return sh4_handle_sar2_addr_r(sh4,mem_mask);
+ case SH4_SAR3_ADDR: return sh4_handle_sar3_addr_r(sh4,mem_mask);
+ case SH4_DAR0_ADDR: return sh4_handle_dar0_addr_r(sh4,mem_mask);
+ case SH4_DAR1_ADDR: return sh4_handle_dar1_addr_r(sh4,mem_mask);
+ case SH4_DAR2_ADDR: return sh4_handle_dar2_addr_r(sh4,mem_mask);
+ case SH4_DAR3_ADDR: return sh4_handle_dar3_addr_r(sh4,mem_mask);
+ case SH4_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(sh4,mem_mask);
+ case SH4_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(sh4,mem_mask);
+ case SH4_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(sh4,mem_mask);
+ case SH4_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(sh4,mem_mask);
+ case SH4_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(sh4,mem_mask);
+ case SH4_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(sh4,mem_mask);
+ case SH4_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(sh4,mem_mask);
+ case SH4_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(sh4,mem_mask);
+ case SH4_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(sh4,mem_mask);
+/*********************************************************************************************************************
I/O Ports
*********************************************************************************************************************/
@@ -1491,270 +1228,6 @@ void sh4_common_init(device_t *device)
sh4->m = auto_alloc_array(device->machine(), UINT32, 16384);
}
-// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu
-int sh4_dma_data(device_t *device, struct sh4_device_dma *s)
-{
- UINT32 pos, len, siz;
- int channel = s->channel;
- void *data = s->buffer;
-
- sh4_state *sh4 = get_safe_token(device);
-
- if (!sh4->dma_timer_active[channel])
- return 0;
-
- if (sh4->dma_mode[channel] == 2)
- {
- // device receives data
- len = sh4->dma_count[channel];
- if (s->length < len)
- len = s->length;
- siz = sh4->dma_wordsize[channel];
- for (pos = 0;pos < len;pos++) {
- switch (siz)
- {
- case 8:
- if (sh4->dma_source_increment[channel] == 2)
- sh4->dma_source[channel] -= 8;
- *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~7);
- if (sh4->dma_source_increment[channel] == 1)
- sh4->dma_source[channel] += 8;
- break;
- case 1:
- if (sh4->dma_source_increment[channel] == 2)
- sh4->dma_source[channel]--;
- *(UINT8 *)data = sh4->program->read_byte(sh4->dma_source[channel]);
- if (sh4->dma_source_increment[channel] == 1)
- sh4->dma_source[channel]++;
- break;
- case 2:
- if (sh4->dma_source_increment[channel] == 2)
- sh4->dma_source[channel] -= 2;
- *(UINT16 *)data = sh4->program->read_word(sh4->dma_source[channel] & ~1);
- if (sh4->dma_source_increment[channel] == 1)
- sh4->dma_source[channel] += 2;
- break;
- case 4:
- if (sh4->dma_source_increment[channel] == 2)
- sh4->dma_source[channel] -= 4;
- *(UINT32 *)data = sh4->program->read_dword(sh4->dma_source[channel] & ~3);
- if (sh4->dma_source_increment[channel] == 1)
- sh4->dma_source[channel] += 4;
- break;
- case 32:
- if (sh4->dma_source_increment[channel] == 2)
- sh4->dma_source[channel] -= 32;
- *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~31);
- *((UINT64 *)data+1) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+8);
- *((UINT64 *)data+2) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+16);
- *((UINT64 *)data+3) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+24);
- if (sh4->dma_source_increment[channel] == 1)
- sh4->dma_source[channel] += 32;
- break;
- }
- sh4->dma_count[channel]--;
- }
- if (sh4->dma_count[channel] == 0) // all data transferred ?
- {
- sh4->dma_timer[channel]->adjust(attotime::zero, channel);
- return 2;
- }
- return 1;
- }
- else if (sh4->dma_mode[channel] == 3)
- {
- // device sends data
- len = sh4->dma_count[channel];
- if (s->length < len)
- len = s->length;
- siz = sh4->dma_wordsize[channel];
- for (pos = 0;pos < len;pos++) {
- switch (siz)
- {
- case 8:
- if (sh4->dma_destination_increment[channel] == 2)
- sh4->dma_destination[channel]-=8;
- sh4->program->write_qword(sh4->dma_destination[channel] & ~7, *(UINT64 *)data);
- if (sh4->dma_destination_increment[channel] == 1)
- sh4->dma_destination[channel]+=8;
- break;
- case 1:
- if (sh4->dma_destination_increment[channel] == 2)
- sh4->dma_destination[channel]--;
- sh4->program->write_byte(sh4->dma_destination[channel], *(UINT8 *)data);
- if (sh4->dma_destination_increment[channel] == 1)
- sh4->dma_destination[channel]++;
- break;
- case 2:
- if (sh4->dma_destination_increment[channel] == 2)
- sh4->dma_destination[channel]-=2;
- sh4->program->write_word(sh4->dma_destination[channel] & ~1, *(UINT16 *)data);
- if (sh4->dma_destination_increment[channel] == 1)
- sh4->dma_destination[channel]+=2;
- break;
- case 4:
- if (sh4->dma_destination_increment[channel] == 2)
- sh4->dma_destination[channel]-=4;
- sh4->program->write_dword(sh4->dma_destination[channel] & ~3, *(UINT32 *)data);
- if (sh4->dma_destination_increment[channel] == 1)
- sh4->dma_destination[channel]+=4;
- break;
- case 32:
- if (sh4->dma_destination_increment[channel] == 2)
- sh4->dma_destination[channel]-=32;
- sh4->program->write_qword(sh4->dma_destination[channel] & ~31, *(UINT64 *)data);
- sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+8, *((UINT64 *)data+1));
- sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+16, *((UINT64 *)data+2));
- sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+24, *((UINT64 *)data+3));
- if (sh4->dma_destination_increment[channel] == 1)
- sh4->dma_destination[channel]+=32;
- break;
- }
- sh4->dma_count[channel]--;
- }
-
- if (sh4->dma_count[channel] == 0) // all data transferred ?
- {
- sh4->dma_timer[channel]->adjust(attotime::zero, channel);
- return 2;
- }
- return 1;
- }
- else
- return 0;
-}
-
-// called by drivers to transfer data in a DDT dma. 'device' must be a SH4 cpu
-void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s)
-{
- sh4_state *sh4 = get_safe_token(device);
- UINT32 chcr;
- UINT32 *p32bits;
- UINT64 *p32bytes;
- UINT32 pos,len,siz;
-
- if (sh4->cpu_type != CPU_TYPE_SH4)
- fatalerror("sh4_dma_ddt uses sh4->m[] with SH3\n");
-
- if (sh4->dma_timer_active[s->channel])
- return;
- if (s->mode >= 0) {
- switch (s->channel)
- {
- case 0:
- if (s->mode & 1)
- s->source = sh4->m[SAR0];
- if (s->mode & 2)
- sh4->m[SAR0] = s->source;
- if (s->mode & 4)
- s->destination = sh4->m[DAR0];
- if (s->mode & 8)
- sh4->m[DAR0] = s->destination;
- break;
- case 1:
- if (s->mode & 1)
- s->source = sh4->m[SAR1];
- if (s->mode & 2)
- sh4->m[SAR1] = s->source;
- if (s->mode & 4)
- s->destination = sh4->m[DAR1];
- if (s->mode & 8)
- sh4->m[DAR1] = s->destination;
- break;
- case 2:
- if (s->mode & 1)
- s->source = sh4->m[SAR2];
- if (s->mode & 2)
- sh4->m[SAR2] = s->source;
- if (s->mode & 4)
- s->destination = sh4->m[DAR2];
- if (s->mode & 8)
- sh4->m[DAR2] = s->destination;
- break;
- case 3:
- default:
- if (s->mode & 1)
- s->source = sh4->m[SAR3];
- if (s->mode & 2)
- sh4->m[SAR3] = s->source;
- if (s->mode & 4)
- s->destination = sh4->m[DAR3];
- if (s->mode & 8)
- sh4->m[DAR3] = s->destination;
- break;
- }
- switch (s->channel)
- {
- case 0:
- chcr = sh4->m[CHCR0];
- len = sh4->m[DMATCR0];
- break;
- case 1:
- chcr = sh4->m[CHCR1];
- len = sh4->m[DMATCR1];
- break;
- case 2:
- chcr = sh4->m[CHCR2];
- len = sh4->m[DMATCR2];
- break;
- case 3:
- default:
- chcr = sh4->m[CHCR3];
- len = sh4->m[DMATCR3];
- break;
- }
- if ((s->direction) == 0) {
- chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10);
- } else {
- chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8);
- }
- siz = dmasize[(chcr >> 4) & 7];
- if (siz && (s->size))
- if ((len * siz) != (s->length * s->size))
- return;
- sh4_dma_transfer(sh4, s->channel, 0, chcr, &s->source, &s->destination, &len);
- } else {
- if (s->size == 4) {
- if ((s->direction) == 0) {
- len = s->length;
- p32bits = (UINT32 *)(s->buffer);
- for (pos = 0;pos < len;pos++) {
- *p32bits = sh4->program->read_dword(s->source);
- p32bits++;
- s->source = s->source + 4;
- }
- } else {
- len = s->length;
- p32bits = (UINT32 *)(s->buffer);
- for (pos = 0;pos < len;pos++) {
- sh4->program->write_dword(s->destination, *p32bits);
- p32bits++;
- s->destination = s->destination + 4;
- }
- }
- }
- if (s->size == 32) {
- if ((s->direction) == 0) {
- len = s->length * 4;
- p32bytes = (UINT64 *)(s->buffer);
- for (pos = 0;pos < len;pos++) {
- *p32bytes = sh4->program->read_qword(s->source);
- p32bytes++;
- s->destination = s->destination + 8;
- }
- } else {
- len = s->length * 4;
- p32bytes = (UINT64 *)(s->buffer);
- for (pos = 0;pos < len;pos++) {
- sh4->program->write_qword(s->destination, *p32bytes);
- p32bytes++;
- s->destination = s->destination + 8;
- }
- }
- }
- }
-}
-
UINT32 sh4_getsqremap(sh4_state *sh4, UINT32 address)
{
if (!sh4->sh4_mmu_enabled)
diff --git a/src/emu/cpu/sh4/sh4comn.h b/src/emu/cpu/sh4/sh4comn.h
index 76476a7202f..fd0faaa3b51 100644
--- a/src/emu/cpu/sh4/sh4comn.h
+++ b/src/emu/cpu/sh4/sh4comn.h
@@ -101,6 +101,29 @@ typedef struct
UINT32 SH4_IPRC;
+ // DMAC regs
+ UINT32 SH4_SAR0;
+ UINT32 SH4_SAR1;
+ UINT32 SH4_SAR2;
+ UINT32 SH4_SAR3;
+
+ UINT32 SH4_DAR0;
+ UINT32 SH4_DAR1;
+ UINT32 SH4_DAR2;
+ UINT32 SH4_DAR3;
+
+ UINT32 SH4_CHCR0;
+ UINT32 SH4_CHCR1;
+ UINT32 SH4_CHCR2;
+ UINT32 SH4_CHCR3;
+
+ UINT32 SH4_DMATCR0;
+ UINT32 SH4_DMATCR1;
+ UINT32 SH4_DMATCR2;
+ UINT32 SH4_DMATCR3;
+
+ UINT32 SH4_DMAOR;
+
// sh3 internal
UINT32 m_sh3internal_upper[0x3000/4];
diff --git a/src/emu/cpu/sh4/sh4dmac.c b/src/emu/cpu/sh4/sh4dmac.c
new file mode 100644
index 00000000000..4649625e957
--- /dev/null
+++ b/src/emu/cpu/sh4/sh4dmac.c
@@ -0,0 +1,686 @@
+/* SHA3/4 DMA Controller */
+
+#include "emu.h"
+#include "debugger.h"
+#include "sh4.h"
+#include "sh4comn.h"
+#include "sh3comn.h"
+#include "sh4dmac.h"
+
+static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 };
+
+static const int sh3_dmasize[4] = { 1, 2, 4, 16 };
+
+TIMER_CALLBACK( sh4_dmac_callback )
+{
+ sh4_state *sh4 = (sh4_state *)ptr;
+ int channel = param;
+
+ LOG(("SH4 '%s': DMA %d complete\n", sh4->device->tag(), channel));
+ sh4->dma_timer_active[channel] = 0;
+ switch (channel)
+ {
+ case 0:
+ sh4->SH4_DMATCR0 = 0;
+ sh4->SH4_CHCR0 |= CHCR_TE;
+ if (sh4->SH4_CHCR0 & CHCR_IE)
+ sh4_exception_request(sh4, SH4_INTC_DMTE0);
+ break;
+ case 1:
+ sh4->SH4_DMATCR1 = 0;
+ sh4->SH4_CHCR1 |= CHCR_TE;
+ if (sh4->SH4_CHCR1 & CHCR_IE)
+ sh4_exception_request(sh4, SH4_INTC_DMTE1);
+ break;
+ case 2:
+ sh4->SH4_DMATCR2 = 0;
+ sh4->SH4_CHCR2 |= CHCR_TE;
+ if (sh4->SH4_CHCR2 & CHCR_IE)
+ sh4_exception_request(sh4, SH4_INTC_DMTE2);
+ break;
+ case 3:
+ sh4->SH4_DMATCR3 = 0;
+ sh4->SH4_CHCR3 |= CHCR_TE;
+ if (sh4->SH4_CHCR3 & CHCR_IE)
+ sh4_exception_request(sh4, SH4_INTC_DMTE3);
+ break;
+ }
+}
+
+static int sh4_dma_transfer(sh4_state *sh4, int channel, int timermode, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
+{
+ int incs, incd, size;
+ UINT32 src, dst, count;
+
+ incd = (chcr & CHCR_DM) >> 14;
+ incs = (chcr & CHCR_SM) >> 12;
+
+ if (sh4->cpu_type == CPU_TYPE_SH4)
+ {
+ size = dmasize[(chcr & CHCR_TS) >> 4];
+ }
+ else
+ {
+ size = sh3_dmasize[(chcr >> 3) & 3];
+ }
+
+ if(incd == 3 || incs == 3)
+ {
+ logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
+ return 0;
+ }
+ src = *sar;
+ dst = *dar;
+ count = *dmatcr;
+ if (!count)
+ count = 0x1000000;
+
+ LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
+
+ if (timermode == 1) // timer actvated after a time based on the number of words to transfer
+ {
+ sh4->dma_timer_active[channel] = 1;
+ sh4->dma_timer[channel]->adjust(sh4->device->cycles_to_attotime(2*count+1), channel);
+ }
+ else if (timermode == 2) // timer activated immediately
+ {
+ sh4->dma_timer_active[channel] = 1;
+ sh4->dma_timer[channel]->adjust(attotime::zero, channel);
+ }
+
+ src &= AM;
+ dst &= AM;
+
+ switch(size)
+ {
+ case 1: // 8 bit
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src --;
+ if(incd == 2)
+ dst --;
+ sh4->program->write_byte(dst, sh4->program->read_byte(src));
+ if(incs == 1)
+ src ++;
+ if(incd == 1)
+ dst ++;
+ }
+ break;
+ case 2: // 16 bit
+ src &= ~1;
+ dst &= ~1;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 2;
+ if(incd == 2)
+ dst -= 2;
+ sh4->program->write_word(dst, sh4->program->read_word(src));
+ if(incs == 1)
+ src += 2;
+ if(incd == 1)
+ dst += 2;
+ }
+ break;
+ case 8: // 64 bit
+ src &= ~7;
+ dst &= ~7;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 8;
+ if(incd == 2)
+ dst -= 8;
+ sh4->program->write_qword(dst, sh4->program->read_qword(src));
+ if(incs == 1)
+ src += 8;
+ if(incd == 1)
+ dst += 8;
+
+ }
+ break;
+ case 4: // 32 bit
+ src &= ~3;
+ dst &= ~3;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 4;
+ if(incd == 2)
+ dst -= 4;
+ sh4->program->write_dword(dst, sh4->program->read_dword(src));
+ if(incs == 1)
+ src += 4;
+ if(incd == 1)
+ dst += 4;
+
+ }
+ break;
+ case 32:
+ src &= ~31;
+ dst &= ~31;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 32;
+ if(incd == 2)
+ dst -= 32;
+ sh4->program->write_qword(dst, sh4->program->read_qword(src));
+ sh4->program->write_qword(dst+8, sh4->program->read_qword(src+8));
+ sh4->program->write_qword(dst+16, sh4->program->read_qword(src+16));
+ sh4->program->write_qword(dst+24, sh4->program->read_qword(src+24));
+ if(incs == 1)
+ src += 32;
+ if(incd == 1)
+ dst += 32;
+ }
+ break;
+ }
+ *sar = (*sar & !AM) | src;
+ *dar = (*dar & !AM) | dst;
+ *dmatcr = count;
+ return 1;
+}
+
+static int sh4_dma_transfer_device(sh4_state *sh4, int channel, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
+{
+ int incs, incd, size, mod;
+ UINT32 src, dst, count;
+
+ incd = (chcr & CHCR_DM) >> 14;
+ incs = (chcr & CHCR_SM) >> 12;
+
+
+ if (sh4->cpu_type == CPU_TYPE_SH4)
+ {
+ size = dmasize[(chcr & CHCR_TS) >> 4];
+ }
+ else
+ {
+ size = sh3_dmasize[(chcr >> 3) & 3];
+ }
+
+ mod = ((chcr & CHCR_RS) >> 8);
+ if (incd == 3 || incs == 3)
+ {
+ logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
+ return 0;
+ }
+ src = *sar;
+ dst = *dar;
+ count = *dmatcr;
+ if (!count)
+ count = 0x1000000;
+
+ LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
+
+ sh4->dma_timer_active[channel] = 1;
+
+ src &= AM;
+ dst &= AM;
+
+ // remember parameters
+ sh4->dma_source[channel]=src;
+ sh4->dma_destination[channel]=dst;
+ sh4->dma_count[channel]=count;
+ sh4->dma_wordsize[channel]=size;
+ sh4->dma_source_increment[channel]=incs;
+ sh4->dma_destination_increment[channel]=incd;
+ sh4->dma_mode[channel]=mod;
+
+ // inform device its ready to transfer
+ sh4->io->write_dword(SH4_IOPORT_DMA, channel | (mod << 16));
+ return 1;
+}
+
+static void sh4_dmac_check(sh4_state *sh4, int channel)
+{
+ UINT32 dmatcr, chcr, sar, dar;
+
+ switch (channel)
+ {
+ case 0:
+ sar = sh4->SH4_SAR0;
+ dar = sh4->SH4_DAR0;
+ chcr = sh4->SH4_CHCR0;
+ dmatcr = sh4->SH4_DMATCR0;
+ break;
+ case 1:
+ sar = sh4->SH4_SAR1;
+ dar = sh4->SH4_DAR1;
+ chcr = sh4->SH4_CHCR1;
+ dmatcr = sh4->SH4_DMATCR1;
+ break;
+ case 2:
+ sar = sh4->SH4_SAR2;
+ dar = sh4->SH4_DAR2;
+ chcr = sh4->SH4_CHCR2;
+ dmatcr = sh4->SH4_DMATCR2;
+ break;
+ case 3:
+ sar = sh4->SH4_SAR3;
+ dar = sh4->SH4_DAR3;
+ chcr = sh4->SH4_CHCR3;
+ dmatcr = sh4->SH4_DMATCR3;
+ break;
+ default:
+ return;
+ }
+ if (chcr & sh4->SH4_DMAOR & DMAOR_DME)
+ {
+ if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6))
+ return;
+ if (!sh4->dma_timer_active[channel] && !(chcr & CHCR_TE) && !(sh4->SH4_DMAOR & (DMAOR_AE | DMAOR_NMIF)))
+ {
+ if (((chcr & CHCR_RS) >> 8) > 3)
+ sh4_dma_transfer(sh4, channel, 1, chcr, &sar, &dar, &dmatcr);
+ else if ((sh4->SH4_DMAOR & DMAOR_DDT) == 0)
+ sh4_dma_transfer_device(sh4, channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer
+ }
+ }
+ else
+ {
+ if (sh4->dma_timer_active[channel])
+ {
+ logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel);
+ sh4->dma_timer[channel]->adjust(attotime::never, channel);
+ sh4->dma_timer_active[channel] = 0;
+ }
+ }
+}
+
+
+// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu
+int sh4_dma_data(device_t *device, struct sh4_device_dma *s)
+{
+ UINT32 pos, len, siz;
+ int channel = s->channel;
+ void *data = s->buffer;
+
+ sh4_state *sh4 = get_safe_token(device);
+
+ if (!sh4->dma_timer_active[channel])
+ return 0;
+
+ if (sh4->dma_mode[channel] == 2)
+ {
+ // device receives data
+ len = sh4->dma_count[channel];
+ if (s->length < len)
+ len = s->length;
+ siz = sh4->dma_wordsize[channel];
+ for (pos = 0;pos < len;pos++) {
+ switch (siz)
+ {
+ case 8:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel] -= 8;
+ *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~7);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel] += 8;
+ break;
+ case 1:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel]--;
+ *(UINT8 *)data = sh4->program->read_byte(sh4->dma_source[channel]);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel]++;
+ break;
+ case 2:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel] -= 2;
+ *(UINT16 *)data = sh4->program->read_word(sh4->dma_source[channel] & ~1);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel] += 2;
+ break;
+ case 4:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel] -= 4;
+ *(UINT32 *)data = sh4->program->read_dword(sh4->dma_source[channel] & ~3);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel] += 4;
+ break;
+ case 32:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel] -= 32;
+ *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~31);
+ *((UINT64 *)data+1) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+8);
+ *((UINT64 *)data+2) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+16);
+ *((UINT64 *)data+3) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+24);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel] += 32;
+ break;
+ }
+ sh4->dma_count[channel]--;
+ }
+ if (sh4->dma_count[channel] == 0) // all data transferred ?
+ {
+ sh4->dma_timer[channel]->adjust(attotime::zero, channel);
+ return 2;
+ }
+ return 1;
+ }
+ else if (sh4->dma_mode[channel] == 3)
+ {
+ // device sends data
+ len = sh4->dma_count[channel];
+ if (s->length < len)
+ len = s->length;
+ siz = sh4->dma_wordsize[channel];
+ for (pos = 0;pos < len;pos++) {
+ switch (siz)
+ {
+ case 8:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]-=8;
+ sh4->program->write_qword(sh4->dma_destination[channel] & ~7, *(UINT64 *)data);
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]+=8;
+ break;
+ case 1:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]--;
+ sh4->program->write_byte(sh4->dma_destination[channel], *(UINT8 *)data);
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]++;
+ break;
+ case 2:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]-=2;
+ sh4->program->write_word(sh4->dma_destination[channel] & ~1, *(UINT16 *)data);
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]+=2;
+ break;
+ case 4:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]-=4;
+ sh4->program->write_dword(sh4->dma_destination[channel] & ~3, *(UINT32 *)data);
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]+=4;
+ break;
+ case 32:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]-=32;
+ sh4->program->write_qword(sh4->dma_destination[channel] & ~31, *(UINT64 *)data);
+ sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+8, *((UINT64 *)data+1));
+ sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+16, *((UINT64 *)data+2));
+ sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+24, *((UINT64 *)data+3));
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]+=32;
+ break;
+ }
+ sh4->dma_count[channel]--;
+ }
+
+ if (sh4->dma_count[channel] == 0) // all data transferred ?
+ {
+ sh4->dma_timer[channel]->adjust(attotime::zero, channel);
+ return 2;
+ }
+ return 1;
+ }
+ else
+ return 0;
+}
+
+// called by drivers to transfer data in a DDT dma. 'device' must be a SH4 cpu
+void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s)
+{
+ sh4_state *sh4 = get_safe_token(device);
+ UINT32 chcr;
+ UINT32 *p32bits;
+ UINT64 *p32bytes;
+ UINT32 pos,len,siz;
+
+ if (sh4->cpu_type != CPU_TYPE_SH4)
+ fatalerror("sh4_dma_ddt uses sh4->m[] with SH3\n");
+
+ if (sh4->dma_timer_active[s->channel])
+ return;
+ if (s->mode >= 0) {
+ switch (s->channel)
+ {
+ case 0:
+ if (s->mode & 1)
+ s->source = sh4->SH4_SAR0;
+ if (s->mode & 2)
+ sh4->SH4_SAR0 = s->source;
+ if (s->mode & 4)
+ s->destination = sh4->SH4_DAR0;
+ if (s->mode & 8)
+ sh4->SH4_DAR0 = s->destination;
+ break;
+ case 1:
+ if (s->mode & 1)
+ s->source = sh4->SH4_SAR1;
+ if (s->mode & 2)
+ sh4->SH4_SAR1 = s->source;
+ if (s->mode & 4)
+ s->destination = sh4->SH4_DAR1;
+ if (s->mode & 8)
+ sh4->SH4_DAR1 = s->destination;
+ break;
+ case 2:
+ if (s->mode & 1)
+ s->source = sh4->SH4_SAR2;
+ if (s->mode & 2)
+ sh4->SH4_SAR2 = s->source;
+ if (s->mode & 4)
+ s->destination = sh4->SH4_DAR2;
+ if (s->mode & 8)
+ sh4->SH4_DAR2 = s->destination;
+ break;
+ case 3:
+ default:
+ if (s->mode & 1)
+ s->source = sh4->SH4_SAR3;
+ if (s->mode & 2)
+ sh4->SH4_SAR3 = s->source;
+ if (s->mode & 4)
+ s->destination = sh4->SH4_DAR3;
+ if (s->mode & 8)
+ sh4->SH4_DAR3 = s->destination;
+ break;
+ }
+ switch (s->channel)
+ {
+ case 0:
+ chcr = sh4->SH4_CHCR0;
+ len = sh4->SH4_DMATCR0;
+ break;
+ case 1:
+ chcr = sh4->SH4_CHCR1;
+ len = sh4->SH4_DMATCR1;
+ break;
+ case 2:
+ chcr = sh4->SH4_CHCR2;
+ len = sh4->SH4_DMATCR2;
+ break;
+ case 3:
+ default:
+ chcr = sh4->SH4_CHCR3;
+ len = sh4->SH4_DMATCR3;
+ break;
+ }
+ if ((s->direction) == 0) {
+ chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10);
+ } else {
+ chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8);
+ }
+
+
+ if (sh4->cpu_type == CPU_TYPE_SH4)
+ {
+ //siz = dmasize[(chcr & CHCR_TS) >> 4];
+ siz = dmasize[(chcr >> 4) & 7];
+ }
+ else
+ {
+ siz = sh3_dmasize[(chcr >> 3) & 3];
+ }
+
+
+ if (siz && (s->size))
+ if ((len * siz) != (s->length * s->size))
+ return;
+ sh4_dma_transfer(sh4, s->channel, 0, chcr, &s->source, &s->destination, &len);
+ } else {
+ if (s->size == 4) {
+ if ((s->direction) == 0) {
+ len = s->length;
+ p32bits = (UINT32 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ *p32bits = sh4->program->read_dword(s->source);
+ p32bits++;
+ s->source = s->source + 4;
+ }
+ } else {
+ len = s->length;
+ p32bits = (UINT32 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ sh4->program->write_dword(s->destination, *p32bits);
+ p32bits++;
+ s->destination = s->destination + 4;
+ }
+ }
+ }
+ if (s->size == 32) {
+ if ((s->direction) == 0) {
+ len = s->length * 4;
+ p32bytes = (UINT64 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ *p32bytes = sh4->program->read_qword(s->source);
+ p32bytes++;
+ s->destination = s->destination + 8;
+ }
+ } else {
+ len = s->length * 4;
+ p32bytes = (UINT64 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ sh4->program->write_qword(s->destination, *p32bytes);
+ p32bytes++;
+ s->destination = s->destination + 8;
+ }
+ }
+ }
+ }
+}
+
+
+ void sh4_handle_sar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_SAR0);
+}
+
+ void sh4_handle_sar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_SAR1);
+}
+
+ void sh4_handle_sar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_SAR2);
+}
+
+ void sh4_handle_sar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_SAR3);
+}
+
+ void sh4_handle_dar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_DAR0);
+}
+
+ void sh4_handle_dar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_DAR1);
+}
+
+ void sh4_handle_dar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_DAR2);
+}
+
+ void sh4_handle_dar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_DAR3);
+}
+
+ void sh4_handle_dmatcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_DMATCR0);
+}
+
+ void sh4_handle_dmatcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_DMATCR1);
+}
+
+ void sh4_handle_dmatcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_DMATCR2);
+}
+
+ void sh4_handle_dmatcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_DMATCR3);
+}
+
+ void sh4_handle_chcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_CHCR0);
+ sh4_dmac_check(sh4, 0);
+}
+
+ void sh4_handle_chcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_CHCR1);
+ sh4_dmac_check(sh4, 1);
+}
+
+ void sh4_handle_chcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_CHCR2);
+ sh4_dmac_check(sh4, 2);
+}
+
+ void sh4_handle_chcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ COMBINE_DATA(&sh4->SH4_CHCR3);
+ sh4_dmac_check(sh4, 3);
+}
+
+ void sh4_handle_dmaor_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask)
+{
+ UINT32 old = sh4->SH4_DMAOR;
+ COMBINE_DATA(&sh4->SH4_DMAOR);
+
+ if ((sh4->SH4_DMAOR & DMAOR_AE) && (~old & DMAOR_AE))
+ sh4->SH4_DMAOR &= ~DMAOR_AE;
+ if ((sh4->SH4_DMAOR & DMAOR_NMIF) && (~old & DMAOR_NMIF))
+ sh4->SH4_DMAOR &= ~DMAOR_NMIF;
+ sh4_dmac_check(sh4, 0);
+ sh4_dmac_check(sh4, 1);
+ sh4_dmac_check(sh4, 2);
+ sh4_dmac_check(sh4, 3);
+}
+
+ UINT32 sh4_handle_sar0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR0; }
+ UINT32 sh4_handle_sar1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR1; }
+ UINT32 sh4_handle_sar2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR2; }
+ UINT32 sh4_handle_sar3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_SAR3; }
+ UINT32 sh4_handle_dar0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR0; }
+ UINT32 sh4_handle_dar1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR1; }
+ UINT32 sh4_handle_dar2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR2; }
+ UINT32 sh4_handle_dar3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DAR3; }
+ UINT32 sh4_handle_dmatcr0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR0; }
+ UINT32 sh4_handle_dmatcr1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR1; }
+ UINT32 sh4_handle_dmatcr2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR2; }
+ UINT32 sh4_handle_dmatcr3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMATCR3; }
+ UINT32 sh4_handle_chcr0_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR0; }
+ UINT32 sh4_handle_chcr1_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR1; }
+ UINT32 sh4_handle_chcr2_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR2; }
+ UINT32 sh4_handle_chcr3_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_CHCR3; }
+ UINT32 sh4_handle_dmaor_addr_r(sh4_state *sh4, UINT32 mem_mask) { return sh4->SH4_DMAOR; }
diff --git a/src/emu/cpu/sh4/sh4dmac.h b/src/emu/cpu/sh4/sh4dmac.h
new file mode 100644
index 00000000000..012ddcc21d2
--- /dev/null
+++ b/src/emu/cpu/sh4/sh4dmac.h
@@ -0,0 +1,63 @@
+/* SHA3/4 DMA Controller */
+
+/* bit definitions */
+#define CHCR_SSA 0xe0000000
+#define CHCR_STC 0x10000000
+#define CHCR_DSA 0x0e000000
+#define CHCR_DTC 0x01000000
+#define CHCR_DS 0x00080000
+#define CHCR_RL 0x00040000
+#define CHCR_AM 0x00020000
+#define CHCR_AL 0x00010000
+#define CHCR_DM 0x0000c000
+#define CHCR_SM 0x00003000
+#define CHCR_RS 0x00000f00
+#define CHCR_TM 0x00000080
+#define CHCR_TS 0x00000070
+#define CHCR_IE 0x00000004
+#define CHCR_TE 0x00000002
+#define CHCR_DE 0x00000001
+
+#define DMAOR_DDT 0x8000
+#define DMAOR_PR 0x0300
+#define DMAOR_COD 0x0010
+#define DMAOR_AE 0x0004
+#define DMAOR_NMIF 0x0002
+#define DMAOR_DME 0x0001
+
+TIMER_CALLBACK( sh4_dmac_callback );
+
+void sh4_handle_sar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_sar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_sar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_sar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_dar0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_dar1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_dar2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_dar3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_dmatcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_dmatcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_dmatcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_dmatcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_chcr0_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_chcr1_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_chcr2_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_chcr3_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+void sh4_handle_dmaor_addr_w(sh4_state *sh4, UINT32 data, UINT32 mem_mask);
+UINT32 sh4_handle_sar0_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_sar1_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_sar2_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_sar3_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_dar0_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_dar1_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_dar2_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_dar3_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_dmatcr0_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_dmatcr1_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_dmatcr2_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_dmatcr3_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_chcr0_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_chcr1_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_chcr2_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_chcr3_addr_r(sh4_state *sh4, UINT32 mem_mask);
+UINT32 sh4_handle_dmaor_addr_r(sh4_state *sh4, UINT32 mem_mask);
diff --git a/src/emu/cpu/sh4/sh4regs.h b/src/emu/cpu/sh4/sh4regs.h
index 422d19cf056..c33dc0a67b4 100644
--- a/src/emu/cpu/sh4/sh4regs.h
+++ b/src/emu/cpu/sh4/sh4regs.h
@@ -49,23 +49,23 @@
#define GPIOIC 0x3012 /* FF800048 */
#define SDMR2 0x3200 /* FF900000 */
#define SDMR3 0x3280 /* FF940000 */
-#define SAR0 0x3400 /* FFA00000 */
-#define DAR0 0x3401 /* FFA00004 */
-#define DMATCR0 0x3402 /* FFA00008 */
-#define CHCR0 0x3403 /* FFA0000C */
-#define SAR1 0x3404 /* FFA00010 */
-#define DAR1 0x3405 /* FFA00014 */
-#define DMATCR1 0x3406 /* FFA00018 */
-#define CHCR1 0x3407 /* FFA0001C */
-#define SAR2 0x3408 /* FFA00020 */
-#define DAR2 0x3409 /* FFA00024 */
-#define DMATCR2 0x340A /* FFA00028 */
-#define CHCR2 0x340B /* FFA0002C */
-#define SAR3 0x340C /* FFA00030 */
-#define DAR3 0x340D /* FFA00034 */
-#define DMATCR3 0x340E /* FFA00038 */
-#define CHCR3 0x340F /* FFA0003C */
-#define DMAOR 0x3410 /* FFA00040 */
+#define SH4_SAR0_ADDR 0x3400 /* FFA00000 */
+#define SH4_DAR0_ADDR 0x3401 /* FFA00004 */
+#define SH4_DMATCR0_ADDR 0x3402 /* FFA00008 */
+#define SH4_CHCR0_ADDR 0x3403 /* FFA0000C */
+#define SH4_SAR1_ADDR 0x3404 /* FFA00010 */
+#define SH4_DAR1_ADDR 0x3405 /* FFA00014 */
+#define SH4_DMATCR1_ADDR 0x3406 /* FFA00018 */
+#define SH4_CHCR1_ADDR 0x3407 /* FFA0001C */
+#define SH4_SAR2_ADDR 0x3408 /* FFA00020 */
+#define SH4_DAR2_ADDR 0x3409 /* FFA00024 */
+#define SH4_DMATCR2_ADDR 0x340A /* FFA00028 */
+#define SH4_CHCR2_ADDR 0x340B /* FFA0002C */
+#define SH4_SAR3_ADDR 0x340C /* FFA00030 */
+#define SH4_DAR3_ADDR 0x340D /* FFA00034 */
+#define SH4_DMATCR3_ADDR 0x340E /* FFA00038 */
+#define SH4_CHCR3_ADDR 0x340F /* FFA0003C */
+#define SH4_DMAOR_ADDR 0x3410 /* FFA00040 */
#define SAR4 0x3414 /* FFA00050 */
#define DAR4 0x3415 /* FFA00054 */
#define DMATCR4 0x3416 /* FFA00058 */
@@ -158,30 +158,7 @@
#define SDINT 0x3E05 /* FFF00014 */
#define SIZEREGS 15878
-/* bit definitions */
-#define CHCR_SSA 0xe0000000
-#define CHCR_STC 0x10000000
-#define CHCR_DSA 0x0e000000
-#define CHCR_DTC 0x01000000
-#define CHCR_DS 0x00080000
-#define CHCR_RL 0x00040000
-#define CHCR_AM 0x00020000
-#define CHCR_AL 0x00010000
-#define CHCR_DM 0x0000c000
-#define CHCR_SM 0x00003000
-#define CHCR_RS 0x00000f00
-#define CHCR_TM 0x00000080
-#define CHCR_TS 0x00000070
-#define CHCR_IE 0x00000004
-#define CHCR_TE 0x00000002
-#define CHCR_DE 0x00000001
-#define DMAOR_DDT 0x8000
-#define DMAOR_PR 0x0300
-#define DMAOR_COD 0x0010
-#define DMAOR_AE 0x0004
-#define DMAOR_NMIF 0x0002
-#define DMAOR_DME 0x0001
#define MMUCR_LRUI 0xfc000000
#define MMUCR_URB 0x00fc0000
diff --git a/src/mame/drivers/cavesh3.c b/src/mame/drivers/cavesh3.c
index 4a6c812621e..3a508e82650 100644
--- a/src/mame/drivers/cavesh3.c
+++ b/src/mame/drivers/cavesh3.c
@@ -6,12 +6,12 @@
#include "cpu/sh4/sh4.h"
+
class cavesh3_state : public driver_device
{
public:
cavesh3_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) { }
-
};
@@ -26,37 +26,22 @@ SCREEN_UPDATE(cavesh3)
-static READ64_HANDLER( serial_rtc_eeprom_r )
-{
- if (mem_mask & U64(0xff00ffffffffffff))
- {
- logerror("unknown serial_rtc_eeprom_r access %08x%08x\n",(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
- }
-
- return (UINT64)(space->machine().rand()&0xff)<<(32+16);
-}
-
-static WRITE64_HANDLER( serial_rtc_eeprom_w )
-{
- if (mem_mask & U64(0xff000000ffffffff))
- {
- logerror("unknown serial_rtc_eeprom_w access %08x%08x\n",(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
- }
-}
-static READ64_HANDLER( cavesh3_blitter_r )
+static READ32_HANDLER( cavesh3_blitter_r )
{
- UINT64 ret = space->machine().rand();
+// UINT64 ret = space->machine().rand();
+ static UINT32 i = 0;
+ i^=0xffffffff;
- logerror("cavesh3_blitter_r access at %08x (%08x) - mem_mask %08x%08x\n",offset, offset*8, (UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
+ logerror("%08x cavesh3_blitter_r access at %08x (%08x) - mem_mask %08x\n",cpu_get_pc(&space->device()), offset, offset*4, mem_mask);
switch (offset)
{
- case 0x2:
- return ret ^ (ret<<32);
-
case 0x4:
+ return i;
+
+ case 0x9:
return 0;
default:
@@ -71,9 +56,9 @@ static READ64_HANDLER( cavesh3_blitter_r )
}
-static WRITE64_HANDLER( cavesh3_blitter_w )
+static WRITE32_HANDLER( cavesh3_blitter_w )
{
- logerror("cavesh3_blitter_w access at %08x (%08x) - %08x%08x %08x%08x\n",offset, offset*8, (UINT32)(data>>32),(UINT32)(data&0xffffffff),(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
+ logerror("%08x cavesh3_blitter_w access at %08x (%08x) - %08x %08x\n",cpu_get_pc(&space->device()),offset, offset*8, data,mem_mask);
}
static READ64_HANDLER( ymz2770c_z_r )
@@ -88,33 +73,308 @@ static WRITE64_HANDLER( ymz2770c_z_w )
}
-static READ64_HANDLER( cavesh3_nand_r )
+
+
+// FLASH
+
+#define FLASH_PAGE_SIZE (2048+64)
+
+UINT8 flash_page_data[FLASH_PAGE_SIZE];
+
+typedef enum { STATE_IDLE = 0, STATE_READ, STATE_READ_ID, STATE_READ_STATUS } flash_state_t;
+static const char *flash_state_name[] = { "IDLE", "READ", "READ_ID", "READ_STATUS" };
+
+static flash_state_t flash_state;
+
+static UINT8 flash_enab;
+
+static UINT8 flash_cmd_seq;
+static UINT32 flash_cmd_prev;
+
+static UINT8 flash_addr_seq;
+static UINT8 flash_read_seq;
+
+static UINT16 flash_row, flash_col;
+static UINT16 flash_page_addr;
+static UINT16 flash_page_index;
+
+static void flash_hard_reset(running_machine &machine)
+{
+// logerror("%08x FLASH: RESET\n", cpuexec_describe_context(machine));
+
+ flash_state = STATE_READ;
+
+ flash_cmd_prev = -1;
+ flash_cmd_seq = 0;
+
+ flash_addr_seq = 0;
+ flash_read_seq = 0;
+
+ flash_row = 0;
+ flash_col = 0;
+
+ memset(flash_page_data, 0, FLASH_PAGE_SIZE);
+ flash_page_addr = 0;
+ flash_page_index = 0;
+}
+
+static WRITE8_HANDLER( flash_enab_w )
+{
+ logerror("%08x FLASH: enab = %02X\n", cpu_get_pc(&space->device()), data);
+ //flash_enab = data;
+ flash_enab = 1; // todo, why does it get turned off again instantly?
+}
+
+static void flash_change_state(running_machine &machine, flash_state_t state)
+{
+ flash_state = state;
+
+ flash_cmd_prev = -1;
+ flash_cmd_seq = 0;
+
+ flash_read_seq = 0;
+ flash_addr_seq = 0;
+
+ logerror("flash_change_state - FLASH: state = %s\n", flash_state_name[state]);
+}
+
+static WRITE8_HANDLER( flash_cmd_w )
{
- if (mem_mask & U64(0x00ffffffffffffff))
+ if (!flash_enab)
+ return;
+
+ logerror("%08x FLASH: cmd = %02X (prev = %02X)\n", cpu_get_pc(&space->device()), data, flash_cmd_prev);
+
+ if (flash_cmd_prev == -1)
{
- logerror("unknown cavesh3_nand_r access %08x%08x\n",(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
+ flash_cmd_prev = data;
+
+ switch (data)
+ {
+ case 0x00: // READ
+ flash_addr_seq = 0;
+ break;
+
+ case 0x70: // READ STATUS
+ flash_change_state( space->machine(), STATE_READ_STATUS );
+ break;
+
+ case 0x90: // READ ID
+ flash_change_state( space->machine(), STATE_READ_ID );
+ break;
+
+ case 0xff: // RESET
+ flash_change_state( space->machine(), STATE_IDLE );
+ break;
+
+ default:
+ {
+ logerror("%08x FLASH: unknown cmd1 = %02X\n", cpu_get_pc(&space->device()), data);
+ }
+ }
}
else
{
- logerror("cavesh3_nand_r access %08x%08x\n",(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
+ switch (flash_cmd_prev)
+ {
+ case 0x00: // READ
+ if (data == 0x30)
+ {
+ UINT8 *region = space->machine().region( "game" )->base();
+
+ memcpy(flash_page_data, region + flash_row * FLASH_PAGE_SIZE, FLASH_PAGE_SIZE);
+ flash_page_addr = flash_col;
+ flash_page_index = flash_row;
+
+ flash_change_state( space->machine(), STATE_READ );
+
+ logerror("%08x FLASH: caching page = %04X\n", cpu_get_pc(&space->device()), flash_row);
+ }
+ break;
+
+ default:
+ {
+ logerror("%08x FLASH: unknown cmd2 = %02X (cmd1 = %02X)\n", cpu_get_pc(&space->device()), data, flash_cmd_prev);
+ }
+ }
+ }
+}
+
+static WRITE8_HANDLER( flash_addr_w )
+{
+ if (!flash_enab)
+ return;
+
+ logerror("%08x FLASH: addr = %02X (seq = %02X)\n", cpu_get_pc(&space->device()), data, flash_addr_seq);
+
+ switch( flash_addr_seq++ )
+ {
+ case 0:
+ flash_col = (flash_col & 0xff00) | data;
+ break;
+ case 1:
+ flash_col = (flash_col & 0x00ff) | (data << 8);
+ break;
+ case 2:
+ flash_row = (flash_row & 0xff00) | data;
+ break;
+ case 3:
+ flash_row = (flash_row & 0x00ff) | (data << 8);
+ flash_addr_seq = 0;
+ break;
+ }
+}
+
+static READ8_HANDLER( flash_io_r )
+{
+ UINT8 data = 0x00;
+ UINT32 old;
+
+ if (!flash_enab)
+ return 0xff;
+
+ switch (flash_state)
+ {
+ case STATE_READ_ID:
+ old = flash_read_seq;
+
+ switch( flash_read_seq++ )
+ {
+ case 0:
+ data = 0xEC; // Manufacturer
+ break;
+ case 1:
+ data = 0xF1; // Device
+ break;
+ case 2:
+ data = 0x00; // XX
+ break;
+ case 3:
+ data = 0x15; // Flags
+ flash_read_seq = 0;
+ break;
+ }
+
+ logerror("%08x FLASH: read %02X from id(%02X)\n", cpu_get_pc(&space->device()), data, old);
+ break;
+
+ case STATE_READ:
+ if (flash_page_addr > FLASH_PAGE_SIZE-1)
+ flash_page_addr = FLASH_PAGE_SIZE-1;
+
+ old = flash_page_addr;
+
+ data = flash_page_data[flash_page_addr++];
+
+// logerror("%08x FLASH: read data %02X from addr %03X (page %04X)\n", cpu_get_pc(&space->device()), data, old, flash_page_index);
+ break;
+
+ case STATE_READ_STATUS:
+ // bit 7 = writeable, bit 6 = ready, bit 5 = ready/true ready, bit 1 = fail(N-1), bit 0 = fail
+ data = 0xe0;
+ logerror("%08x FLASH: read status %02X\n", cpu_get_pc(&space->device()), data);
+ break;
+
+ default:
+ {
+ logerror("%08x FLASH: unknown read in state %s\n", cpu_get_pc(&space->device()), flash_state_name[flash_state]);
+ }
}
- return 0;// (UINT64)(space->machine().rand()&0xff)<<(32+16+8);
+ return data;
+}
+/*
+static READ8_HANDLER( flash_ready_r )
+{
+ return 1;
+}
+
+// FLASH interface
+
+static READ32_HANDLER( ibara_flash_ready_r )
+{
+ // 400012a contains test bit (shown in service mode)
+ return ((flash_ready_r(space, offset) ? 0x20 : 0x00) << 24) |
+ input_port_read(space->machine(), "PORT_EF");
+}
+*/
+static READ8_HANDLER( ibara_flash_io_r )
+{
+ switch (offset)
+ {
+ default:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+
+ // logerror("ibara_flash_io_r offset %04x\n", offset);
+ return 0xff;
+
+ case 0x00:
+ return flash_io_r(space,offset);
+ }
}
-static WRITE64_HANDLER( cavesh3_nand_w )
+static WRITE8_HANDLER( ibara_flash_io_w )
{
- if (mem_mask & U64(0xff0000ffffffffff))
+ switch (offset)
{
- logerror("unknown cavesh3_nand_w access %08x%08x %08x%08x\n",(UINT32)(data>>32),(UINT32)(data&0xffffffff),(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
+ default:
+ case 0x00:
+ case 0x03:
+ logerror("unknown ibara_flash_io_w offset %04x data %02x\n", offset, data); // 03 enable/disable fgpa access?
+ break;
+
+ case 0x01:
+ flash_cmd_w(space, offset, data);
+ break;
+
+ case 0x2:
+ flash_addr_w(space, offset, data);
+ break;
}
- else
+}
+
+
+
+
+static READ8_HANDLER( serial_rtc_eeprom_r )
+{
+ switch (offset)
+ {
+ default:
+ logerror("unknown serial_rtc_eeprom_r access offset %02x\n", offset);
+ return 0xff;
+ }
+}
+
+static WRITE8_HANDLER( serial_rtc_eeprom_w )
+{
+ switch (offset)
{
- logerror("cavesh3_nand_w access %08x%08x %08x%08x\n",(UINT32)(data>>32),(UINT32)(data&0xffffffff),(UINT32)(mem_mask>>32),(UINT32)(mem_mask&0xffffffff));
+ case 0x01:
+ // data & 0x00010000 = DATA
+ // data & 0x00020000 = CLK
+ // data & 0x00040000 = CE
+ break;
+
+ case 0x03:
+ flash_enab_w(space,offset,data);
+ return;
+
+ default:
+ logerror("unknown serial_rtc_eeprom_w access offset %02x data %02x\n",offset, data);
+ break;
}
+
}
+
static ADDRESS_MAP_START( cavesh3_map, AS_PROGRAM, 64 )
AM_RANGE(0x00000000, 0x001fffff) AM_ROM AM_REGION("maincpu", 0)
AM_RANGE(0x00200000, 0x003fffff) AM_ROM AM_REGION("maincpu", 0)
@@ -124,10 +384,10 @@ static ADDRESS_MAP_START( cavesh3_map, AS_PROGRAM, 64 )
AM_RANGE(0x0c000000, 0x0c7fffff) AM_RAM // work RAM
AM_RANGE(0x0c800000, 0x0cffffff) AM_RAM // mirror of above on type B boards, extra ram on type D
- AM_RANGE(0x10000000, 0x10000007) AM_READWRITE(cavesh3_nand_r, cavesh3_nand_w)
+ AM_RANGE(0x10000000, 0x10000007) AM_READWRITE8(ibara_flash_io_r, ibara_flash_io_w, U64(0xffffffffffffffff))
AM_RANGE(0x10400000, 0x10400007) AM_READWRITE(ymz2770c_z_r, ymz2770c_z_w)
- AM_RANGE(0x10C00000, 0x10C00007) AM_READWRITE(serial_rtc_eeprom_r, serial_rtc_eeprom_w)
- AM_RANGE(0x18000000, 0x18000057) AM_READWRITE(cavesh3_blitter_r, cavesh3_blitter_w)
+ AM_RANGE(0x10C00000, 0x10C00007) AM_READWRITE8(serial_rtc_eeprom_r, serial_rtc_eeprom_w, U64(0xffffffffffffffff))
+ AM_RANGE(0x18000000, 0x18000057) AM_READWRITE32(cavesh3_blitter_r, cavesh3_blitter_w, U64(0xffffffffffffffff))
AM_RANGE(0xf0000000, 0xf0ffffff) AM_RAM // mem mapped cache (sh3 internal?)
/* 0xffffe000, 0xffffffff SH3 Internal Regs 2 */
@@ -143,26 +403,12 @@ static INPUT_PORTS_START( cavesh3 )
INPUT_PORTS_END
-#define CAVE_CPU_CLOCK 133333333
+#define CAVE_CPU_CLOCK 12800000 * 8
static const struct sh4_config sh4cpu_config = { 1, 0, 1, 0, 0, 0, 1, 1, 0, CAVE_CPU_CLOCK };
-static IRQ_CALLBACK(cavesh3_int_callback)
-{
- if (irqline == 4)
- {
- return 0;
- }
- else
- {
- logerror("irqline %02x\n",irqline);
-
- return 0;
- }
-}
-
static INTERRUPT_GEN(cavesh3_interrupt)
{
@@ -171,9 +417,11 @@ static INTERRUPT_GEN(cavesh3_interrupt)
static MACHINE_RESET( cavesh3 )
{
- device_set_irq_callback(machine.device("maincpu"), cavesh3_int_callback);
+ flash_enab = 0;
+ flash_hard_reset(machine);
}
+
static MACHINE_CONFIG_START( cavesh3, cavesh3_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", SH3BE, CAVE_CPU_CLOCK)
@@ -375,6 +623,7 @@ ROM_END
+
GAME( 2004, mushisam, 0, cavesh3, cavesh3, 0, ROT0, "Cave", "Mushihime Sama (2004/10/12 MASTER VER.)", GAME_NOT_WORKING | GAME_NO_SOUND )
GAME( 2004, mushisama, mushisam, cavesh3, cavesh3, 0, ROT0, "Cave", "Mushihime Sama (2004/10/12 MASTER VER)", GAME_NOT_WORKING | GAME_NO_SOUND )
GAME( 2005, espgal2, 0, cavesh3, cavesh3, 0, ROT0, "Cave", "EspGaluda II (2005/11/14 MASTER VER)", GAME_NOT_WORKING | GAME_NO_SOUND )