Skip to content

Commit c66c309

Browse files
committed
SA1 emulation fixes from the current git version of snes9x.
1 parent 4b70a73 commit c66c309

File tree

1 file changed

+108
-71
lines changed

1 file changed

+108
-71
lines changed

source/sa1.c

Lines changed: 108 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -277,31 +277,39 @@ uint8_t S9xGetSA1(uint32_t address)
277277
{
278278
switch (address)
279279
{
280-
case 0x2300:
281-
return (uint8_t)((Memory.FillRAM [0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)));
282-
case 0x2301:
283-
return (Memory.FillRAM [0x2200] & 0xf) | (Memory.FillRAM [0x2301] & 0xf0);
284-
case 0x2306:
285-
return (uint8_t) SA1.sum;
286-
case 0x2307:
287-
return (uint8_t) (SA1.sum >> 8);
288-
case 0x2308:
289-
return (uint8_t) (SA1.sum >> 16);
290-
case 0x2309:
291-
return (uint8_t) (SA1.sum >> 24);
292-
case 0x230a:
293-
return (uint8_t) (SA1.sum >> 32);
294-
case 0x230d:
295-
{
296-
uint8_t byte = Memory.FillRAM [0x230d];
280+
case 0x2300:
281+
return (Memory.FillRAM[0x2209] & 0x5f) | (Memory.FillRAM[0x2300] & 0xa0);
282+
case 0x2301:
283+
return (Memory.FillRAM[0x2200] & 0x0f) | (Memory.FillRAM[0x2301] & 0xf0);
284+
case 0x2306:
285+
return (uint8_t) SA1.sum;
286+
case 0x2307:
287+
return (uint8_t) (SA1.sum >> 8);
288+
case 0x2308:
289+
return (uint8_t) (SA1.sum >> 16);
290+
case 0x2309:
291+
return (uint8_t) (SA1.sum >> 24);
292+
case 0x230a:
293+
return (uint8_t) (SA1.sum >> 32);
294+
case 0x230b:
295+
return SA1.overflow ? 0x80 : 0;
296+
case 0x230c:
297+
return Memory.FillRAM[0x230c];
298+
case 0x230d:
299+
{
300+
uint8_t byte = Memory.FillRAM[0x230d];
297301

298-
if (Memory.FillRAM [0x2258] & 0x80)
299-
S9xSA1ReadVariableLengthData(true, false);
300-
return byte;
301-
}
302+
if (Memory.FillRAM[0x2258] & 0x80)
303+
S9xSA1ReadVariableLengthData(true, false);
304+
return byte;
305+
}
306+
case 0x230e: /* version code register */
307+
return 0x01;
308+
default:
309+
break;
302310
}
303311

304-
return Memory.FillRAM [address];
312+
return Memory.FillRAM[address];
305313
}
306314

307315
void S9xSetSA1(uint8_t byte, uint32_t address)
@@ -314,26 +322,37 @@ void S9xSetSA1(uint8_t byte, uint32_t address)
314322
case 0x2200:
315323
SA1.Waiting = (byte & 0x60) != 0;
316324

