<commit_before>/******************************************************************************\
* Project:  SP SU Emulation Table:  Move to System Control Coprocessor (MTC0)  *
* Creator:  <NAME>                                                      *
* Release:  2013.01.10                                                         *
* License:  none (public domain)                                               *
\******************************************************************************/

#define DMA_CACHE   (*RSP.SP_MEM_ADDR_REG)
#define DMA_DRAM    (*RSP.SP_DRAM_ADDR_REG)

/* defined in systems/n64.c */
#define rdram ((UINT32*)RSP.RDRAM)
//extern UINT32 *rdram;
#define rsp_imem ((UINT32*)RSP.IMEM)
//extern UINT32 *rsp_imem;
#define rsp_dmem ((UINT32*)RSP.DMEM)
//extern UINT32 *rsp_dmem;
//extern void dp_full_sync(void);

static int sp_dma_length;

static void sp_dma(int direction)
{
//    Ville Linde
    int i, j;
    int length;
    int count;
    int skip;
//  
    UINT8 *src, *dst;
    INT32 l = sp_dma_length;

    length = ((l & 0xFFF) | 7) + 1;
    skip   = (l >> 20) + length;
    count  = ((l >> 12) & 0xFF) + 1;

    if (direction == 0) // RDRAM -> I/DMEM
    {
// 2    
// UINT32 src_address = DMA_DRAM & 0xFFFFFF;
// UINT32 dst_address = (DMA_CACHE & 0x1000) ? 0x4001000 : 0x4000000;
//  
        src = (UINT8*)&rdram[(DMA_DRAM & 0xFFFFFF) / 4];
        dst = (DMA_CACHE & 0x1000)
            ? (UINT8*)&rsp_imem[(DMA_CACHE & 0xFFF) / 4]
            : (UINT8*)&rsp_dmem[(DMA_CACHE & 0xFFF) / 4];
        // cpuintrf_push_context(0); // 
#define BYTE8_XOR_BE(a) ((a)^7) //  JFG, Ocarina of Time
        for (j = 0; j < count; j++)
        {
            for (i = 0; i < length; i++)
            {
                // UINT8 b = program_read_byte_64be(src_address + i + (j*skip));
// program_write_byte_64be(dst_address + ((DMA_CACHE + i + (j*length)) & 0xFFF), b);
                dst[BYTE8_XOR_BE((i + j*length)&0xfff)] = src[BYTE8_XOR_BE(i + j*skip)];
            }
        }
        // cpuintrf_pop_context(); // 
        *RSP.SP_DMA_BUSY_REG = 0;
        *RSP.SP_STATUS_REG  &= ~SP_STATUS_DMABUSY;
    }
    else // I/DMEM -> RDRAM
    {
        // 2    
        // UINT32 dst_address = DMA_DRAM & 0xFFFFFF;
        // UINT32 src_address = (DMA_CACHE & 0x1000) ? 0x4001000 : 0x4000000;
//  
        dst = (UINT8*)&rdram[(DMA_DRAM & 0xFFFFFF) / 4];
        src = (DMA_CACHE & 0x1000)
            ? (UINT8*)&rsp_imem[(DMA_CACHE & 0xFFF) / 4]
            : (UINT8*)&rsp_dmem[(DMA_CACHE & 0xFFF) / 4];
        // cpuintrf_push_context(0); // 
        for (j = 0; j < count; j++)
        {
            for (i = 0; i < length; i++)
            {
                // UINT8 b = program_read_byte_64be(src_address + ((DMA_CACHE + i + (j*length)) & 0xfff));
                // program_write_byte_64be(dst_address + i + (j*skip), b);
                dst[BYTE8_XOR_BE(i + j*skip)]
              = src[BYTE8_XOR_BE((i + j*length)&0xfff)];
            }
        }
        // cpuintrf_pop_context(); // 
        *RSP.SP_DMA_BUSY_REG = 0;
        *RSP.SP_STATUS_REG  &= ~SP_STATUS_DMABUSY;
    }
}

