~random-stuff/random-stuff/snes9x-OLD

1 by OV2
Initial 1.52 import
1
/***********************************************************************************
2
  Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
4
  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
                             Jerremy Koot (jkoot@snes9x.com)
6
7
  (c) Copyright 2002 - 2004  Matthew Kendora
8
9
  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
11
  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
13
  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
15
  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
                             Kris Bleakley (codeviolation@hotmail.com)
17
18
  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
                             Nach (n-a-c-h@users.sourceforge.net),
87 by OV2
Update copyright in all files
20
21
  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
1 by OV2
Initial 1.52 import
22
23
  (c) Copyright 2006 - 2007  nitsuja
24
290 by Brandon Wright
Update some copyrights, bump version number.
25
  (c) Copyright 2009 - 2016  BearOso,
1 by OV2
Initial 1.52 import
26
                             OV2
27
28
29
  BS-X C emulator code
30
  (c) Copyright 2005 - 2006  Dreamer Nom,
31
                             zones
32
33
  C4 x86 assembler and some C emulation code
34
  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
                             Nach,
36
                             zsKnight (zsknight@zsnes.com)
37
38
  C4 C++ code
39
  (c) Copyright 2003 - 2006  Brad Jorsch,
40
                             Nach
41
42
  DSP-1 emulator code
43
  (c) Copyright 1998 - 2006  _Demo_,
44
                             Andreas Naive (andreasnaive@gmail.com),
45
                             Gary Henderson,
46
                             Ivar (ivar@snes9x.com),
47
                             John Weidman,
48
                             Kris Bleakley,
49
                             Matthew Kendora,
50
                             Nach,
51
                             neviksti (neviksti@hotmail.com)
52
53
  DSP-2 emulator code
54
  (c) Copyright 2003         John Weidman,
55
                             Kris Bleakley,
56
                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
                             Matthew Kendora,
58
                             neviksti
59
60
  DSP-3 emulator code
61
  (c) Copyright 2003 - 2006  John Weidman,
62
                             Kris Bleakley,
63
                             Lancer,
64
                             z80 gaiden
65
66
  DSP-4 emulator code
67
  (c) Copyright 2004 - 2006  Dreamer Nom,
68
                             John Weidman,
69
                             Kris Bleakley,
70
                             Nach,
71
                             z80 gaiden
72
73
  OBC1 emulator code
74
  (c) Copyright 2001 - 2004  zsKnight,
75
                             pagefault (pagefault@zsnes.com),
76
                             Kris Bleakley
77
                             Ported from x86 assembler to C by sanmaiwashi
78
79
  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
  (c) Copyright 2002         Matthew Kendora with research by
81
                             zsKnight,
82
                             John Weidman,
83
                             Dark Force
84
85
  SPC7110 and RTC C++ emulator code used in 1.52+
86
  (c) Copyright 2009         byuu,
87
                             neviksti
88
89
  S-DD1 C emulator code
90
  (c) Copyright 2003         Brad Jorsch with research by
91
                             Andreas Naive,
92
                             John Weidman
93
94
  S-RTC C emulator code
95
  (c) Copyright 2001 - 2006  byuu,
96
                             John Weidman
97
98
  ST010 C++ emulator code
99
  (c) Copyright 2003         Feather,
100
                             John Weidman,
101
                             Kris Bleakley,
102
                             Matthew Kendora
103
104
  Super FX x86 assembler emulator code
105
  (c) Copyright 1998 - 2003  _Demo_,
106
                             pagefault,
107
                             zsKnight
108
109
  Super FX C emulator code
110
  (c) Copyright 1997 - 1999  Ivar,
111
                             Gary Henderson,
112
                             John Weidman
113
114
  Sound emulator code used in 1.5-1.51
115
  (c) Copyright 1998 - 2003  Brad Martin
116
  (c) Copyright 1998 - 2006  Charles Bilyue'
117
118
  Sound emulator code used in 1.52+
119
  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
295 by Brandon Wright
Add byuu copyright for his S-SMP
121
  S-SMP emulator code used in 1.54+
122
  (c) Copyright 2016         byuu
123
1 by OV2
Initial 1.52 import
124
  SH assembler code partly based on x86 assembler code
125
  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
126
127
  2xSaI filter
128
  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
129
130
  HQ2x, HQ3x, HQ4x filters
131
  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
132
133
  NTSC filter
134
  (c) Copyright 2006 - 2007  Shay Green
135
136
  GTK+ GUI code
290 by Brandon Wright
Update some copyrights, bump version number.
137
  (c) Copyright 2004 - 2016  BearOso
1 by OV2
Initial 1.52 import
138
139
  Win32 GUI code
140
  (c) Copyright 2003 - 2006  blip,
141
                             funkyass,
142
                             Matthew Kendora,
143
                             Nach,
144
                             nitsuja
298 by Brandon Wright
Bump OV2 Windows port copyright.
145
  (c) Copyright 2009 - 2016  OV2
1 by OV2
Initial 1.52 import
146
147
  Mac OS GUI code
148
  (c) Copyright 1998 - 2001  John Stiles
87 by OV2
Update copyright in all files
149
  (c) Copyright 2001 - 2011  zones
1 by OV2
Initial 1.52 import
150
151
152
  Specific ports contains the works of other authors. See headers in
153
  individual files.
154
155
156
  Snes9x homepage: http://www.snes9x.com/
157
158
  Permission to use, copy, modify and/or distribute Snes9x in both binary
159
  and source form, for non-commercial purposes, is hereby granted without
160
  fee, providing that this license information and copyright notice appear
161
  with all copies and any derived work.
162
163
  This software is provided 'as-is', without any express or implied
164
  warranty. In no event shall the authors be held liable for any damages
165
  arising from the use of this software or it's derivatives.
166
167
  Snes9x is freeware for PERSONAL USE only. Commercial users should
168
  seek permission of the copyright holders first. Commercial use includes,
169
  but is not limited to, charging money for Snes9x or software derived from
170
  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
171
  using Snes9x as a promotion for your commercial product.
172
173
  The copyright holders request that bug fixes and improvements to the code
174
  should be forwarded to them so everyone can benefit from the modifications
175
  in future versions.
176
177
  Super NES and Super Nintendo Entertainment System are trademarks of
178
  Nintendo Co., Limited and its subsidiary companies.
179
 ***********************************************************************************/