317-
if (!(byte & 0x20) && (Memory.FillRAM [0x2200] & 0x20))
325+
if (!(byte & 0x80) && (Memory.FillRAM[0x2200] & 0x20))
318326
S9xSA1Reset();
319327
if (byte & 0x80)
320328
{
321-
Memory.FillRAM [0x2301] |= 0x80;
322-
if (Memory.FillRAM [0x220a] & 0x80)
329+
Memory.FillRAM[0x2301] |= 0x80;
330+
if (Memory.FillRAM[0x220a] & 0x80)
323331
{
332+
Memory.FillRAM[0x220b] &= ~0x80;
324333
SA1.Flags |= IRQ_PENDING_FLAG;
325334
SA1.IRQActive |= SNES_IRQ_SOURCE;
326335
SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
327336
}
328337
}
329338
if (byte & 0x10)
330-
Memory.FillRAM [0x2301] |= 0x10;
339+
{
340+
Memory.FillRAM[0x2301] |= 0x10;
341+
if (Memory.FillRAM[0x220a] & 0x10)
342+
Memory.FillRAM[0x220b] &= ~0x10;
343+
}
331344
break;
332345
case 0x2201:
333-
if (((byte ^ Memory.FillRAM [0x2201]) & 0x80) && (Memory.FillRAM [0x2300] & byte & 0x80))
346+
if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80))
347+
{
348+
Memory.FillRAM[0x2202] &= ~0x80;
334349
S9xSetIRQ(SA1_IRQ_SOURCE);
335-
if (((byte ^ Memory.FillRAM [0x2201]) & 0x20) && (Memory.FillRAM [0x2300] & byte & 0x20))
350+
}
351+
if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20))
352+
{
353+
Memory.FillRAM[0x2202] &= ~0x20;
336354
S9xSetIRQ(SA1_DMA_IRQ_SOURCE);
355+
}
337356
break;
338357
case 0x2202:
339358
if (byte & 0x80)
@@ -348,29 +367,37 @@ void S9xSetSA1(uint8_t byte, uint32_t address)
348367
}
349368
break;
350369
case 0x2209:
351-
Memory.FillRAM [0x2209] = byte;
352370
if (byte & 0x80)
353-
Memory.FillRAM [0x2300] |= 0x80;
354-
355-
if (byte & Memory.FillRAM [0x2201] & 0x80)
356-
S9xSetIRQ(SA1_IRQ_SOURCE);
357-
return;
371+
{
372+
Memory.FillRAM[0x2300] |= 0x80;
373+
if (Memory.FillRAM[0x2201] & 0x80)
374+
{
375+
Memory.FillRAM[0x2202] &= ~0x80;
376+
S9xSetIRQ(SA1_IRQ_SOURCE);
377+
}
378+
}
379+
break;
358380
case 0x220a:
359-
if (((byte ^ Memory.FillRAM [0x220a]) & 0x80) && (Memory.FillRAM [0x2301] & byte & 0x80))
381+
if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80))
360382
{
383+
Memory.FillRAM[0x220b] &= ~0x80;
361384
SA1.Flags |= IRQ_PENDING_FLAG;
362385
SA1.IRQActive |= SNES_IRQ_SOURCE;
363386
}
364-
if (((byte ^ Memory.FillRAM [0x220a]) & 0x40) && (Memory.FillRAM [0x2301] & byte & 0x40))
387+
if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40))
365388
{
389+
Memory.FillRAM[0x220b] &= ~0x40;
366390
SA1.Flags |= IRQ_PENDING_FLAG;
367391
SA1.IRQActive |= TIMER_IRQ_SOURCE;
368392
}
369-
if (((byte ^ Memory.FillRAM [0x220a]) & 0x20) && (Memory.FillRAM [0x2301] & byte & 0x20))
393+
if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20))
370394
{
395+
Memory.FillRAM[0x220b] &= ~0x20;
371396
SA1.Flags |= IRQ_PENDING_FLAG;
372397
SA1.IRQActive |= DMA_IRQ_SOURCE;
373398
}
399+
if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10))
400+
Memory.FillRAM[0x220b] &= ~0x10;
374401
break;
375402
case 0x220b:
376403
if (byte & 0x80)
@@ -389,7 +416,7 @@ void S9xSetSA1(uint8_t byte, uint32_t address)
389416
Memory.FillRAM [0x2301] &= ~0x20;
390417
}
391418
if (byte & 0x10)
392-
Memory.FillRAM [0x2301] &= ~0x10; // Clear NMI
419+
Memory.FillRAM [0x2301] &= ~0x10;
393420
if (!SA1.IRQActive)
394421
SA1.Flags &= ~IRQ_PENDING_FLAG;
395422
break;
@@ -410,38 +437,41 @@ void S9xSetSA1(uint8_t byte, uint32_t address)
410437
if (byte & 0x80)
411438
SA1.in_char_dma = 0;
412439
break;
413-
case 0x2236:
414-
Memory.FillRAM [address] = byte;
415-
if ((Memory.FillRAM [0x2230] & 0xa4) == 0x80)
416-
S9xSA1DMA(); // Normal DMA to I-RAM
417-
else if ((Memory.FillRAM [0x2230] & 0xb0) == 0xb0)
440+
case 0x2236: /* DMA destination start address (LH) */
441+
Memory.FillRAM[address] = byte;
442+
if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) /* Normal DMA to I-RAM */
443+
S9xSA1DMA(); /* Normal DMA to I-RAM */
444+
else if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0)
418445
{
419-
Memory.FillRAM [0x2300] |= 0x20;
420-
if (Memory.FillRAM [0x2201] & 0x20)
421-
S9xSetIRQ(SA1_DMA_IRQ_SOURCE);
422446
SA1.in_char_dma = 1;
447+
Memory.FillRAM[0x2300] |= 0x20;
448+
if (Memory.FillRAM[0x2201] & 0x20)
449+
{
450+
Memory.FillRAM[0x2202] &= ~0x20;
451+
S9xSetIRQ(SA1_DMA_IRQ_SOURCE);
452+
}
423453
}
424-
return;
454+
break;
425455
case 0x2237:
426456
Memory.FillRAM [address] = byte;
427457
if ((Memory.FillRAM [0x2230] & 0xa4) == 0x84)
428458
S9xSA1DMA(); // Normal DMA to BW-RAM
429-
return;
459+
break;
430460
case 0x223f:
431461
SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4;
432462
break;
433463
case 0x224f:
434464
Memory.FillRAM [address] = byte;
435465
if ((Memory.FillRAM [0x2230] & 0xb0) == 0xa0)
436466
{
437-
// Char conversion 2 DMA enabled
438-
// memmove converted: Same malloc but constant non-overlapping addresses [Neb]
467+
/* Char conversion 2 DMA enabled */
468+
/* memmove converted: Same malloc but constant non-overlapping addresses [Neb] */
439469
memcpy(&Memory.ROM [MAX_ROM_SIZE - 0x10000] + (SA1.in_char_dma << 4), &Memory.FillRAM [0x2240], 16);
440470
SA1.in_char_dma = (SA1.in_char_dma + 1) & 7;
441471
if ((SA1.in_char_dma & 3) == 0)
442472
S9xSA1CharConv2();
443473
}
444-
return;
474+
break;
445475
case 0x2250:
446476
if (byte & 2)
447477
SA1.sum = 0;
@@ -451,48 +481,55 @@ void S9xSetSA1(uint8_t byte, uint32_t address)
451481
SA1.op1 = (SA1.op1 & 0xff00) | byte;
452482
break;
453483
case 0x2252:
454-
SA1.op1 = (SA1.op1 & 0xff) | (byte << 8);
484+
SA1.op1 = (SA1.op1 & 0x00ff) | (byte << 8);
455485
break;
456486
case 0x2253:
457487
SA1.op2 = (SA1.op2 & 0xff00) | byte;
458488
break;
459489
case 0x2254:
460-
SA1.op2 = (SA1.op2 & 0xff) | (byte << 8);
490+
SA1.op2 = (SA1.op2 & 0x00ff) | (byte << 8);
461491
switch (SA1.arithmetic_op)
462492
{
463-
case 0: // multiply
464-
SA1.sum = SA1.op1 * SA1.op2;
493+
case 0: /* multiply */
494+
SA1.sum = (int16_t) SA1.op1 * (int16_t) SA1.op2;
495+
SA1.op2 = 0;
465496
break;
466-
case 1: // divide
497+
case 1: /* divide */
467498
if (SA1.op2 == 0)
468-
SA1.sum = SA1.op1 << 16;
499+
SA1.sum = 0;
469500
else
470501
{
471-
uint32_t x = (SA1.op1 / (uint16_t) SA1.op2);
472-
SA1.sum = x | ((SA1.op1 - (x * (uint16_t) SA1.op2)) << 16);
502+
int16_t quotient = (int16_t) SA1.op1 / (uint16_t) SA1.op2;
503+
uint16_t remainder = (int16_t) SA1.op1 % (uint16_t) SA1.op2;
504+
SA1.sum = (remainder << 16) | quotient;
473505
}
506+
SA1.op1 = 0;
507+
SA1.op2 = 0;
474508
break;
475-
default: // cumulative sum
476-
SA1.sum += SA1.op1 * SA1.op2;
477-
if (SA1.sum & ((int64_t) 0xffffff << 32))
478-
SA1.overflow = true;
509+
default: /* cumulative sum */
510+
SA1.sum += (int16_t) SA1.op1 * (int16_t) SA1.op2;
511+
SA1.overflow = (SA1.sum >= (1ULL << 40));
512+
SA1.sum &= (1ULL << 40) - 1;
513+
SA1.op2 = 0;
479514
break;
480515
}
481516
break;
482-
case 0x2258: // Variable bit-field length/auto inc/start.
483-
Memory.FillRAM [0x2258] = byte;
517+
case 0x2258: /* Variable bit-field length/auto inc/start. */
518+
Memory.FillRAM[0x2258] = byte;
484519
S9xSA1ReadVariableLengthData(true, false);
485520
return;
486521
case 0x2259:
487522
case 0x225a:
488-
case 0x225b: // Variable bit-field start address
489-
Memory.FillRAM [address] = byte;
523+
case 0x225b: /* Variable bit-field start address */
524+
Memory.FillRAM[address] = byte;
490525
SA1.variable_bit_pos = 0;
491526
S9xSA1ReadVariableLengthData(false, true);
492527
return;
528+
default:
529+
break;
493530
}
494531