void MTC0(int rt, int rd)
{
/* Not yet implemented:  SP interrupt locking.
 * One or two games need to do this with SP_STATUS, but left it out to see.
 * I forgot the games. :( :) :D
 */
    switch (rd)
    {
        case 0x0:
            *RSP.SP_MEM_ADDR_REG = SR[rt];
            if (SR[rt] & 07)
            { /* All DMA transfers must be 64-bit-aligned. */
                message("MTC0\nDMA_CACHE", 1);
                *RSP.SP_MEM_ADDR_REG &= 0xFFFFFFF8;
            } /* Do NOT worry about the extra bits 0xFFFFE000 until DMA R/W. */
            return;
        case 0x1:
            *RSP.SP_DRAM_ADDR_REG = SR[rt]; /* 24-bit RDRAM pt */
            if (SR[rt] & 07)
            { /* We don't really care about the reserved bits, just & 07. */
                message("MTC0\nDMA_DRAM", 1);
                *RSP.SP_DRAM_ADDR_REG &= 0xFFFFFFF8;
            } /* If extra bits (SR[rt]&0xFF000000) are used, DMA R/W adapts. */
            return;
        case 0x2:
            sp_dma_length = SR[rt] | 07;
            sp_dma(0);
            return;
        case 0x3:
            sp_dma_length = SR[rt] | 07;
            sp_dma(1);
            return;
        case 0x4:
/* To-do:  It is possible to use a switch statement here to massively speed
 * up all of the flags maintenance in place of this massive, complex chain of
 * if()'s, by using a switch on every combination possibility of SR[rt] flags
 * set, but that of course is going to take time to implement.  The real
 * bottleneck behind why games are slow is the RDP and VU computational ops.
 */
            if (SR[rt] & 0x00000001) /* clear halt */
                *RSP.SP_STATUS_REG &= ~SP_STATUS_HALT;
            if (SR[rt] & 0x00000002) /* set halt */
                *RSP.SP_STATUS_REG |= SP_STATUS_HALT;
            if (SR[rt] & 0x00000004) /* clear broke */<commit_msg>destroy static DMA length segment; use raw CP0 access<commit_after>/******************************************************************************\
* Project:  SP SU Emulation Table:  Move to System Control Coprocessor (MTC0)  *
* Creator:  <NAME>                                                      *
* Release:  2013.01.10                                                         *
* License:  none (public domain)                                               *
\******************************************************************************/

#define DMA_CACHE   (*RSP.SP_MEM_ADDR_REG)
#define DMA_DRAM    (*RSP.SP_DRAM_ADDR_REG)

/* defined in systems/n64.c */
#define rdram ((UINT32*)RSP.RDRAM)
//extern UINT32 *rdram;
#define rsp_imem ((UINT32*)RSP.IMEM)
//extern UINT32 *rsp_imem;
#define rsp_dmem ((UINT32*)RSP.DMEM)
//extern UINT32 *rsp_dmem;
//extern void dp_full_sync(void);

#define BYTE8_XOR_BE(a) ((a)^7)
/*  JFG, Ocarina of Time */

static void sp_dma(int direction)
{
//    Ville Linde
    int i, j;
    int length;
    int count;
    int skip;
//  
    UINT8 *src, *dst;
    INT32 l = direction ? *RSP.SP_WR_LEN_REG : *RSP.SP_RD_LEN_REG;

    length = ((l & 0xFFF) | 7) + 1;
    skip   = (l >> 20) + length;
    count  = ((l >> 12) & 0xFF) + 1;

    if (direction == 0) // RDRAM -> I/DMEM
    {
// 2    
// UINT32 src_address = DMA_DRAM & 0xFFFFFF;
// UINT32 dst_address = (DMA_CACHE & 0x1000) ? 0x4001000 : 0x4000000;
//  
        src = (UINT8*)&rdram[(DMA_DRAM & 0xFFFFFF) / 4];
        dst = (DMA_CACHE & 0x1000)
            ? (UINT8*)&rsp_imem[(DMA_CACHE & 0xFFF) / 4]
            : (UINT8*)&rsp_dmem[(DMA_CACHE & 0xFFF) / 4];
        // cpuintrf_push_context(0); // 
        for (j = 0; j < count; j++)
        {
            for (i = 0; i < length; i++)
            {
                // UINT8 b = program_read_byte_64be(src_address + i + (j*skip));
// program_write_byte_64be(dst_address + ((DMA_CACHE + i + (j*length)) & 0xFFF), b);
                dst[BYTE8_XOR_BE((i + j*length)&0xfff)] = src[BYTE8_XOR_BE(i + j*skip)];
            }
        }
        // cpuintrf_pop_context(); // 
        *RSP.SP_DMA_BUSY_REG = 0;
        *RSP.SP_STATUS_REG  &= ~SP_STATUS_DMABUSY;
    }
    else // I/DMEM -> RDRAM
    {
        // 2    
        // UINT32 dst_address = DMA_DRAM & 0xFFFFFF;
        // UINT32 src_address = (DMA_CACHE & 0x1000) ? 0x4001000 : 0x4000000;
//  
        dst = (UINT8*)&rdram[(DMA_DRAM & 0xFFFFFF) / 4];
        src = (DMA_CACHE & 0x1000)
            ? (UINT8*)&rsp_imem[(DMA_CACHE & 0xFFF) / 4]
            : (UINT8*)&rsp_dmem[(DMA_CACHE & 0xFFF) / 4];
        // cpuintrf_push_context(0); // 
        for (j = 0; j < count; j++)
        {
            for (i = 0; i < length; i++)
            {
                // UINT8 b = program_read_byte_64be(src_address + ((DMA_CACHE + i + (j*length)) & 0xfff));
                // program_write_byte_64be(dst_address + i + (j*skip), b);
                dst[BYTE8_XOR_BE(i + j*skip)]
              = src[BYTE8_XOR_BE((i + j*length)&0xfff)];
            }
        }
        // cpuintrf_pop_context(); // 
        *RSP.SP_DMA_BUSY_REG = 0;
        *RSP.SP_STATUS_REG  &= ~SP_STATUS_DMABUSY;
    }
}

void MTC0(int rt, int rd)
{
/* Not yet implemented:  SP interrupt locking.
 * One or two games need to do this with SP_STATUS, but left it out to see.
 * I forgot the games. :( :) :D
 */
    switch (rd)
    {
        case 0x0:
            *RSP.SP_MEM_ADDR_REG = SR[rt];
            if (SR[rt] & 07)
            { /* All DMA transfers must be 64-bit-aligned. */
                message("MTC0\nDMA_CACHE", 1);
                *RSP.SP_MEM_ADDR_REG &= 0xFFFFFFF8;
            } /* Do NOT worry about the extra bits 0xFFFFE000 until DMA R/W. */
            return;
        case 0x1:
            *RSP.SP_DRAM_ADDR_REG = SR[rt]; /* 24-bit RDRAM pt */
            if (SR[rt] & 07)
            { /* We don't really care about the reserved bits, just & 07. */
                message("MTC0\nDMA_DRAM", 1);
                *RSP.SP_DRAM_ADDR_REG &= 0xFFFFFFF8;
            } /* If extra bits (SR[rt]&0xFF000000) are used, DMA R/W adapts. */
            return;
        case 0x2:
            *RSP.SP_RD_LEN_REG = SR[rt]; /* length |= 07; // immed or on DMA? */
            sp_dma(0);
            return;
        case 0x3:
            *RSP.SP_WR_LEN_REG = SR[rt]; /* length |= 07; // immed or on DMA? */
            sp_dma(1);
            return;
        case 0x4:
/* To-do:  It is possible to use a switch statement here to massively speed
 * up all of the flags maintenance in place of this massive, complex chain of
 * if()'s, by using a switch on every combination possibility of SR[rt] flags
 * set, but that of course is going to take time to implement.  The real
 * bottleneck behind why games are slow is the RDP and VU computational ops.
 */
            if (SR[rt] & 0x00000001) /* clear halt */
                *RSP.SP_STATUS_REG &= ~SP_STATUS_HALT;
            if (SR[rt] & 0x00000002) /* set halt */
                *RSP.SP_STATUS_REG |= SP_STATUS_HALT;
            if (SR[rt] & 0x00000004) /* clear broke */
{'fraction_non_alphanumeric': 0.1622645270606997, 'fraction_numerical': 0.04375560649855477, 'mean_word_length': 1.8352641989262504, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 10, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3159002', 'n_tokens_mistral': 3820, 'n_tokens_neox': 3426, 'n_words': 847}