180
181
182
#include "snes9x.h"
183
#include "memmap.h"
184
185
uint8	SA1OpenBus;
186
187
static void S9xSA1SetBWRAMMemMap (uint8);
188
static void S9xSetSA1MemMap (uint32, uint8);
189
static void S9xSA1CharConv2 (void);
190
static void S9xSA1DMA (void);
191
static void S9xSA1ReadVariableLengthData (bool8, bool8);
192
193
194
void S9xSA1Init (void)
195
{
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
196
	SA1.Cycles = 0;
197
	SA1.PrevCycles = 0;
1 by OV2
Initial 1.52 import
198
	SA1.Flags = 0;
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
199
	SA1.WaitingForInterrupt = FALSE;
200
1 by OV2
Initial 1.52 import
201
	memset(&Memory.FillRAM[0x2200], 0, 0x200);
202
	Memory.FillRAM[0x2200] = 0x20;
203
	Memory.FillRAM[0x2220] = 0x00;
204
	Memory.FillRAM[0x2221] = 0x01;
205
	Memory.FillRAM[0x2222] = 0x02;
206
	Memory.FillRAM[0x2223] = 0x03;
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
207
	Memory.FillRAM[0x2228] = 0x0f;
208
209
	SA1.in_char_dma = FALSE;
210
	SA1.TimerIRQLastState = FALSE;
211
	SA1.HTimerIRQPos = 0;
212
	SA1.VTimerIRQPos = 0;
213
	SA1.HCounter = 0;
214
	SA1.VCounter = 0;
215
	SA1.PrevHCounter = 0;
216
	SA1.arithmetic_op = 0;
1 by OV2
Initial 1.52 import
217
	SA1.op1 = 0;
218
	SA1.op2 = 0;
219
	SA1.sum = 0;
220
	SA1.overflow = FALSE;
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
221
	SA1.VirtualBitmapFormat = 0;
222
	SA1.variable_bit_pos = 0;
1 by OV2
Initial 1.52 import
223
224
	SA1Registers.PBPC = 0;
225
	SA1Registers.PB = 0;
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
226
	SA1Registers.PCw = 0;
1 by OV2
Initial 1.52 import
227
	SA1Registers.D.W = 0;
228
	SA1Registers.DB = 0;
229
	SA1Registers.SH = 1;
230
	SA1Registers.SL = 0xFF;
231
	SA1Registers.XH = 0;
232
	SA1Registers.YH = 0;
233
	SA1Registers.P.W = 0;
234
235
	SA1.ShiftedPB = 0;
236
	SA1.ShiftedDB = 0;
237
	SA1SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
238
	SA1ClearFlags(Decimal);
239
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
240
	SA1.MemSpeed = SLOW_ONE_CYCLE;
241
	SA1.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
242
1 by OV2
Initial 1.52 import
243
	SA1.S9xOpcodes = S9xSA1OpcodesM1X1;
244
	SA1.S9xOpLengths = S9xOpLengthsM1X1;
245
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
246
	S9xSA1SetPCBase(SA1Registers.PBPC);
247
1 by OV2
Initial 1.52 import
248
	S9xSA1UnpackStatus();
249
	S9xSA1FixCycles();
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
250
1 by OV2
Initial 1.52 import
251
	SA1.BWRAM = Memory.SRAM;
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
252
253
	CPU.IRQExternal = FALSE;
1 by OV2
Initial 1.52 import
254
}
255
256
static void S9xSA1SetBWRAMMemMap (uint8 val)
257
{
258
	if (val & 0x80)
259
	{
260
		for (int c = 0; c < 0x400; c += 16)
261
		{
262
			SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2;
263
			SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2;
264
			SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2;
265
			SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2;
266
		}
267
268
		SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4;
269
	}
270
	else
271
	{
272
		for (int c = 0; c < 0x400; c += 16)
273
		{
274
			SA1.Map[c + 6] = SA1.Map[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM;
275
			SA1.Map[c + 7] = SA1.Map[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM;
276
			SA1.WriteMap[c + 6] = SA1.WriteMap[c + 0x806] = (uint8 *) CMemory::MAP_BWRAM;
277
			SA1.WriteMap[c + 7] = SA1.WriteMap[c + 0x807] = (uint8 *) CMemory::MAP_BWRAM;
278
		}
279
280
		SA1.BWRAM = Memory.SRAM + (val & 7) * 0x2000;
281
	}
282
}
283
284
void S9xSA1PostLoadState (void)
285
{
286
	SA1.ShiftedPB = (uint32) SA1Registers.PB << 16;
287
	SA1.ShiftedDB = (uint32) SA1Registers.DB << 16;
288
289
	S9xSA1SetPCBase(SA1Registers.PBPC);
290
	S9xSA1UnpackStatus();
291
	S9xSA1FixCycles();
292
	SA1.VirtualBitmapFormat = (Memory.FillRAM[0x223f] & 0x80) ? 2 : 4;
293
	Memory.BWRAM = Memory.SRAM + (Memory.FillRAM[0x2224] & 7) * 0x2000;
294
	S9xSA1SetBWRAMMemMap(Memory.FillRAM[0x2225]);
295
}
296
297
static void S9xSetSA1MemMap (uint32 which1, uint8 map)
298
{
299
	int	start  = which1 * 0x100 + 0xc00;
300
	int	start2 = which1 * 0x200;
301
302
	if (which1 >= 2)
303
		start2 += 0x400;
304
305
	for (int c = 0; c < 0x100; c += 16)
306
	{
307
		uint8	*block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)];
308
		for (int i = c; i < c + 16; i++)
309
			Memory.Map[start  + i] = SA1.Map[start  + i] = block;
310
	}
311
312
	for (int c = 0; c < 0x200; c += 16)
313
	{
223 by OV2
Fix MMC reg for 64bit builds
314
        // conversion to int is needed here - map is promoted but which1 is not
315
        int32 offset = (((map & 0x80) ? map : which1) & 7) * 0x100000 + (c << 11) - 0x8000;
316
		uint8	*block = &Memory.ROM[offset];
1 by OV2
Initial 1.52 import
317
		for (int i = c + 8; i < c + 16; i++)
318
			Memory.Map[start2 + i] = SA1.Map[start2 + i] = block;
319
	}
320
}
321
322
uint8 S9xGetSA1 (uint32 address)
323
{
324
	switch (address)
325
	{
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
326
		case 0x2300: // S-CPU flag
327
			return ((Memory.FillRAM[0x2209] & 0x5f) | (Memory.FillRAM[0x2300] & 0xa0));
328
329
		case 0x2301: // SA-1 flag
330
			return ((Memory.FillRAM[0x2200] & 0x0f) | (Memory.FillRAM[0x2301] & 0xf0));
331
332
		case 0x2302: // H counter (L)
333
			SA1.HTimerIRQPos = SA1.HCounter / ONE_DOT_CYCLE;
334
			SA1.VTimerIRQPos = SA1.VCounter;
335
			return ((uint8)  SA1.HTimerIRQPos);
336
337
		case 0x2303: // H counter (H)
338
			return ((uint8) (SA1.HTimerIRQPos >> 8));
339
340
		case 0x2304: // V counter (L)
341
			return ((uint8)  SA1.VTimerIRQPos);
342
343
		case 0x2305: // V counter (H)
344
			return ((uint8) (SA1.VTimerIRQPos >> 8));
345
346
		case 0x2306: // arithmetic result (LLL)
1 by OV2
Initial 1.52 import
347
			return ((uint8)  SA1.sum);
348
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
349
		case 0x2307: // arithmetic result (LLH)
1 by OV2
Initial 1.52 import
350
			return ((uint8) (SA1.sum >>  8));
351
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
352
		case 0x2308: // arithmetic result (LHL)
1 by OV2
Initial 1.52 import
353
			return ((uint8) (SA1.sum >> 16));
354
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
355
		case 0x2309: // arithmetic result (LLH)
1 by OV2
Initial 1.52 import
356
			return ((uint8) (SA1.sum >> 24));
357
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
358
		case 0x230a: // arithmetic result (HLL)
1 by OV2
Initial 1.52 import
359
			return ((uint8) (SA1.sum >> 32));
360
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
361
		case 0x230b: // arithmetic overflow
362
			return (SA1.overflow ? 0x80 : 0);
363
364
		case 0x230c: // variable-length data read port (L)
1 by OV2
Initial 1.52 import
365
			return (Memory.FillRAM[0x230c]);
366
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
367
		case 0x230d: // variable-length data read port (H)
1 by OV2
Initial 1.52 import
368
		{
369
			uint8	byte = Memory.FillRAM[0x230d];
370
371
			if (Memory.FillRAM[0x2258] & 0x80)
372
				S9xSA1ReadVariableLengthData(TRUE, FALSE);
373
374
			return (byte);
375
		}
376
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
377
		case 0x230e: // version code register
378
			return (0x01);
379
1 by OV2
Initial 1.52 import
380
		default:
381
			break;
382
	}
383
384
	return (Memory.FillRAM[address]);
385
}
386
387
void S9xSetSA1 (uint8 byte, uint32 address)
388
{
389
	switch (address)
390
	{
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
391
		case 0x2200: // SA-1 control
392
		#ifdef DEBUGGER
393
			if (byte & 0x60)
394
				printf("SA-1 sleep\n");
395
		#endif
396
397
			// SA-1 reset
398
			if (!(byte & 0x80) && (Memory.FillRAM[0x2200] & 0x20))
399
			{
400
			#ifdef DEBUGGER
401
				printf("SA-1 reset\n");
402
			#endif
403
				SA1Registers.PBPC = 0;
404
				SA1Registers.PB = 0;
405
				SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8);
406
				S9xSA1SetPCBase(SA1Registers.PBPC);
407
			}
408
409
			// SA-1 IRQ control
1 by OV2
Initial 1.52 import
410
			if (byte & 0x80)
411
			{
412
				Memory.FillRAM[0x2301] |= 0x80;
413
				if (Memory.FillRAM[0x220a] & 0x80)
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
414
					Memory.FillRAM[0x220b] &= ~0x80;
1 by OV2
Initial 1.52 import
415
			}
416
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
417
			// SA-1 NMI control
1 by OV2
Initial 1.52 import
418
			if (byte & 0x10)
419
			{
420
				Memory.FillRAM[0x2301] |= 0x10;
421
				if (Memory.FillRAM[0x220a] & 0x10)
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
422
					Memory.FillRAM[0x220b] &= ~0x10;
1 by OV2
Initial 1.52 import
423
			}
424
425
			break;
426
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
427
		case 0x2201: // S-CPU interrupt enable
428
			// S-CPU IRQ enable
1 by OV2
Initial 1.52 import
429
			if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80))
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
430
			{
431
				Memory.FillRAM[0x2202] &= ~0x80;
432
				CPU.IRQExternal = TRUE;
433
			}