495-
Memory.FillRAM [address] = byte;
532+
Memory.FillRAM[address] = byte;
496533
}
497534

498535
static void S9xSA1CharConv2()
@@ -537,14 +574,14 @@ static void S9xSA1DMA()
537574

538575
switch (Memory.FillRAM [0x2230] & 3)
539576
{
540-
case 0: // ROM
577+
case 0: /* ROM */
541578
s = SA1.Map [(src >> MEMMAP_SHIFT) & MEMMAP_MASK];
542579
if (s >= (uint8_t*) MAP_LAST)
543580
s += (src & 0xffff);
544581
else
545582
s = Memory.ROM + (src & 0xffff);
546583
break;
547-
case 1: // BW-RAM
584+
case 1: /* BW-RAM */
548585
src &= Memory.SRAMMask;
549586
len &= Memory.SRAMMask;
550587
s = Memory.SRAM + src;
@@ -568,7 +605,7 @@ static void S9xSA1DMA()
568605
len &= 0x3ff;
569606
d = &Memory.FillRAM [0x3000] + dst;
570607
}
571-
// memmove required: Can overlap arbitrarily [Neb]
608+
/* memmove required: Can overlap arbitrarily [Neb] */
572609
memmove(d, s, len);
573610
Memory.FillRAM [0x2301] |= 0x20;
574611

0 commit comments

Comments
 (0)