1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - rdp_core.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2014 Bobby Smiles *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22 #include "rdp_core.h"
23
24 #include "../memory/memory.h"
25 #include "../plugin/plugin.h"
26 #include "../r4300/r4300_core.h"
27 #include "../rsp/rsp_core.h"
28
29 #include <string.h>
30
update_dpc_status(struct rdp_core * dp,uint32_t w)31 static int update_dpc_status(struct rdp_core* dp, uint32_t w)
32 {
33 /* see do_SP_Task for more info */
34 int do_sp_task_on_unfreeze = 0;
35
36 /* clear / set xbus_dmem_dma */
37 if (w & DPC_STATUS_CLR_XBUS_DMEM_DMA) dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_XBUS_DMEM_DMA;
38 if (w & DPC_STATUS_SET_XBUS_DMEM_DMA) dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_XBUS_DMEM_DMA;
39
40 /* clear / set freeze */
41 if (w & DPC_STATUS_CLR_FREEZE)
42 {
43 dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_FREEZE;
44
45 if (!(dp->sp->regs[SP_STATUS_REG] & (SP_STATUS_HALT | SP_STATUS_BROKE)))
46 do_sp_task_on_unfreeze = 1;
47 }
48
49 if (w & DPC_STATUS_SET_FREEZE) dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_FREEZE;
50
51 /* clear / set flush */
52 if (w & DPC_STATUS_CLR_FLUSH) dp->dpc_regs[DPC_STATUS_REG] &= ~DPC_STATUS_FLUSH;
53 if (w & DPC_STATUS_SET_FLUSH) dp->dpc_regs[DPC_STATUS_REG] |= DPC_STATUS_FLUSH;
54
55 return do_sp_task_on_unfreeze;
56 }
57
58
init_rdp(struct rdp_core * dp,struct r4300_core * r4300,struct rsp_core * sp,struct ri_controller * ri)59 void init_rdp(struct rdp_core* dp,
60 struct r4300_core* r4300,
61 struct rsp_core* sp,
62 struct ri_controller *ri)
63 {
64 dp->r4300 = r4300;
65 dp->sp = sp;
66 dp->ri = ri;
67 }
68
poweron_rdp(struct rdp_core * dp)69 void poweron_rdp(struct rdp_core* dp)
70 {
71 memset(dp->dpc_regs, 0, DPC_REGS_COUNT*sizeof(uint32_t));
72 memset(dp->dps_regs, 0, DPS_REGS_COUNT*sizeof(uint32_t));
73
74 poweron_fb(&dp->fb);
75 }
76
77
read_dpc_regs(void * opaque,uint32_t address,uint32_t * value)78 int read_dpc_regs(void* opaque, uint32_t address, uint32_t* value)
79 {
80 struct rdp_core* dp = (struct rdp_core*)opaque;
81 uint32_t reg = DPC_REG(address);
82
83 *value = dp->dpc_regs[reg];
84
85 return 0;
86 }
87
write_dpc_regs(void * opaque,uint32_t address,uint32_t value,uint32_t mask)88 int write_dpc_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
89 {
90 struct rdp_core* dp = (struct rdp_core*)opaque;
91 uint32_t reg = DPC_REG(address);
92
93 switch(reg)
94 {
95 case DPC_STATUS_REG:
96 if (update_dpc_status(dp, value & mask) != 0)
97 do_SP_Task(dp->sp);
98 case DPC_CURRENT_REG:
99 case DPC_CLOCK_REG:
100 case DPC_BUFBUSY_REG:
101 case DPC_PIPEBUSY_REG:
102 case DPC_TMEM_REG:
103 return 0;
104 }
105
106 dp->dpc_regs[reg] = MASKED_WRITE(&dp->dpc_regs[reg], value, mask);
107
108 switch(reg)
109 {
110 case DPC_START_REG:
111 dp->dpc_regs[DPC_CURRENT_REG] = dp->dpc_regs[DPC_START_REG];
112 break;
113 case DPC_END_REG:
114 gfx.processRDPList();
115 signal_rcp_interrupt(dp->r4300, MI_INTR_DP);
116 break;
117 }
118
119 return 0;
120 }
121
122
read_dps_regs(void * opaque,uint32_t address,uint32_t * value)123 int read_dps_regs(void* opaque, uint32_t address, uint32_t* value)
124 {
125 struct rdp_core* dp = (struct rdp_core*)opaque;
126 uint32_t reg = DPS_REG(address);
127
128 *value = dp->dps_regs[reg];
129
130 return 0;
131 }
132
write_dps_regs(void * opaque,uint32_t address,uint32_t value,uint32_t mask)133 int write_dps_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
134 {
135 struct rdp_core* dp = (struct rdp_core*)opaque;
136 uint32_t reg = DPS_REG(address);
137
138 dp->dps_regs[reg] = MASKED_WRITE(&dp->dps_regs[reg], value, mask);
139
140 return 0;
141 }
142
rdp_interrupt_event(struct rdp_core * dp)143 void rdp_interrupt_event(struct rdp_core* dp)
144 {
145 raise_rcp_interrupt(dp->r4300, MI_INTR_DP);
146 }
147