2012-12-19 09:30:18 +00:00
/****************************************************************************
* *
* Project 64 - A Nintendo 64 emulator . *
* http : //www.pj64-emu.com/ *
* Copyright ( C ) 2012 Project64 . All rights reserved . *
* *
* License : *
* GNU / GPLv2 http : //www.gnu.org/licenses/gpl-2.0.html *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-22 20:36:28 +00:00
# include "stdafx.h"
CDMA : : CDMA ( CFlashram & FlashRam , CSram & Sram ) :
m_FlashRam ( FlashRam ) ,
m_Sram ( Sram )
{
2015-03-29 17:19:28 +00:00
2010-06-22 20:36:28 +00:00
}
2015-04-28 22:19:02 +00:00
void CDMA : : OnFirstDMA ( )
2015-03-29 17:19:28 +00:00
{
switch ( g_Rom - > CicChipID ( ) )
{
2015-02-14 02:26:26 +00:00
case CIC_NUS_6101 : * ( DWORD * ) & ( ( g_MMU - > Rdram ( ) ) [ 0x318 ] ) = g_MMU - > RdramSize ( ) ; break ;
2015-05-08 02:48:46 +00:00
case CIC_NUS_8303 : * ( DWORD * ) & ( ( g_MMU - > Rdram ( ) ) [ 0x318 ] ) = g_MMU - > RdramSize ( ) ; break ;
2015-02-14 03:10:05 +00:00
case CIC_UNKNOWN :
2015-02-14 02:26:26 +00:00
case CIC_NUS_6102 : * ( DWORD * ) & ( ( g_MMU - > Rdram ( ) ) [ 0x318 ] ) = g_MMU - > RdramSize ( ) ; break ;
case CIC_NUS_6103 : * ( DWORD * ) & ( ( g_MMU - > Rdram ( ) ) [ 0x318 ] ) = g_MMU - > RdramSize ( ) ; break ;
case CIC_NUS_6105 : * ( DWORD * ) & ( ( g_MMU - > Rdram ( ) ) [ 0x3F0 ] ) = g_MMU - > RdramSize ( ) ; break ;
case CIC_NUS_6106 : * ( DWORD * ) & ( ( g_MMU - > Rdram ( ) ) [ 0x318 ] ) = g_MMU - > RdramSize ( ) ; break ;
2015-03-04 09:36:08 +00:00
default : g_Notify - > DisplayError ( L " Unhandled CicChip(%d) in first DMA " , g_Rom - > CicChipID ( ) ) ;
2010-06-22 20:36:28 +00:00
}
}
2015-04-28 22:19:02 +00:00
void CDMA : : PI_DMA_READ ( )
2015-03-29 17:19:28 +00:00
{
2010-06-22 20:36:28 +00:00
// PI_STATUS_REG |= PI_STATUS_DMA_BUSY;
2013-03-22 05:47:20 +00:00
if ( g_Reg - > PI_DRAM_ADDR_REG + g_Reg - > PI_RD_LEN_REG + 1 > g_MMU - > RdramSize ( ) )
{
2015-03-29 17:19:28 +00:00
if ( bHaveDebugger ( ) )
{
2015-06-23 14:02:20 +00:00
g_Notify - > DisplayError ( L " PI_DMA_READ not in Memory: %08X " , g_Reg - > PI_DRAM_ADDR_REG + g_Reg - > PI_RD_LEN_REG + 1 ) ;
2015-03-29 17:19:28 +00:00
}
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
return ;
}
2015-05-14 12:34:45 +00:00
if ( g_Reg - > PI_CART_ADDR_REG > = 0x10000000 & & g_Reg - > PI_CART_ADDR_REG < = 0x1FBFFFFF & & g_Settings - > LoadBool ( Game_AllowROMWrites ) )
{
DWORD i ;
BYTE * ROM = g_Rom - > GetRomAddress ( ) ;
BYTE * RDRAM = g_MMU - > Rdram ( ) ;
DWORD OldProtect ;
VirtualProtect ( ROM , g_Rom - > GetRomSize ( ) , PAGE_READWRITE , & OldProtect ) ;
g_Reg - > PI_CART_ADDR_REG - = 0x10000000 ;
if ( g_Reg - > PI_CART_ADDR_REG + g_Reg - > PI_RD_LEN_REG < g_Rom - > GetRomSize ( ) )
{
for ( i = 0 ; i < g_Reg - > PI_RD_LEN_REG ; i + + )
{
* ( ROM + ( ( g_Reg - > PI_CART_ADDR_REG + i ) ^ 3 ) ) = * ( RDRAM + ( ( g_Reg - > PI_DRAM_ADDR_REG + i ) ^ 3 ) ) ;
}
}
else
{
DWORD Len ;
Len = g_Rom - > GetRomSize ( ) - g_Reg - > PI_CART_ADDR_REG ;
for ( i = 0 ; i < Len ; i + + )
{
* ( ROM + ( ( g_Reg - > PI_CART_ADDR_REG + i ) ^ 3 ) ) = * ( RDRAM + ( ( g_Reg - > PI_DRAM_ADDR_REG + i ) ^ 3 ) ) ;
}
}
g_Reg - > PI_CART_ADDR_REG + = 0x10000000 ;
if ( ! g_System - > DmaUsed ( ) )
{
g_System - > SetDmaUsed ( true ) ;
OnFirstDMA ( ) ;
}
if ( g_Recompiler & & g_System - > bSMM_PIDMA ( ) )
{
g_Recompiler - > ClearRecompCode_Phys ( g_Reg - > PI_DRAM_ADDR_REG , g_Reg - > PI_WR_LEN_REG , CRecompiler : : Remove_DMA ) ;
}
VirtualProtect ( ROM , g_Rom - > GetRomSize ( ) , PAGE_READONLY , & OldProtect ) ;
}
2015-03-29 17:19:28 +00:00
if ( g_Reg - > PI_CART_ADDR_REG > = 0x08000000 & & g_Reg - > PI_CART_ADDR_REG < = 0x08010000 )
{
if ( g_System - > m_SaveUsing = = SaveChip_Auto )
{
g_System - > m_SaveUsing = SaveChip_Sram ;
}
if ( g_System - > m_SaveUsing = = SaveChip_Sram )
{
2010-06-22 20:36:28 +00:00
m_Sram . DmaToSram (
2012-11-17 02:18:14 +00:00
g_MMU - > Rdram ( ) + g_Reg - > PI_DRAM_ADDR_REG ,
g_Reg - > PI_CART_ADDR_REG - 0x08000000 ,
g_Reg - > PI_RD_LEN_REG + 1
2010-06-22 20:36:28 +00:00
) ;
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
return ;
}
2015-03-29 17:19:28 +00:00
if ( g_System - > m_SaveUsing = = SaveChip_FlashRam )
{
2010-06-22 20:36:28 +00:00
m_FlashRam . DmaToFlashram (
2012-11-17 02:18:14 +00:00
g_MMU - > Rdram ( ) + g_Reg - > PI_DRAM_ADDR_REG ,
g_Reg - > PI_CART_ADDR_REG - 0x08000000 ,
2015-02-12 21:26:17 +00:00
g_Reg - > PI_RD_LEN_REG + 1
2010-06-22 20:36:28 +00:00
) ;
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
return ;
}
}
2012-11-17 01:07:04 +00:00
if ( g_System - > m_SaveUsing = = SaveChip_FlashRam )
2010-06-30 21:35:44 +00:00
{
2015-06-23 14:02:20 +00:00
g_Notify - > DisplayError ( L " **** FLashRam DMA Read address %08X ***** " , g_Reg - > PI_CART_ADDR_REG ) ;
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
return ;
}
2013-03-22 05:47:20 +00:00
if ( bHaveDebugger ( ) )
{
2015-03-04 09:36:08 +00:00
g_Notify - > DisplayError ( L " PI_DMA_READ where are you dmaing to ? " ) ;
2013-03-22 05:47:20 +00:00
}
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
return ;
}
2015-04-28 22:19:02 +00:00
void CDMA : : PI_DMA_WRITE ( )
2015-02-12 21:26:17 +00:00
{
DWORD PI_WR_LEN_REG = ( ( g_Reg - > PI_WR_LEN_REG ) & 0x00FFFFFFul ) + 1 ;
if ( ( PI_WR_LEN_REG & 1 ) ! = 0 )
{
PI_WR_LEN_REG + = 1 ; /* fixes AI Shougi 3, Doraemon 3, etc. */
}
2010-06-22 20:36:28 +00:00
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG | = PI_STATUS_DMA_BUSY ;
2015-02-12 21:26:17 +00:00
if ( g_Reg - > PI_DRAM_ADDR_REG + PI_WR_LEN_REG > g_MMU - > RdramSize ( ) )
2010-06-22 20:36:28 +00:00
{
2015-06-23 14:02:20 +00:00
if ( g_Settings - > LoadBool ( Debugger_ShowUnhandledMemory ) ) { g_Notify - > DisplayError ( L " PI_DMA_WRITE not in Memory: %08X " , g_Reg - > PI_DRAM_ADDR_REG + PI_WR_LEN_REG ) ; }
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
return ;
}
2015-03-29 17:19:28 +00:00
if ( g_Reg - > PI_CART_ADDR_REG > = 0x08000000 & & g_Reg - > PI_CART_ADDR_REG < = 0x08010000 )
{
if ( g_System - > m_SaveUsing = = SaveChip_Auto )
{
g_System - > m_SaveUsing = SaveChip_Sram ;
}
if ( g_System - > m_SaveUsing = = SaveChip_Sram )
{
2010-06-22 20:36:28 +00:00
m_Sram . DmaFromSram (
2012-11-17 02:18:14 +00:00
g_MMU - > Rdram ( ) + g_Reg - > PI_DRAM_ADDR_REG ,
g_Reg - > PI_CART_ADDR_REG - 0x08000000 ,
2015-02-12 21:26:17 +00:00
PI_WR_LEN_REG
2010-06-22 20:36:28 +00:00
) ;
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
return ;
}
2015-03-29 17:19:28 +00:00
if ( g_System - > m_SaveUsing = = SaveChip_FlashRam )
{
2010-06-22 20:36:28 +00:00
m_FlashRam . DmaFromFlashram (
2012-11-17 02:18:14 +00:00
g_MMU - > Rdram ( ) + g_Reg - > PI_DRAM_ADDR_REG ,
g_Reg - > PI_CART_ADDR_REG - 0x08000000 ,
2015-02-12 21:26:17 +00:00
PI_WR_LEN_REG
2010-06-22 20:36:28 +00:00
) ;
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
}
return ;
}
2012-11-17 02:18:14 +00:00
if ( g_Reg - > PI_CART_ADDR_REG > = 0x10000000 & & g_Reg - > PI_CART_ADDR_REG < = 0x1FBFFFFF )
2010-06-30 21:35:44 +00:00
{
2010-06-22 20:36:28 +00:00
DWORD i ;
2015-05-14 12:34:45 +00:00
2010-06-22 20:36:28 +00:00
# ifdef tofix
# ifdef ROM_IN_MAPSPACE
2015-03-29 17:19:28 +00:00
if ( WrittenToRom )
{
2010-06-22 20:36:28 +00:00
DWORD OldProtect ;
2012-09-30 12:24:07 +00:00
VirtualProtect ( ROM , m_RomFileSize , PAGE_READONLY , & OldProtect ) ;
2010-06-22 20:36:28 +00:00
}
# endif
# endif
2015-05-14 12:34:45 +00:00
2012-11-17 02:24:42 +00:00
BYTE * ROM = g_Rom - > GetRomAddress ( ) ;
2012-11-17 01:18:00 +00:00
BYTE * RDRAM = g_MMU - > Rdram ( ) ;
2012-11-17 02:18:14 +00:00
g_Reg - > PI_CART_ADDR_REG - = 0x10000000 ;
2015-03-29 17:19:28 +00:00
if ( g_Reg - > PI_CART_ADDR_REG + PI_WR_LEN_REG < g_Rom - > GetRomSize ( ) )
{
for ( i = 0 ; i < PI_WR_LEN_REG ; i + + )
{
2012-11-17 02:18:14 +00:00
* ( RDRAM + ( ( g_Reg - > PI_DRAM_ADDR_REG + i ) ^ 3 ) ) = * ( ROM + ( ( g_Reg - > PI_CART_ADDR_REG + i ) ^ 3 ) ) ;
2010-06-22 20:36:28 +00:00
}
2015-03-29 17:19:28 +00:00
}
2015-06-21 14:51:37 +00:00
else if ( g_Reg - > PI_CART_ADDR_REG > = g_Rom - > GetRomSize ( ) )
{
DWORD cart = g_Reg - > PI_CART_ADDR_REG - g_Rom - > GetRomSize ( ) ;
while ( cart > = g_Rom - > GetRomSize ( ) )
{
cart - = g_Rom - > GetRomSize ( ) ;
}
for ( i = 0 ; i < PI_WR_LEN_REG ; i + + )
{
* ( RDRAM + ( ( g_Reg - > PI_DRAM_ADDR_REG + i ) ^ 3 ) ) = * ( ROM + ( ( cart + i ) ^ 3 ) ) ;
}
}
2015-03-29 17:19:28 +00:00
else
{
2010-06-22 20:36:28 +00:00
DWORD Len ;
2012-11-17 02:24:42 +00:00
Len = g_Rom - > GetRomSize ( ) - g_Reg - > PI_CART_ADDR_REG ;
2015-03-29 17:19:28 +00:00
for ( i = 0 ; i < Len ; i + + )
{
2012-11-17 02:18:14 +00:00
* ( RDRAM + ( ( g_Reg - > PI_DRAM_ADDR_REG + i ) ^ 3 ) ) = * ( ROM + ( ( g_Reg - > PI_CART_ADDR_REG + i ) ^ 3 ) ) ;
2010-06-22 20:36:28 +00:00
}
2015-03-29 17:19:28 +00:00
for ( i = Len ; i < PI_WR_LEN_REG - Len ; i + + )
{
2012-11-17 02:18:14 +00:00
* ( RDRAM + ( ( g_Reg - > PI_DRAM_ADDR_REG + i ) ^ 3 ) ) = 0 ;
2010-06-22 20:36:28 +00:00
}
}
2012-11-17 02:18:14 +00:00
g_Reg - > PI_CART_ADDR_REG + = 0x10000000 ;
2010-06-22 20:36:28 +00:00
2012-11-17 01:07:04 +00:00
if ( ! g_System - > DmaUsed ( ) )
2010-06-22 20:36:28 +00:00
{
2012-11-17 01:07:04 +00:00
g_System - > SetDmaUsed ( true ) ;
2010-06-22 20:36:28 +00:00
OnFirstDMA ( ) ;
}
2012-11-29 11:23:35 +00:00
if ( g_Recompiler & & g_System - > bSMM_PIDMA ( ) )
2010-06-22 20:36:28 +00:00
{
2012-11-17 02:18:14 +00:00
g_Recompiler - > ClearRecompCode_Phys ( g_Reg - > PI_DRAM_ADDR_REG , g_Reg - > PI_WR_LEN_REG , CRecompiler : : Remove_DMA ) ;
2010-06-22 20:36:28 +00:00
}
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
//ChangeTimer(PiTimer,(int)(PI_WR_LEN_REG * 8.9) + 50);
//ChangeTimer(PiTimer,(int)(PI_WR_LEN_REG * 8.9));
return ;
}
2015-06-23 14:02:20 +00:00
if ( g_Settings - > LoadBool ( Debugger_ShowUnhandledMemory ) )
{
g_Notify - > DisplayError ( L " PI_DMA_WRITE not in ROM: %08X " , g_Reg - > PI_CART_ADDR_REG ) ;
}
2012-11-17 02:18:14 +00:00
g_Reg - > PI_STATUS_REG & = ~ PI_STATUS_DMA_BUSY ;
g_Reg - > MI_INTR_REG | = MI_INTR_PI ;
g_Reg - > CheckInterrupts ( ) ;
2010-06-22 20:36:28 +00:00
}
2015-04-28 22:19:02 +00:00
void CDMA : : SP_DMA_READ ( )
2015-03-29 17:19:28 +00:00
{
2012-11-17 02:18:14 +00:00
g_Reg - > SP_DRAM_ADDR_REG & = 0x1FFFFFFF ;
2010-06-22 20:36:28 +00:00
2013-03-22 05:47:20 +00:00
if ( g_Reg - > SP_DRAM_ADDR_REG > g_MMU - > RdramSize ( ) )
{
if ( bHaveDebugger ( ) )
{
2015-06-23 14:02:20 +00:00
g_Notify - > DisplayError ( __FUNCTIONW__ L " \n SP_DRAM_ADDR_REG not in RDRam space: %08X " , g_Reg - > SP_DRAM_ADDR_REG ) ;
2013-03-22 05:47:20 +00:00
}
2012-11-17 02:18:14 +00:00
g_Reg - > SP_DMA_BUSY_REG = 0 ;
g_Reg - > SP_STATUS_REG & = ~ SP_STATUS_DMA_BUSY ;
2010-06-22 20:36:28 +00:00
return ;
}
2013-03-22 05:47:20 +00:00
if ( g_Reg - > SP_RD_LEN_REG + 1 + ( g_Reg - > SP_MEM_ADDR_REG & 0xFFF ) > 0x1000 )
{
if ( bHaveDebugger ( ) )
{
2015-06-23 14:02:20 +00:00
g_Notify - > DisplayError ( __FUNCTIONW__ L " \n Could not fit copy in memory segment " ) ;
2013-03-22 05:47:20 +00:00
}
2010-06-22 20:36:28 +00:00
return ;
}
2015-03-29 17:19:28 +00:00
if ( ( g_Reg - > SP_MEM_ADDR_REG & 3 ) ! = 0 )
{
g_Notify - > BreakPoint ( __FILEW__ , __LINE__ ) ;
}
if ( ( g_Reg - > SP_DRAM_ADDR_REG & 3 ) ! = 0 )
{
g_Notify - > BreakPoint ( __FILEW__ , __LINE__ ) ;
}
if ( ( ( g_Reg - > SP_RD_LEN_REG + 1 ) & 3 ) ! = 0 )
{
g_Notify - > BreakPoint ( __FILEW__ , __LINE__ ) ;
}
2010-06-22 20:36:28 +00:00
2012-11-17 02:18:14 +00:00
memcpy ( g_MMU - > Dmem ( ) + ( g_Reg - > SP_MEM_ADDR_REG & 0x1FFF ) , g_MMU - > Rdram ( ) + g_Reg - > SP_DRAM_ADDR_REG ,
g_Reg - > SP_RD_LEN_REG + 1 ) ;
2010-06-22 20:36:28 +00:00
2012-11-17 02:18:14 +00:00
g_Reg - > SP_DMA_BUSY_REG = 0 ;
g_Reg - > SP_STATUS_REG & = ~ SP_STATUS_DMA_BUSY ;
2010-06-22 20:36:28 +00:00
}
2015-04-28 22:19:02 +00:00
void CDMA : : SP_DMA_WRITE ( )
2013-03-22 05:47:20 +00:00
{
if ( g_Reg - > SP_DRAM_ADDR_REG > g_MMU - > RdramSize ( ) )
{
if ( bHaveDebugger ( ) )
{
2015-06-23 14:02:20 +00:00
g_Notify - > DisplayError ( L " SP DMA WRITE \n SP_DRAM_ADDR_REG not in RDRam space: %08X " , g_Reg - > SP_DRAM_ADDR_REG ) ;
2013-03-22 05:47:20 +00:00
}
2010-06-22 20:36:28 +00:00
return ;
}
2013-03-22 05:47:20 +00:00
if ( g_Reg - > SP_WR_LEN_REG + 1 + ( g_Reg - > SP_MEM_ADDR_REG & 0xFFF ) > 0x1000 )
{
if ( bHaveDebugger ( ) )
{
2015-03-04 09:36:08 +00:00
g_Notify - > DisplayError ( L " SP DMA WRITE \n could not fit copy in memory segement " ) ;
2013-03-22 05:47:20 +00:00
}
2010-06-22 20:36:28 +00:00
return ;
}
2015-03-29 17:19:28 +00:00
if ( ( g_Reg - > SP_MEM_ADDR_REG & 3 ) ! = 0 )
{
g_Notify - > BreakPoint ( __FILEW__ , __LINE__ ) ;
2015-03-29 21:58:51 +00:00
}
2015-03-29 17:19:28 +00:00
if ( ( g_Reg - > SP_DRAM_ADDR_REG & 3 ) ! = 0 )
{
g_Notify - > BreakPoint ( __FILEW__ , __LINE__ ) ;
}
if ( ( ( g_Reg - > SP_WR_LEN_REG + 1 ) & 3 ) ! = 0 )
{
g_Notify - > BreakPoint ( __FILEW__ , __LINE__ ) ;
}
2010-06-22 20:36:28 +00:00
2012-11-17 02:18:14 +00:00
memcpy ( g_MMU - > Rdram ( ) + g_Reg - > SP_DRAM_ADDR_REG , g_MMU - > Dmem ( ) + ( g_Reg - > SP_MEM_ADDR_REG & 0x1FFF ) ,
g_Reg - > SP_WR_LEN_REG + 1 ) ;
2010-06-22 20:36:28 +00:00
2012-11-17 02:18:14 +00:00
g_Reg - > SP_DMA_BUSY_REG = 0 ;
g_Reg - > SP_STATUS_REG & = ~ SP_STATUS_DMA_BUSY ;
2010-06-22 20:36:28 +00:00
}