1 by OV2
Initial 1.52 import
434
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
435
			// S-CPU CHDMA IRQ enable
1 by OV2
Initial 1.52 import
436
			if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20))
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
437
			{
438
				Memory.FillRAM[0x2202] &= ~0x20;
439
				CPU.IRQExternal = TRUE;
440
			}
1 by OV2
Initial 1.52 import
441
442
			break;
443
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
444
		case 0x2202: // S-CPU interrupt clear
445
			// S-CPU IRQ clear
1 by OV2
Initial 1.52 import
446
			if (byte & 0x80)
447
				Memory.FillRAM[0x2300] &= ~0x80;
448
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
449
			// S-CPU CHDMA IRQ clear
1 by OV2
Initial 1.52 import
450
			if (byte & 0x20)
451
				Memory.FillRAM[0x2300] &= ~0x20;
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
452
453
			if (!(Memory.FillRAM[0x2300] & 0xa0))
454
				CPU.IRQExternal = FALSE;
455
456
			break;
457
458
		case 0x2203: // SA-1 reset vector (L)
459
		case 0x2204: // SA-1 reset vector (H)
460
		case 0x2205: // SA-1 NMI vector (L)
461
		case 0x2206: // SA-1 NMI vector (H)
462
		case 0x2207: // SA-1 IRQ vector (L)
