c62d2810 |
1 | /* FCE Ultra - NES/Famicom Emulator |
2 | * |
3 | * Copyright notice for this file: |
d97315ac |
4 | * Copyright (C) 2002 Xodnizel |
c62d2810 |
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 Free Software |
43725da7 |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | * |
20 | * VRC-7 |
21 | * |
c62d2810 |
22 | */ |
23 | |
24 | #include "mapinc.h" |
25 | |
26 | #define vrctemp mapbyte1[0] |
d97315ac |
27 | static uint8 indox; |
28 | |
29 | #include "emu2413.h" |
c62d2810 |
30 | |
31 | static int acount=0; |
32 | |
d97315ac |
33 | static OPLL *VRC7Sound=NULL; |
34 | static int dwave=0; |
35 | |
36 | void DoVRC7Sound(void) |
37 | { |
38 | int32 z,a; |
39 | |
386f5371 |
40 | if(FSettings.soundq>=1) return; |
d97315ac |
41 | z=((SOUNDTS<<16)/soundtsinc)>>4; |
42 | a=z-dwave; |
43 | |
386f5371 |
44 | moocow(VRC7Sound, &Wave[dwave], a, 1); |
d97315ac |
45 | |
46 | dwave+=a; |
47 | } |
48 | |
49 | void UpdateOPLNEO(int32 *Wave, int Count) |
50 | { |
51 | moocow(VRC7Sound, Wave, Count, 4); |
52 | } |
53 | |
54 | void UpdateOPL(int Count) |
55 | { |
56 | int32 z,a; |
57 | |
58 | z=((SOUNDTS<<16)/soundtsinc)>>4; |
59 | a=z-dwave; |
60 | |
61 | if(VRC7Sound && a) |
386f5371 |
62 | moocow(VRC7Sound, &Wave[dwave], a, 1); |
d97315ac |
63 | |
64 | dwave=0; |
65 | } |
c62d2810 |
66 | |
67 | static INLINE void DaMirror(int V) |
68 | { |
69 | int salpo[4]={MI_V,MI_H,MI_0,MI_1}; |
70 | setmirror(salpo[V&3]); |
71 | } |
72 | |
73 | DECLFW(Mapper85_write) |
74 | { |
d97315ac |
75 | A|=(A&8)<<1; |
76 | |
77 | if(A>=0xa000 && A<=0xDFFF) |
78 | { |
79 | // printf("$%04x, $%04x\n",X.PC,A); |
80 | A&=0xF010; |
81 | { |
82 | int x=((A>>4)&1)|((A-0xA000)>>11); |
83 | mapbyte3[x]=V; |
84 | setchr1(x<<10,V); |
85 | } |
86 | } |
87 | else if(A==0x9030) |
88 | { |
89 | if(FSettings.SndRate) |
90 | { |
91 | OPLL_writeReg(VRC7Sound, indox, V); |
92 | GameExpSound.Fill=UpdateOPL; |
93 | GameExpSound.NeoFill=UpdateOPLNEO; |
94 | } |
95 | } |
96 | else switch(A&0xF010) |
c62d2810 |
97 | { |
d97315ac |
98 | case 0x8000:mapbyte2[0]=V;setprg8(0x8000,V);break; |
99 | case 0x8010:mapbyte2[1]=V;setprg8(0xa000,V);break; |
100 | case 0x9000:mapbyte2[2]=V;setprg8(0xc000,V);break; |
c62d2810 |
101 | case 0x9010:indox=V;break; |
102 | case 0xe000:mapbyte2[3]=V;DaMirror(V);break; |
103 | case 0xE010:IRQLatch=V; |
d97315ac |
104 | X6502_IRQEnd(FCEU_IQEXT); |
c62d2810 |
105 | break; |
106 | case 0xF000:IRQa=V&2; |
107 | vrctemp=V&1; |
d97315ac |
108 | if(V&2) {IRQCount=IRQLatch;} |
109 | acount=0; |
110 | X6502_IRQEnd(FCEU_IQEXT); |
c62d2810 |
111 | break; |
112 | case 0xf010:if(vrctemp) IRQa=1; |
113 | else IRQa=0; |
d97315ac |
114 | X6502_IRQEnd(FCEU_IQEXT); |
c62d2810 |
115 | break; |
116 | } |
117 | } |
118 | |
43725da7 |
119 | static void FP_FASTAPASS(1) KonamiIRQHook(int a) |
c62d2810 |
120 | { |
d97315ac |
121 | #define ACBOO 341 |
122 | // #define ACBOO ((227*2)+1) |
c62d2810 |
123 | if(IRQa) |
124 | { |
d97315ac |
125 | acount+=a*3; |
126 | |
127 | if(acount>=ACBOO) |
c62d2810 |
128 | { |
d97315ac |
129 | doagainbub:acount-=ACBOO; |
130 | IRQCount++; |
131 | if(IRQCount&0x100) {X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch;} |
132 | if(acount>=ACBOO) goto doagainbub; |
c62d2810 |
133 | } |
134 | } |
135 | } |
136 | |
137 | void Mapper85_StateRestore(int version) |
138 | { |
139 | int x; |
140 | |
d97315ac |
141 | if(version<7200) |
c62d2810 |
142 | { |
143 | for(x=0;x<8;x++) |
144 | mapbyte3[x]=CHRBankList[x]; |
145 | for(x=0;x<3;x++) |
146 | mapbyte2[x]=PRGBankList[x]; |
147 | mapbyte2[3]=(Mirroring<0x10)?Mirroring:Mirroring-0xE; |
148 | } |
149 | |
150 | for(x=0;x<8;x++) |
151 | setchr1(x*0x400,mapbyte3[x]); |
152 | for(x=0;x<3;x++) |
153 | setprg8(0x8000+x*8192,mapbyte2[x]); |
154 | DaMirror(mapbyte2[3]); |
d97315ac |
155 | //LoadOPL(); |
c62d2810 |
156 | } |
157 | |
158 | static void M85SC(void) |
159 | { |
d97315ac |
160 | if(VRC7Sound) |
161 | OPLL_set_rate(VRC7Sound, FSettings.SndRate); |
c62d2810 |
162 | } |
163 | |
d97315ac |
164 | static void M85SKill(void) |
165 | { |
166 | if(VRC7Sound) |
167 | OPLL_delete(VRC7Sound); |
168 | VRC7Sound=NULL; |
169 | } |
170 | |
171 | static void VRC7SI(void) |
172 | { |
173 | GameExpSound.RChange=M85SC; |
174 | GameExpSound.Kill=M85SKill; |
175 | |
176 | VRC7Sound=OPLL_new(3579545, FSettings.SndRate?FSettings.SndRate:44100); |
177 | OPLL_reset(VRC7Sound); |
178 | OPLL_reset(VRC7Sound); |
179 | } |
180 | |
181 | void NSFVRC7_Init(void) |
c62d2810 |
182 | { |
c62d2810 |
183 | SetWriteHandler(0x9010,0x901F,Mapper85_write); |
184 | SetWriteHandler(0x9030,0x903F,Mapper85_write); |
d97315ac |
185 | VRC7SI(); |
c62d2810 |
186 | } |
187 | |
188 | void Mapper85_init(void) |
189 | { |
190 | MapIRQHook=KonamiIRQHook; |
191 | SetWriteHandler(0x8000,0xffff,Mapper85_write); |
192 | GameStateRestore=Mapper85_StateRestore; |
c62d2810 |
193 | if(!VROM_size) |
194 | SetupCartCHRMapping(0, CHRRAM, 8192, 1); |
d97315ac |
195 | //AddExState(VRC7Instrument, 16, 0, "VC7I"); |
196 | //AddExState(VRC7Chan, sizeof(VRC7Chan), 0, "V7CH"); |
197 | VRC7SI(); |
c62d2810 |
198 | } |