463
		case 0x2208: // SA-1 IRQ vector (H)
464
			break;
465
466
		case 0x2209: // S-CPU control
467
			// 0x40: S-CPU IRQ overwrite
468
			// 0x20: S-CPU NMI overwrite
469
470
			// S-CPU IRQ control
1 by OV2
Initial 1.52 import
471
			if (byte & 0x80)
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
472
			{
1 by OV2
Initial 1.52 import
473
				Memory.FillRAM[0x2300] |= 0x80;
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
474
				if (Memory.FillRAM[0x2201] & 0x80)
475
				{
476
					Memory.FillRAM[0x2202] &= ~0x80;
477
					CPU.IRQExternal = TRUE;
478
				}
479
			}
1 by OV2
Initial 1.52 import
480
481
			break;
482
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
483
		case 0x220a: // SA-1 interrupt enable
484
			// SA-1 IRQ enable
1 by OV2
Initial 1.52 import
485
			if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80))
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
486
				Memory.FillRAM[0x220b] &= ~0x80;
1 by OV2
Initial 1.52 import
487
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
488
			// SA-1 timer IRQ enable
1 by OV2
Initial 1.52 import
489
			if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40))
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
490
				Memory.FillRAM[0x220b] &= ~0x40;
1 by OV2
Initial 1.52 import
491
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
492
			// SA-1 DMA IRQ enable
1 by OV2
Initial 1.52 import
493
			if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20))
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
494
				Memory.FillRAM[0x220b] &= ~0x20;
1 by OV2
Initial 1.52 import
495
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
496
			// SA-1 NMI enable
1 by OV2
Initial 1.52 import
497
			if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10))
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
498
				Memory.FillRAM[0x220b] &= ~0x10;
1 by OV2
Initial 1.52 import
499
500
			break;
501
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
502
		case 0x220b: // SA-1 interrupt clear
503
			// SA-1 IRQ clear
1 by OV2
Initial 1.52 import
504
			if (byte & 0x80)
505
				Memory.FillRAM[0x2301] &= ~0x80;
506
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
507
			// SA-1 timer IRQ clear
1 by OV2
Initial 1.52 import
508
			if (byte & 0x40)
509
				Memory.FillRAM[0x2301] &= ~0x40;
510
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
511
			// SA-1 DMA IRQ clear
1 by OV2
Initial 1.52 import
512
			if (byte & 0x20)
513
				Memory.FillRAM[0x2301] &= ~0x20;
514
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
515
			// SA-1 NMI clear
24 by zones
Added SA-1 NMI and fixed its override mode.
516
			if (byte & 0x10)
1 by OV2
Initial 1.52 import
517
				Memory.FillRAM[0x2301] &= ~0x10;
518
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
519
			break;
520
521
		case 0x220c: // S-CPU NMI vector (L)
522
		case 0x220d: // S-CPU NMI vector (H)
523
		case 0x220e: // S-CPU IRQ vector (L)
524
		case 0x220f: // S-CPU IRQ vector (H)
525
			break;
526
527
		case 0x2210: // SA-1 timer control
528
			// 0x80: mode (linear / HV)
529
			// 0x02: V timer enable
530
			// 0x01: H timer enable
531
		#ifdef DEBUGGER
532
			printf("SA-1 timer control write:%02x\n", byte);
1 by OV2
Initial 1.52 import
533
		#endif
534
			break;
535
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
536
		case 0x2211: // SA-1 timer reset
537
			SA1.HCounter = 0;
538
			SA1.VCounter = 0;
539
			break;
540
541
		case 0x2212: // SA-1 H-timer (L)
542
			SA1.HTimerIRQPos = byte | (Memory.FillRAM[0x2213] << 8);
543
			break;
544
545
		case 0x2213: // SA-1 H-timer (H)
546
			SA1.HTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2212];
547
			break;
548
549
		case 0x2214: // SA-1 V-timer (L)
550
			SA1.VTimerIRQPos = byte | (Memory.FillRAM[0x2215] << 8);
551
			break;
552
553
		case 0x2215: // SA-1 V-timer (H)
554
			SA1.VTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2214];
555
			break;
556
557
		case 0x2220: // MMC bank C
558
		case 0x2221: // MMC bank D
559
		case 0x2222: // MMC bank E
560
		case 0x2223: // MMC bank F
1 by OV2
Initial 1.52 import
561
			S9xSetSA1MemMap(address - 0x2220, byte);
562
			break;
563
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
564
		case 0x2224: // S-CPU BW-RAM mapping
1 by OV2
Initial 1.52 import
565
			Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000;
566
			break;
567
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
568
		case 0x2225: // SA-1 BW-RAM mapping
1 by OV2
Initial 1.52 import
569
			if (byte != Memory.FillRAM[0x2225])
570
				S9xSA1SetBWRAMMemMap(byte);
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
571
572
			break;
573
574
		case 0x2226: // S-CPU BW-RAM write enable
575
		case 0x2227: // SA-1 BW-RAM write enable
576
		case 0x2228: // BW-RAM write-protected area
577
		case 0x2229: // S-CPU I-RAM write protection
578
		case 0x222a: // SA-1 I-RAM write protection
579
			break;
580
581
		case 0x2230: // DMA control
582
			// 0x80: enable
583
			// 0x40: priority (DMA / SA-1)
584
			// 0x20: character conversion / normal
585
			// 0x10: BW-RAM -> I-RAM / SA-1 -> I-RAM
586
			// 0x04: destinatin (BW-RAM / I-RAM)
587
			// 0x03: source
588
			break;
589
590
		case 0x2231: // character conversion DMA parameters
591
			// 0x80: CHDEND (complete / incomplete)
592
			// 0x03: color mode
593
			// (byte >> 2) & 7: virtual VRAM width
1 by OV2
Initial 1.52 import
594
			if (byte & 0x80)
595
				SA1.in_char_dma = FALSE;
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
596
597
			break;
598
599
		case 0x2232: // DMA source start address (LL)
600
		case 0x2233: // DMA source start address (LH)
601
		case 0x2234: // DMA source start address (HL)
602
			break;
603
604
		case 0x2235: // DMA destination start address (LL)
605
			break;
606
607
		case 0x2236: // DMA destination start address (LH)
1 by OV2
Initial 1.52 import
608
			Memory.FillRAM[0x2236] = byte;
609
610
			if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) // Normal DMA to I-RAM
611
				S9xSA1DMA();
612
			else
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
613
			if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0) // CC1
1 by OV2
Initial 1.52 import
614
			{
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
615
				SA1.in_char_dma = TRUE;
616
1 by OV2
Initial 1.52 import
617
				Memory.FillRAM[0x2300] |= 0x20;
618
				if (Memory.FillRAM[0x2201] & 0x20)
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
619
				{
620
					Memory.FillRAM[0x2202] &= ~0x20;
621
					CPU.IRQExternal = TRUE;
622
				}
1 by OV2
Initial 1.52 import
623
			}
624
625
			break;
626
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
627
		case 0x2237: // DMA destination start address (HL)
1 by OV2
Initial 1.52 import
628
			Memory.FillRAM[0x2237] = byte;
629
630
			if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) // Normal DMA to BW-RAM
631
				S9xSA1DMA();
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
632
633
			break;
634
635
		case 0x2238: // DMA terminal counter (L)
636
		case 0x2239: // DMA terminal counter (H)
637
			break;
638
639
		case 0x223f: // BW-RAM bitmap format
1 by OV2
Initial 1.52 import
640
			SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4;
641
			break;
642
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
643
		case 0x2240: // bitmap register 0
644
		case 0x2241: // bitmap register 1
645
		case 0x2242: // bitmap register 2
646
		case 0x2243: // bitmap register 3
647
		case 0x2244: // bitmap register 4
648
		case 0x2245: // bitmap register 5
649
		case 0x2246: // bitmap register 6
650
		case 0x2247: // bitmap register 7
651
		case 0x2248: // bitmap register 8
652
		case 0x2249: // bitmap register 9
653
		case 0x224a: // bitmap register A
654
		case 0x224b: // bitmap register B
655
		case 0x224c: // bitmap register C
656
		case 0x224d: // bitmap register D
657
		case 0x224e: // bitmap register E
1 by OV2
Initial 1.52 import
658
			break;
659
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
660
		case 0x224f: // bitmap register F
1 by OV2
Initial 1.52 import
661
			Memory.FillRAM[0x224f] = byte;
662
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
663
			if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // CC2
1 by OV2
Initial 1.52 import
664
			{
665
				memmove(&Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16);
666
				SA1.in_char_dma = (SA1.in_char_dma + 1) & 7;
667
				if ((SA1.in_char_dma & 3) == 0)
668
					S9xSA1CharConv2();
669
			}
670
671
			break;
672
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
673
		case 0x2250: // arithmetic control
1 by OV2
Initial 1.52 import
674
			if (byte & 2)
675
				SA1.sum = 0;
676
			SA1.arithmetic_op = byte & 3;
677
			break;
678
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
679
		case 0x2251: // multiplicand / dividend (L)
680
			SA1.op1 = (SA1.op1 & 0xff00) |  byte;
681
			break;
682
683
		case 0x2252: // multiplicand / dividend (H)
684
			SA1.op1 = (SA1.op1 & 0x00ff) | (byte << 8);
685
			break;
686
687
		case 0x2253: // multiplier / divisor (L)
688
			SA1.op2 = (SA1.op2 & 0xff00) |  byte;
689
			break;
690
691
		case 0x2254: // multiplier / divisor (H)
692
			SA1.op2 = (SA1.op2 & 0x00ff) | (byte << 8);
1 by OV2
Initial 1.52 import
693
694
			switch (SA1.arithmetic_op)
695
			{
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
696
				case 0:	// signed multiplication
697
					SA1.sum = (int16) SA1.op1 * (int16) SA1.op2;
698
					SA1.op2 = 0;
1 by OV2
Initial 1.52 import
699
					break;
700
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
701
				case 1: // unsigned division
1 by OV2
Initial 1.52 import
702
					if (SA1.op2 == 0)
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
703
						SA1.sum = 0;
1 by OV2
Initial 1.52 import
704
					else
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
705
					{
706
						int16	quotient  = (int16) SA1.op1 / (uint16) SA1.op2;
707
						uint16	remainder = (int16) SA1.op1 % (uint16) SA1.op2;
708
						SA1.sum = (remainder << 16) | quotient;
709
					}
710
711
					SA1.op1 = 0;
712
					SA1.op2 = 0;
1 by OV2
Initial 1.52 import
713
					break;
714
715
				case 2: // cumulative sum
716
				default:
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
717
					SA1.sum += (int16) SA1.op1 * (int16) SA1.op2;
718
					SA1.overflow = (SA1.sum >= (1ULL << 40));
719
					SA1.sum &= (1ULL << 40) - 1;
720
					SA1.op2 = 0;
1 by OV2
Initial 1.52 import
721
					break;
722
			}
723
724
			break;
725
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
726
		case 0x2258: // variable bit-field length / auto inc / start
1 by OV2
Initial 1.52 import
727
			Memory.FillRAM[0x2258] = byte;
728
			S9xSA1ReadVariableLengthData(TRUE, FALSE);
729
			return;
730
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
731
		case 0x2259: // variable bit-field start address (LL)
732
		case 0x225a: // variable bit-field start address (LH)
733
		case 0x225b: // variable bit-field start address (HL)
1 by OV2
Initial 1.52 import
734
			Memory.FillRAM[address] = byte;
735
			// XXX: ???
736
			SA1.variable_bit_pos = 0;
737
			S9xSA1ReadVariableLengthData(FALSE, TRUE);
738
			return;
739
740
		default:
741
			break;
742
	}
743
744
	if (address >= 0x2200 && address <= 0x22ff)
745
		Memory.FillRAM[address] = byte;
746
}
747
748
static void S9xSA1CharConv2 (void)
749
{
750
	uint32	dest           = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8);
751
	uint32	offset         = (SA1.in_char_dma & 7) ? 0 : 1;
752
	int		depth          = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2;
753
	int		bytes_per_char = 8 * depth;
2 by OV2
Update to latest WIP
754
	uint8	*p             = &Memory.FillRAM[0x3000] + (dest & 0x7ff) + offset * bytes_per_char;
1 by OV2
Initial 1.52 import
755
	uint8	*q             = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64;
756
757
	switch (depth)
758
	{
759
		case 2:
2 by OV2
Update to latest WIP
760
			for (int l = 0; l < 8; l++, q += 8)
761
			{
762
				for (int b = 0; b < 8; b++)
763
				{
764
					uint8	r = *(q + b);
765
					*(p +  0) = (*(p +  0) << 1) | ((r >> 0) & 1);
766
					*(p +  1) = (*(p +  1) << 1) | ((r >> 1) & 1);
767
				}
768
769
				p += 2;
770
			}
771
772
			break;
773
1 by OV2
Initial 1.52 import
774
		case 4:
2 by OV2
Update to latest WIP
775
			for (int l = 0; l < 8; l++, q += 8)
776
			{
777
				for (int b = 0; b < 8; b++)
778
				{
779
					uint8	r = *(q + b);
780
					*(p +  0) = (*(p +  0) << 1) | ((r >> 0) & 1);
781
					*(p +  1) = (*(p +  1) << 1) | ((r >> 1) & 1);
782
					*(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1);
783
					*(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1);
784
				}
785
786
				p += 2;
787
			}
788
1 by OV2
Initial 1.52 import
789
			break;
790
791
		case 8:
792
			for (int l = 0; l < 8; l++, q += 8)
793
			{
794
				for (int b = 0; b < 8; b++)
795
				{
796
					uint8	r = *(q + b);
797
					*(p +  0) = (*(p +  0) << 1) | ((r >> 0) & 1);
798
					*(p +  1) = (*(p +  1) << 1) | ((r >> 1) & 1);
799
					*(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1);
800
					*(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1);
801
					*(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1);
802
					*(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1);
803
					*(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1);
804
					*(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1);
805
				}
806
807
				p += 2;
808
			}
809
810
			break;
811
	}
812
}
813
814
static void S9xSA1DMA (void)
815
{
816
	uint32	src = Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16);
817
	uint32	dst = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16);
818
	uint32	len = Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8);
819
	uint8	*s, *d;
820
821
	switch (Memory.FillRAM[0x2230] & 3)
822
	{
823
		case 0: // ROM
824
			s = SA1.Map[((src & 0xffffff) >> MEMMAP_SHIFT)];
825
			if (s >= (uint8 *) CMemory::MAP_LAST)
826
				s += (src & 0xffff);
827
			else
828
				s = Memory.ROM + (src & 0xffff);
829
			break;
830
831
		case 1: // BW-RAM
832
			src &= Memory.SRAMMask;
833
			len &= Memory.SRAMMask;
834
			s = Memory.SRAM + src;
835
			break;
836
837
		default:
838
		case 2:
839
			src &= 0x3ff;
840
			len &= 0x3ff;
841
			s = &Memory.FillRAM[0x3000] + src;
842
			break;
843
	}
844
845
	if (Memory.FillRAM[0x2230] & 4)
846
	{
847
		dst &= Memory.SRAMMask;
848
		len &= Memory.SRAMMask;
849
		d = Memory.SRAM + dst;
850
	}
851
	else
852
	{
853
		dst &= 0x3ff;
854
		len &= 0x3ff;
855
		d = &Memory.FillRAM[0x3000] + dst;
856
	}
857
858
	memmove(d, s, len);
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
859
860
	// SA-1 DMA IRQ control
1 by OV2
Initial 1.52 import
861
	Memory.FillRAM[0x2301] |= 0x20;
862
	if (Memory.FillRAM[0x220a] & 0x20)
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
863
		Memory.FillRAM[0x220b] &= ~0x20;
1 by OV2
Initial 1.52 import
864
}
865
866
static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift)
867
{
868
	uint32	addr  = Memory.FillRAM[0x2259] | (Memory.FillRAM[0x225a] << 8) | (Memory.FillRAM[0x225b] << 16);
869
	uint8	shift = Memory.FillRAM[0x2258] & 15;
870
871
	if (no_shift)
872
		shift = 0;
873
	else
874
	if (shift == 0)
875
		shift = 16;
876
877
	uint8	s = shift + SA1.variable_bit_pos;
878
879
	if (s >= 16)
880
	{
881
		addr += (s >> 4) << 1;
882
		s &= 15;
883
	}
884
885
	uint32	data = S9xSA1GetWord(addr) | (S9xSA1GetWord(addr + 2) << 16);
886
887
	data >>= s;
888
	Memory.FillRAM[0x230c] = (uint8) data;
889
	Memory.FillRAM[0x230d] = (uint8) (data >> 8);
890
891
	if (inc)
892
	{
893
		SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15;
894
		Memory.FillRAM[0x2259] = (uint8) addr;
895
		Memory.FillRAM[0x225a] = (uint8) (addr >> 8);
896
		Memory.FillRAM[0x225b] = (uint8) (addr >> 16);
897
	}
898
}
899
900
uint8 S9xSA1GetByte (uint32 address)
901
{
902
	uint8	*GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT];
903
904
	if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
905
		return (*(GetAddress + (address & 0xffff)));
906
907
	switch ((pint) GetAddress)
908
	{
909
		case CMemory::MAP_PPU:
910
			return (S9xGetSA1(address & 0xffff));
911
912
		case CMemory::MAP_LOROM_SRAM:
913
		case CMemory::MAP_SA1RAM:
914
			return (*(Memory.SRAM + (address & 0xffff)));
915
916
		case CMemory::MAP_BWRAM:
917
			return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000)));
918
919
		case CMemory::MAP_BWRAM_BITMAP:
920
			address -= 0x600000;
921
			if (SA1.VirtualBitmapFormat == 2)
922
				return ((Memory.SRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) &  3);
923
			else
924
				return ((Memory.SRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15);
925
926
		case CMemory::MAP_BWRAM_BITMAP2:
927
			address = (address & 0xffff) - 0x6000;
928
			if (SA1.VirtualBitmapFormat == 2)
929
				return ((SA1.BWRAM[(address >> 2) & 0xffff] >> ((address & 3) << 1)) &  3);
930
			else
931
				return ((SA1.BWRAM[(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15);
932
933
		default:
934
			return (SA1OpenBus);
935
	}
936
}
937
938
uint16 S9xSA1GetWord (uint32 address, s9xwrap_t w)
939
{
940
	PC_t	a;
941
942
	SA1OpenBus = S9xSA1GetByte(address);
943
944
	switch (w)
945
	{
946
		case WRAP_PAGE:
947
			a.xPBPC = address;
948
			a.B.xPCl++;
949
			return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8));
950
951
		case WRAP_BANK:
952
			a.xPBPC = address;
953
			a.W.xPC++;
954
			return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8));
955
956
		case WRAP_NONE:
957
		default:
958
			return (SA1OpenBus | (S9xSA1GetByte(address + 1) << 8));
959
	}
960
}
961
962
void S9xSA1SetByte (uint8 byte, uint32 address)
963
{
964
	uint8	*SetAddress = SA1.WriteMap[(address & 0xffffff) >> MEMMAP_SHIFT];
965
966
	if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
967
	{
968
		*(SetAddress + (address & 0xffff)) = byte;
969
		return;
970
	}
971
972
	switch ((pint) SetAddress)
973
	{
974
		case CMemory::MAP_PPU:
975
			S9xSetSA1(byte, address & 0xffff);
976
			return;
977
978
		case CMemory::MAP_LOROM_SRAM:
979
		case CMemory::MAP_SA1RAM:
980
			*(Memory.SRAM + (address & 0xffff)) = byte;
981
			return;
982
983
		case CMemory::MAP_BWRAM:
984
			*(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte;
985
			return;
986
987
		case CMemory::MAP_BWRAM_BITMAP:
988
			address -= 0x600000;
989
			if (SA1.VirtualBitmapFormat == 2)
990
			{
991
				uint8	*ptr = &Memory.SRAM[(address >> 2) & 0xffff];
992
				*ptr &= ~(3  << ((address & 3) << 1));
993
				*ptr |= (byte &  3) << ((address & 3) << 1);
994
			}
995
			else
996
			{
997
				uint8	*ptr = &Memory.SRAM[(address >> 1) & 0xffff];
998
				*ptr &= ~(15 << ((address & 1) << 2));
999
				*ptr |= (byte & 15) << ((address & 1) << 2);
1000
			}
1001
1002
			return;
1003
1004
		case CMemory::MAP_BWRAM_BITMAP2:
1005
			address = (address & 0xffff) - 0x6000;
1006
			if (SA1.VirtualBitmapFormat == 2)
1007
			{
1008
				uint8	*ptr = &SA1.BWRAM[(address >> 2) & 0xffff];
1009
				*ptr &= ~(3  << ((address & 3) << 1));
1010
				*ptr |= (byte &  3) << ((address & 3) << 1);
1011
			}
1012
			else
1013
			{
1014
				uint8	*ptr = &SA1.BWRAM[(address >> 1) & 0xffff];
1015
				*ptr &= ~(15 << ((address & 1) << 2));
1016
				*ptr |= (byte & 15) << ((address & 1) << 2);
1017
			}
1018
1019
			return;
1020
1021
		default:
1022
			return;
1023
	}
1024
}
1025
1026
void S9xSA1SetWord (uint16 Word, uint32 address, enum s9xwrap_t w, enum s9xwriteorder_t o)
1027
{
1028
	PC_t	a;
1029
1030
	if (!o)
1031
		S9xSA1SetByte((uint8) Word, address);
1032
1033
	switch (w)
1034
	{
1035
		case WRAP_PAGE:
1036
			a.xPBPC = address;
1037
			a.B.xPCl++;
1038
			S9xSA1SetByte(Word >> 8, a.xPBPC);
1039
			break;
1040
1041
		case WRAP_BANK:
1042
			a.xPBPC = address;
1043
			a.W.xPC++;
1044
			S9xSA1SetByte(Word >> 8, a.xPBPC);
1045
			break;
1046
1047
		case WRAP_NONE:
1048
		default:
1049
			S9xSA1SetByte(Word >> 8, address + 1);
1050
			break;
1051
	}
1052
1053
	if (o)
1054
		S9xSA1SetByte((uint8) Word, address);
1055
}
1056
1057
void S9xSA1SetPCBase (uint32 address)
1058
{
1059
	SA1Registers.PBPC = address & 0xffffff;
1060
	SA1.ShiftedPB = address & 0xff0000;
1061
26.1.1 by zones
Rewrite IRQ / Update SA-1 / Remove CPUShutdown
1062
	// FIXME
1063
	SA1.MemSpeed = memory_speed(address);
1064
	SA1.MemSpeedx2 = SA1.MemSpeed << 1;
1065
1 by OV2
Initial 1.52 import
1066
	uint8	*GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT];
1067
1068
	if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
1069
	{
1070
		SA1.PCBase = GetAddress;
1071
		return;
1072
	}
1073
1074
	switch ((pint) GetAddress)
1075
	{
1076
		case CMemory::MAP_LOROM_SRAM:
1077
			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
1078
				SA1.PCBase = NULL;
1079
			else
1080
				SA1.PCBase = (Memory.SRAM + ((((address & 0xff0000) >> 1) | (address & 0x7fff)) & Memory.SRAMMask)) - (address & 0xffff);
1081
			return;
1082
1083
		case CMemory::MAP_HIROM_SRAM:
1084
			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
1085
				SA1.PCBase = NULL;
1086
			else
1087
				SA1.PCBase = (Memory.SRAM + (((address & 0x7fff) - 0x6000 + ((address & 0xf0000) >> 3)) & Memory.SRAMMask)) - (address & 0xffff);
1088
			return;
1089
1090
		case CMemory::MAP_BWRAM:
1091
			SA1.PCBase = SA1.BWRAM - 0x6000 - (address & 0x8000);
1092
			return;
1093
1094
		case CMemory::MAP_SA1RAM:
1095
			SA1.PCBase = Memory.SRAM;
1096
			return;
1097
1098
		default:
1099
			SA1.PCBase = NULL;
1100
			return;
1101
	}
1102
}